-- -------------------------------------------------------------------------------- -- 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 mplife = {} gol.setup = gol.setup or {} gol.setup.current = gol.setup.current or {} do local c = gol.setup.current c.file = c.file or "examples/puffertrain.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 = .03 c.fade = true c.firstframe = 1 c.frames = 5 c.preamble = [[ \setupcolors[state=start] \setupbackgrounds[state=start] \setuppapersize[S6][S6] ]] --c.before_frame = [[ --\defineoverlay --[back] --[\bgroup --]] --c.after_frame = [[ --\egroup] --\setupbackgrounds [paper] [background=back] --\page --]] c.before_frame = [[ \startuseMPgraphic{back} pickup pensquare scaled ]] .. c.pensize .. [[pt; ]] c.after_frame = [[ currentpicture := currentpicture xysized (PaperHeight*.6,PaperWidth*.6) ; \stopuseMPgraphic \defineoverlay[back][\useMPgraphic{back}] \setupbackgrounds [page] [background=back] ]] gol.setup.current = c end mplife.fade = true 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.p_square (from, filled, fade_level) local f = mplife.format -- p1 p2 -- from from + d.x -- +-------+ -- | | -- | | -- | | -- | | -- +-------+ -- from - d.y from + d.x && - d.y -- p4 p3 local d = { x = 1, y = 1, unit = "" } local points = { [1] = { x = from.x, y = from.y }, [2] = { x = from.x+d.x, y = from.y }, [3] = { x = from.x+d.x, y = from.y-d.y }, [4] = { x = from.x, y = from.y-d.y }, } local buildsqr = function (unit) local draw if filled then draw = f.filldraw else draw = f.draw end local tmp = f.nl .. draw tmp = tmp .. f.p( points[1].x .. unit, points[1].y .. unit ) .. f.path -- automatic type conversion to string tmp = tmp .. f.p( points[2].x .. unit, points[2].y .. unit ) .. f.path tmp = tmp .. f.p( points[3].x .. unit, points[3].y .. unit ) .. f.path tmp = tmp .. f.p( points[4].x .. unit, points[4].y .. unit ) .. f.path tmp = tmp .. f.cycle if filled and fade_level then --tmp = tmp .. f.space .. "withcolor" .. f.space .. 1/fade_level .. "black" if fade_level == 0 then fade_level = 1 elseif fade_level == 1 then fade_level = 0 else fade_level = .05 * fade_level + .5 end tmp = tmp .. f.space .. "withcolor" .. f.space .. fade_level .. "white" end tmp = tmp .. f.scolon return tmp end return buildsqr (from.unit) end function mplife.draw_grid(grid) print (grid) local h = gol.helpers local pat = "" --"StartPage; " 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 n = 1 --for n, row in ipairs(grid) do while grid[n] ~= nil do local row = grid[n] local pos = 1 repeat local cell = row:sub(pos, pos) local p = { x = pos, y = 1 - n, unit = "" } local fill, fade_level --if cell ~= "0" then fill = true end fill = true if fill and mplife.fade then fade_level = tonumber(cell) end --if fade_level ~= 0 then -- dont draw dead cells (workaround for rounded pens) --pat = pat .. mplife.p_square( p, fill, fade_level ) --end pat = pat .. mplife.p_square( p, fill, fade_level ) --.. "\nlabel.bot(btex $" .. pos .. "$ etex, (" .. --pos .. "cm," .. 1 - n .. "cm));" pos = pos + 1 --print ("pos: " .. pos .. "," .. n .. " -->" .. row .. "<-- " .. type(row)) until pos > row:len() pat = pat .. "\n" n = n + 1 end 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, unit = "" } 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 --print(mplife.rand_pattern(10,1)) --- interfacing with life.lua function mplife.life_frame (frame) --local c = gol.setup.current mplife.draw_grid(frame) return true end function mplife.life_movie (frames, next_page) local c = gol.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 = gol.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 = gol.setup.current context(c.before_frame) mplife.draw_grid(c.last) context(c.after_frame) gol.setup.current.last = gol.next_frame( c.last, c.rule ) return true end function mplife.main () local c = gol.setup.current 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,55,1 do mplife.successive() context(Test) context.page() end context.stoptext() return 0 end return mplife.main()