summaryrefslogtreecommitdiff
path: root/life.lua
diff options
context:
space:
mode:
authorPhilipp Gesang <pgesang@ix.urz.uni-heidelberg.de>2010-08-15 20:14:01 +0200
committerPhilipp Gesang <pgesang@ix.urz.uni-heidelberg.de>2010-08-15 20:14:01 +0200
commit665d59554d270d8a56a43a2007981463581a055d (patch)
treeec707d41ee3545c3af51cee3b81dd98a933c1f75 /life.lua
parent2e2ea4b49f9f3101b4e09b77cd33fefc93c9c3cf (diff)
downloadautomata-backgrounds-665d59554d270d8a56a43a2007981463581a055d.tar.gz
restructured directory layout and renamed most files.
Diffstat (limited to 'life.lua')
-rw-r--r--life.lua427
1 files changed, 0 insertions, 427 deletions
diff --git a/life.lua b/life.lua
deleted file mode 100644
index af0cb6e..0000000
--- a/life.lua
+++ /dev/null
@@ -1,427 +0,0 @@
---
---------------------------------------------------------------------------------
--- FILE: life.lua
--- USAGE: ./life.lua
--- DESCRIPTION: Conway's Game of Life?
--- OPTIONS: ---
--- REQUIREMENTS: ---
--- BUGS: ---
--- NOTES: ---
--- AUTHOR: Philipp Gesang (Phg), <megas.kapaneus@gmail.com>
--- COMPANY:
--- VERSION: 1.0
--- CREATED: 05/08/10 12:03:11 CEST
--- REVISION: ---
---------------------------------------------------------------------------------
---
-
-gol = {}
-
-gol.helpers = {}
-
-local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match
-
-
--- http://lua-users.org/lists/lua-l/2009-06/msg00343.html
-gol.helpers.utfchar = R("\000\127") +
- R("\194\223") * R("\128\191") +
- R("\224\240") * R("\128\191") * R("\128\191") +
- R("\241\244") * R("\128\191") * R("\128\191") * R("\128\191")
-
-
--- by Roberto, captures everything in a table
--- http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html
-function gol.helpers.split (s, sep)
- sep = P(sep)
- local elem = C((1 - sep)^0)
- local p = Ct(elem * (sep * elem)^0) -- make a table capture
- return match(p, s)
-end
-
--- Modified to match left and right of one separator only.
-function gol.helpers.split_once (s, sep)
- local utfchar = gol.helpers.utfchar
- sep = S(sep)
- local left = C((1 - sep)^0)
- local right = C((utfchar)^0)
- local p = Ct(left * sep * right)
- return p:match(s)
-end
-
--- Modified stripper from Roberto to support trimming other chars than whitespace
-function gol.helpers.strip(str, chars)
- local chars = chars or " \t\v\n"
- chars = S(chars)
- local nochars = 1 - chars
- local stripper = chars^0 * C((chars^0 * nochars^1)^0)
-
- return match(stripper,str) or ""
-end
-
-function gol.helpers.dead_row(len)
- local row = ""
- local dead = "0"
- for i=1, len, 1 do
- row = row .. dead
- end
- return row
-end
-
--- Read rules of type "B3[/.-]S23"
--- => “birth” of a new cell if exactly 3 adjacent cells are “alive”
--- => “staying alive” of cells with two or three adjacent “live” cells
-function gol.parse_rule (raw_rule)
- local help = gol.helpers
- local b_s = help.split_once (raw_rule, "/.-")
- local tmp_b = help.strip(b_s[1], "B")
- local tmp_s = help.strip(b_s[2], "S")
-
- local b, s = {}, {}
-
- -- single digits express birth/stay conditions
- local n = 1
- repeat
- table.insert( b, tonumber(tmp_b:sub(n,n)) )
- n = n + 1
- until n > string.len(tmp_b)
-
- n = 1
- repeat
- table.insert( s, tonumber(tmp_s:sub(n,n)) )
- n = n + 1
- until n > string.len(tmp_s)
-
- return { birth = b, stay = s }
-end
-
-function gol.apply_rule (cell, cnt, rule, fade, keep)
- --local live, dead = "1", "0"
- --local new = dead
- local new = 0
- local live = "1"
- local stay = rule.stay
- local birth = rule.birth
-
- -- checking if cnt matches the numbers from the conditions list
- if cell == live then
- for _, cond in ipairs(stay) do
- if cnt == cond then
- new = "1"
- break
- end
- end
- else -- ==dead
- for _, cond in ipairs(birth) do
- if cnt == cond then
- new = "1"
- break
- end
- end
- end
-
- if fade then
- if not (live == new) then
- local add = tonumber (cell)
- if not add then -- == "D"
- add = "D"
- else
- if add and add < 9 and add ~= 0 then
- add = add + 1
- elseif keep and add and add == 9 then -- marking dead cells once alive
- add = "D"
- else
- add = 0
- end
- end
- new = tostring(add)
- end
- end
-
- return new
-end
-
-gol.formats = {}
-
-gol.formats[".gol"] = function (fname)
- local tmp = {} -- return an array
- local len -- check for equal line length
-
- if fname:sub(-4,-1) ~= ".gol" then
- fname = fname .. ".gol"
- end
-
- local file = assert(io.open(fname, "r"), "Not a file: " .. fname)
- local data = file:read("*all")
- file:close()
-
- local cell = R"09" + P"D"
- local nl = Cs(P"\n") / ""
- local line = Cs(cell^1) / function (l)
- if not len then len = string.len(l) end
- if len ~= string.len(l) then
- -- inconsistent horizontal sizes; kill off program
- return nil
- else
- table.insert(tmp,l)
- end
- end
-
- local gol_parser = Cs(line * (nl + line)^0)
-
- if gol_parser:match(data) then
- if context then
- context.writestatus("simpleslides", "Sucessfully loaded frame from "..fname..".")
- end
- return tmp
- else
- return false
- end
-end
-
-gol.formats[".cell"] = function (fname)
- return false -- stub
-end
-
-gol.formats[".rle"] = function (fname)
- local parser = require "parsers/rle"
- return parser(fname)
-end
-
-function gol.extend_area(rows)
- local tmp = {}
- local c = mplife.setup.current
-
- context.writestatus("simpleslides","Extending area horizontally by "..c.extendx.."cells.")
- context.writestatus("simpleslides","Extending area vertically by "..c.extendy.."cells.")
-
- if c.extendy > 0 then
- local row = ""
- for i=1, rows[1]:len(), 1 do -- buildling an empty row
- row = row.."0"
- end
-
- for i=1, c.extendy, 1 do
- table.insert(tmp, row)
- end
-
- for _, r in ipairs(rows) do
- table.insert(tmp, r)
- end
-
- for i=1, c.extendy, 1 do
- table.insert(tmp, row)
- end
- end
-
- if c.extendx > 0 then
- local add = ""
- for i=1, c.extendx, 1 do -- building an empty pre- and suffix
- add = add .. "0"
- end
-
- for n, r in ipairs(tmp) do
- tmp[n] = add .. r .. add
- end
- end
-
- --for i,j in ipairs(tmp) do print(i,j) end
- return tmp
-end
-
-function gol.parse_file (fname)
- local p_suf = P"." * (1-P".")^3 * -P(1)
- local p_fn = (1-p_suf)^1 * C(p_suf)
- local suffix = p_fn:match(fname) or ".gol" -- assume .gol format as default
-
- print("HERE!!!!!!!!!"..suffix)
- local tmp = gol.formats[suffix] ( fname )
- if mplife and mplife.setup.current and (
- mplife.setup.current.extendx > 0 or
- mplife.setup.current.extendy > 0) then
- tmp = gol.extend_area(tmp)
- end
- return tmp
-end
-
-
---- Computing single lines and whole frames and intervals thereof
-
-function gol.next_line (rows, rule)
- local live = "1"
-
- local fade = false
- if mplife then
- fade = mplife.setup.current.fade
- end
-
- local n = 1
- local max = string.len(rows[2])
-
- local cell = R("09") + P("D")
- local nocell = 1-cell
- local ce = Cs(cell) / function (current)
-
- local env = {}
- local lpos, rpos -- positions left of / right of current
-
- -- toroidal, flips over at borders
- if n == 1 then
- lpos = max
- else
- lpos = n - 1
- end
-
- if n == max then
- rpos = 1
- else
- rpos = n + 1
- end
-
- -- +---+---+---+
- -- |nw | n | ne|
- -- +---+---+---+
- -- |w | c | e| env[ironment] of current
- -- +---+---+---+
- -- |sw | s | se|
- -- +---+---+---+
-
- env.nw = string.sub( rows[1], lpos, lpos )
- env.n = string.sub( rows[1], n , n )
- env.ne = string.sub( rows[1], rpos, rpos )
-
- env.w = string.sub( rows[2], rpos, rpos )
- env.e = string.sub( rows[2], lpos, lpos )
-
- env.sw = string.sub( rows[3], lpos, lpos )
- env.s = string.sub( rows[3], n , n )
- env.se = string.sub( rows[3], rpos, rpos )
-
- -- counting live cells in the environment
- local cnt = 0
- for _, chr in pairs(env) do
- if chr == live then
- cnt = cnt + 1
- end
- end
-
- n = n + 1
- --
- -- adding new cell according to ruleset
- return gol.apply_rule(current, cnt, rule, fade, true)
- end
-
- local noce = Cs(nocell) / ""
- local c = Cs(ce * (noce + ce)^0)
-
- return c:match(rows[2])
-end
-
-function gol.next_frame (old, rule)
- local new = {}
-
- local n = 1
-
- repeat
- local rows = {}
-
- rows[2] = old[n] -- current
-
- -- toroidal
- rows[1] = old[n-1] or old[#old] -- last
- rows[3] = old[n+1] or old[1] -- next
-
- new[n] = gol.next_line( rows, rule )
-
- n = n + 1
- until n > #old
-
- return new
-end
-
--- get the nth frame starting from init
-function gol.frame (init, rule, n)
- local frame = init
- local gnext = gol.next_frame
-
- for i=1, n, 1 do
- frame = gnext( frame, rule )
- end
-
- return frame
-end
-
--- get array of frames until nth [from offset]
-function gol.frames (init, rule, n, offset)
- local frames = {}
- local last
- local gnext = gol.next_frame
-
- -- “fast forward”
- if offset then
- last = gol.frame( init, rule, offset )
- else
- last = init
- end
-
- for i=1, n, 1 do
- frames[i] = last
- last = gnext( last, rule )
- end
-
- return frames
-end
-
---- pretty printing frames (ascii)
-
--- pp a heading: len should exceed length of mark + 4
-function gol.pre_section (len, mark)
- local mark = mark or "Frame"
- local t = "-"
-
- local s = t..t.." "..mark.." "
- if s:len() < len then
- for n=1, len - s:len(), 1 do
- s = s..t
- end
- end
-
- io.write ("\n\n"..s.."\n")
-end
-
-function gol.pre_frame (frame)
- local repl = {
- ["0"] = "·",
- ["1"] = "O",
- ["2"] = "2",
- ["3"] = "3",
- ["4"] = "4",
- ["5"] = "5",
- ["6"] = "6",
- ["7"] = "7",
- ["8"] = "8",
- ["9"] = "9",
- }
-
- local cell = R"09" + P"D"
- local nocell = 1-cell
- local ce = Cs(cell) / repl
- local noce = Cs(nocell) / ""
- local c = Cs(ce * (noce + ce)^0)
-
- for j, row in ipairs(frame) do
- io.write("\n" .. c:match(row))
- end
-end
-
-function gol.pre_movie (frames, section)
- for i, frame in ipairs(frames) do
- if section then
- local l = string.len(frame[1])
- gol.pre_section( l, "Nr. " .. tostring(i) )
- end
- gol.pre_frame( frame )
- end
- io.write("\n")
-end
-
-return gol