CS 100  Programming I
Project 2

Revision Date: January 8, 2017

Printable Version


Preamble

This is your third Python assignment. You may develop your code on your USB-stick (or anywhere else), but you must ensure it runs correctly on your stick before submission.

Life!

"Life! Don't talk to me about life." - Marvin the Paranoid Android, The Hitchhiker's Guide to the Galaxy

Your task is to program the classic Computer Science demonstration of cellular automata, The Game of Life.

You can read more about Conway's Game of Life on the Web.

Generational rules

There are many rule sets that have been proposed for the Game of Life. Use the mailing list to discuss and decide upon the rule set to be used in this project.

Creating a two-dimensional list

The Game of Life is most easily implemented using a two-dimensional array. Python doesn't have arrays, so we will use a two-dimensional list instead. Suppose you wish to create a two-dimensional list, which is a list of lists, with r rows and c columns. First, we need the ability to create a single list of a given length:

    def createList(size):
        if size == 0: return []
        else: return [None] + createList(size - 1)

Next, we create a list to hold all of the rows; this row-holding list is known as a backbone. Each slot in the backbone will hold a row and we need r slots.

    backbone = createList(r)

Finally, for each slot in the backbone, we create a row that is c columns long:

    for i in range(r):
        backbone[i] = createList(c)

Now, the variable backbone points to the two-dimensional list. Pictorially, the list looks like this after creation:

This list has five rows and eight columns. The backbone list is shown in yellow. Note that it has five slots since it is a holder for the five rows. The row lists are shown in red. Each of the row lists have eight slots since there are eight columns.

To access the ith row and the jth column, one uses the notation:

    storedValue = backbone[i][j]

To set the value at the ith row and the jth column, one uses this notation:

    backbone[i][j] = newValue;

Remember, lists use zero-based counting!

Input / output

The name of file containing the first generation and the number of generations in the simulation are to be passed as command-line arguments, as in:

    python3 life.py xxxx yyyy

where xxxx is the name of the file containing the initial generation and yyyy is the number of generations to simulate.

Your program should output a series of generation representations preceded by the generation number, starting with generation zero. See the compliance instructions for what a generation representation looks like. If n generations are desired, then n generation representations should be output by the program, each preceded by its generation number.

Reading from a file

To read from a file, you may use the Scanner class, which you can retrieve with:

    wget http://troll.cs.ua.edu/cs100/python/projects/scanner.py

To read a line at a time instead of a token at a time, use the scanner's readline function instead of the readtoken function. To read a character at a time, use the readchar function. The readchar function ignores whitespace. To read all characters in a file, one after another, including whitespace characters, use the readrawchar function.

The initial generation

The initial generation is to be stored in a file and will look similar to:

...........................xx.........
..x..............xx........xxx........
..x...x.........x..x........xxx.......
.................xx..........xx.......
......x....................x..........
x....x..........x..........xxxx.......
................xx................x...
.x...x.................x..xx......x...
..................................xx..
..x.......x............x...........x..

The file will be composed of only dots and x's with no blank lines. To determine the dimensions of the grid, read the first line using the Scanner's readline function and find out the number of characters in the line (remember to take into account the newline character at the end of the line - you don't want to count that). This step gives you the number of columns. Then keep reading lines to determine the number of rows. Once the number of rows and columns have been determined. close the scanner. Always remember to close the scanner when you are finished reading.

You can now re-read the input file using the readchar method of the scanner. You will have to recreate the a scanner object to reread the file.

Stepwise refinement

You should use stepwise refinement in implementing this project.

Level 0
Write a program that prints out the name of the file containing the initial population and the number of generations to simulate.
Level 1
Write a program that prints out each line of the initial population.
Level 2
Write a program that prints out the number of rows and the number of columns in the initial population file.
Level 3
Write a program that reads each character of the initial population file, placing that character into its proper place in a two-dimensional list. Print out the two-dimensional list in a pleasing format when finished.
Level 4
Write a program that prints out the initial generation (unmodified each time) for the desired number of generations.
Level 5
Write a program that, for each generational step, copies the current generation to another two-dimensional list, replacing each non-dot character with the previous character in the alphabet. This new two-dimensional list becomes the current generation. Thus, the first generation has x's, the second w's, the third v's, and so on. If the variable a1 points to a letter, then after this expression:
    a2 = chr(ord(a1) - 1)

the variable a2 points to the previous letter.

Level 6

Like Level 5, but replaces the each non-dot characters with the number of non-dot characters in the neighboorhood. Note, the only change you will see is from the first generation to the second. After that, there should be no changes.

Level 7

Like Level 6, but replaces each non-dot characters with a dot or an x, depending on the number of non-dot neighbors.

Level 8

Like Level 7, but also replaces each dot characters with a dot or an x, depending on the number of non-dot neighbors.

Write programs with the names level0.py, level1.py, etc. When you are ready to move to the next level, copy the previous level's program. For example:

    cp level0.py level1.py

copies the code in level0.py and creates a new file named level1.py. Instructors and mentoring students have been informed that before they can help you, you must demonstrate what levels you have completed.

Program Organization

Create a directory named project2 that hangs off of your cs100 directory. Do your work in that directory.

Name your main file life.py. Make sure you have scanner.py in your directory as well.

Compliance Instructions

To make sure that you have implemented your program correctly, create a file named test0 and populate the world within appropriately. You should then be able to run the following command:

    python3 life.py test2 1

and see the exact output:

Generation 1:
...........................xx.........
..x..............xx........xxx........
..x...x.........x..x........xxx.......
.................xx..........xx.......
......x....................x..........
x....x..........x..........xxxx.......
................xx................x...
.x...x.................x..xx......x...
..................................xx..
..x.......x............x...........x..

Generation 2:
...........................x.x........
.................xx...........x.......
................x..x.......x..........
.................xx...........x.......
.................x.........x..........
................xx.........xxx........
................xx........x..x........
.................................xx...
..................................xx..
..................................xx..

Generation 3:
......................................
.................xx.........x.........
................x..x..................
................xxx...................
...........................x.x........
..................x.......xx.x........
................xx.........x.x........
.................................xxx..
......................................
..................................xx..

Adjust the contents of test0 until you get the desired output.

If your code does not produce this output or fails with a runtime error while running this test, then you will receive a zero for this assignment.

Submission Instructions

Change to the directory containing your assignment. If you are working on your USB-stick, run the command:

    submit cs100 xxxx project2

Replace xxxx with your instructor name.

Due Date

The due date for this assignment can be found on the class schedule.

lusth@cs.ua.edu