Conway's Game of Life

I’m here to share a bit of my code, spent the last hour or so writing it and here it is, it’s Conway's Game of Life, I’ve decided to give this away since it’s quite simple and great for learning about Codea. It’s by no means perfect but it looks quite nice and it’s very simple :slight_smile:

Here’s the code

###Main.lua

-- golly

-- Use this function to perform your initial setup
function setup()
    parameter.color("DeadCellColour", color(123,123,223,255))
    parameter.color("AliveCellColour", color(10,10,10,255))
    parameter.color("Background", color(255,255,255,255))
    parameter.boolean("Play")
    
    gol = Gol(15, 30)

    gol.drawMethod = function (cell)
        wid = WIDTH / 15
        hei = HEIGHT / 30
    
        if cell.s == gol._alive then
            fill(AliveCellColour)
        else
            fill(DeadCellColour)
        end
        rect(wid * (cell.x - 1), hei * cell.y, wid, hei)
    end
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(Background)

    -- If we've paused, stop calculating
    if Play then
        gol:calculate()
    end
    
    -- Always draw
    gol:draw()
end

function touched(t)
    gol:touched(t)
end

###Gol.lua

Gol = class()

function Gol:init(W, H)
    -- Set the size
    self.columns  = W
    self.rows     = H
    
    -- The varying states of cells
    self._alive    = 1
    self._dead     = 0
    
    -- The game states
    self._paused   = 0
    self._stepping = 1
    
    -- Some public things
    self.matrix    = {}
    
    -- This is a method to set for a draw method
    -- Called for every cell every frame
    self.drawMethod = function(cell) end
    
    -- Create a blank board
    self:create()
end

function Gol:create()
    for r = 1, self.rows do
        table.insert(self.matrix, {})
        for c = 1, self.columns do
            table.insert(self.matrix[r], {})
            self.matrix[r][c] = self._dead
        end
    end
end

function Gol:clear()
    for r = 1, self.rows do
        for c = 1, self.columns do
            self.matrix[r][c] = self._dead
        end
    end
end

function Gol:alive(c, r)
    if self.matrix[r][c] == self._alive then
        return true
    end
    
    return false
end

function Gol:dead(c, r)
    if self.matrix[r][c] == self._dead then
        return true
    end
    
    return false
end

function Gol:calculate()
    local n    = 0
    local tab  = self.matrix
    
    -- Neighbour positions from the current index
    local nbrs = {
        {-1,-1},
        {-1,0},
        {-1,1},
        {0,-1},
        {0,1},
        {1,-1},
        {1,0},
        {1,1}
    }
    
    for r = 2, self.rows - 1 do
        for c = 2, self.columns - 1 do
            n = 0
            
            -- How many neighbours does this cell have?
            for _,a in ipairs(nbrs) do
                if self:alive(c + a[2], r + a[1]) then
                    n = n + 1
                end
            end

            -- Kill or live
            if self:alive(c, r) and n < 2 then
                tab[r][c] = self._dead
            elseif self:alive(c, r) and (n == 2 or n == 3) then
                tab[r][c] = self._alive
            elseif self:alive(c, r) and n >= 3 then
                tab[r][c] = self._dead
            elseif self:dead(c, r) and n == 3 then
                tab[r][c] = self._alive
            end
           
        end
    end
end

function Gol:draw()
    for r = 1, self.rows do
        for c = 1, self.columns do
            self.drawMethod({
                x = c,
                y = r,
                s = self.matrix[r][c]
            })
        end
    end
end

function Gol:touched(touch)
    local x = math.floor(touch.x / (WIDTH / self.columns))
    local y = math.floor(touch.y / (HEIGHT / self.rows))
    
    self.matrix[y][x] = self._alive
end

Any criticism is welcome as well as improvements and ideas :slight_smile:

###Enjoy!

@dmackintosh88 See these posts.


http://twolivesleft.com/Codea/Talk/discussion/comment/15872

http://twolivesleft.com/Codea/Talk/discussion/3523/the-game-of-life/p1

http://twolivesleft.com/Codea/Talk/discussion/comment/4712

http://twolivesleft.com/Codea/Talk/discussion/comment/16728

@dmackintosh88 I tried your code. It doesn’t seem to be working the way I know the game of life to work. See the above post for examples.

Ah. Lol slightly embarrassing, that’s much more concise and correct than mine is. I shall learn from these posts and return!

@dmackintosh88 That’s the whole purpose of this forum, either learn from others or to teach others. I’ve been here for a year and a half and I’m still learning things. There are a lot of examples posted on the forum, the hard part is trying to find them.

I liked the idea of having neighbour positions as a table to loop over instead of lots of if statements and the size as a square instead of dividing the screen estate up. I’ve made my changes, the rules were off because of the order they were in. I blame being tired after being at work but I’ve updated the code to be correct now and I’m just optimising it now so it doesn’t run like a bag of rusty nails.

I didn’t want to just rip anyone else’s code off so I’m just going to improve on what I have here, I like it and it works quite well (and it’s been great to learn more about Lua), I can get it to size 8 before it starts stuttering on my iPad mini. A few optimisations might work well with this or I might have a go at making this a shader side operation instead of using rect.

Since GoL is all about doing parallel computations, shaders really make sense for this and I’m bemused by all these attempts to do it linearly on the CPU! On my iPad4 then I can run a shader version of GoL at full screen size with a decent FPS (don’t recall off the top of my head what it was exactly).

(Somewhere in the links that dave1707 listed are links to my shader version of GoL. An explanation of it is on my website.)

Oh, I didn’t see you’d done a shader version. I saw you’d mentioned it but I got as far as the second link down before just going to Wikipedia and revising the order of my rules.

I’ll definitely check out your shader version though, it’s definitely a shader based computation on anything where the size is below 16. This, for me, was just an exercise of the mind and my understanding of Lua and Codea, a combined time of 1.5 hours on this isn’t that bad I’d say but I do still want to push my knowledge of GLES with something like this!