From f9de5a1d4cf71647752fbc0539deb1302c93d3f2 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 29 Jan 2009 00:23:38 +0000 Subject: new context package context-games (28jan09) git-svn-id: svn://tug.org/texlive/trunk@12005 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/context/third/games/games-go.lua | 521 +++++++++++++++++++++ .../tex/context/third/games/games-go.tex | 381 +++++++++++++++ .../tex/context/third/games/games-hex.lua | 90 ++++ .../tex/context/third/games/games-hex.tex | 119 +++++ .../texmf-dist/tex/context/third/games/holz280.jpg | Bin 0 -> 4759 bytes .../texmf-dist/tex/context/third/games/t-games.tex | 97 ++++ 6 files changed, 1208 insertions(+) create mode 100644 Master/texmf-dist/tex/context/third/games/games-go.lua create mode 100644 Master/texmf-dist/tex/context/third/games/games-go.tex create mode 100644 Master/texmf-dist/tex/context/third/games/games-hex.lua create mode 100644 Master/texmf-dist/tex/context/third/games/games-hex.tex create mode 100644 Master/texmf-dist/tex/context/third/games/holz280.jpg create mode 100644 Master/texmf-dist/tex/context/third/games/t-games.tex (limited to 'Master/texmf-dist/tex/context') diff --git a/Master/texmf-dist/tex/context/third/games/games-go.lua b/Master/texmf-dist/tex/context/third/games/games-go.lua new file mode 100644 index 00000000000..444bfd06378 --- /dev/null +++ b/Master/texmf-dist/tex/context/third/games/games-go.lua @@ -0,0 +1,521 @@ +if not modules then modules = { } end modules ['games-go'] = { + version = 1.000, + comment = "Go", + author = "Wolfgang Schuster", + copyright = "Wolfgang Schuster", + email = "schuster.wolfgang@googlemail.com", + license = "Public Domain" +} + +do + +thirddata = thirddata or { } +thirddata.games = thirddata.games or { } +thirddata.games.go = thirddata.games.go or { } +thirddata.games.go.field = thirddata.games.go.field or { } +thirddata.games.go.setup = thirddata.games.go.setup or { } +thirddata.games.go.deadstone = thirddata.games.go.deadstone or { } + +local nx = function() return thirddata.games.go.setup.nx end +local ny = function() return thirddata.games.go.setup.ny end +local dx = function() return thirddata.games.go.setup.dx end +local dy = function() return thirddata.games.go.setup.dy end +local offset = function() return thirddata.games.go.setup.offset end +local size = function() return thirddata.games.go.setup.stonesize end +local board = function() return thirddata.games.go.setup.board end +local distance = function() return thirddata.games.go.setup.labeldistance end +local symbolset = function() return thirddata.games.go.setup.symbolset end +local bp = function(value) return number.tobasepoints(value) end +local sp = function(value) return value * 65536/(7227/7200) end +local line = function(k,v,s) return bp(thirddata.games.go.lines [k][v]*s) end +local arrow = function(k,v,s) return bp(thirddata.games.go.arrows[k][v]*s) end + +-- Drawing functions + +thirddata.games.go.lastcolor = 0 +thirddata.games.go.currentmove = 0 + +function thirddata.games.go.move(color) + thirddata.games.go.lastcolor = color + thirddata.games.go.currentmove = thirddata.games.go.currentmove + 1 +end + +thirddata.games.go.linecount = 0 +thirddata.games.go.lines = { } + +function thirddata.games.go.line(x1,y1,x2,y2) + thirddata.games.go.linecount = thirddata.games.go.linecount + 1 + thirddata.games.go.lines[thirddata.games.go.linecount] = { x1, y1, x2, y2 } +end + +thirddata.games.go.arrowcount = 0 +thirddata.games.go.arrows = { } + +function thirddata.games.go.arrow(x1,y1,x2,y2) + thirddata.games.go.arrowcount = thirddata.games.go.arrowcount + 1 + thirddata.games.go.arrows[thirddata.games.go.arrowcount] = { x1, y1, x2, y2 } +end + +function thirddata.games.go.board_color() + if thirddata.games.go.setup['backgroundcolor'] ~= nil then + tex.sprint("board := currentpicture ;") + tex.sprint("currentpicture := nullpicture ;") + tex.sprint("fill unitsquare xyscaled (" .. bp((nx()-1)*dx()+2*offset()) .. "," .. bp((ny()-1)*dy()+2*offset()) .. ")") + tex.sprint("shifted (" .. bp(-offset()) .. "," .. bp(-offset()) .. ")") + tex.sprint("withcolor \\MPcolor{" .. thirddata.games.go.setup['backgroundcolor'] .. "} ;") + tex.sprint("addto currentpicture also board ;") + end +end + +thirddata.games.go.setup.figurewidth = 0 +thirddata.games.go.setup.figureheight = 0 + +function thirddata.games.go.board_figure() + local width = thirddata.games.go.setup.figurewidth + local height = thirddata.games.go.setup.figureheight + local columns = math.floor( ((nx()-1)*dx()+2*offset()) / width ) -- floor and not ceil because + local rows = math.floor( ((ny()-1)*dy()+2*offset()) / height ) -- I start from 0 and not 1 + if thirddata.games.go.setup['backgroundimage'] ~= nil then + tex.sprint("board := currentpicture ;") + tex.sprint("currentpicture := nullpicture ;") + for row=0,rows do + for col=0,columns do + tex.sprint('externalfigure "' .. thirddata.games.go.setup['backgroundimage'] .. '"') + tex.sprint('xyscaled (' .. bp(width) .. ',' .. bp(height) .. ')') + tex.sprint('shifted (' .. bp(-offset()+row*width) .. ',' .. bp(-offset()+col*height) .. ') ;') + end + end + tex.sprint("mine := unitsquare xyscaled (" .. bp((nx()-1)*dx()+2*offset()) .. "," .. bp((ny()-1)*dy()+2*offset()) .. ")") + tex.sprint(" shifted (" .. bp(-offset()) .. "," .. bp(-offset()) .. ") ;") + tex.sprint("clip currentpicture to mine ;") + tex.sprint("addto currentpicture also board ;") + end +end + +function thirddata.games.go.board_new() + local xy = 0 + thirddata.games.go.field[0] = { } + for col=0,nx()+1 do + thirddata.games.go.field[0][col] = { } + for row=0,ny()+1 do + if col==0 then + xy = 3 + elseif col==nx()+1 then + xy = 3 + elseif row==0 then + xy = 3 + elseif row==ny()+1 then + xy = 3 + else + xy = 0 + end + thirddata.games.go.field[0][col][row] = { color = xy, marker = nil, label = nil, move = nil } + end + end +end + +function thirddata.games.go.board_copy(from,to) + thirddata.games.go.field[to] = { } + for k,v in pairs(thirddata.games.go.field[from]) do + thirddata.games.go.field[to][k] = { } + for x,y in pairs(thirddata.games.go.field[from][k]) do + thirddata.games.go.field[to][k][x] = { } + for a,b in pairs(thirddata.games.go.field[from][k][x]) do + thirddata.games.go.field[to][k][x][a] = thirddata.games.go.field[from][k][x][a] + end + end + end +end + +function thirddata.games.go.board_lines() + for col=1,nx() do + tex.sprint("draw (" .. bp((col-1)*dx()) .. ",0) -- (" .. bp((col-1)*dx()) .. "," .. bp((ny()-1)*dy()) .. ") ;") + end + for row=1,ny() do + tex.sprint("draw (0," .. bp((row-1)*dy()) .. ") -- (" .. bp((nx()-1)*dx()) .. "," .. bp((row-1)*dy()) .. ") ;") + end +end + +function thirddata.games.go.board_lines_alt() + -- draw horizontal rules + for row=2,ny()-1 do + for col=1,nx()-1 do + if thirddata.games.go.field[0][col][row]['color'] == 0 then + tex.sprint("draw (" .. bp((col-1)*dx()) .. "," .. bp((row-1)*dy()) .. ") -- (" .. bp((col)*dx()) .. "," .. bp((row-1)*dy()) .. ") ;") + else + if thirddata.games.go.field[0][col+1][row]['color'] == 0 then + tex.sprint("draw (" .. bp((col-1)*dx()) .. "," .. bp((row-1)*dy()) .. ") -- (" .. bp((col)*dx()) .. "," .. bp((row-1)*dy()) .. ") ;") + end + end + end + end + -- draw vertical rules + for col=2,nx()-1 do + for row=1,ny()-1 do + if thirddata.games.go.field[0][col][row]['color'] == 0 then + tex.sprint("draw (" .. bp((col-1)*dx()) .. "," .. bp((row-1)*dy()) .. ") -- (" .. bp((col-1)*dx()) .. "," .. bp((row)*dy()) .. ") ;") + else + if thirddata.games.go.field[0][col][row+1]['color'] == 0 then + tex.sprint("draw (" .. bp((col-1)*dx()) .. "," .. bp((row-1)*dy()) .. ") -- (" .. bp((col-1)*dx()) .. "," .. bp((row)*dy()) .. ") ;") + end + end + end + end + -- draw border frame + tex.sprint("draw (0,0) -- (0," .. bp((ny()-1)*dy()) .. ") ;") + tex.sprint("draw (" .. bp((nx()-1)*dx()).. ",0) -- (" .. bp((nx()-1)*dx()).. "," .. bp((ny()-1)*dy()) .. ") ;") + tex.sprint("draw (0,0) -- (" .. bp((nx()-1)*dx()) .. ",0) ;") + tex.sprint("draw (0," .. bp((ny()-1)*dy()).. ") -- (" .. bp((nx()-1)*dx()).. "," .. bp((ny()-1)*dy()) .. ") ;") +end + +function thirddata.games.go.board_hoshi() + for col=1,nx() do + for row=1,ny() do + tex.sprint("\\ifcsname go:hoshi:" .. row .. ":" .. col .. ":" .. board() .. "\\endcsname") + tex.sprint("\\csname go:marker:hoshi\\endcsname") + tex.sprint("{" .. bp(size()/5) .. "}") + tex.sprint("{" .. bp((col-1)*dx()) .. "}") + tex.sprint("{" .. bp((row-1)*dy()) .. "}") + tex.sprint("\\fi") + end + end +end + +function thirddata.games.go.board_stones() + for col=1,nx() do + for row=1,ny() do + local color = thirddata.games.go.field[0][col][row]['color'] + if color==1 then + tex.sprint("\\csname go:stone:" .. symbolset() .. ":black\\endcsname") + tex.sprint("{" .. bp(size()) .. "}") + tex.sprint("{" .. bp((col-1)*dx()) .. "}") + tex.sprint("{" .. bp((row-1)*dy()) .. "}") + elseif color==2 then + tex.sprint("\\csname go:stone:" .. symbolset() .. ":white\\endcsname") + tex.sprint("{" .. bp(size()) .. "}") + tex.sprint("{" .. bp((col-1)*dx()) .. "}") + tex.sprint("{" .. bp((row-1)*dy()) .. "}") + end + end + end +end + +function thirddata.games.go.board_marker() + for col=1,nx() do + for row=1,ny() do + local marker = thirddata.games.go.field[0][col][row]['marker'] + local label = thirddata.games.go.field[0][col][row]['label'] + if marker==nil then + elseif marker=='label' then + tex.sprint("\\csname go:marker:label\\endcsname") + tex.sprint("{" .. label .. "}") + tex.sprint("{" .. bp((col-1)*dx()) .. "}") + tex.sprint("{" .. bp((row-1)*dy()) .. "}") + else + tex.sprint("\\ifcsname go:marker:" .. marker .. "\\endcsname") + tex.sprint("\\csname go:marker:" .. marker .. "\\endcsname") + tex.sprint("{" .. nx() .. "}") + tex.sprint("{" .. ny() .. "}") + tex.sprint("{" .. bp(dx()) .. "}") + tex.sprint("{" .. bp(dy()) .. "}") + tex.sprint("{" .. bp(size()) .. "}") + tex.sprint("{" .. bp((col-1)*dx()) .. "}") + tex.sprint("{" .. bp((row-1)*dy()) .. "}") + tex.sprint("{" .. bp(offset()) .. "}") + tex.sprint("\\fi") + end + end + end +end + +function thirddata.games.go.board_label() + for col=1,nx() do + tex.sprint('label.bot(textext("\\doattributes{@@@@gmgo}{labelstyle}{labelcolor}{\\sgfchar{' .. col .. '}}"),%') + tex.sprint('(' .. bp((col-1)*dx()) .. ',' .. bp(-distance()) .. ')) ;') + end + for row=1,ny() do + tex.sprint('label.lft(textext("\\doattributes{@@@@gmgo}{labelstyle}{labelcolor}{' .. row .. '}"),%') + tex.sprint('(' .. bp(-distance()) .. ',' .. bp((row-1)*dy()) .. ')) ;') + end +end + +function thirddata.games.go.board_markerlines() + for k, v in pairs(thirddata.games.go.lines) do + tex.sprint("draw (" .. line(k,1,dx()) .. "," .. line(k,2,dy()) .. ") -- ") + tex.sprint(" (" .. line(k,3,dx()) .. "," .. line(k,4,dy()) .. ") ; ") + end +end + +function thirddata.games.go.board_markerarrows() + for k, v in pairs(thirddata.games.go.arrows) do + tex.sprint("drawarrow (" .. arrow(k,1,dx()) .. "," .. arrow(k,2,dy()) .. ") -- ") + tex.sprint(" (" .. arrow(k,3,dx()) .. "," .. arrow(k,4,dy()) .. ") ; ") + end +end + +function thirddata.games.go.board_size() + tex.sprint("setbounds currentpicture to unitsquare %") + tex.sprint("xyscaled (" .. bp((nx()-1)*dx()+2*offset()) .. "," .. bp((ny()-1)*dy()+2*offset()) .. ")") + tex.sprint("shifted (" .. bp(-offset()) .. "," .. bp(-offset()) .. ") ;") + tex.sprint("draw boundingbox currentpicture withpen pensquare scaled 1.2 ;") +end + +function thirddata.games.go.board_draw(name) + tex.sprint("\\startuseMPgraphic{" .. name .. "}{}") + tex.sprint("path mine ; picture board ;") + -- thirddata.games.go.board_figure() -- not here, I have to do this at the end + -- thirddata.games.go.board_lines() + thirddata.games.go.board_lines_alt() + thirddata.games.go.board_hoshi() + thirddata.games.go.board_stones() + thirddata.games.go.board_marker() + thirddata.games.go.board_markerlines() + thirddata.games.go.board_markerarrows() + thirddata.games.go.board_label() + thirddata.games.go.board_size() + thirddata.games.go.board_color() + thirddata.games.go.board_figure() + tex.sprint("\\stopuseMPgraphic") +end + + +-- Deadstone calculator + +local stone = function() return thirddata.games.go.deadstone.stone end +local enemy = function() return thirddata.games.go.deadstone.enemy end +local wall = function() return thirddata.games.go.deadstone.wall end +local marked = function() return thirddata.games.go.deadstone.marked end +local error = function() return thirddata.games.go.deadstone.error end +local dead = function() return thirddata.games.go.deadstone.dead end + +function thirddata.games.go.deadstone.black() + thirddata.games.go.deadstone.stone = 1 + thirddata.games.go.deadstone.enemy = 2 + thirddata.games.go.deadstone.wall = 3 + thirddata.games.go.deadstone.marked = 4 + thirddata.games.go.deadstone.error = 6 + thirddata.games.go.deadstone.dead = 7 +end + +function thirddata.games.go.deadstone.white() + thirddata.games.go.deadstone.stone = 2 + thirddata.games.go.deadstone.enemy = 1 + thirddata.games.go.deadstone.wall = 3 + thirddata.games.go.deadstone.marked = 5 + thirddata.games.go.deadstone.error = 6 + thirddata.games.go.deadstone.dead = 7 +end + +thirddata.games.go.deadstone.deadcount = 2 + +function thirddata.games.go.deadstone.doprocesstones() + for i=1,2 do -- for the moment, I have to check the code + thirddata.games.go.deadstone.markstones() + end + thirddata.games.go.deadstone.deadstones() + for n=1,thirddata.games.go.deadstone.deadcount do + thirddata.games.go.deadstone.checkstones() + end + thirddata.games.go.deadstone.revertstones() +end + +function thirddata.games.go.deadstone.processtones() + -- we placed a black stone + if thirddata.games.go.lastcolor==1 then + thirddata.games.go.deadstone.process_white() + thirddata.games.go.deadstone.process_black() + -- we placed a white stone + elseif thirddata.games.go.lastcolor==2 then + thirddata.games.go.deadstone.process_black() + thirddata.games.go.deadstone.process_white() + end +end + +function thirddata.games.go.deadstone.process_black() + thirddata.games.go.deadstone.black() + thirddata.games.go.deadstone.doprocesstones() +end + +function thirddata.games.go.deadstone.process_white() + thirddata.games.go.deadstone.white() + thirddata.games.go.deadstone.doprocesstones() +end + +local field = function(x,y) return thirddata.games.go.field[0][x][y]['color'] end +-- local field_top = function(x,y) return thirddata.games.go.field[0][x][y+1]['color'] end +-- local field_bottom = function(x,y) return thirddata.games.go.field[0][x][y-1]['color'] end +local field_bottom = function(x,y) return thirddata.games.go.field[0][x][y+1]['color'] end +local field_top = function(x,y) return thirddata.games.go.field[0][x][y-1]['color'] end +local field_left = function(x,y) return thirddata.games.go.field[0][x-1][y]['color'] end +local field_right = function(x,y) return thirddata.games.go.field[0][x+1][y]['color'] end + +--[[ldx-- +

The markstones mark the stones if they +have the right stones on their sides or let them keep untouched.

+--ldx]]-- + +function thirddata.games.go.deadstone.markstones() + for col=1,nx() do + for row=1,ny() do + if field(col,row)==stone() then + if (field_left(col,row)==wall() + or field_left(col,row)==enemy() + or field_left(col,row)==marked()) + and (field_right(col,row)==wall() + or field_right(col,row)==enemy() + or field_right(col,row)==stone()) + and (field_bottom(col,row)==wall() + or field_bottom(col,row)==enemy() + or field_bottom(col,row)==marked()) + and (field_top(col,row)==wall() + or field_top(col,row)==enemy() + or field_top(col,row)==stone()) + then + thirddata.games.go.field[0][col][row]['color'] = marked() + end + end + end + end +end + +--[[ldx-- +

The deadstones set stones with the value marked +to dead if the conditions in the function are true.

+--ldx]]-- + +function thirddata.games.go.deadstone.deadstones() + for col=nx(),1,-1 do + for row=ny(),1,-1 do + if field(col,row)==marked() then + if (field_left(col,row)==wall() + or field_left(col,row)==enemy() + or field_left(col,row)==marked()) + and (field_right(col,row)==enemy() + or field_right(col,row)==wall() + or field_right(col,row)==dead()) + and (field_bottom(col,row)==enemy() + or field_bottom(col,row)==wall() + or field_bottom(col,row)==dead()) + then + thirddata.games.go.field[0][col][row]['color'] = dead() + end + end + end + end +end + +--[[ldx-- +

Because the deadstones can sometimes set +already living stones to dead. To prevent this in the final result this +function looks through all stones with a loop in reverse direction and +reset the values to their original value if the stone is not dead and +should remain on the board. The function is currently called twice within +processtones but this can be changed with the counter deadcount.

+--ldx]]-- + +function thirddata.games.go.deadstone.checkstones() + for col=1,nx() do + for row=1,ny() do + if field(col,row)==marked() then + thirddata.games.go.field[0][col][row]['color'] = stone() + elseif thirddata.games.go.field[0][col][row]['color']==dead() then + if (field_left(col,row)==dead() + or field_left(col,row)==enemy() + or field_left(col,row)==wall()) + and (field_right(col,row)==dead() + or field_right(col,row)==enemy() + or field_right(col,row)==wall()) + and (field_bottom(col,row)==dead() + or field_bottom(col,row)==enemy() + or field_bottom(col,row)==wall()) + and (field_top(col,row)==dead() + or field_top(col,row)==enemy() + or field_top(col,row)==wall()) + then + thirddata.games.go.field[0][col][row]['color'] = dead() + else + thirddata.games.go.field[0][col][row]['color'] = stone() + end + end + end + end +end + +--[[ldx-- +

The last thing to do after all dead stones are found on the board +is to remove them and to reset all other stones which are still in a +marked state or we will get wrong input for the next move.

+--ldx]]-- + +function thirddata.games.go.deadstone.revertstones() + for col=1,nx() do + for row=1,ny() do + if thirddata.games.go.field[0][col][row]['color']==marked() then + thirddata.games.go.field[0][col][row] = stone() + elseif thirddata.games.go.field[0][col][row]['color']==dead() then + thirddata.games.go.field[0][col][row]['color'] = 0 + end + end + end +end + +end + + +-- SGF parser + +do + + thirddata = thirddata or { } + thirddata.games = thirddata.games or { } + thirddata.games.sgf = thirddata.games.sgf or { } + + local function command(name,x) + tex.sprint(string.format("\\csname sgf!%s\\endcsname{%s}",name,x)) + end + + local nodes = { } + + function nodes.B (x) command("black" ,x) end + function nodes.W (x) command("white" ,x) end + function nodes.AW(x) command("addwhite" ,x) end + function nodes.C (x) command("comment" ,x) end + + local function action(what,data) + local a = nodes[what] + if a then + for w in string.gmatch(data, "%b[]") do + a(string.sub(w,2,-2)) + end + else + print("unknown action: " .. what) + end + end + + local function nodecontent(str) + tex.sprint(string.format("\\csname sgf!node\\endcsname{%s}",string.sub(str,2))) + end + + local space = lpeg.S(' \r\n')^1 + local lcletter = lpeg.R("az") + local ucletter = lpeg.R("AZ") + local letter = lcletter + ucletter + + local propindent = ucletter^1 + + local property = lpeg.C(propindent) * lpeg.C{ (lpeg.P("[") * (1 - lpeg.S"[]")^0 * lpeg.P("]"))^1} / action + + local function nest(str) + tex.sprint(tex.ctxcatcodes,string.format("\\parsesgf{%s}",string.sub(str,2,-2))) + end + + local node = lpeg.P{ ";" * (propindent * (lpeg.P("[") * (1 - lpeg.S"[]")^0 * lpeg.P("]"))^1)^1} / nodecontent + local branch = lpeg.P{ "(" * ((1 - lpeg.S"()") + lpeg.V(1))^0 * ")" } / nest + + local parser = (branch + node + property + space)^0 + + function thirddata.games.sgf.parse(str) + parser:match(str) + end + +end diff --git a/Master/texmf-dist/tex/context/third/games/games-go.tex b/Master/texmf-dist/tex/context/third/games/games-go.tex new file mode 100644 index 00000000000..b02480862d2 --- /dev/null +++ b/Master/texmf-dist/tex/context/third/games/games-go.tex @@ -0,0 +1,381 @@ +%D \module +%D [ file=games-go, +%D version=2008.12.30, +%D title=\CONTEXT\ User Module, +%D subtitle=Go, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D copyright=Wolfgang Schuster, +%D email=schuster.wolfgang@googlemail.com, +%D license=Public Domain] + +\writestatus{loading}{Context User Module / Games - Go} + +\unprotect + +%D The \type{\definegame} command creates the new goban environment, it is +%D important to use the goban environment in a document and not the game +%D environment itself because in sgf mode the content untill \type{\stopgoban} +%D is read and \type{\endgame} is executed at the end of the parsing process. + +\definegame[\v!goban][\v!go] % not final +%\definegame[\v!weiqi][\v!go] +%\definegame[\v!baduk][\v!go] + +%D Convert number into labels for the board, could be replaced with \type{\ifcase} solution (faster?) + +\def\sgfchar#1% + {\ifnum#1<9 + \char\number\numexpr#1+64\relax + \else\ifnum#1<26 + \char\number\numexpr#1+65\relax + \fi\fi} + +%D List with the commands for the user interface + +\def\go!commands + {newboard,saveboard,useboard,drawboard,marker,stone,move,line,arrow} + +\def\go!copygamecommands + {\expanded{\copyparameters[][go!][\go!commands]}} + +\setvalue{\e!begin\????gm\????gm\v!go}% + {\go!copygamecommands + \go!backgroundcolor + \go!backgroundimage + \go!boardsize % should I set the size with \newboard? + \go!boardvalues + \go!inputtype} % input has to be the last command + +\def\go!inputtype + {\doif{\gameparameter\c!option}\v!sgf\go!inputtype!sgf} + +\def\go!inputtype!sgf + {\grabuntil{\e!stop\currentname}\dogo!inputtype!sgf} + +\def\dogo!inputtype!sgf#1% + {\newboard + \parsesgf{#1}% + \drawboard + \dostopgame} + +\defineoverlay[overlay:go][\overlaybutton{JS(Walk_Field{games!go})}] + +\setvalue{\e!end\????gm\????gm\v!go}% + {\doif{\gameparameter\c!interactive}\v!yes\go!fieldstack} + +\def\go!fieldstack + {\expanded{\definefieldstack[games!go][\go!list!symbols][\c!frame=\v!off]}% + \framed + [\c!frame=\v!off, + \c!background={foreground,overlay:go}, + \c!offset=\v!overlay] + {\fieldstack[games!go]}} + +\def\go!backgroundcolor + {\doifsomethingelse{\gameparameter\c!backgroundcolor} + {\ctxlua{thirddata.games.go.setup['backgroundcolor'] = '\gameparameter\c!backgroundcolor' }}% + {\ctxlua{thirddata.games.go.setup['backgroundcolor'] = nil }}} + +\def\go!backgroundimage % use groups to keep the dimensions local + {\doifsomethingelse{\gameparameter\c!backgroundimage} + {\ctxlua{thirddata.games.go.setup['backgroundimage'] = '\gameparameter\c!backgroundimage' }% + \getfiguredimensions[\gameparameter\c!backgroundimage][scale=500]% I need a scale parameter + \ctxlua{thirddata.games.go.setup.figurewidth = \number\dimexpr\figurewidth \relax }% + \ctxlua{thirddata.games.go.setup.figureheight = \number\dimexpr\figureheight\relax }}% + {\ctxlua{thirddata.games.go.setup.backgroundimage = nil }}} + +\def\go!boardsize + {\assignvalue{\gameparameter\c!size}\go!board!size{9}{13}{19}% size is only used for hoshi points + \assignvalue{\gameparameter\c!nx }\go!board!nx {9}{13}{19}% + \assignvalue{\gameparameter\c!ny }\go!board!ny {9}{13}{19}% + \ctxlua{thirddata.games.go.setup.board = \number\go!board!size }% + \ctxlua{thirddata.games.go.setup.nx = \number\go!board!nx }% + \ctxlua{thirddata.games.go.setup.ny = \number\go!board!ny }} + +\def\go!boardvalues + {\startlua + thirddata.games.go.setup.dx = \number\dimexpr\gameparameter\c!dx\relax ; + thirddata.games.go.setup.dy = \number\dimexpr\gameparameter\c!dy\relax ; + thirddata.games.go.setup.offset = \number\dimexpr\gameparameter\c!frameoffset\relax ; + thirddata.games.go.setup.labeldistance = \number\dimexpr\gameparameter\c!labeldistance\relax ; + thirddata.games.go.setup.stonesize = \number\dimexpr\gameparameter\c!stonesize\relax ; + thirddata.games.go.setup.symbolset = '\gameparameter\c!symbolset' ; + \stoplua} + +%D User command with protected names + +\def\go!newboard + {\ctxlua{thirddata.games.go.board_new()}% + \doif{\gameparameter\c!interactive}\v!yes\go!symbol} % too early, I should take care of \stone + +\def\go!saveboard#1% + {\ctxlua{thirddata.games.go.board_copy( 0, '#1' )}} + +\def\go!useboard#1% + {\ctxlua{thirddata.games.go.board_copy( '#1', 0 )}} + +\def\go!drawboard + {\doifnot{\gameparameter\c!interactive}\v!yes + {\go!setboard{0}% + \go!getboard{0}}} + +\def\go!setboard#1% + {\ctxlua{thirddata.games.go.board_draw("games:go:#1")}} + +\def\go!getboard#1% + {\useMPgraphic{games:go:#1}} + +\def\go!marker + {\dodoubleempty\dogo!marker} + +\def\dogo!marker[#1][#2]#3#4% + {\ifsecondargument % needed for labels + \ctxlua{thirddata.games.go.field[0][#3][#4]['label'] = '#2' }% + \fi + \ctxlua{thirddata.games.go.field[0][#3][#4]['marker'] = '#1' }} + +\def\go!stone[#1]#2#3% + {\bgroup % keep \stonecolor as local command, this is no problem because Lua calls are global + \processaction + [#1] + [\v!black=>\chardef\stonecolor\plusone, + \v!white=>\chardef\stonecolor\plustwo]% + \ctxlua{thirddata.games.go.field[0][#2][#3]['color'] = \number\stonecolor }% + \ctxlua{thirddata.games.go.lastcolor = \number\stonecolor }% + \doif{\gameparameter\c!calculate}\v!yes{\ctxlua{thirddata.games.go.deadstone.processtones()}}% + \egroup} + +\def\go!move + {\dosingleempty\dogo!move} + +\def\dogo!move[#1]#2#3% + {\iffirstargument + \go!stone[#1]{#2}{#3}% + \fi + \doif{\gameparameter\c!interactive}\v!yes\go!symbol} + +\newcount\go!count!symbols + +\let\go!list!symbols\empty + +\def\go!symbol + {\expanded{\advance\go!count!symbols\plusone}% + \expanded{\go!setboard{\number\go!count!symbols}}% + \expanded{\definesymbol[go!symbol!\number\go!count!symbols][\noexpand\go!getboard{\number\go!count!symbols}]}% + \expanded{\appendtocommalist{go!symbol!\number\go!count!symbols}}\go!list!symbols} + +\def\go!line#1#2#3#4% + {\ctxlua{thirddata.games.go.line(#1,#2,#3,#4)}} + +\def\go!arrow#1#2#3#4% + {\ctxlua{thirddata.games.go.arrow(#1,#2,#3,#4)}} + +%D Stones + +% simple/pure style + +\starttexdefinition go:stone:pure:black #1#2#3 + fill fullcircle scaled #1 shifted (#2,#3) ; + draw fullcircle scaled #1 shifted (#2,#3) ; +\stoptexdefinition + +\starttexdefinition go:stone:pure:white #1#2#3 + fill fullcircle scaled (#1-.2) shifted (#2,#3) withcolor white ; + draw fullcircle scaled (#1-.2) shifted (#2,#3) ; +\stoptexdefinition + +% complex/shade style + +\starttexdefinition go:stone:shade:black #1#2#3 +circular_shade ( fullcircle scaled (#1+.4) shifted (#2,#3) , 4 , .8white , black ) ; +\stoptexdefinition + +\starttexdefinition go:stone:shade:white #1#2#3 +circular_shade ( fullcircle scaled (#1+.4) shifted (#2,#3) , 2 , .8white , white ) ; +\stoptexdefinition + +%D Marker + +% #1 = nx +% #2 = ny +% #3 = dx +% #4 = dy +% #5 = stonesize +% #6 = hoffset +% #7 = voffset +% #8 = frameoffset + +\starttexdefinition go:marker:circle #1#2#3#4#5#6#7#8 + draw fullcircle scaled (0.6*#5) shifted (#6,#7) ; +\stoptexdefinition + +\starttexdefinition go:marker:square #1#2#3#4#5#6#7#8 + draw fullsquare scaled (sqrt(2)*(#5-.4)/2) shifted (#6,#7) ; +\stoptexdefinition + +\starttexdefinition go:marker:cross #1#2#3#4#5#6#7#8 + draw (((-(#5-.4)/2,0)--((#5-.4)/2,0)) rotated -45) shifted (#6,#7) ; + draw (((-(#5-.4)/2,0)--((#5-.4)/2,0)) rotated +45) shifted (#6,#7) ; +\stoptexdefinition + +\starttexdefinition go:marker:triangle #1#2#3#4#5#6#7#8 + draw (origin--((3*(#5-.4))/(2*sqrt(3)),0)--((3*(#5-.4))/(2*sqrt(3)),0) rotated 60--cycle) shifted (#6-(3*(#5-.4))/(2*sqrt(3))/2,#7-(#5-.4)/4) ; +\stoptexdefinition + +\starttexdefinition go:marker:select #1#2#3#4#5#6#7#8 + width := #1*#2+2*#8 ; % I have to do this + height := #2*#4+2*#8 ; % in a better way + board := currentpicture ; + currentpicture := nullpicture ; + mine := unitsquare xyscaled (width,height) shifted (-#8,-#8) -- reverse % + fullsquare scaled sqrt(5*4mm) shifted (#6,#7)--cycle ; + clip board to mine ; + currentpicture := board ; + fill fullsquare scaled sqrt(2.5*4mm) shifted (#6,#7) ; +\stoptexdefinition + +\starttexdefinition go:marker:hash #1#2#3#4#5#6#7#8 + % make a hole in the board, should only be done if no stone is on this position + width := #1*#3+2*#8 ; % I have to do this + height := #2*#4+2*#8 ; % in a better way + board := currentpicture ; + currentpicture := nullpicture ; + mine := unitsquare xyscaled (width,height) shifted (-#8,-#8) -- reverse % + fullsquare scaled sqrt(5*4mm) shifted (#6,#7) -- cycle ; + clip board to mine ; + currentpicture := board ; + % draw the pattern + board := currentpicture ; + currentpicture := nullpicture ; + for i=-5 upto 5: + draw ((sqrt((#2**2)/2)*i*.25,-5mm)--(sqrt((#2**2)/2)*i*.25,5mm)) rotated - 45 shifted (#6,#7) ; + endfor ; % why do I need a simikolon here, it worked in MPdrawing without them (related to obeylines in texdefintion?) + clip currentpicture to fullsquare xyscaled (#2,#4) shifted (#6,#7) ; + addto board also currentpicture ; + currentpicture := board ; +\stoptexdefinition + +\starttexdefinition go:marker:label #1#2#3 + label(textext("\doattributes{\????gm\currentgame}{style}{color}{#1}"),(#2,#3)) ; +\stoptexdefinition + +\starttexdefinition go:marker:label #1#2#3 + label(textext("\doattributes{\????gm\currentgame}{style}{color}{#1}"),(#2,#3)) ; +\stoptexdefinition + +\starttexdefinition go:marker:hoshi #1#2#3 + fill fullcircle scaled #1 shifted (#2,#3) ; +\stoptexdefinition + +%D Hoshi points + +\def\definehoshi #1 #2 #3 + {\resetvalue{go:hoshi:#2:#3:#1}} + +% #1 = boardsize +% #1 = column +% #3 = row + +%D small board: 9 + +\definehoshi 9 3 3 +\definehoshi 9 3 7 +\definehoshi 9 5 5 +\definehoshi 9 7 3 +\definehoshi 9 7 7 + +%D medium board: 13 + +\definehoshi 13 4 4 +\definehoshi 13 4 10 +\definehoshi 13 7 7 +\definehoshi 13 10 4 +\definehoshi 13 10 10 + +%D big board: 19 + +\definehoshi 19 4 4 +\definehoshi 19 4 10 +\definehoshi 19 4 16 +\definehoshi 19 10 4 +\definehoshi 19 10 10 +\definehoshi 19 10 16 +\definehoshi 19 16 4 +\definehoshi 19 16 10 +\definehoshi 19 16 16 + +%D Mapping from SGF code to TeX commands + +\def\sgfflush#1{\ctxlua{thirddata.games.sgf.parse("#1")}} + +\def\sgfnumber#1% + {\ifnum`#1>105 + \number\numexpr`#1-97\relax + \else\ifnum`#1>96 + \number\numexpr`#1-96\relax + \else\ifnum`#1<73 + \number\numexpr`#1-39\relax + \else + \number\numexpr`#1-40\relax + \fi\fi\fi} + +\def\convertsgfnumber#1#2\relax + {\edef\valuea{\sgfnumber{#1}}% + \edef\valueb{\sgfnumber{#1}}} + +\starttexdefinition parsesgf #1 + \sgfflush{#1} +\stoptexdefinition + +\starttexdefinition sgf!node #1 + \sgfflush{#1} +\stoptexdefinition + +\starttexdefinition sgf!white #1 + \expandafter\convertsgfnumber#1\relax + \move[white]\valuea\valueb +\stoptexdefinition + +\starttexdefinition sgf!black #1 + \expandafter\convertsgfnumber#1\relax + \move[black]\valuea\valueb +\stoptexdefinition + +\starttexdefinition sgf!addwhite #1 + \expandafter\convertsgfnumber#1\relax + \stone[white]\valuea\valueb +\stoptexdefinition + +\starttexdefinition sgf!comment #1 + % no output +\stoptexdefinition + +%D Lua functions are saved in a separate file + +\ctxloadluafile{games-go}{} + +%D Setup for the default values + +\setupgame % \setupgame[go] == \setupgoban + [\v!go] + [\c!size=\v!medium, + \c!stonesize=.92\bodyfontsize, + \c!nx=\gameparameter\c!size, + \c!ny=\gameparameter\c!size, + \c!dx=\bodyfontsize, + \c!dy=\gameparameter\c!dx, + \c!style=\txx, + \c!color=, + \c!labelstyle=\txx, + \c!labelcolor=, + \c!symbolset=\v!pure, % \v!shade + \c!labeldistance=.25\bodyfontsize, + \c!frameoffset=2\bodyfontsize, + \c!interactive=\v!no, + \c!calculate=\v!no, + \c!option=\v!tex, + \c!backgroundcolor=, + \c!backgroundimage=] + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/third/games/games-hex.lua b/Master/texmf-dist/tex/context/third/games/games-hex.lua new file mode 100644 index 00000000000..b8aee372d42 --- /dev/null +++ b/Master/texmf-dist/tex/context/third/games/games-hex.lua @@ -0,0 +1,90 @@ +if not modules then modules = { } end modules ['games-hex'] = { + version = 1.000, + comment = "Hex", + author = "Wolfgang Schuster", + copyright = "Wolfgang Schuster", + email = "schuster.wolfgang@googlemail.com", + license = "Public Domain" +} + +do + +thirddata = thirddata or { } +thirddata.games = thirddata.games or { } +thirddata.games.hex = thirddata.games.hex or { } +thirddata.games.hex.setup = thirddata.games.hex.setup or { } + +local nx = function() return thirddata.games.hex.setup.nx end +local ny = function() return thirddata.games.hex.setup.ny end +local dx = function() return thirddata.games.hex.setup.dx end +local dy = function() return thirddata.games.hex.setup.dy end +local offset = function() return thirddata.games.hex.setup.offset end +local size = function() return thirddata.games.hex.setup.size end +local distance = function() return thirddata.games.hex.setup.distance end +local bp = function(value) return number.tobasepoints(value) end +local sp = function(value) return value * 65536/(7227/7200) end + +function thirddata.games.hex.board_new() + thirddata.games.hex.field = { } + for col=1,nx() do + thirddata.games.hex.field[col] = { } + for row=1,ny() do + thirddata.games.hex.field[col][row] = { color = 0 } + end + end +end + +function thirddata.games.hex.board_lines() + for row=1,ny() do + for col=1,ny() do + tex.sprint("draw (") + for rot=0,5 do + tex.sprint("(" .. bp(size()) .. ",0) rotated (" .. rot*60+90 .. ") --") + end + tex.sprint("cycle) shifted (" .. bp(math.cos(math.pi/6)*size()*(2*(col-1)+(row-1))) .. "," .. bp(-size()*1.5*(row-1)) .. ") ; ") + end + end +end + +function thirddata.games.hex.board_labels() + for col=1,nx() do + tex.sprint('label.top(textext("\\doattributes{@@@@gmhex}{labelstyle}{labelcolor}{\\sgfchar{' .. col .. '}}"),%') + tex.sprint('(' .. bp(-(size()+distance())*math.tan(math.pi/6)+2*(col-1)*math.cos(math.pi/6)*size()) .. ',' .. bp(size()+distance()) .. ')) ;') + end + for row=1,ny() do + tex.sprint('label.lft(textext("\\doattributes{@@@@gmhex}{labelstyle}{labelcolor}{' .. row .. '}"),%') + tex.sprint('(' .. bp(-math.cos(math.pi/6)*size()-distance()+(row-1)*math.cos(math.pi/6)*size()) .. ',' .. bp(-1.5*(row-1)*size()) .. ')) ;') + end +end + +function thirddata.games.hex.board_stones() + local color = function(x,y) return thirddata.games.hex.field[x][y]['color'] end + for col=1,nx() do + for row=1,ny() do + if color(col,row)==1 then + thirddata.games.hex.stone(math.cos(math.pi/6)*size()*(2*(col-1)+(row-1)),-size()*1.5*(row-1),"red") + elseif color(col,row)==2 then + thirddata.games.hex.stone(math.cos(math.pi/6)*size()*(2*(col-1)+(row-1)),-size()*1.5*(row-1),"blue") + end + end + end +end + +function thirddata.games.hex.stone(x,y,color) + tex.sprint("fill (") + for rot=0,5 do + tex.sprint("(" .. bp(size()) .. ",0) rotated (" .. rot*60+90 .. ") --") + end + tex.sprint("cycle) shifted (" .. bp(x) .. "," .. bp(y) .. ")") + tex.sprint("withcolor \\MPcolor{" .. color .. "} ;") +end + +function thirddata.games.hex.board_draw(name) + tex.sprint("\\startuniqueMPgraphic{" .. name .. "}{}") + thirddata.games.hex.board_stones() + thirddata.games.hex.board_lines() + thirddata.games.hex.board_labels() + tex.sprint("\\stopuniqueMPgraphic") +end + +end diff --git a/Master/texmf-dist/tex/context/third/games/games-hex.tex b/Master/texmf-dist/tex/context/third/games/games-hex.tex new file mode 100644 index 00000000000..e03554a16fa --- /dev/null +++ b/Master/texmf-dist/tex/context/third/games/games-hex.tex @@ -0,0 +1,119 @@ +%D \module +%D [ file=games-hex, +%D version=2008.10.29, +%D title=\CONTEXT\ User Module, +%D subtitle=Hex, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D email=schuster.wolfgang@googlemail.com, +%D copyright=Wolfgang Schuster] + +\writestatus{loading}{Context User Module / Games - Hex} + +\unprotect + +\definegame[\v!hexgame][\v!hex] + +\def\sgfchar#1% + {\ifnum#1<9 + \char\number\numexpr#1+64\relax + \else\ifnum#1<26 + \char\number\numexpr#1+65\relax + \fi\fi} + +\def\hex!commands + {newboard,drawboard,player} + +\def\hex!copygamecommands + {\expanded{\copyparameters[][hex!][\hex!commands]}} + +\setvalue{\e!begin\????gm\????gm\v!hex}% + {\hex!copygamecommands + \hex!boardsize + \hex!gamevalues} + +\defineoverlay[overlay:hex][\overlaybutton{JS(Walk_Field{games!hex})}] + +\setvalue{\e!end\????gm\????gm\v!hex}% + {\doif{\gameparameter\c!interactive}\v!yes\hex!fieldstack} + +\def\hex!fieldstack + {\expanded{\definefieldstack[games!hex][\hex!list!symbols][\c!frame=\v!off]}% + \framed + [\c!frame=\v!off, + \c!background={foreground,overlay:hex}, + \c!offset=\v!overlay] + {\fieldstack[games!hex]}} + +\def\hex!boardsize % what are common values for hex + {\assignvalue{\gameparameter\c!nx}\hex!board!nx{11}{14}{19}% + \assignvalue{\gameparameter\c!ny}\hex!board!ny{11}{14}{19}% + \ctxlua{thirddata.games.hex.setup.nx = \number\hex!board!nx }% + \ctxlua{thirddata.games.hex.setup.ny = \number\hex!board!ny }} + +\def\hex!gamevalues + {\startlua + thirddata.games.hex.setup.size = \number\dimexpr\gameparameter\c!stonesize\relax ; + thirddata.games.hex.setup.dx = \number\dimexpr\gameparameter\c!dx\relax ; + thirddata.games.hex.setup.dy = \number\dimexpr\gameparameter\c!dy\relax ; + thirddata.games.hex.setup.offset = \number\dimexpr\gameparameter\c!frameoffset\relax ; + thirddata.games.hex.setup.distance = \number\dimexpr\gameparameter\c!labeldistance\relax ; + \stoplua} + +%D User commands + +\def\hex!newboard + {\ctxlua{thirddata.games.hex.board_new()}} + +\def\hex!drawboard + {\doifnot{\gameparameter\c!interactive}\v!yes + {\hex!setboard{0}% + \hex!getboard{0}}} + +\def\hex!setboard#1% + {\ctxlua{thirddata.games.hex.board_draw("games:hex:#1")}} + +\def\hex!getboard#1% + {\uniqueMPgraphic{games:hex:#1}} + +\def\hex!player[#1]#2#3% + {\bgroup + \processaction + [#1] + [ \v!red=>\chardef\stonecolor\plusone, + \v!blue=>\chardef\stonecolor\plustwo]% + \ctxlua{thirddata.games.hex.field[#2][#3] = { color = \number\stonecolor }}% + \egroup + \doif{\gameparameter\c!interactive}\v!yes\hex!symbol} + +\newcount\hex!count!symbols + +\let\hex!list!symbols\empty + +\def\hex!symbol + {\expanded{\advance\hex!count!symbols\plusone}% + \expanded{\hex!setboard{\number\hex!count!symbols}}% + \expanded{\definesymbol[hex!symbol!\number\hex!count!symbols][\noexpand\hex!getboard{\number\hex!count!symbols}]}% + \expanded{\appendtocommalist{hex!symbol!\number\hex!count!symbols}}\hex!list!symbols} + +%D Lua functions + +\ctxloadluafile{games-hex}{} + +%D Default values + +\setupgame + [\v!hex] + [\c!size=\v!small, + \c!nx=\gameparameter\c!size, + \c!ny=\gameparameter\c!size, + \c!stonesize=\bodyfontsize, + \c!dx=\gameparameter\c!stonesize, + \c!dy=\gameparameter\c!dx, + \c!frameoffset=0pt, + \c!labeldistance=0pt, + \c!labelstyle=\tx, + \c!labelcolor=, + \c!interaction=\v!no] + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/third/games/holz280.jpg b/Master/texmf-dist/tex/context/third/games/holz280.jpg new file mode 100644 index 00000000000..9d7f23fc016 Binary files /dev/null and b/Master/texmf-dist/tex/context/third/games/holz280.jpg differ diff --git a/Master/texmf-dist/tex/context/third/games/t-games.tex b/Master/texmf-dist/tex/context/third/games/t-games.tex new file mode 100644 index 00000000000..3cc11617f7a --- /dev/null +++ b/Master/texmf-dist/tex/context/third/games/t-games.tex @@ -0,0 +1,97 @@ +%D \module +%D [ file=t-games, +%D version=2008.10.29, +%D title=\CONTEXT\ User Module, +%D subtitle=Games, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D copyright=Wolfgang Schuster, +%D email=schuster.wolfgang@googlemail.com, +%D license=Public Domain] + +\writestatus{loading}{Context User Module / Games} + +\unprotect + +%D Constants + +\startinterface all + \setinterfaceconstant {labelstyle} {labelstyle} + \setinterfaceconstant {labelcolor} {labelcolor} + \setinterfaceconstant {labeldistance} {labeldistance} + \setinterfaceconstant {stonesize} {stonesize} + \setinterfaceconstant {backgroundimage} {backgroundimage} + \setinterfaceconstant {interactive} {interactive} +\stopinterface + +%D Variables + +\startinterface all + \setinterfacevariable {black} {black} + \setinterfacevariable {white} {white} + \setinterfacevariable {go} {go} + \setinterfacevariable {hex} {hex} + \setinterfacevariable {goban} {goban} + \setinterfacevariable {hexgame} {hexgame} + \setinterfacevariable {red} {red} + \setinterfacevariable {blue} {blue} + \setinterfacevariable {weiqi} {weiqi} + \setinterfacevariable {baduk} {baduk} + \setinterfacevariable {pure} {pure} + \setinterfacevariable {shade} {shade} + \setinterfacevariable {tex} {tex} + \setinterfacevariable {sgf} {sgf} + \setinterfacevariable {chess} {chess} +\stopinterface + +%D Namespace + +\def\????ga{@@@@ga} +\def\????gm{@@@@gm} + +\def\gameparameter#1% + {\csname\????gm\currentgame#1\endcsname} + +%D Game environment, not more than a simple wrapper to load the real +%D environments in the from \type {\????gm\????gm...}. + +\def\dostartgame + {\dotripleempty\dodostartgame} + +\def\dodostartgame[#1][#2][#3]% + {\bgroup + \edef\currentname{#1}% needed for the parser + \edef\currentgame{#2}% I should look for better names + \gameparameter\c!before + \ifsecondargument + \setupgame[#2][#3]% + \fi + \executeifdefined{\e!begin\????gm\????gm\currentgame}{\@EA\gobbleuntil\csname\e!stop\currentname\endcsname}} + +\def\dostopgame + {\executeifdefined{\e!end\????gm\????gm\currentgame}\donothing + \gameparameter\c!after + \egroup} + +\def\definegame + {\dodoubleargument\dodefinegame} + +\def\dodefinegame[#1][#2]% + {\setvalue{\e!start#1}{\dostartgame[#1][#2]}% + \setvalue{\e!stop #1}{\dostopgame}% + \setvalue{\e!setup#1\e!endsetup}{\setupgame[#2]}} + +%D Setup command. + +\def\setupgame + {\dodoubleargument\dosetupgame} + +\def\dosetupgame[#1][#2]% + {\getparameters[\????gm#1][#2]} + +%D Load the games with their own macros. + +\input games-go +\input games-hex + +\protect \endinput -- cgit v1.2.3