\input mftmac
$\9ttt3.mf\par
$\5{mode\_setup};\ \2{if}\1{not}\1{known}\\{screen\_topleft}\?:$\par
$\2{message}\7"screen_topleft undefined, defaults to (-50,300)";$\par
$\2{pair}\\{screen\_topleft};\ \\{screen\_topleft}:=(-50,300);\3{fi};$\par
\BL
A program should cope with inproper inputs, preconditions, etc.,
gracefully.  For example, as said above, I assume that {\tt
screen\_topleft} has been compiled into {\tt mf.base}. If not, I set
it to the value appropriate for the standard {\tt plain.mf} which is
used to creat the base file.  The message is just meant to give the
user a clue, more information could well be given.

Our first task is to draw the `\#' we're going to play on.
First, let's change the origin's position:
currently it is {\tt -xpart screen\_topleft} over from the left edge
and {\tt screen\_rows - ypart screen\_topleft} pixels up from the
bottom edge. To move the origin close to the bottom left corner, we
can set:
\BL
$\\{currenttransform}:=\\{identity}\6{shifted}(20+\1{xpart}$\par
\quad\quad$\\{screen\_topleft},20-\\{screen\_rows}+\1{ypart}\\{screen%
\_topleft});$\par
$\\{ttt}:=\1{min}(\\{screen\_rows},\\{screen\_cols})-40;$\par
\BL
\noindent Now, let's draw the `board' using a for loop. We'll worry
about generalizing later.
\BL
$\2{for}i=1,2\?:\2{draw}(0,i\ast \\{ttt}/3)\8{..}(\\{ttt},i\ast \\{ttt}/3);$\par
$\2{draw}(i\ast \\{ttt}/3,0)\8{..}(i\ast \\{ttt}/3,\\{ttt});\3{endfor};$\par
$\9We will want to do some experimenting now so\par
$\9first save the current picture:\par
$\2{picture}\\{tttboard};\ \\{tttboard}:=\\{currentpicture};$\par
$\2{path}\\{ttto},\\{tttxa},\\{tttxb};$\par
$\\{ttto}:=\\{fullcircle}\6{scaled}(.8\ast \\{ttt}/3)\6{shifted}(\\{ttt}/6,%
\\{ttt}/6);$\par
$\2{draw}\\{ttto};$\par
\BL
\noindent The predefined {\tt fullcircle} is a circle of diameter 1
centered at
the origin. We shift it to the center of the bottom left square after
scaling it to an appropriate size.
\BL
$\\{tttxa}:=(20,20)\8{..}(\\{ttt}/3-20,\\{ttt}/3-20);$\par
$\\{tttxb}:=(20,\\{ttt}/3-20)\8{..}(\\{ttt}/3-20,20);$\par
$\2{draw}\\{tttxa}\6{shifted}(\\{ttt}/3,\\{ttt}/3);$\par
$\2{draw}\\{tttxb}\6{shifted}(\\{ttt}/3,\\{ttt}/3);$\par
$\\{sscreen}(80\\{pt}\SH ,40\\{pt}\SH ,2\\{pt}\SH ,1);$\par
\BL
\font\tttthree=ttt3 scaled 1200
\vglue .7in\line{\hfil\hfil\tttthree A\hfil}\vglue 24pt
Now we're ready to actually play the game. The users need to be able
to 1) start a new game, 2) make a move, and 3) undo a move. Let's have
the user enter two digits to determine this:
\BL
$\2{message}\7"enter 00 to quit, 10 to start new game";$\par
$\2{message}\7"enter 11 to place mark at bottom left square";$\par
$\2{message}\7"enter -33 to erase mark just placed at top right square";$\par
\BL
The erasing is there so the user won't get frustrated by careless
mistakes. The program will alternate the marks, starting with an
`X'.  I purposely use Cartesian coordinates for the position; some
people might prefer {\tt (row,column)} notation.
\BL
$\2{boolean}\\{tttmarkx};\ \\{tttmarkx}:=\5{true};\ \2{string}s;$\par
$\5{screenstrokes};\ \\{currentpicture}:=\\{tttboard};\ \5{showit};$\par
$\2{forever}\?:\2{message}\7"Move? ";\ s:=\5{readstring};$\par
\quad$\\{move}:=\1{round}(\2{scantokens}s);\ \2{exitif}\\{move}=0;$\par
\BL
We make a general loop in which we get input from the players and then
do the appropriate action. The {\tt numeric} is rounded to an integer;
more error checking could well be done here. Non-count loops are done
by using {\tt forever: $\ldots$exitif $<boolean>\;\ldots$
endfor;} loops.
\BL
\quad$\2{if}(\\{move}=10)\6{or}(\\{move}=1)\?:\\{currentpicture}:=%
\\{tttboard};$\par
\quad\quad$\5{showit};\ \\{tttmarkx}:=\5{false};$\par
\BL
Here we start handling the {\tt move} cases (included an
`undocumented' one). After each `move', we
will change the mark used so the {\tt tttmarkx:=false} is needed here
since we're not actually not making a move.
\BL
\quad$\2{elseif}\\{move}>0\?:$\par
\quad\quad$\\{move}:=\\{move}-11;$\par
\BL
We adjust {\tt move} so that its digits give how much to shift the
mark (in units of {\tt ttt/3}).
\BL
\quad\quad$\2{if}\\{tttmarkx}\?:$\par
\quad\quad\quad$\2{draw}\\{tttxa}\6{shifted}((\\{move}\6{div}10)\ast %
\\{ttt}/3,(\\{move}\6{mod}10)\ast \\{ttt}/3);$\par
\quad\quad\quad$\2{draw}\\{tttxb}\6{shifted}((\\{move}\6{div}10)\ast %
\\{ttt}/3,(\\{move}\6{mod}10)\ast \\{ttt}/3);$\par
\quad\quad$\2{else}\?:$\par
\quad\quad\quad$\2{draw}\\{ttto}\6{shifted}((\\{move}\6{div}10)\ast \\{ttt}/3,(%
\\{move}\6{mod}10)\ast \\{ttt}/3);$\par
\quad\quad$\!\3{fi};\ \9end if tttmarks\par
\BL
Since I'm writing the program using Emacs, the redundancy above needs
little extra typing. It does, of course, waste CPU time so when we
rewrite this, we'll want to change this.
\BL
\quad$\2{else}\?:$\par
\quad\quad$\\{move}:=\1{abs}\\{move};$\par
\quad\quad$\\{move}:=\\{move}-11;$\par
\BL
Recall that when we make a move the mark type flag is changed; thus,
here we want to erase the {\it previous\/} mark type so we say:
\BL
\quad\quad$\2{if}\1{not}\\{tttmarkx}\?:$\par
\quad\quad\quad$\2{undraw}\\{tttxa}\6{shifted}((\\{move}\6{div}10)\ast %
\\{ttt}/3,(\\{move}\6{mod}10)\ast \\{ttt}/3);$\par
\quad\quad\quad$\2{undraw}\\{tttxb}\6{shifted}((\\{move}\6{div}10)\ast %
\\{ttt}/3,(\\{move}\6{mod}10)\ast \\{ttt}/3);$\par
\quad\quad$\2{else}\?:$\par
\quad\quad\quad$\2{undraw}\\{ttto}\6{shifted}((\\{move}\6{div}10)\ast %
\\{ttt}/3,(\\{move}\6{mod}10)\ast \\{ttt}/3);$\par
\quad\quad$\!\3{fi};$\par
\quad$\!\3{fi};\ \9 end if (move=10\par
\BL
Now we flip the mark type and go back through the loop. We only end
the program if {\tt exitif} gets called.
\BL
\quad$\\{tttmarkx}:=\1{not}\\{tttmarkx};$\par
$\!\3{endfor};\3{end}\9quit if we exit the for loop\par
