CS21 Lab 11: The Game of Life

Due 11:59pm Tuesday, April 20

You may work with a partner on this assignment.

Run update21, to create the cs21/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 has a Grid data member. You may add additional data members as you like.

  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.
    • close: will invoke the grid's close method that will wait for a mouse click and then close the graphics window.
    • 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). 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. Use cell[0][0] as the special "stop clicking" cell.
    • playGame: takes the number of steps to simulate as a parameter, and plays the game of life using the rules given above on the current world state for that many steps. Use 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 and toggle) in turn your program should:
    • call the appropriate start method to initialize the world for that game
    • prompt the user to enter the number of time steps to simulate the game
    • play the game of life
    • 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, add the following line before your call to the main program:
    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. At the top of your gameoflife.py file, import the classes and functions that you'll need:
    from grid import *
    from time import sleep
    

  3. Create the GameOfLife class incrementally. First implement the __init__, close and playGame methods.

  4. 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:

  5. 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.
Enter the number of steps: 50

Try the expander game.
Enter the number of steps: 20

Try the toggle game.
Enter the number of steps: 30

In this game you create your own starting point by clicking on cells to
make them alive.  Clicking on the cell in the lower left corner (0,0) 
will start the game.
Click one last time to end the Game of Life.

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 handin21 in a terminal window.