Conway’s game of life in Python

Another agent-based simulation example from my side! In this article I will implement Conway’s game of life in Python, using the agent-based modeling framework abm_framework. You can find the framework by clicking the link below.

Conway’s game of life is a good introduction to agent-based modeling and it is also taught at universities for exactly this reason. It is also a good introduction to programming in Python in general.

I have recently shared a range of examples on how you can implement the abm_framework in Python for agent-based modeling. You can find the framework here:

The following section describes the rules of Conway’s game of life. After that I implement the game of life in Python.

Rules of Conway’s game of life

Conceptionally, the game of life consists of a grid. Every grid in the cell is populated by an agent. The agent is either dead or alive. Starting from an initial state the game of life updates iteration upon iteration. During each iteration the following rules apply:

  • If an agent is alive and its neighbouring cells contain 2 or 3 living agents, the agent survives until the next round. It is then alive in the next round. Otherwise the agent dies and is dead in the next round.
  • If a dead agent has exactly 3 living agents in its neighbourhood, the agent is reborn and is alive in the next round.

These rules are sufficient for modeling Conway’s game of life. The initial state, defined by the agents dead or alive at the beginning of the simulation, is the only input that the simulation needs to run. In this article I run three versions of the model. The first two version have a random intial distribution of living agent cells. The third version has a specific initial seed pattern of living agents. In the first and third version the grid is endless. This means that if you exit the grid to the left, you enter the grid on the right side, and if you exit the grid on the top you enter the grid on the bottom. The second version applies a grid with boundaries, i.e. a grid that is not endless.

Implementing the game of life in Python

Using the abm_framework in Python (made available by me on Github) I implement the model in Python. I create a simulation grid with 100 cells. The initial state (referred to as seed) consists of 50 living agents that are randomly distributed across the grid. The code below implements the endless grid version of the simulation model.

__author__ = "Linnart Felkl"
__email__ = "LinnartSF@gmail.com"

if __name__ == "__main__":

    print("demo starts")

    import sys
    from pathlib import Path
    file = Path(__file__).resolve()
    parent, root = file.parent, file.parents[1]
    sys.path.append(str(root))

    # remove the current file's directory from sys.path, unless already removed
    try:
        sys.path.remove(str(parent))
    except ValueError:
        pass

    import data
    import stats
    import config
    import framework
    import random
    import animation

    # setup database manager and connection
    db = data.Database("sqlite3", config.path_databasefile)
    db_manager = data.Manager(db)
    
    # create an empty environment
    env = framework.Environment(1, True, 10, 10, db_manager) # Environment constructor implicitly resets environment table in database

    # create initial population of healthy humans
    attrs = ["life_t0","life_t1"]
    datatypes = ["INTEGER","INTEGER"]
    pops = framework.Populations(amount = 1, env = env, db_manager = db_manager, attributes = attrs, datatypes = datatypes)
    pops.add_population(name = "units", 
                        size = 100, 
                        attributes = attrs, 
                        datatypes = datatypes, 
                        initialvals = [0, 0]
                        )
   
    # set seed of simulation (number of agents alive and their pattern)
    agents = pops.get_agents()
    random.shuffle(agents)
    for i in range(50):
        agents[i].set_attr_value("life_t0",1)

    # setup simulation
    sim = framework.Simulation(50)

    # make sure that environment and agents tables in database are setup at this time
    pops.write_env_to_db(sim.Iteration)
    pops.write_agents_to_db(sim.Iteration)

    # execute simulation run; with centralized simulation control
    while sim.run():
        
        for agent in agents:

            # get that agents neighbourhood
            neighbours = env.get_neighbourhood(agent, mode = "moore", radius = 1)

            _neighbours_alive = 0
            for neighbour in neighbours:
                
                if neighbour.get_attr_value("life_t0") == 1: 
                    _neighbours_alive  += 1

            if agent.get_attr_value("life_t0") == 1: 

                if _neighbours_alive == 2 or _neighbours_alive == 3: 
                    
                    agent.set_attr_value("life_t1", 1)

                else:

                    agent.set_attr_value("life_t1", 0)

            elif _neighbours_alive == 3:

                agent.set_attr_value("life_t1", 1)

            else:

                agent.set_attr_value("life_t1", 0)
                
        # update results in database, for agents and for environment
        pops.write_agents_to_db(sim.Iteration)
        pops.write_density_to_db(sim.Iteration)

        # update attributes for next round
        for agent in agents:

            agent.set_attr_value("life_t0", agent.get_attr_value("life_t1"))
    
    # get dataframes with simulation results
    density_df = db_manager.get_densitydf()

    # visualize simulation data
    stats.set_fontsizes(8,10,12)

    animation.animate_density(
        df = density_df,
        filename = "gol_randomendless",
        attr = "life_t1",
        defaultsize = 50,
        color = "black",
        tpf = 0.30
    )

    # end program
    db.close()
    print("demo ends")

In a second version of the model I implemented a grid that is not endless. The only adjustment in the code is in the Environment constructor call, setting endless grid argument to False instead of True.

Animation of Conway’s game of life

Below is the animation of Conway’s game of life in Python. The first animation represents the model with an endless grid.

The second animation, displayed below, represents the model with a bounded grid.

Lastly, I run a scenario in which I defined a specific initial model state. The animation can be seen below and represents an endless grid.

You can find various game of life examples by doing a simple Google query. There are also various tools available for specifying your own seed and running the model step by step.

Concluding remarks

In this article I implemented Conway’s game of life in Python, using a framework that I named abm_framework. I ran three scenarios, differing in grid boundary definition (endless vs. not endless) and initial seed (random initial seed vs. specific initial seed). If you want to learn agent-based modeling implementing the game of life in Python could be a good first step for you.

You May Also Like

Leave a Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.