How the 1d GOL is built.

Usually when the process of building a program is discussed we talk in plain English about the abstractions involved, then use some sort of flowchart to describe the algorithm, then begin to write the program in a non-existent generalised programming language - a technique called "pseudocoding".

There is no space here for a detailed discussion so I am going to jump straight to the pseudocoding. But I will use Matlab as the pseudocode so that each section of the code will actually run.

First we think of a name for the program, then put in some beginning statements, add a middle, and then and end. The outline pseudocode looks like this

function theGolProgram()
    number_of_cells = 80;
    number_of_gens = 100;
    % the complex middle bit goes here
end

This is the first version of our program. Notice that it is easy to read. We can type it in to a Matlab script and save it - the script *must* have the right name because it is written as a function. The function is called theGolProgram so the file must have the same name. We can run it by typing theGolProgram at the command prompt (it doesn't do much).

So what goes in the middle? At the heart of the program is a loop, which repeats as many times as there are generations - we will choose 100 generations as an example. The first generation doesn't require any calculation so we start the loop at 2.

theGolProgram     
    number_of_cells = 80;
    number_of_gens = 100;
    % the middle - everything else goes here
    for curr_gen = 2:number_of_gens
        % the complex middle bit goes here inside a loop
    end 
end

Something gets calculated many times. You can also run this code but it still doesn't do much!

We need to calculate all the births and deaths (we will call this 'the rule book') and draw a picture of what is happening on the screen. We add two lines to the code to do these two things:

function theGolProgram()
    number_of_cells = 80;
    number_of_gens = 100;
    % the middle - everything else goes here
    for curr_gen = 2:number_of_gens
        % do something this many times
        apply_rulebook;
        update_screen;
    end 
end

Note that we have no idea how to "apply_rulebook" or "update_screen" when we write this. This doesn't matter. Now the code will not run until we have written two new procedures which have matching names. The easy one first:

function update_screen
    % imagesc is the name of a Matlab function which creates a
    % picture from an array of numbers
    imagesc(population);
    drawnow;
end

That was easy! Now the slightly more complicated one. First the start and end:

function apply_rulebook
    % rule number 1 
    % rule number 2
end

There are two rules - first:

  • If a cell is alive in one generation, it will be dead in the next i.e. each cell has a lifespan of one iteration.

we can code this like so:

function apply_rulebook
    % rule number 1
    last_gen = curr_gen-1;
    for p_cell = 1:num_of_cells
        % for live cells only
        if population(last_gen, p_cell)==1
            population(curr_gen, p_cell)==0;
        end
    end
    % rule number 2
end

The second rule is more tricky:

  • If a cell is dead but has one and only one live neighbour, it will come alive in the next generation i.e. new lives are born where there is no overcrowding.
function apply_rulebook
    % rule number 1
    last_gen = curr_gen-1;
    for p_cell = 1:num_of_cells
        % for live cells only
        if population(last_gen, p_cell)==1
            population(curr_gen, p_cell)==0;
        end
    end
    % rule number 2
for p_cell = 1:num_of_cells
        % for dead cells only
        if population(last_gen, p_cell)==0
            
            % handle special cases for first and last cell
            % to put population in a ring
            if p_cell ==1
                leftn = population(last_gen, number_of_cells);
            else
                leftn = population(last_gen, p_cell-1);
            end
            
            if p_cell == number_of_cells
                rghtn = population(last_gen, 1);
            else
                rghtn = population(last_gen, p_cell+1);
            end
            
            % only one neighbour?
            % then a cell is born 
            if (rghtn + leftn) == 1
                population(curr_gen, p_cell) = 1;
            end
        end
    end
end

This is really the only tricky bit of the code. I have made it so that the first and last cell are joined together in a ring - that is why there are two if ... then ... else statements.

The code described above will ALMOST run in Matlab - but we need to add just a few other statements that make sure we have some initial values, and that these values are available where they are needed.

The code below can be copied and pasted in to Matlab, saved as theGolProram.m and run from the command window by typing theGolProram

function theGolProgram()

    % the parameters
    number_of_cells = 80;
    number_of_gens = 100;
    
    % set up the structure to hold the results
    % and give it some initial values
    population = zeros(number_of_gens+1, number_of_cells);
    population(1,10)=1; population(1,40) = 1;

    % the middle - everything else goes here
    for curr_gen = 2:number_of_gens
        
        % do something this many times
        population = apply_rulebook(population, number_of_cells, curr_gen);
        update_screen(population);
        
    end 
end

function update_screen(population)
    % imagesc is the name of a Matlab function which creates a
    % picture from an array of numbers
    imagesc(population);
    drawnow;
end

function population = apply_rulebook(population, number_of_cells, curr_gen) 

    % rule number 1
    last_gen = curr_gen-1;
    for curr_cell = 1:number_of_cells;
        % for live cells only
        if population(last_gen, curr_cell)==1
            population(curr_gen, curr_cell)=0;
        end
    end
    
    % rule number 2
    for curr_cell = 1:number_of_cells;
        % rule 2 applies to dead cells only
        if population(last_gen, curr_cell)==0
            % handle special cases for first and last cell
            % to put population in a ring
            if curr_cell ==1
                leftn = population(last_gen, number_of_cells);
            else
                leftn = population(last_gen, curr_cell-1);
            end
            if curr_cell == number_of_cells
                rghtn = population(last_gen, 1);
            else
                rghtn = population(last_gen, curr_cell+1);
            end
            % only one neighbour?
            % then a cell is born
            if (rghtn + leftn) == 1
                population(curr_gen, curr_cell) = 1;
            end
        end
    end
end