← Back

Contents

What is the game of life? Basic terminology The rules Task 1: Basic simulation in Python Further terminology Task 2: Make it toroidal Task 3: Print useful statistics Task 4: Detect equilibrium Task 5: Color-code for age Explore more

Conway's Game of Life

What is the game of life?

Conway's Game of Life is a cellular automaton created by mathematician John Conway. t's a zero-player game, meaning its evolution is determined by its initial state without any further input. The game is played on an infinite grid of square cells, each of which can be either alive or dead. The state of the grid evolves in discrete time steps according to a set of simple rules based on the states of neighboring cells. Despite simple rules, the Game of Life can produce incredibly complex and varied patterns, being used in practical applications such as neural networks research in computer science and simulating population dynamics in theoretical biology

Basic terminology

Cell: The basic unit in the grid, either alive or dead.

Grid: The environment where the Game of Life is played, consisting of cells in a two-dimensional array.

Neighbor: Any of the eight surrounding cells influencing a cell's future state.

Alive: A cell state that is "on" or active, represented by `1`.

Dead: A cell state that is "off" or inactive, represented by `0`.

Initial Configuration: The starting arrangement of alive and dead cells in the grid.

Generation: A time step where the state of each cell is updated based on the game's rules (the initial configuration being generation 0).

Survival: A condition where a live cell remains alive in the next generation.

The rules

Conway's Game of Life typically uses the B3/S23 rules, which are the most common despite many possible variations. "B3/S23" means a dead cell with exactly three alive neighbors becomes alive (B3), and a live cell with two or three alive neighbors survives (S23). The rules are:

  1. Any live cell with fewer than two alive neighbors dies (the underpopulation rule).
  2. A live cell with two or three alive neighbors survives (the survival rule).
  3. Any live cell with more than three alive neighbors dies (the overcrowding rule).
  4. A dead cell with exactly three alive neighbors becomes alive (the reproduction rule).

Task 1: The basic simulation

Consider the following simulation of Conway's Game of Life. This simulation uses a 100x100 grid. This is a good size because it allows intricate patterns to emerge without overwhelming computational resources. In this grid, black cells represent alive states, while white cells represent dead states. The initial configuration of the grid is populated randomly with a mix of alive and dead cells. Our first goal is to write code that can produce such simulations, showing the evolution of this grid over any number of generations, continuing until the window is closed by the user.

Figure 1: Python-based simulation using Pygame with a randomly generated initial configuration reaching equilibrium.

Given below is an incomplete Python code for the basic simulation.

Copy and run the code. You will see the initial state of the grid but there will be no evolution. To implement the evolution, complete the following two functions:

  • count_alive_neighbors (for update_grid)
  • update_grid

                        
                    
Further terminology

Age: The number of generations a cell has been alive.

Pattern: A specific arrangement of live and dead cells in the grid.

Period: The number of generations it takes for an oscillator to return to its initial state.

Spaceship: A pattern that translates itself across the grid over generations.

Glider: A common type of spaceship that moves diagonally across the grid, consisting of 5 live cells in a specific formation.

Oscillator: A pattern that returns to its initial state after a fixed number of generations, known as its period.

Still Lifes: Stable patterns that do not change from one generation to the next.

Equilibrium: A state where the grid either remains unchanged or cycles through the same sequence of configurations repeatedly.

Population: The total number of live cells in the grid \( P(t) = \sum_{i,j} \text{grid}[i][j] \). Purpose: tracks how the number of live cells changes over generations.

Growth Rate: The rate at which the population of live cells changes over time \( G(t) = \frac{P(t+1) - P(t)}{P(t)} \). Purpose: measures how quickly the population is increasing or decreasing.

Stability: The tendency of a pattern to remain unchanged or return to its original configuration after disturbances. One way to calculate stability is by counting the number of cells that do not change state between generations \( \text{Stability} = \frac{\text{Unchanged Cells}}{\text{Total Cells}} \).

Entropy: A measure of the disorder or randomness in the grid. One way to calculate entropy: \( H(t) = - \sum_{i,j} \left( \frac{\text{grid}[i][j]}{N} \right) \log_2 \left( \frac{\text{grid}[i][j]}{N} \right) \) where \(N\) is the total number of cells.

Task 2: Make it toroidal

Implement a wrap-around effect by modifying count_alive_neighbors to treat the grid edges as continuous. This creates a toroidal grid, where cells on the edges connect to cells on the opposite side, mimicking an infinite, unbounded environment. This change is beneficial for observing uninterrupted patterns, like oscillators or spaceships moving freely across the grid.

Task 3: Print useful statistics

Add code to display statistics for each generation, such as the generation count, live cell population, and growth rate. These statistics provide insight into how the grid evolves and can reveal trends in pattern dynamics. You may print these statistics to the console for easy monitoring as the simulation runs.

Implement functions to calculate:

  • Generation Number
  • Population (total live cells)
  • Growth Rate

Task 4: Detect equilibrium

In this task, you need to detect when the Game of Life grid reaches equilibrium and stop the simulation at that point. This is useful to stop unnecessary computations once the grid no longer changes. Equilibrium is achieved when the grid either becomes static (all cells remain the same) or enters a repeating cycle of configurations (dynamic equilibrium). To detect equilibrium, you need to add the necessary code to identify when the grid reaches one of these states and then stop the simulation, reporting the final statistics. While dynamic equilibrium can theoretically involve long cycles, you only need to cater to cycles of size 10 or less for this task. Make sure to maintain the necessary information and write the required functions to detect equilibrium and manage the simulation accordingly.

Task 5: Color-code for age

For this task, you need to maintain the necessary information and write the required code to color-code the simulation based on the age of the cells. In this context, the age of a cell refers to the number of generations it has been alive. Cells that have been alive for longer should appear darker. You can use a gradient where the color darkens progressively with each generation, but for cells that have been alive for 20 generations or more, the color may no longer change. Feel free to experiment with this number to find what works best for your simulation. To achieve this, you will need to modify the code in the draw_grid function. Make sure to update and manage the age of each cell as the simulation progresses. This task will help visualize the longevity and stability of various patterns in the simulation. Ideal visualization depends on several factors, so you are encouraged to experiment with different methods to enhance the quality of your visualization.

Figure 2: Age-based color coding highlights persistent patterns.

Some incredibly beautiful things are possible when colorful Game of Life is implemented at high resolutions with interactivity. For example, check out this beautiful implementation by Lucas Crane.

Explore more

The Game of Life is truly a world in itself. It's a Turing complete system, meaning that, given enough time and space, it can simulate any computation that can be described algorithmically. Game of Life is often programmed to simulate the basic logic gates, such as AND, OR, and NOT gates, from which more complex circuits may be built. For example, gliders can act as signals, and by their interactions they can simulate an OR gate: two gliders present at the input produce a single glider at the output, and similarly for other gates. For more information, tutorials, and the latest contributions about the Game of Life, visit the Conway Life Wiki.