# Copyright (C) 2008, Parrot Foundation.

## John Conway's Game of Life
## Implementation based on life.lua, found in Lua's distribution.
##
var width          = 40    # width of "board"
var height         = 20    # height of "board"
var generation     = 1     # generation couner
var numgenerations = 50    # how often should we evolve?

## initialize board to all zeroes
sub initboard(board)
    for var y = 0, height do
        for var x = 0, width do
            board[y][x] = 0
        end
    end
end

## spawn new life in board, at position (left, top),
## the life data is stored in shapedata, and shape width and
## height are specified.
sub spawn(board, left, top, shape, shapedata)
    for var y = 0, shape.h - 1 do
        for var x = 0, shape.w - 1 do
            board[top + y][left + x] = shapedata[y * shape.w + x]
        end
    end
end

## calculate the next generation.
sub evolve(thisgen, nextgen)
    var ym1 = height - 1
    var y   = height
    var yp1 = 1
    var yi  = height

    while yi > 0 do
        var xm1 = width-1
        var x   = width
        var xp1 = 1
        var xi  = width

        while xi > 0 do

            var sum = thisgen[ym1][xm1]
                    + thisgen[ym1][x]
                    + thisgen[ym1][xp1]
                    + thisgen[y][xm1]
                    + thisgen[y][xp1]
                    + thisgen[yp1][xm1]
                    + thisgen[yp1][x]
                    + thisgen[yp1][xp1]

            nextgen[y][x] = sum==2 and thisgen[y][x] or sum==3

            xm1 = x
            x   = xp1
            xp1 = xp1 + 1
            xi  = xi - 1
        end

        ym1 = y
        y   = yp1
        yp1 = yp1 + 1
        yi  = yi - 1

    end
end

## display thisgen to stdout.
sub display(thisgen)
    var line = ""
    for var y = 0, height do
        for var x = 0, width do
            if thisgen[y][x] == 0 then
                line = line .. "-"
            else
                line = line .. "O"
            end

        end
        line = line .. "\n"
    end
    print(line, "\nLife - generation: ", generation)
end

## main program
sub main()
    var heart   = [1,0,1,1,0,1,1,1,1]
    var glider  = [0,0,1,1,0,1,0,1,1]
    var explode = [0,1,0,1,1,1,1,0,1,0,1,0]

    var thisgen = []
    initboard(thisgen)

    var nextgen = []
    initboard(nextgen)

    spawn(thisgen,3,5,{"w"=>3,"h"=>3},heart)
    spawn(thisgen,5,4,{"w"=>3,"h"=>3},glider)
    spawn(thisgen,25,10,{"w"=>3,"h"=>4},explode)

    while generation <= numgenerations do
        evolve(thisgen, nextgen)
        display(thisgen)
        generation = generation + 1

        ## prevent switching nextgen and thisgen around,
        ## just call evolve with arguments switched.
        evolve(nextgen, thisgen)
        display(nextgen)
        generation = generation + 1

    end
end

## start here.
main()
