-- -------------------------------------------------------------------------------- -- FILE: mplife.cld -- USAGE: ./mplife.cld -- DESCRIPTION: Metapost output for Conway's Game of Life -- OPTIONS: --- -- REQUIREMENTS: --- -- BUGS: --- -- NOTES: --- -- AUTHOR: Philipp Gesang (Phg), -- COMPANY: -- VERSION: 1.0 -- CREATED: 06/08/10 12:28:35 CEST -- REVISION: --- -------------------------------------------------------------------------------- -- require "run" local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match mplife = {} mplife.setup = mplife.setup or {} mplife.setup.current = mplife.setup.current or {} do local c = mplife.setup.current --c.file = c.file or "examples/10x10_glider.gol" --c.file = c.file or "examples/gliders.gol" c.file = c.file or "examples/ggun.gol" c.rule = gol.parse_rule("B3/S23") -- default Conway c.init = gol.parse_file(c.file) c.last = c.init -- for successive mode c.pensize = .1 c.color = { r = .6, g = .6, b = .8 } c.opacity = 1/3 c.fade = true c.gestalt = "unitsquare" -- try "unitcircle" c.firstframe = 1 c.frames = 5 c.preamble = [[ \setupcolors[state=start] \setupbackgrounds[state=start] \setuppapersize[S6][S6] \setuppagenumbering[state=stop,location=] \defineoverlay[back][\ctxlua{mplife.successive()}] \setupbackgrounds [page] [background=back] ]] c.before_frame = [[ \startMPcode pickup pencircle xyscaled (.25*]] .. c.pensize .. [[pt, ]] .. c.pensize .. [[pt) rotated 45; ]] c.after_frame = [[ currentpicture := currentpicture xysized (\the\paperwidth, \the\paperheight); \stopMPcode ]] mplife.setup.current = c end mplife.format = { nl = "\n", space = " ", opar = "(", cpar = ")", hyphen = "-", comma = ",", scolon = ";", path = "--", filldraw = "fill", -- "draw", draw = "draw", cycle = "cycle", p = function (x,y) return string.format("(%s,%s)", x, y) end, } function mplife.runcode (mpcode) --context.startMPcode() context(mpcode) --context.stopMPcode() --context.MPdrawing(mpcode) -- comes with next beta! end function mplife.draw_grid(grid, settings) local h = gol.helpers local c = mplife.setup.current local pat = "" if type(grid) == "string" then grid = h.split(grid, "\n") -- may leave an empty string as last item if grid[#grid] == "" then grid[#grid] = nil end end local max = {} max.x, max.y = grid[1]:len(), #grid local n = 0 while grid[#grid-n] ~= nil do local row = grid[#grid-n] local pos = 1 local cell = Cs(R("09") + P("D")) / function (char) --repeat local opacity = c.opacity local p = { x = pos-1, y = n} local fill, fade_level = true --fill = true if fill and c.fade then fade_level = tonumber(char) end if not fade_level then -- no number --> cell once dead (marked "D") fade_level = 9.3 end if fade_level ~= 0 then -- skip dead cells if fade_level == 1 then pat = pat .. string.format("%s %s shifted (%s,%s) withcolor transparent(1,%s,%s);\n", "draw", c.gestalt, p.x, p.y, opacity*2, settings.color) else opacity = opacity - (fade_level * opacity * .1) end pat = pat .. string.format("%s %s scaled .9 shifted (%s+.05,%s+.05) withcolor transparent(1,%s,%s);\n", "filldraw", c.gestalt, p.x, p.y, opacity, settings.color) end pos = pos + 1 end local line = cell * ((1-cell) + cell)^0 line:match(row) pat = pat .. "\n" n = n + 1 end pat = pat .. string.format([[ path border; border = (0,0)--(%s,0)--(%s,%s)--(0,%s)--cycle; setbounds currentpicture to boundingbox border ; ]], max.x, max.x, max.y, max.y) --fill border withcolor transparent (1,.75, white) ; --fill border withcolor transparent (1,.3,1white) ; --print("Pic\n", pat) mplife.runcode(pat) return true end --- testing section function mplife.checker(n) local squares = "" local cnt = 0 for y=1, n, 1 do for x=1, n, 1 do local fill if cnt % 2 == 0 then fill = true end local p = { x = x, y = y } squares = squares .. mplife.p_square( p, fill ) cnt = cnt + 1 end if n % 2 == 0 then cnt = cnt + 1 end -- needed for even column numbers end --print (squares) return squares end function mplife.rand_pattern(n, digits) local pat = "" for y=1, n, 1 do for x=1, n, 1 do pat = pat .. math.random(0,digits) end pat = pat .. "\n" end return pat end --- interfacing with life.lua function mplife.life_frame (frame) --local c = mplife.setup.current mplife.draw_grid(frame) return true end function mplife.life_movie (frames, next_page) local c = mplife.setup.current for i, frame in ipairs(frames) do context(c.before_frame) mplife.life_frame(frame) context(c.after_frame) end end function mplife.life_frames () local c = mplife.setup.current local frames = gol.frames( c.init, c.rule, c.frames, c.firstframe ) mplife.life_movie( frames, false ) return true end function mplife.successive () local c = mplife.setup.current local settings = {} if mplife.slides then settings.color = "\\MPcolor{simpleslides:contrastcolor}" else context.definecolor({ "automaton:color" }, c.color) settings.color = "\\MPcolor{automaton:color}" end context(c.before_frame) mplife.draw_grid(c.last, settings) context(c.after_frame) mplife.setup.current.last = gol.next_frame( c.last, c.rule ) return true end function mplife.main () local c = mplife.setup.current if context then context.definecolor({ "lifesquare" }, c.color) end --mplife.successive() --context(c.preamble) -- only once --context.starttext() --mplife.runcode (mplife.checker(20)) --mplife.draw_grid(mplife.rand_pattern(10,6)) --mplife.life_frames() --for i=1,10,1 do --context("\\input knuth") --context.page() --end --context.stoptext() return 0 end if not mplife.slides then -- standalone return mplife.main() end