CS21B Lab 11: The Game of Life

Due 11:59pm Tuesday, April 26

Run update21b, to create the cs21b/labs/11 directory. This week's lab depends on last week's lab. If you are still having issues with your Grid and Cell classes, you'll need to correct them first. Once your previous lab is working correctly, copy your grid.py solution from your labs/10 directory into your labs/11 directory. You will add the new code for this week's lab to the file called gameoflife.py.

Read through this entire lab description before you begin coding your solution. Then go to the section on getting started and follow the directions given there to begin.

Introduction

For this assignment, you will implement a class called GameOfLife that can be used to play John Conway's Game of Life. The GameOfLife class will use the Grid and Cell classes you wrote for the previous lab.

The Game of Life simulates the evolution of a cellular automata in a two dimensional grid world. During the simulation, a cell either lives or dies based on its state and the state of its neighbors. The neighbors of a cell are the eight cells that directly surround it. If a cell is on the edge of the grid, it will only have five neighboring cells. If a cell is in the corner of the grid, it will only have three neighboring cells. To play the game of life first, an initial configuration of the grid's cells are set. Then, at each time step, a cell's state changes according to the following rules:


Requirements

  1. You must implement a GameOfLife class that stores a Grid as data. You may store additional data in the class as well.

  2. Your GameOfLife class should have at least these methods (you may add more if you'd like):
    • __init__: the constructor takes the desired width and height of the grid as parameters and creates the Grid object data member.
    • startWalkerGame: creates a starting point world of the walker pattern in the lower left corner (see the sample output section for what this pattern should look like). The walker pattern should cause a set of live cells to move diagonally toward the upper right corner of the screen.
    • startExpanderGame: creates a starting point world of the expander pattern such that it is drawn centered in the grid (see the sample output section for what this pattern should look like). Be sure to use the getWidth() and getHeight() methods of the grid to help you determine its center. The expander game should cause the initial pattern to expand outward and then end with four stable structures on the grid.
    • startToggleGame: a starting point world that the user can specify by toggling cells in the grid using the mouse.
    • startRandomGame: takes a percentage as a parameter, and randomly turns on the requested percentage of cells in the grid.
    • playGame: plays the game of life, based on the rules given above, until the user presses the 'q' key to quit. Uses the sleep function from the time library to delay 0.2 seconds between each step.

  3. The final version of your main program should prompt the user to enter the width and height of the grid, create a GameOfLife object of the given dimensions. For each of the game starting points (walker, expander, toggle, and random) in turn your program should:
    • call the appropriate start method to initialize the world for that game
    • start the game when the user presses any key
    • play the game until the user presses 'q' key to quit
    • clear the grid prior to starting the next game

You should follow the directions in the next section to implement and test your program incrementally.

Getting Started

  1. At the bottom of your grid.py file, make sure that you call your main program like this:
    if __name__ == '__main__': main()
    
    This ensures that when you import this file into another program that the main program inside this file will not be called.

  2. Create the GameOfLife class incrementally. First implement the __init__ and playGame methods.

  3. Next test that you've implemented the rules correctly. One way to test for correctness is to try a pattern that repeats in a well known way. For example, if you initialize three cells in a column to be alive, then in the next time step the live cells will flip to be three cells in a row with the same middle cell. This pattern repeats forever (alternating between three cells in a row and three cells in a column). Here is a pattern on a 5 by 5 grid based on this:

  4. Once the above test pattern successfully flips between a vertical and a horizontal line, you can implement each of the games, testing after adding each one.


Sample output

In the sample output given below, only the initial starting conditions of each game are shown.

$ python gameoflife.py

This program plays Conway's Game of Life

Enter width of the grid: 21
Enter height of the grid: 21

Try the walker game.
Press any key to start the game.
Press q key to quit.

Try the expander game.
Press any key to start the game.
Press q key to quit.

Try the toggle game.
In this game you create your own starting point by
clicking on cells to make them alive.
Press any key when done toggling.
Press q key to quit.

Try the random game.
Press any key to start the game.
Press q key to quit.

Optional Extensions

Do not try these extensions until you have the basic assignment implemented, tested, and working correctly.

Add other starting point methods that initialize the world to different configurations. There are many that will lead to interesting patterns that repeat forever or that converge to a static pattern. Look online for some examples.

Submit

Once you are satisfied with your program, hand it in by typing handin21b in a terminal window.