lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


   Here's a tiny challenge for those interested.  Attached at the bottom is
a quick implementation of Conway's game of life in Lua, an algorithm which
should be widely-enough recognized and well-enough defined to make this
practical.

   The challenge is simply to demonstrate alternate ways of coding it,
using any features of Lua desired.  For example, might nested foreachi's be
used within the main evolve() method?  Or some entirely different data
representation which lends itself to a unique solution.  Or any additional
methods which may suggest themselves.

   The only purpose is to provide comparitive examples of Lua code, for
learning purposes.  Basically, I'm just curious to see other people's Lua
code.  :->  It isn't meant to have any practical "real-world" significance
or to be judged by any particular standards.

   Anyone care to join in on the fun?

   Cheers,

   Dave

   (By the way, if Life seems too trivial, perhaps someone could suggest a
better topic which is still small enough to encourage "spare time"
participation?)

--
-- life.lua
-- Conway's classic CA implemented in Lua
-- to spark discussion on alternate methods of coding it
-- dbollinger@compuserve.com
--

function clearscreen() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary
  execute("clear")  -- unixes
  -- execute("cls") -- windows
end

function delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary
  local i=10000
  while i>0 do i=i-1 end
  -- local i=clock()+1 while(clock()<i) do end
end

function ARRAY2D(w,h)
  local t = {}
  t.w=w
  t.h=h
  while h>0 do
    t[h] = {}
    local x=w
    while x>0 do
      t[h][x]=0
      x=x-1
    end
    h=h-1
  end
  return t
end

_CELLS = {}

-- give birth to a "shape" within the cell array
function _CELLS:spawn(shape,left,top)
  local y=0
  while y<shape.h do
    local x=0
    while x<shape.w do
      self[top+y][left+x] = shape[y*shape.w+x+1]
      x=x+1
    end
    y=y+1
  end
end

-- run the CA and produce the next generation
function _CELLS:evolve(next)
  local ym1,y,yp1,yi=self.h-1,self.h,1,self.h
  while yi > 0 do
    local xm1,x,xp1,xi=self.w-1,self.w,1,self.w
    while xi > 0 do
      local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] +
                  self[y][xm1] + self[y][xp1] +
                  self[yp1][xm1] + self[yp1][x] + self[yp1][xp1]
      next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0
      xm1,x,xp1,xi = x,xp1,xp1+1,xi-1
    end
    ym1,y,yp1,yi = y,yp1,yp1+1,yi-1
  end
end

-- output the array to screen
function _CELLS:draw()
  local out="" -- accumulate to reduce flicker
  local y=1
  while y <= self.h do
    local x=1
    while x <= self.w do
      out=out..(((self[y][x]>0) and "*") or ".")
      x=x+1
    end
    out=out.."\n"
    y=y+1
  end
  clearscreen()
  write(out)
end

-- constructor
function CELLS(w,h)
  local c = ARRAY2D(w,h)
  c.spawn = _CELLS.spawn
  c.evolve = _CELLS.evolve
  c.draw = _CELLS.draw
  return c
end

--
-- shapes suitable for use with spawn() above
--
HEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 }
GLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 }
EXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 }
FISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 }
BUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 }

-- the main routine
function LIFE(w,h)
  -- create two arrays
  local thisgen = CELLS(w,h)
  local nextgen = CELLS(w,h)

  -- create some life
  -- about 1000 generations of fun, then a glider steady-state
  thisgen:spawn(GLIDER,5,4)
  thisgen:spawn(EXPLODE,25,10)
  thisgen:spawn(FISH,4,12)

  -- run until break
  local gen=1
  while 1 do
    thisgen:evolve(nextgen)
    thisgen,nextgen = nextgen,thisgen
    thisgen:draw()
    write("Generation: "..gen.."\n")
    gen=gen+1
    delay()
  end
end

LIFE(40,20)

--EOF--