home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / go / part04 / go.pas next >
Pascal/Delphi Source File  |  1988-03-09  |  26KB  |  1,001 lines

  1. {---------------------------------------------------------------}
  2. { Go Game Manager                                               }
  3. { Copyright (c) 1982 by Three Rivers Computer Corp.             }
  4. {                                                               }
  5. { Written: June 3, 1982 by Stoney Ballard                       }
  6. { Edit History:                                                 }
  7. {    June  3, 1982 Started                                      }
  8. {    June  4, 1982 Add dead group removal                       }
  9. {    June 10, 1982 Use new go file manager                      }
  10. {    Nov  10, 1982 Extensively Hacked Up                        }
  11. {    Dec  29, 1982 Changed "Erase Branch" to "Prune Branches"   }
  12. {    Jan   6, 1983 Added ^C escape from all readlns             }
  13. {---------------------------------------------------------------}
  14.  
  15. program Go;
  16.  
  17. exports
  18.  
  19. imports stream from stream;
  20.  
  21. procedure resetInput;
  22.  
  23. private
  24.  
  25. imports system from System;
  26. imports raster from raster;
  27. imports screen from screen;
  28. imports popUp from popUp;
  29. imports IO_Others from IO_Others;
  30. imports goCom from goCom;
  31. imports goMgr from goMgr;
  32. imports goTree from goTree;
  33. imports goBoard from goBoard;
  34. imports goMenu from goMenu; 
  35. imports memory from memory;
  36. imports perq_string from perq_string;
  37. imports goPlayer from goPlayer;
  38.  
  39. label
  40.   99;       (* the fatal error point *)
  41.  
  42. var
  43.   oCurPosX, oCurPosY: integer;
  44.   oScreenPtr: rasterPtr;
  45.  
  46.   procedure resetInput;
  47.   begin { resetInput }
  48.     streamKeyboardReset(input);
  49.   end { resetInput };
  50.  
  51.   procedure newTitle;
  52.   var
  53.     ts: string[128];
  54.     fn: string;
  55.     fl, fPos, tPos, i: integer;
  56.   begin { newTitle }
  57.     ts := 'Go  Version ';
  58.     ts := concat(ts, version);
  59.     getFNameString(fn);
  60.     fl := length(fn);
  61.     if fl > 0 then
  62.       begin
  63.         fPos := 81 - fl;
  64.         tPos := length(ts) + 1;
  65.         adjust(ts, 80);
  66.         for i := tPos to 80 do
  67.           ts[i] := ' ';
  68.         for i := fPos to fPos + fl - 1 do
  69.           ts[i] := fn[i - fPos + 1];
  70.       end;
  71.     changeTitle(ts);
  72.   end { newTitle };
  73.  
  74.   procedure initialize;
  75.   var
  76.     sseg: integer;
  77.  
  78.     procedure setupWindows;
  79.     var
  80.       ts: string;
  81.     begin { setupWindows }
  82.       createWindow(boardWin, bWinX, bWinY, bWinW, bWinH, ' ');
  83.       createWindow(menuWin, mWinX, mWinY, mWinW, mWinH, '');
  84.       createWindow(statWin, sWinX, sWinY, sWinW, sWinH, '');      
  85.       changeWindow(0);
  86.       gameFName := '';
  87.       newTitle;
  88.     end { setupWindows };
  89.  
  90.   begin { initialize }
  91.     createSegment(sseg, 192, 1, 192);
  92.     oScreenPtr := makePtr(sseg, 0, rasterPtr);
  93.     SReadCursor(oCurPosX, oCurPosY);
  94.     rasterop(rRpl, 768, 1024, 0, 0, SScreenW, oScreenPtr,
  95.                               0, 0, SScreenW, SScreenP);
  96.     IOSetFunction(CTCursCompl);
  97.     rasterop(RAndNot, 768, 1024, 0, 0, SScreenW, SScreenP,
  98.                                  0, 0, SScreenW, SScreenP);
  99.     setupWindows;
  100.     initMenu;
  101.     captures[black] := 0;
  102.     captures[white] := 0;
  103.     initGoTree;
  104.     initGoBoard;
  105.     makeGoTree;
  106.     initGoMgr;
  107.     gameFName := '';
  108.     numbEnabled := false;
  109.     treeDirty := false;
  110.     playLevel := 0;
  111.     debug := false;
  112.     printLarge := true;
  113.     initGoPlayer;
  114.   end { initialize };
  115.   
  116.   procedure doit;
  117.   var
  118.     done, foundIt, endLoop, gbg: boolean;
  119.     CtlCseen, playMyself, lastWasPass: boolean;
  120.     whoseTurn, whoWasLast: sType;
  121.     i, xi, yi, xs, ys: integer;
  122.     numDead, numHC, cmd: integer;
  123.     lastBuM: integer;
  124.     thisTag: tagPtr;
  125.     lastMove: pMRec;
  126.  
  127.     function getLine(var l: string): boolean;
  128.     label
  129.       1;
  130.     var
  131.       i, j, cx, cy: integer;
  132.  
  133.       handler ctlC;
  134.       begin { ctlC }
  135.         IOKeyClear;
  136.         streamKeyboardReset(input);
  137.         beep(error);
  138.         prompt('');
  139.         l := '';
  140.         getLine := false;
  141.         exit(getLine); 
  142.       end { ctlC }; 
  143.  
  144.       handler pastEOF(fn: pathName);
  145.       begin { pastEOF }
  146.         reset(input, fn);
  147.         sSetCursor(cx, cy);
  148.         write('    ');
  149.         sSetCursor(cx, cy);
  150.         goto 1;
  151.       end { pastEOF };
  152.  
  153.     begin { getLine }
  154.       sReadCursor(cx, cy);
  155.     1:
  156.       readln(l);
  157.       getLine := true;
  158.       j := 0;
  159.       for i := 1 to length(l) do
  160.         if ord(l[i]) >= 32 then
  161.           begin
  162.             j := j + 1;
  163.             l[j] := l[i];
  164.           end;
  165.       adjust(l, j);
  166.     end { getLine };
  167.  
  168.     procedure resetGame;
  169.     begin { resetGame }
  170.       clearBoard;
  171.       koX := -1;
  172.       koY := -1;
  173.       moveNum := 0;
  174.       curMove := treeRoot;
  175.       captures[black] := 0;
  176.       captures[white] := 0; 
  177.       showCaptures;
  178.       whoseTurn := black;
  179.       turnIs(black);
  180.       gameFname := '';
  181.       newTitle;
  182.       gameOver := false;
  183.       initGoMgr;
  184.     end { resetGame };
  185.  
  186.     procedure switchWho;
  187.     begin { switchWho }
  188.       if curMove = treeRoot then
  189.         whoseTurn := black
  190.       else if curMove^.id = remove then
  191.         whoseTurn := curMove^.who
  192.       else if curMove^.id = hcPlay then
  193.         whoseTurn := white
  194.       else if curMove^.who = black then
  195.         whoseTurn := white
  196.       else
  197.         whoseTurn := black;
  198.       turnIs(whoseTurn);
  199.     end { switchWho };
  200.  
  201.     procedure updateStatus;
  202.     begin { updateStatus }
  203.       dotLast;
  204.       showCaptures;
  205.       showComment;
  206.       showTag;
  207.       switchWho;
  208.     end { updateStatus };
  209.  
  210.     procedure doReadGame;
  211.     var
  212.       fName: pathName;
  213.  
  214.       handler badFileVersion;
  215.       begin { badFileVersion }
  216.         beep(error);
  217.         prompt('');
  218.         write(gameFName, ' is not compatable with this version of GO');
  219.         resetGame;
  220.         exit(doReadGame);
  221.       end { badFileVersion };
  222.  
  223.     begin { doReadGame }
  224.       if menuGoFile(fName) then
  225.         begin
  226.           prompt('Reading ');
  227.           write(fName, '.Go ...');
  228.           readTree(concat(fName, '.GO'));
  229.           resetGame;
  230.           gameFName := fName;
  231.           if treeRoot^.lastMove <> nil then
  232.             switchBranch(treeRoot^.lastMove);
  233.           treeDirty := false;
  234.           prompt('');
  235.           newTitle;
  236.         end;
  237.     end { doReadGame };
  238.  
  239.     procedure doWriteGame;
  240.     var
  241.       fs: string;
  242.       procedure addExt(var nam: string);
  243.       var
  244.         es: string;
  245.       begin { addExt }
  246.         if length(nam) > 3 then
  247.           begin
  248.             es := substr(nam, length(nam) - 2, 3);
  249.             convUpper(es);
  250.             if es <> '.GO' then
  251.               nam := concat(nam, '.Go');
  252.           end
  253.         else
  254.           nam := concat(nam, '.Go');
  255.       end { addExt };
  256.  
  257.       handler badGoWrite;
  258.       begin { badGoWrite };
  259.         beep(error);
  260.         prompt('Unable to write file ');
  261.         write(fs);
  262.         exit(doWriteGame);
  263.       end { badGoWrite };
  264.  
  265.     begin { doWriteGame }
  266.       IOKeyClear;
  267.       streamKeyboardReset(input);
  268.       if gameFName <> '' then
  269.         begin
  270.           prompt('Game File Name [');
  271.           write(gameFName, ']? ');
  272.         end
  273.       else
  274.         prompt('Game File Name? ');
  275.       if not getLine(fs) then
  276.         exit(doWriteGame);
  277.       if fs = '' then
  278.         if gameFName = '' then
  279.           begin
  280.             beep(error);
  281.             prompt('');
  282.             exit(doWriteGame);
  283.           end
  284.         else
  285.           fs := gameFName;
  286.       gameFName := fs;
  287.       addExt(fs);
  288.       prompt('Writing ');
  289.       write(fs, ' ...');
  290.       writeTree(fs, curMove);
  291.       treeDirty := false;
  292.       prompt('');
  293.       newTitle;
  294.     end { doWriteGame };
  295.  
  296.     function chooseAlt: boolean;
  297.     label
  298.       10;
  299.     var
  300.       bx, by, xs, ys: integer;
  301.       tm: pMRec;
  302.       hc0There: boolean;
  303.       hcMenu: pNameDesc;
  304.       res: resres;
  305.       numHC, i, j, numNHC: integer;
  306.  
  307.       handler outside;
  308.       begin { outside }
  309.         destroyNameDesc(hcMenu);
  310.         chooseAlt := false;
  311.         beep(error);
  312.         restoreCursor;
  313.         exit(chooseAlt);
  314.       end { outside };
  315.  
  316.     begin { chooseAlt }
  317.       chooseAlt := false;
  318.       switchWho;
  319.       waitNoButton;
  320.       tm := curMove^.flink;
  321.       numHC := 0;
  322.       numNHC := 0;
  323.       hc0There := false;
  324.       while tm <> nil do
  325.         begin
  326.           if tm^.id = hcPlay then
  327.             numHC := numHC + 1
  328.           else
  329.             begin
  330.               hc0There := true;
  331.               numNHC := numNHC + 1;
  332.             end;
  333.           tm := tm^.slink;
  334.         end;
  335.       if numHC > 0 then
  336.         begin
  337.           if hc0There then
  338.             numHC := numHC + 1;
  339.           allocNameDesc(numHC, 0, hcMenu);
  340.           hcMenu^.header := 'Handicap Alternates';
  341.           j := 1;
  342.           if hc0There then
  343.             begin
  344.               hcMenu^.commands[1] := '0';
  345.               j := 2;
  346.             end;
  347.           tm := curMove^.flink;
  348.           for i := j to numHC do
  349.             begin
  350.               while tm^.id <> hcPlay do
  351.                 tm := tm^.slink;
  352.     {$R-}
  353.               hcMenu^.commands[i] := ' ';
  354.               hcMenu^.commands[i][1] := chr(tm^.hcNum + ord('0'));
  355.     {$R=}
  356.               tm := tm^.slink;
  357.             end;
  358.           menu(hcMenu, false, 1, numHC, -1, -1, -1, res);
  359.           restoreCursor;
  360.           destroyNameDesc(hcMenu);
  361.           i := res^.indices[1];
  362.           destroyRes(res);
  363.           if hc0There then
  364.             if i = 1 then
  365.               begin
  366.                 if numNHC > 1 then
  367.                   goto 10;
  368.                 tm := curMove^.flink;
  369.                 while tm^.id <> move do
  370.                   tm := tm^.slink;
  371.                 forwardTo(tm);
  372.                 chooseAlt := true;
  373.                 exit(chooseAlt);
  374.               end
  375.             else
  376.               i := i - 1;
  377.           tm := curMove^.flink;
  378.           j := 0;
  379.           repeat
  380.             while tm^.id <> hcPlay do
  381.               tm := tm^.slink;
  382.             j := j + 1;
  383.             if j <> i then
  384.               tm := tm^.slink;
  385.           until j = i;
  386.           forwardTo(tm);
  387.           chooseAlt := true;
  388.         end
  389.       else
  390.         begin
  391.   10:
  392.           showAlts;
  393.           waitButton;
  394.           if passLocCur(tabRelX, tabRelY) then
  395.             begin
  396.               if passIsAlt then
  397.                 begin
  398.                   selPass;
  399.                   chooseAlt := true;
  400.                   waitNoButton;
  401.                   exit(chooseAlt);
  402.                 end;
  403.             end
  404.           else if bLocCur(tabRelX, tabRelY, bx, by, xs, ys) then
  405.             if board[bx][by].val = alternate then
  406.               begin
  407.                 selAlt(bx, by);
  408.                 chooseAlt := true;
  409.                 waitNoButton;
  410.                 exit(chooseAlt);
  411.               end;
  412.           remAlts;
  413.           beep(error);
  414.         end;
  415.       waitNoButton;
  416.     end { chooseAlt };
  417.  
  418.     procedure mForward;
  419.     var
  420.       gbg: boolean;
  421.     begin { mForward }
  422.       if gameOver then
  423.         restoreDead;
  424.       if atLeaf(curMove) then
  425.         beep(error)
  426.       else if atBranch(curMove) then
  427.         gbg := chooseAlt
  428.       else
  429.         forwardTo(curMove^.flink);
  430.     end { mForward };
  431.  
  432.     procedure doBkToS;
  433.     var
  434.       bx, by, sx, sy: integer;
  435.     begin { doBkToS }
  436.       prompt('Point at stone to backup to');
  437.       waitButton;
  438.       if bLocCur(tabRelX, tabRelY, bx, by, xs, ys) then
  439.         if board[bx][by].val <> empty then
  440.           begin
  441.             while not lastPlayAt(bx, by) do
  442.               backup1;
  443.             exit(doBkToS);
  444.           end;
  445.       beep(error);
  446.       waitNoButton;
  447.     end { doBkToS };
  448.  
  449.     procedure doPutTag;
  450.     var
  451.       ts: tagStr;
  452.       cm: pMRec;
  453.     begin { doPutTag }
  454.       if curMove = treeRoot then
  455.         beep(error)
  456.       else
  457.         begin
  458.           IOKeyClear;
  459.           streamKeyboardReset(input);
  460.           prompt('Tag String: ');
  461.           if not getLine(ts) then
  462.             exit(doPutTag);
  463.           if length(ts) > maxTagLen then
  464.             begin
  465.               beep(error);
  466.               prompt('Tags may be no longer than ');
  467.               write(maxTagLen:0, ' characters');
  468.             end
  469.           else if length(ts) = 0 then
  470.             begin
  471.               if curMove^.tag = nil then
  472.                 begin
  473.                   beep(error);
  474.                   prompt('');
  475.                 end
  476.               else
  477.                 begin
  478.                   delTag(curMove^.tag);
  479.                   prompt('Tag Deleted');
  480.                 end;
  481.             end
  482.           else if tagExists(ts) then
  483.             begin
  484.               beep(error);
  485.               prompt('That tag already exists');
  486.             end
  487.           else
  488.             begin
  489.               tagMove(curMove, ts);
  490.             end;
  491.         end;
  492.     end { doPutTag };
  493.  
  494.     procedure doGoToTag;
  495.     var
  496.       thisTag: tagPtr;
  497.     begin { doGoToTag }
  498.       thisTag := getTagMenu;
  499.       if thisTag <> nil then  
  500.         switchBranch(thisTag^.mPtr);
  501.     end { doGoToTag };
  502.  
  503.     procedure doPutCmt;
  504.     var
  505.       cs, curCmt: string;
  506.     begin { doPutCmt }
  507.       IOKeyClear;
  508.       streamKeyboardReset(input);
  509.       prompt('Comment: ');
  510.       if not getLine(cs) then
  511.         exit(doPutCmt);
  512.       if length(cs) = 0 then
  513.         if getComment(curMove, curCmt) then
  514.           prompt('Comment Deleted')
  515.         else
  516.           begin
  517.             beep(error);
  518.             prompt('');
  519.           end;
  520.       commentMove(curMove, cs);
  521.     end { doPutCmt };
  522.  
  523.     procedure doScore;
  524.     var
  525.       wScore, bScore, wr, br: integer;
  526.       done: boolean;
  527.       bx, by, xs, ys: integer;
  528.     begin { doScore }
  529.       putEnd;
  530.       done := false;
  531.       prompt('Point at dead groups, Press outside of board to stop');
  532.       repeat
  533.         waitButton;
  534.         if bLocCur(tabRelX, tabRelY, bx, by, xs, ys) then
  535.           begin
  536.             if board[bx, by].val <> empty then
  537.               delGroup(bx, by);
  538.           end
  539.         else
  540.           done := true;
  541.         showCaptures;
  542.         waitNoButton;
  543.       until done;
  544.       prompt('Counting Score ...');
  545.       scoreGame(wScore, bScore);
  546.       wScore := wScore - captures[black];
  547.       bScore := bScore - captures[white];
  548.       if wScore < 0 then
  549.         begin
  550.           wr := -wScore;
  551.           wScore := 0;
  552.         end
  553.       else
  554.         wr := 0;
  555.       if bScore < 0 then
  556.         begin
  557.           br := -bScore;
  558.           bScore := 0;
  559.         end
  560.       else
  561.         br := 0;
  562.       bScore := bScore + wr;
  563.       wScore := wScore + br;
  564.       prompt('Score is: ');
  565.       write('White = ', wScore:0, ', Black = ', bScore:0);
  566.       if wScore = bScore then
  567.         write(' - A Tie!')
  568.       else if wScore > bScore then
  569.         write(' - White Wins by ', (wScore - bScore):0)
  570.       else
  571.         write(' - Black Wins by ', (bScore - wScore):0)
  572.     end { doScore };
  573.  
  574.     procedure doEraseMove;
  575.     var
  576.       lm: pMRec;
  577.     begin { doEraseMove }
  578.       if gameOver then
  579.         restoreDead;
  580.       if curMove = treeRoot then
  581.         beep(error)
  582.       else
  583.         begin
  584.           lm := curMove;
  585.           backup1;
  586.           lm := delBranch(lm);
  587.           treeDirty := true;
  588.         end;
  589.     end { doEraseMove };
  590.  
  591.     procedure doPruneBranches;
  592.     var
  593.       lm, sm, tm: pMRec;
  594.       tp: tagPtr;
  595.       didPrune: boolean;
  596.     begin { doPruneBranches }
  597.       if gameOver then
  598.         restoreDead;
  599.       if not isBranch(curMove) then
  600.         beep(error)
  601.       else if not confirmed then
  602.         beep(error)
  603.       else
  604.         begin
  605.           didPrune := false;
  606.           wipeTreeMarks;
  607.           lm := curMove;
  608.           while lm <> treeRoot do
  609.             begin
  610.               lm^.mark := true;
  611.               lm := lm^.blink;
  612.             end;
  613.           tp := treeRoot^.lastTag;
  614.           while tp <> nil do
  615.             begin
  616.               lm := tp^.mPtr;
  617.               while lm <> treeRoot do
  618.                 begin
  619.                   lm^.mark := true;
  620.                   lm := lm^.blink;
  621.                 end;
  622.               tp := tp^.nextTag;
  623.             end;
  624.           lm := curMove;
  625.           while lm <> treeRoot do
  626.             begin
  627.               if lm^.blink^.flink^.slink <> nil then
  628.                 begin
  629.                   sm := lm^.blink^.flink;
  630.                   while sm <> nil do
  631.                     if not sm^.mark then
  632.                       begin
  633.                         tm := sm;
  634.                         sm := sm^.slink;
  635.                         tm := delBranch(tm);
  636.                         didPrune := true;
  637.                         treeDirty := true;
  638.                       end
  639.                     else
  640.                       sm := sm^.slink;
  641.                 end;
  642.               lm := lm^.blink;
  643.             end;
  644.           if not didPrune then
  645.             prompt('All Branches Were Tagged');
  646.         end;
  647.     end { doPruneBranches };
  648.  
  649.     handler ctlC;
  650.     begin { ctlC }
  651.       IOKeyClear;
  652.       CtlCseen := true;
  653.     end { ctlC }; 
  654.  
  655.   begin { doit }
  656.     resetGame;
  657.     done := false;
  658.     lastMove := nil;
  659.     CtlCseen := false;
  660.     playMyself := false;
  661.     lastWasPass := false;
  662.     IOSetModeTablet(relTablet);
  663.     IOCursorMode(trackCursor);
  664.     activate(mReadFile, true);
  665.     activate(mTogNums, true);
  666.     activate(mQuit, true);
  667.     activate(mPutCmt, true);
  668.     activate(mAutoPlay, true);
  669.     activate(mPlayMyself, true);
  670.     activate(mSetPlayLevel, true);
  671.     activate(mDebug, true);
  672.     activate(mRefBoard, true);
  673.     activate(mShoState, true);
  674.     activate(mBoardSize, true);
  675.     repeat
  676.       if curMove <> lastMove then
  677.         checkAtari(curMove);
  678.       updateStatus;
  679.       lastMove := curMove;
  680.       if not playMyself then
  681.         begin
  682.           activate(mPrintBoard, curMove <> treeRoot);
  683.           activate(mPrintDiag, curMove <> treeRoot);
  684.           activate(mStepToTag, stepTagPossible);
  685.           activate(mSetStepTag, treeRoot^.lastTag <> nil);
  686.           activate(mGotoTag, treeRoot^.lastTag <> nil);
  687.           activate(mInit, treeRoot^.flink <> nil);
  688.           activate(mWriteFile, treeRoot^.flink <> nil);
  689.           activate(mSetHc, curMove = treeRoot);
  690.           activate(mPass, curMove <> treeRoot);
  691.           activate(mScore, curMove <> treeRoot);
  692.           activate(mForToBr, hasBranch(curMove));
  693.           activate(mBackToBr, isBranch(curMove));
  694.           activate(mBackToStone, curMove <> treeRoot);
  695.           activate(mForToLeaf, curMove^.flink <> nil);
  696.           activate(mPutTag, curMove <> treeRoot);
  697.           activate(mGotoRoot, curMove <> treeRoot);
  698.           activate(mEraseMove, curMove <> treeRoot);
  699.           activate(mPruneBranches, isBranch(curMove));
  700.           activate(mBackOne, curMove <> treeRoot);
  701.           activate(mForOne, curMove^.flink <> nil);
  702.         end;
  703.       if CtlCseen then
  704.         cmd := mCtlC
  705.       else if playMyself then
  706.         cmd := mAutoPlay
  707.       else
  708.         repeat
  709.           cmd := getMenuCmd;
  710.         until cmd <> none;
  711.       prompt('');
  712.       case cmd of
  713.         mCtlC:
  714.           begin
  715.             playMyself := false;
  716.             CtlCseen := false;
  717.           end;
  718.         mPlaceStone:
  719.           begin
  720.             if gameOver then
  721.               restoreDead;
  722.             if bLocCur(tabRelX, tabRelY, xi, yi, xs, ys) then
  723.               begin
  724.                 if board[xi, yi].val <> empty then
  725.                   beep(error)
  726.                 else if (xi = koX) and (yi = koY) then
  727.                   beep(koV)
  728.                 else
  729.                   doMove(whoseTurn, xi, yi, xs, ys);
  730.               end
  731.             else
  732.               beep(error);
  733.             waitNoButton;
  734.           end;
  735.         mAutoPlay:
  736.           begin
  737.             if gameOver then
  738.               restoreDead;
  739.             prompt('Thinking...');
  740.             if curMove = treeRoot then
  741.               lastWasPass := false
  742.             else
  743.               lastWasPass := curMove^.id = pass;
  744.             if playMove(whoseTurn, xi, yi) then
  745.               begin
  746.                 if board[xi, yi].val <> empty then
  747.                   begin
  748.                     beep(error);
  749.                     prompt('Bad move at ');
  750.                     write((xi + 1):0, ', ', (yi + 1):0);
  751.                     playMyself := false;
  752.                     write(' - Generated by ', playreason);
  753.                   end
  754.                 else if (xi = koX) and (yi = koY) then
  755.                   begin
  756.                     beep(koV);
  757.                     prompt('ko violation at ');
  758.                     write((xi + 1):0, ', ', (yi + 1):0);
  759.                     write(' - Generated by ', playreason);
  760.                     playMyself := false;
  761.                   end
  762.                 else
  763.                   begin
  764.                     doMove(whoseTurn, xi, yi, 0, 0);
  765.                     if board[xi, yi].val = empty then
  766.                       begin
  767.                         prompt('self kill at ');
  768.                         write((xi + 1):0, ', ', (yi + 1):0);
  769.                         write(' - Generated by ', playreason);
  770.                         playMyself := false;
  771.                       end
  772.                     else
  773.                       commentMove(curMove, playReason);
  774.                   end;
  775.               end
  776.             else
  777.               begin
  778.                 doPass(whoseTurn);
  779.                 if lastWasPass then
  780.                   playMyself := false;
  781.               end;
  782.             waitNoButton;
  783.             prompt('');
  784.           end;
  785.         mPlayMyself:
  786.           playMyself := true;
  787.         mSetPlayLevel:
  788.           menuPlayLevel(playLevel, maxPlayLevel);
  789.         mShoState:
  790.           showPlayState(whoseTurn);
  791.         mInit:
  792.           if confirmed then
  793.             begin
  794.               makeGoTree;
  795.               resetGame;
  796.               treeDirty := false;
  797.             end
  798.           else
  799.             beep(error);
  800.         mSetHc:
  801.           if moveNum = 0 then
  802.             begin
  803.               if gameOver then
  804.                 restoreDead;
  805.               numHC := getHCMenu;
  806.               if numHC > 0 then
  807.                 doHCPlay(numHC)
  808.               else
  809.                 beep(error);
  810.             end
  811.           else
  812.             beep(error);
  813.         mPass:
  814.           begin
  815.             if gameOver then
  816.               restoreDead;
  817.             doPass(whoseTurn);
  818.           end;
  819.         mScore:
  820.           doScore;
  821.         mForToBr:
  822.           begin
  823.             if gameOver then
  824.               restoreDead;
  825.             if atLeaf(curMove) then
  826.               beep(error)
  827.             else if not atBranch(curMove) then
  828.                forwToBr;
  829.             if not atLeaf(curMove) then
  830.               gbg := chooseAlt;
  831.           end;
  832.         mBackToBr:
  833.           begin
  834.             if gameOver then
  835.               restoreDead;
  836.             if curMove = treeRoot then
  837.               beep(error)
  838.             else
  839.               backToBr;
  840.             if atBranch(curMove) then
  841.               gbg := chooseAlt;
  842.           end;
  843.         mBackToStone:
  844.           begin
  845.             if gameOver then
  846.               restoreDead;
  847.             if curMove = treeRoot then
  848.               beep(error)
  849.             else
  850.               doBkToS;
  851.           end;
  852.         mForToLeaf:
  853.           begin
  854.             if gameOver then
  855.               restoreDead;
  856.             if atLeaf(curMove) then
  857.               beep(error)
  858.             else
  859.               begin
  860.                 endLoop := false;
  861.                 repeat
  862.                   if atLeaf(curMove) then
  863.                     endLoop := true
  864.                   else if atBranch(curMove) then
  865.                     begin
  866.                       if not chooseAlt then
  867.                         begin
  868.                           endLoop := true;
  869.                           beep(error);
  870.                         end;
  871.                     end
  872.                   else
  873.                     forwToBr;                    
  874.                 until endLoop;
  875.               end;
  876.           end;
  877.         mPutTag:
  878.           doPutTag;
  879.         mGotoTag:
  880.           doGoToTag;
  881.         mGotoRoot:
  882.           switchBranch(treeRoot);
  883.         mPutCmt:
  884.           doPutCmt;
  885.         mReadFile:
  886.           if confirmed then
  887.             doReadGame;
  888.         mWriteFile:
  889.           doWriteGame;
  890.         mEraseMove:
  891.           doEraseMove;
  892.         mPruneBranches:
  893.           doPruneBranches;
  894.         mTogNums:
  895.           if not numbEnabled then
  896.             begin
  897.               numbEnabled := true;
  898.               showAllStones;
  899.               dotSX := -1;
  900.               putMString(mTogNums, 'Erase Numbers');
  901.             end
  902.           else
  903.             begin
  904.               numbEnabled := false;
  905.               showAllStones;
  906.               dotSX := -1;
  907.               dotLast;
  908.               putMString(mTogNums, 'Show Stone Numbers');
  909.             end;
  910.         mDebug:
  911.           if debug then
  912.             begin
  913.               debug := false;
  914.               putMString(mDebug, 'Turn Debug On');
  915.             end
  916.           else
  917.             begin
  918.               debug := true;
  919.               putMString(mDebug, 'Turn Debug Off');
  920.             end;
  921.         mBoardSize:
  922.           begin
  923.             printLarge := not printLarge;
  924.             if printLarge then
  925.               begin
  926.                 prompt('Will Print on Large Board Now');
  927.                 putMString(mBoardSize, 'Use Small Board');
  928.               end
  929.             else
  930.               begin
  931.                 prompt('Will Print on Small Board Now');
  932.                 putMString(mBoardSize, 'Use Large Board');
  933.               end;
  934.           end;
  935.         mPrintBoard:
  936.           printBoard(false);
  937.         mPrintDiag:
  938.           printBoard(true);
  939.         mStepToTag:
  940.           begin
  941.             if gameOver then
  942.               restoreDead;
  943.             if stepTag = nil then
  944.               stepTag := getTagMenu;
  945.             if stepTag <> nil then
  946.               doStepTag
  947.             else
  948.               beep(error);
  949.           end;
  950.         mSetStepTag:
  951.           begin
  952.             thisTag := getTagMenu;
  953.             if thisTag <> nil then
  954.               stepTag := thisTag;
  955.           end;
  956.         mQuit:
  957.           if confirmed then
  958.             done := true;
  959.         mBackOne:
  960.           begin
  961.             if gameOver then
  962.               restoreDead
  963.             else if curMove = treeRoot then
  964.               beep(error)
  965.             else
  966.               backUp1;
  967.           end;
  968.         mForOne:
  969.           begin
  970.             if gameOver then
  971.               restoreDead;
  972.             mForward;
  973.           end;
  974.         mRefBoard:
  975.           refreshBoard;
  976.       end { case };
  977.       if not playMyself then
  978.         endCmd;
  979.     until done;
  980.   end { doit };
  981.  
  982.   procedure cleanup;
  983.   begin { cleanup }
  984.     screenReset;
  985.     rasterOp(rRpl, 768, 1024, 0, 0, SScreenW, SScreenP,
  986.                               0, 0, SScreenW, oScreenPtr);
  987.     SSetCursor(oCurPosX, oCurPosY);
  988.   end { cleanup };
  989.  
  990.   handler ctlC;
  991.   begin { ctlC }
  992.     IOKeyClear; 
  993.   end { ctlC };
  994.  
  995. begin { Go } 
  996.   initialize;
  997.   doit;
  998. 99:
  999.   cleanUp;
  1000. end { Go }.
  1001.