Conway's Game of Life

http://en.wikipedia.org/wiki/Conway’s_Game_of_Life

I wrote this independently before I saw Alex’s adaptation. Change block size and sparsity with the sliders (changes will restart the simulation).

Code at the end :wink:

Some further ideas:


• ability to control speed of simulation
• color variations (color groups randomly or even by state)
• user-selectable color
• library of interesting starting states (i.e. Gosper's Glider Gun)
• wrap-around world (edges are currently treated as dead)
• optimize calculations (only check changed areas, etc.)
• run/stop parameter slider
• tap-for-next-generation (these last 2 are features of Alex's version)

Here’s the source:


function setup()
    blockSize = 12
    sparsity = 10

    watch("generation")
    iparameter("sparsity",2,25,sparsity)
    iparameter("blockSize",6,24,blockSize)
    
    resetGrid()
end

function resetGrid()
    generation = 0
    oSparsity = sparsity
    oBlockSize = blockSize
    
    grid = {}
    nextGrid = {}
    
    for i = 1,HEIGHT,blockSize do
        grid[i] = {}
        nextGrid[i] = {}
        
        for j = 1,WIDTH,blockSize do
            -- zero is alive, non-zero is dead
            grid[i][j] = math.random(0,sparsity)
            nextGrid[i][j] = 1
        end
    end
end

function draw()
    background(0,0,0)
    fill(0, 255, 41, 255)
    
    generation = generation + 1
    
    for i = 1,HEIGHT,blockSize do      
        for j = 1,WIDTH,blockSize do
			
			-- reset on parameter changes
            if (oSparsity ~= sparsity) then
                resetGrid()
            end
            if (oBlockSize ~= blockSize) then
                resetGrid()
            end
            
			-- draw live cells
            if (grid[i][j] == 0) then
                rect(i,j,blockSize,blockSize)
            end
            
            n = 0
                
			-- count live neighbors
            for k = (i - blockSize),(i + blockSize),blockSize do
                for l = (j - blockSize),(j + blockSize),blockSize do
                    
                    --skip off grid coords
                    if (k < 0 or l < 0 or k > HEIGHT or l > WIDTH) then
                        --nop
                    --skip myself
                    elseif (k == i and l == j) then
                        --nop
                    else
                        if (grid[k][l] == 0) then
                            n = n + 1
                        end
                    end
                end
            end
            
			-- conway's game of life rules
            if (n < 2) then
                nextGrid[i][j] = 1
            elseif (n == 2) then
                nextGrid[i][j] = grid[i][j]
            elseif (n == 3) then
                --print(i,j,"birth")
                nextGrid[i][j] = 0
            elseif (n > 3) then
                nextGrid[i][j] = 1
            end
            
        end
    end
    
    grid = tableCopy(nextGrid)
end

function tableCopy(t)
    if type(t) ~= 'table' then return t end
    local mt = getmetatable(t)
    local res = {}
    for k,v in pairs(t) do
        if type(v) == 'table' then
            v = tableCopy(v)
        end
        res[k] = v
    end
    setmetatable(res,mt)
    return res
end

Thanks for sharing, this is great, learning a new way of understanding tables :slight_smile:

Added to wiki https://bitbucket.org/TwoLivesLeft/codea/wiki/UserContrib