Conway's Game of Life

Conway’s Game of Life has simple rules, yet can breed unpredictable behaviour. The game proceeds on a regular grid as follows: you update all cells at once, cells survive if there are more than one, but less than four, cells in neighbouring sites. Dead cells are (re)born if they have exactly three neighbours. It was originally played with counters on a Go board, but rose to fame with the increasing availability of computers, which can play it faster. I won’t go into more detail because many excellent descriptions already exist:

Nevertheless, here are a couple of my implementations which may be of interest.

Life in one (long) Line of Matlab

It is possible to play the Game of Life in a single line of Matlab. It weighs in with twice the characters of the single line of APL, but at least you can find them all on a normal keyboard. If you can see a way of condensing it from these 53 characters, claim your prize in the comment form below. . .

l=9;G=int8(rand(l));u=[2:l 1];d=[l 1:l-1];for i=u,n=G(u,:)+G(d,:)+G(:,u)+G(:,d)+G(u,u)+G(u,d)+G(d,u)+G(d,d);G=n==3|G&n==2,end

A Sedate Matlab Life

An exercise in conciseness, with the update rule complete in two statements and although it would be hard to beat a version in one line of APL, this Matlab code wins in the readability stakes! You'll need Matlab; it runs with Octave too, but creates a new window for the grid at each timestep, so move the display outside the loop (and try imshow instead).

Update - someone emailed to tell me that Matlab actually plays life as a built-in function - just type life. But having looked at the code, while the method is obviously identical to the one below, I don't mind claiming that the code here is a little more elegant.

Life grid, showing various interesting patterns

A stage of Life, as lived by Matlab

% life.m - Conway's Game of Life
%
% A grid of dead and living cells is made.
% Cells are born to three adjacent parents,
% and die of overcrowding or loneliness.
%        Iain Haslam, December 2005
 
len=50; GRID=int8(rand(len,len));
up=[2:len 1]; down=[len 1:len-1]; %the world is round
colormap(gray(2));
for i=1:100
    neighbours=GRID(up,:)+GRID(down,:)+GRID(:,up)+GRID(:,down)+...
        GRID(up,up)+GRID(up,down)+GRID(down,up)+GRID(down,down);
    GRID = neighbours==3 | GRID & neighbours==2;
    image(GRID*2); pause(0.02);
end

The code as presented here starts with a random grid of living and dead cells. If you want to see a particular pattern,
start with a blank grid GRID=zero(len,len), and add one of the following:

Blinker GRID(5,4:6)=1;
Toad GRID(5,4:6)=1;GRID(6,3:5)=1;
Glider GRID(3,1:3)=1;GRID(2,3)=1;GRID(1,2)=1;
Lightweight
spaceship
GRID(5,5:8)=1;GRID(4,9)=1;GRID(3:4,5)=1; GRID(2,6)=1;GRID(2,9)=1;
Diehard GRID(10,10:11)=1;GRID(11,11)=1; GRID(11,15:17)=1;GRID(9,16)=1;

Python

The Matlab version only allows you to define the initial grid by altering the code. This Python version allows you to toggle each cell's state of health with a mouse-click.

It also serves as a concise example of how to create a useful Tk Dialog with Python. Naturally, you'll need Python and
TkInter installed to run it, but they’re both free and top notch, so go for it.

#!/usr/bin/python 
"""A minimal implementation of Conway's Game of Life.
 
Each cell's survival depends on the number of occupied nearest and
next-nearest neighbours (calculated in Grid::step). A living cell dies
of overcrowding or loneliness if it has more than three or fewer than
two neighbours; a dead cell is brought to life if it has exactly three
neighbours (determined in Cell::setNextState).
    Iain Haslam, June 2005.
""" 
from Tkinter import *
root = Tk()
 
class Cell(Label):
    DEAD = 0
    LIVE = 1
    def __init__(self,parent):
        Label.__init__(self,parent,relief="raised",width=2,borderwidth=1)
        self.bind("<Button-1>", self.toggle)
        self.displayState(Cell.DEAD)
 
    def toggle(self,event):
        self.displayState(1-self.state)
 
    def setNextState(self,numNeighbours):
        """Work out whether this cell will be alive at the next iteration.""" 
        if self.state==Cell.LIVE and \
            (numNeighbours>3 or numNeighbours<2):
            self.nextState = Cell.DEAD
        elif self.state==Cell.DEAD and numNeighbours==3:
            self.nextState = Cell.LIVE
        else:
            self.nextState = self.state
 
    def stepToNextState(self):
        self.displayState(self.nextState)
 
    def displayState(self,newstate):
        self.state = newstate
        if self.state==Cell.LIVE:
            self["bg"] = "black" 
        else:
            self["bg"] = "white" 
 
class Grid:
    def __init__(self,parent,sizex,sizey):
        self.sizex = sizex
        self.sizey = sizey
        #numpy.zeros(sizex,sizey) is a better choice,
        #but an additional dependency might be rude...
        self.cells = []
        for a in range(0,self.sizex):
            rowcells = []
            for b in range(0,self.sizey):
                c = Cell(parent)
                c.grid(row=b, column=a)
                rowcells.append(c)
            self.cells.append(rowcells)
        if sizex>10 and sizey>10:
            #Start with a glider
            self.cells[10][9].displayState(Cell.LIVE)
            self.cells[11][10].displayState(Cell.LIVE)
            self.cells[9][11].displayState(Cell.LIVE)
            self.cells[10][11].displayState(Cell.LIVE)
            self.cells[11][11].displayState(Cell.LIVE)
 
    def step(self):
        """Calculate then display the next iteration of the game of life.
 
        This function uses wraparound boundary conditions.
        """ 
        cells = self.cells
        for x in range(0,self.sizex):
            if x==0: x_down = self.sizex-1
            else: x_down = x-1
            if x==self.sizex-1: x_up = 0
            else: x_up = x+1
            for y in range(0,self.sizey):
                if y==0: y_down = self.sizey-1
                else: y_down = y-1
                if y==self.sizey-1: y_up = 0
                else: y_up = y+1
                sum = cells[x_down][y].state + cells[x_up][y].state + \
                    cells[x][y_down].state + cells[x][y_up].state + \
                    cells[x_down][y_down].state + cells[x_up][y_up].state + \
                    cells[x_down][y_up].state + cells[x_up][y_down].state
                cells[x][y].setNextState(sum)
        for row in cells:
            for cell in row:
                cell.stepToNextState()
 
    def clear(self):
        for row in self.cells:
            for cell in row:
                cell.displayState(Cell.DEAD)
 
if __name__ == "__main__":
    frame = Frame(root)
    frame.pack()
    grid = Grid(frame,25,25)
    bottomFrame = Frame(root)
    bottomFrame.pack(side=BOTTOM)
    buttonStep = Button(bottomFrame,text="Step",command=grid.step)
    buttonStep.pack(side=LEFT)
    buttonClear = Button(bottomFrame,text="Clear",command=grid.clear)
    buttonClear.pack(side=LEFT,after=buttonStep)
    root.mainloop()

Put that into a text file, run it through Python, and you'll get:

Screenshot of pylife running under Gnome. It's a bit bland.

Pylife running under Gnome