From 665d59554d270d8a56a43a2007981463581a055d Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Sun, 15 Aug 2010 20:14:01 +0200 Subject: restructured directory layout and renamed most files. --- .../third/simpleslides/automata/automata-eca.lua | 108 ++++++ .../third/simpleslides/automata/automata-life.lua | 420 +++++++++++++++++++++ .../third/simpleslides/automata/automata-main.lua | 247 ++++++++++++ .../simpleslides/automata/automatarc-global.lua | 63 ++++ .../simpleslides/automata/parsers/parser-rle.lua | 95 +++++ .../simpleslides/simpleslides-s-Automaton.tex | 261 +++++++++++++ 6 files changed, 1194 insertions(+) create mode 100644 module/tex/context/third/simpleslides/automata/automata-eca.lua create mode 100644 module/tex/context/third/simpleslides/automata/automata-life.lua create mode 100644 module/tex/context/third/simpleslides/automata/automata-main.lua create mode 100644 module/tex/context/third/simpleslides/automata/automatarc-global.lua create mode 100644 module/tex/context/third/simpleslides/automata/parsers/parser-rle.lua create mode 100644 module/tex/context/third/simpleslides/simpleslides-s-Automaton.tex (limited to 'module') diff --git a/module/tex/context/third/simpleslides/automata/automata-eca.lua b/module/tex/context/third/simpleslides/automata/automata-eca.lua new file mode 100644 index 0000000..95d1f71 --- /dev/null +++ b/module/tex/context/third/simpleslides/automata/automata-eca.lua @@ -0,0 +1,108 @@ +-- +-------------------------------------------------------------------------------- +-- FILE: automata-eca.lua +-- DESCRIPTION: drawing elementary cellular automata +-- REQUIREMENTS: ConTeXt MkIV with Simple Slides module +-- BUGS: uncountable +-- AUTHOR: Philipp Gesang (Phg), +-- VERSION: 1.0 +-- CREATED: 14/08/10 19:43:35 CEST +-------------------------------------------------------------------------------- +-- + +environment.loadluafile( "automata-life" ) + +local help = gol.helpers + +local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match + + +eca = {} + + +function eca.parse_file (fname) + local f = assert(io.open(fname, "r"), "No such file: "..fname..".") + local init = f:read("*all") + f:close() + + return help.strip(init) +end + +function eca.to_base(number, base) + local alphabet, result, cnt, remainder = "0123456789abcdef", "", 0 + while number > 0 do + cnt = cnt + 1 + number, remainder = math.floor(number / base), (number % base) + 1 + result = string.sub(alphabet, remainder, remainder) .. result + end + return result +end + +function eca.gen_rule(nr) + local rules = {} + local states = { "111", "110", "101", "100", "011", "010", "001", "000" } + + nr = string.format("%8s",eca.to_base(nr, 2)):gsub(" ", "0") + + local n = 1 + while n <= #states do + rules[states[n]] = nr:sub(n,n) + n = n + 1 + end + + return rules +end + +function eca.next_line(from, rule) + local new = "" + from = "0"..from.."0" -- assume dead borders + --from = string.format("0%s0", from) -- too slow + + local cell = C(S"01") + local cells= Ct(cell * #(cell * cell)) / function (t) + local three = t[1]..t[2]..t[3] + new = new .. rule[three] + end + lpeg.match(cells^1, from) + return new +end + +function eca.stripcells (str, dir, cnt) + if dir == "left" then + return str:sub( cnt ) + elseif dir == "right" then + return str:sub( 0, str:len() - cnt ) + else -- assume ambilateral clipping + return str:sub( cnt, str:len() - cnt ) + end +end + +function eca.gen_frame(from, lines, rule) + + local cnt = 1 + local c = mplife.setup.current + + local new = { [1] = eca.stripcells(from, c.clip, c.diff ) } + + repeat + from = eca.next_line(from, rule) + table.insert( new, eca.stripcells(from, c.clip, c.diff) ) + cnt = cnt + 1 + until cnt == lines + return eca.next_line(from, rule), new +end + +function eca.successive (current) + local thisframe + current.from, thisframe = eca.gen_frame(current.from, current.framesize, current.rule) + if not context then -- cli invocation + for _,j in ipairs(thisframe) do + io.write(j:gsub("0","·"):gsub("1","O").."\n") + end + else + + end + return 0 +end + +return eca diff --git a/module/tex/context/third/simpleslides/automata/automata-life.lua b/module/tex/context/third/simpleslides/automata/automata-life.lua new file mode 100644 index 0000000..01fc97b --- /dev/null +++ b/module/tex/context/third/simpleslides/automata/automata-life.lua @@ -0,0 +1,420 @@ +-- +-------------------------------------------------------------------------------- +-- FILE: automata-life.lua +-- DESCRIPTION: Conway's Game of Life? +-- REQUIREMENTS: ConTeXt MkIV / Simple Slides module +-- BUGS: almost infinite but not quite +-- AUTHOR: Philipp Gesang (Phg), +-- VERSION: 1.0 +-- CREATED: 05/08/10 12:03:11 CEST +-------------------------------------------------------------------------------- +-- + +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) + environment.loadluafile( "parser-rle" ) + return gol.rleparser(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 + + 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 + + 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 diff --git a/module/tex/context/third/simpleslides/automata/automata-main.lua b/module/tex/context/third/simpleslides/automata/automata-main.lua new file mode 100644 index 0000000..c7d1435 --- /dev/null +++ b/module/tex/context/third/simpleslides/automata/automata-main.lua @@ -0,0 +1,247 @@ +-- +-------------------------------------------------------------------------------- +-- FILE: automata-main.lua +-- USAGE: use with ConTeXt MkIV and the Simple Slides Module +-- DESCRIPTION: Metapost output for Conway's Game of Life and Elementary +-- Cellular Automata +-- AUTHOR: Philipp Gesang (Phg), +-- VERSION: 1.0 +-- CREATED: 06/08/10 12:28:35 CEST +-------------------------------------------------------------------------------- +-- + +environment.loadluafile( "automata-life" ) +environment.loadluafile( "automata-eca" ) + +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 {} + +if context then + environment.loadluafile( "automatarc-global" ) + environment.loadluafile( "automatarc-eca" ) +else -- assuming we're staying in pwd + require ( "automatarc-eca" ) +end + +mplife.setup.current = {} + + +do + local g, r, c = mplife.setup.global, mplife.setup.rc, mplife.setup.current + for key,_ in pairs(g) do + c[key] = r[key] or g[key] -- prefer local settings + end + 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) + + 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 + 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.gol_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.eca_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 + + local thisframe + + mplife.setup.current.init, thisframe = eca.gen_frame(c.init, c.framesize, c.rule) + context(c.before_frame) + mplife.draw_grid(thisframe, settings) + context(c.after_frame) + 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 diff --git a/module/tex/context/third/simpleslides/automata/automatarc-global.lua b/module/tex/context/third/simpleslides/automata/automatarc-global.lua new file mode 100644 index 0000000..22f8fd9 --- /dev/null +++ b/module/tex/context/third/simpleslides/automata/automatarc-global.lua @@ -0,0 +1,63 @@ +-- +-------------------------------------------------------------------------------- +-- FILE: automatarc-global.lua +-- USAGE: with ConTeXt +-- DESCRIPTION: default settings for the automaton module +-- AUTHOR: Philipp Gesang (Phg), +-- VERSION: 1.0 +-- CREATED: 13/08/10 10:35:46 CEST +-------------------------------------------------------------------------------- +-- + +if not mplife then return 1 end + +mplife.setup.global = {} + +do + local c = {} + +-- c.file = "sships.gol" +-- c.init = gol.parse_file(c.file) +-- c.last = c.init -- for successive mode + + c.rule = gol.parse_rule("B3/S23") -- default Conway + + c.aspect = 3/4 -- actually 1/(x/y), for eca mode + + c.extendxy = 0 + c.extendx = 0 + c.extendy = 0 + + 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.global = c +end + +return mplife.setup.global diff --git a/module/tex/context/third/simpleslides/automata/parsers/parser-rle.lua b/module/tex/context/third/simpleslides/automata/parsers/parser-rle.lua new file mode 100644 index 0000000..e51eeea --- /dev/null +++ b/module/tex/context/third/simpleslides/automata/parsers/parser-rle.lua @@ -0,0 +1,95 @@ +-- http://psoup.math.wisc.edu/mcell/ca_files_formats.html#RLE +local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match + +local rows = {} +local coords = {} + +local n_row = 1 +rows[n_row] = "" + +local eol = P"\n" +local hashmark = P"#" +local space = S" \t" +local whitespace = S(" \n\t")^0 +local num = R"09" +local comma = P"," +local exclam = P"!" +local equals = P"=" +local dollar = P"$" +local state = S"bo" +--local sign = S("+-")^0 -- support negative grid values? not yet, if ever… + +local comment = hashmark * (1-eol)^0 * eol + +local getx = space^0 * P"x" * space^0 * equals * space^0 * C(num^1) / function (x) + coords.x = tonumber(x) +end +local gety = space^0 * P"y" * space^0 * equals * space^0 * C(num^1) / function (y) + coords.y = tonumber(y) +end +geometry = getx * comma * gety * (1-eol)^0 * eol + +local function n_of_t (n, c) + local tmp = "" + if c == "o" then -- live + c = "1" + else -- dead + c = "0" + end + + for i=1, n, 1 do + tmp = tmp .. c + end + return tmp +end + +local cell = C(num^0) * C(state) / function (n, c) + if n == "" then + n = 1 + end + + if n_of_t (tonumber(n), c) == nil then + end + rows[n_row] = rows[n_row] .. n_of_t (tonumber(n), c) +end + +local line = whitespace * (cell * whitespace)^0 * C(num^0) / function (empty) + + if rows[n_row]:len() < coords.x then -- fill grid with dead cells + rows[n_row] = rows[n_row] .. n_of_t( coords.x - rows[n_row]:len(), "0" ) + end + + if empty ~= "" then + for n=1, tonumber(empty)-1, 1 do + n_row = n_row + 1 + rows[n_row] = n_of_t( coords.x, "0" ) + end + end + + n_row = n_row + 1 + + if n_row <= coords.y then + rows[n_row] = "" + end +end + +local p_rle = comment^0 * geometry * line * (dollar * line)^0 * whitespace * exclam + +function gol.rleparser(fname) + local file = assert(io.open(fname, "r"), "Not a file: " .. fname) + local data = file:read("*all") + file:close() + + if p_rle:match(data) then + if context then + context.writestatus("simpleslides", "Sucessfully loaded frame from "..fname..".") + end + return rows + else + if context then + context.writestatus("simpleslides", "There were problems loading file "..fname..".") + end + return false + end +end + diff --git a/module/tex/context/third/simpleslides/simpleslides-s-Automaton.tex b/module/tex/context/third/simpleslides/simpleslides-s-Automaton.tex new file mode 100644 index 0000000..0fa089a --- /dev/null +++ b/module/tex/context/third/simpleslides/simpleslides-s-Automaton.tex @@ -0,0 +1,261 @@ +%D \module +%D [ file=simpleslides-s-Automaton, +%D version=2010-08-10-15:28:22+0200, +%D title=\CONTEXT\ Style File, +%D subtitle=Presentation Module --- Automaton Style, +%D author=Philipp Gesang, +%D date=\currentdate, +%D copyright={Philipp Gesang}] +%C +%C Copyright 2007 Aditya Mahajan and Thomas A. Schmitz +%C This file may be distributed under the GNU General Public License v. 2.0. +%C Modified 2010 by Philipp Gesang + +%D Providing presentation Backgrounds according to Conway's Game of Life. +%D Initially based on the BigNumber theme by A. Mahajan and Th. Schmitz. (Many, +%D many thanks!) + +\writestatus{simpleslides}{loading Theme Automata} + +\startmodule[simpleslides-s-Automaton] + +\setupmodule[ + mode=, + file=, + rule=, + extendxy=, + clip=, +] % using defaults from lua config + +\ctxlua{environment.loadluafile( "automata-main" )} +\ctxlua{mplife.slides = true} + +\unprotect + +%D First, we change the page layout to have more space all around + +\setuplayout [ width=fit, + margin=2cm, + height=fit, + leftmargindistance=.2cm, + rightmargindistance=.2cm, + header=18mm, + headerdistance=.3cm, + footer=0cm, + footerdistance=0mm, + topspace=.5cm, + backspace=1.9cm, + location=singlesided] + +\setuplayout [simpleslides:layout:horizontal][header=14mm] +\setuplayout [simpleslides:layout:vertical] [header=0mm] +\setuplayout [simpleslides:layout:title] + +\setuplayer[simpleslides:layer:slidetitle] + [width=\paperwidth, + height=\paperheight,x=20mm] + +%D Next we a generic frames, which will be used by other macros to +%D get a consistent look and feel. + +\defineframed[simpleslides:framed:small] + [ frame=off, + offset=0pt, + width=1.7cm, + align=middle] + +\setupcombinations[distance=2.5em] + +%D These macros are used for placing figures/pictures: + +\define\NormalHeight {\textheight} +\define\NormalWidth {.46\textwidth} +\define\PictureFrameHeight {\textheight} +\define\PictureFrameWidth {.46\textwidth} + +%D This module has two color schemes, a blue one and a red one. + +\startsetups simpleslides:setups:blue +\definecolor [simpleslides:contrastcolor] [r=0.7,g=0.7,b=0.9] +%\definecolor [simpleslides:backgroundcolor] [s=1] +\definecolor [simpleslides:backgroundoutside] [r=0.9,g=0.9,b=0.95] +\definecolor [simpleslides:backgroundscreen] [s=.975] +\definecolor [simpleslides:textcolor] [s=0] +\stopsetups + +\startsetups simpleslides:setups:red +\definecolor [simpleslides:contrastcolor] [r=0.4] +%\definecolor [simpleslides:backgroundcolor] [s=.95] +\definecolor [simpleslides:backgroundoutside] [r=0.5,g=0.2,b=0.2] +\definecolor [simpleslides:backgroundscreen] [s=.4] +\definecolor [simpleslides:textcolor] [s=1] +\stopsetups + +%D Now we choose the scheme that the user asked for + +\doifsetupselse + {simpleslides:setups:\moduleparameter{simpleslides}{color}} + {\setups{simpleslides:setups:\moduleparameter{simpleslides}{color}}} + {\setups{simpleslides:setups:blue}} + +\setupcolors[textcolor={simpleslides:textcolor}] + +%D Set the initial snapshot (from file) and the rule, if given. + +\doifsomethingelse{\moduleparameter{simpleslides}{mode}} +{\ctxlua{ +mplife.setup.current.mode = "\luaescapestring{\moduleparameter{simpleslides}{mode}}" +if mplife.setup.current.mode == "life" then + mplife.successive = mplife.gol_successive +else + environment.loadluafile("automata-eca") + mplife.successive = mplife.eca_successive +end}} +{\ctxlua{mplife.successive = mplife.gol_successive}} + +%D The number of dead cells to add left and right / before and after +%D the initial frame. + +\doifsomething{\moduleparameter{simpleslides}{extendxy}}{\ctxlua + {mplife.setup.current.extendx = tonumber("\luaescapestring{\moduleparameter{simpleslides}{extendxy}}") + mplife.setup.current.extendy = tonumber("\luaescapestring{\moduleparameter{simpleslides}{extendxy}}") }} + +\doifsomething{\moduleparameter{simpleslides}{extendx}}{\ctxlua + {mplife.setup.current.extendx = tonumber("\luaescapestring{\moduleparameter{simpleslides}{extendx}}") }} + +\doifsomething{\moduleparameter{simpleslides}{extendy}}{\ctxlua + {mplife.setup.current.extendy = tonumber("\luaescapestring{\moduleparameter{simpleslides}{extendy}}") }} + +\doifsomething{\moduleparameter{simpleslides}{file}}{\ctxlua{ +mplife.setup.current.file = "\luaescapestring{\moduleparameter{simpleslides}{file}}" +}} + +\doifsomething{\moduleparameter{simpleslides}{clip}}{\ctxlua + {mplife.setup.current.clip = "\luaescapestring{\moduleparameter{simpleslides}{clip}}" }} + +\startluacode +do + local c = mplife.setup.current + if c.mode == "life" then + c.init = gol.parse_file(c.file) + c.last = c.init + else + c.init = eca.parse_file(c.file) + c.framesize = math.floor(c.aspect * c.init:len()) + c.pages = structure.counters.record("realpage")["last"] + -- Clipping is essential to cope with left/right propagation of + -- patterns. E.g. with rule 158 the total propagation at iteration + -- n is itself n to the left and n to the right. Whereas rule 102 + -- (a Sierpiński fractal generator) protrudes only to the left at + -- a rate of n. + -- Frames cannot be simply cut off at the borders with adjacient + -- cells treated as “dead” because it would distort the pattern. + -- Therefore, frames are generated as complete sections which are + -- clipped to the desired size, as specified by the initial row. + -- To determine whether to clip your pattern to the left, right, + -- or in both directions, check the propagation at + -- string.format("http://mathworld.wolfram.com/Rule%s.html", rule) + -- or consult Wolfram's “A New Kind of Science” but beware not to + -- buy everything he claims… + if c.clip then + c.xneeded = c.pages * c.framesize + if c.clip == "both" then -- Assume initial pattern is centered. + c.diff = c.xneeded - math.ceil(c.init:len()/2) + else + c.diff = c.xneeded - c.init:len() + end + if c.diff > 0 then + local affix = "" + for i=1, c.diff, 1 do + affix = affix .. "0" + end + if c.clip == "left" or c.clip == "both" then + c.init = affix .. c.init + end + if c.clip == "right" or c.clip == "both" then + c.init = c.init .. affix + end + end + end + end + mplife.setup.current = c +end +\stopluacode + +\doifsomething{\moduleparameter{simpleslides}{rule}}{\ctxlua{ +if mplife.setup.current.mode == "life" then + mplife.setup.current.rule = gol.parse_rule("\luaescapestring{\moduleparameter{simpleslides}{rule}}") +else + mplife.setup.current.rule = eca.gen_rule(tonumber("\luaescapestring{\moduleparameter{simpleslides}{rule}}")) +end +}} + +%D We also use \METAPOST\ to draw the horizontal and vertical page backgrounds. +%D Backgrounds will be of solid color, the ornament gets the transparency. + +\startuniqueMPgraphic{simpleslides:MP:horizontal} +StartPage ; +fill Page withcolor \MPcolor{simpleslides:backgroundoutside} ; +fill Field[Text][Text] enlarged 0.2cm + withcolor \MPcolor{simpleslides:backgroundscreen} ; +StopPage ; +\stopuniqueMPgraphic + +\startuniqueMPgraphic{simpleslides:MP:vertical} +StartPage ; +fill Page withcolor \MPcolor{simpleslides:backgroundoutside} ; + +z1 = urcorner Field[Text][Text] shifted (.2cm,0) ; +z2 = lrcorner Field[Text][Text] shifted (.2cm,-.2cm) ; +z3 = z1 shifted (-8.05cm,0) ; +z4 = (x3,y2) ; + +save Main ; +path Main ; +Main := z1 -- z2 -- z4 -- z3 --cycle ; + +fill Main withcolor \MPcolor{simpleslides:backgroundscreen} ; +StopPage ; +\stopuniqueMPgraphic + + +%D We define these backgrounds as overlays: + +\defineoverlay + [simpleslides:background:horizontal] + [\useMPgraphic{simpleslides:MP:horizontal}] + +\defineoverlay + [simpleslides:background:vertical] + [\useMPgraphic{simpleslides:MP:vertical}] + +\defineoverlay + [simpleslides:background:title] + [\useMPgraphic{simpleslides:MP:horizontal}] + +\defineoverlay + [simpleslides:background:ornament] + [\ctxlua{mplife.successive()}] + +%D The slide title is placed on the top of the text area. The layer takes care +%D of the positioning. + +\setupSlideTitle + [\c!after=, + \c!alternative=layer, + \c!width=\textwidth, + \c!height=2.5cm, + \c!command=\doSlideTitle] + + +%D Squares are used as the first level of itemizations + +\definesymbol[1][$\square$] +\setupitemize[1][inmargin] +%\setupitemize[each][joinedup,unpacked] + +\protect +\stopmodule + +\endinput + -- cgit v1.2.3