%tttn.mf
if not known screen_topleft:
 message "screen_topleft undefined, (-50,screen_rows-100) used";
 pair screen_topleft; screen_topleft:=(-50,screen_rows-100); 
fi;
currenttransform:=identity shifted (20+xpart screen_topleft, 
 20-screen_rows + ypart screen_topleft);
ttt:=min(screen_rows, screen_cols)-40;
message "Boardsize? (3,...,9) "; string s; s:=readstring;

%%We won't insure that the user in fact inputs a number. However, we
%%do round it to an integer. Then, if it's too small, we replace it
%%with 3 and if too big, we replace it with 9.

boardsize:=min(9,max(3,round(scantokens s)));
ss:=ttt/boardsize;

%%If a larger boardsize were needed, it would probably be best to change
%%the input scheme.  In the following, we just have to replace {\tt
%%ttt/3} with {\tt ss}, 
%%the {\it squaresize\/} (use Emacs' {\tt query-replace}). There are a
%%few other places we have to change 
%%also, such as the for loop for the board:

m:=3/boardsize; pickup currentpen scaled m;
for i=1 upto boardsize-1: 
 draw (0,i*ss)..(ttt,i*ss);
 draw (i*ss,0)..(i*ss,ttt); 
endfor;
picture tttboard; tttboard:=currentpicture;
path ttto,tttxa,tttxb;
%Changed shift; to keep size 3 board ratios, we scale with m.\]
ttto:=fullcircle scaled (.8*ss) shifted (ss/2,ss/2);
tttxa:=(20*m,20*m)..(ss-20*m,ss-20*m);
tttxb:=(20*m,ss-20*m)..(ss-20*m,20*m);
message "enter 00 to quit, 10 to start new game";
message "enter 11 to place mark at bottom left square";
 tr:=boardsize+10*boardsize;
s:=" to erase mark just placed at top right square";
message "enter "&decimal -tr&s;
boolean tttmarkx; tttmarkx:=true;
screenstrokes; currentpicture:=tttboard; showit;
forever:
 forever: 
  message "Move? "; s:=readstring; move:=scantokens s;
  exitif known move; message "bad input, reenter"; 
 endfor;
 move:=round move; exitif move=0;

%%To make sure that {\tt move} has
%%acceptable data, we round it if known. We've implicitly declared it as
%%numeric; however, {\tt known move} will be false  if it 
%%contains a string token in which case ask for the move again. We
%%haven't prevented the players from placing a marker off the board. If
%%one wanted to do this, the input loop could be expanded to check this.  
%% Let's fix some of the redundancy: 

 mx:=(((abs move) div 10)-1)*ss; my:=(((abs move) mod 10)-1)*ss;
 if (move=10) or (move=1): 
  currentpicture:=tttboard;showit; tttmarkx:=false;
 elseif move>0: 
  if tttmarkx:
   draw tttxa shifted (mx,my);draw tttxb shifted (mx,my);
  else: 
   draw ttto shifted (mx,my); 
  fi;
 else:
  if not tttmarkx:
   undraw tttxa shifted (mx,my);undraw tttxb shifted (mx,my);
  else: 
   undraw ttto shifted (mx,my);
  fi; 
 fi;
 tttmarkx:=not tttmarkx;
endfor;
end;
