home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / go / part04 / goMgr.pas < prev   
Pascal/Delphi Source File  |  1988-03-09  |  21KB  |  927 lines

  1. {---------------------------------------------------------------}
  2. { GoMgr.Pas                                                     }
  3. {                                                               }
  4. { Go Game Manager                                               }
  5. { Copyright (c) 1982 by Three Rivers Computer Corp.             }
  6. {                                                               }
  7. { Written: June 3, 1982 by Stoney Ballard                       }
  8. { Edit History:                                                 }
  9. {    June  3, 1982  Started                                     }
  10. {    June  4, 1982  Add dead group removal                      }
  11. {    June 10, 1982  Use new go file manager                     }
  12. {    Nov   9, 1982  Extracted from GO.PAS                       }
  13. {---------------------------------------------------------------}
  14.  
  15. module goMgr;
  16.  
  17. exports
  18.  
  19. imports goCom from goCom;
  20. imports goTree from goTree;
  21.  
  22. var
  23.   curMove: pMRec;
  24.   gameOver: boolean;
  25.   passIsAlt: boolean;
  26.  
  27. procedure initGoMgr;
  28. procedure backUp1;
  29. procedure doMove(which: sType; ix, iy, pox, poy: integer);
  30. procedure doPass(which: sType);
  31. procedure doHCPlay(num: integer);
  32. procedure forwardTo(m: pMRec);
  33. procedure forwToBr;
  34. procedure backToBr;
  35. procedure showAlts;
  36. procedure remAlts;
  37. procedure selAlt(lx, ly: integer);
  38. procedure selPass;
  39. function atBranch(cm: pMRec): boolean;
  40. function atLeaf(cm: pMRec): boolean;
  41. procedure checkAtari(cm: pMRec);
  42. procedure switchBranch(bm: pMRec);
  43. procedure scoreGame(var ws, bs: integer);
  44. procedure putEnd;
  45. procedure delGroup(bx, by: integer);
  46. procedure restoreDead;
  47. procedure dotLast;
  48. function lastPlayAt(bx, by: integer): boolean;
  49. procedure doStepTag;
  50. function stepTagPossible: boolean;
  51. procedure wipeTreeMarks;
  52.  
  53. private
  54.  
  55. imports goBoard from goBoard;
  56. imports goMenu from goMenu;
  57. imports screen from screen;
  58.  
  59. type
  60.   deadRec = record
  61.               dx, dy, dox, doy, mn: integer;
  62.               whoDead: sType;
  63.             end;
  64.  
  65. var
  66.   killX, killY: integer;
  67.   endDead: array[1..361] of deadRec;
  68.   numEndDead: integer;
  69.  
  70. procedure wipeMarks;
  71. var
  72.   i, j: integer;
  73. begin { wipeMarks }
  74.   for i := 0 to maxPoint do
  75.     for j := 0 to maxPoint do
  76.       board[i, j].marked := false;
  77. end { wipeMarks };
  78.  
  79. procedure wipeTreeMarks;
  80.  
  81.   procedure recWipe(m: pMRec);
  82.   begin { recWipe }
  83.     while m <> nil do
  84.       begin
  85.         recWipe(m^.slink);
  86.         m^.mark := false;
  87.         m := m^.flink;
  88.       end;
  89.   end { recWipe };
  90.  
  91. begin { wipeTreeMarks }
  92.   treeRoot^.mark := false;
  93.   if treeRoot^.flink <> nil then
  94.     recWipe(treeRoot^.flink);
  95. end { wipeTreeMarks };
  96.  
  97. procedure spanGroup(s: sType; xi, yi: integer; var libs, size: integer);
  98. begin { spanGroup }
  99.   if (xi >= 0) and (xi <= maxPoint) and
  100.      (yi >= 0) and (yi <= maxPoint) then
  101.     with board[xi, yi] do
  102.       if not marked then
  103.         if val = empty then
  104.           begin
  105.             libs := libs + 1;
  106.             marked := true;
  107.           end
  108.         else if val = s then
  109.           begin
  110.             marked := true;
  111.             size := size + 1;
  112.             spanGroup(s, xi - 1, yi, libs, size);
  113.             spanGroup(s, xi + 1, yi, libs, size);
  114.             spanGroup(s, xi, yi - 1, libs, size);
  115.             spanGroup(s, xi, yi + 1, libs, size);
  116.           end;
  117. end { spanGroup };
  118.  
  119. function libertyCount(xi, yi: integer): integer;
  120. var
  121.   libs, size: integer;
  122. begin { libertyCount }
  123.   wipeMarks;
  124.   libs := 0; 
  125.   size := 0;
  126.   spanGroup(board[xi, yi].val, xi, yi, libs, size);
  127.   libertyCount := libs;
  128. end { libertyCount };
  129.  
  130. function groupSize(xi, yi: integer): integer;
  131. var
  132.   gbg, size: integer;
  133. begin { groupSize }
  134.   wipeMarks;
  135.   size := 0;
  136.   gbg := 0;
  137.   spanGroup(board[xi, yi].val, xi, yi, gbg, size); 
  138.   groupSize := size;
  139. end { groupSize };
  140.  
  141. procedure killGroup(s: sType; xi, yi: integer);
  142. begin { killGroup }
  143.   if (xi >= 0) and (xi <= maxPoint) and
  144.      (yi >= 0) and (yi <= maxPoint) then
  145.     with board[xi, yi] do
  146.       if val = s then
  147.         begin
  148.           remStone(xi, yi);
  149.           curMove := newMove(curMove);
  150.           with curMove^ do
  151.             begin
  152.               mx := xi;
  153.               my := yi;
  154.               ox := board[xi, yi].xOfs;
  155.               oy := board[xi, yi].yOfs;
  156.               moveN := board[xi, yi].mNum;
  157.               who := s;
  158.               id := remove;
  159.             end;
  160.           curMove := mergeMove(curMove);
  161.           killGroup(s, xi - 1, yi);
  162.           killGroup(s, xi + 1, yi);
  163.           killGroup(s, xi, yi - 1);
  164.           killGroup(s, xi, yi + 1);
  165.         end;
  166. end { killGroup };
  167.  
  168. procedure remDead(xi, yi: integer; var numDead: integer);
  169. var
  170.   i, j, libs, size: integer;
  171.   s, other: bVal;
  172.  
  173. begin { remDead }
  174.   numDead := 0;
  175.   s := board[xi, yi].val;
  176.   if s = white then
  177.     other := black
  178.   else
  179.     other := white;
  180.   if xi > 0 then
  181.     if (board[xi - 1, yi].val = other) then
  182.       begin
  183.         wipeMarks;
  184.         libs := 0;
  185.         size := 0;
  186.         spanGroup(other, xi - 1, yi, libs, size);
  187.         if libs = 0 then
  188.           begin
  189.             killGroup(other, xi - 1, yi);
  190.             numDead := numDead + size;
  191.             killX := xi - 1;
  192.             killY := yi;
  193.           end;
  194.       end;
  195.   if xi < maxPoint then
  196.     if (board[xi + 1, yi].val = other) then
  197.       begin
  198.         wipeMarks;
  199.         libs := 0;
  200.         size := 0;
  201.         spanGroup(other, xi + 1, yi, libs, size);
  202.         if libs = 0 then
  203.           begin
  204.             killGroup(other, xi + 1, yi);
  205.             numDead := numDead + size;
  206.             killX := xi + 1;
  207.             killY := yi;
  208.           end;
  209.       end;
  210.   if yi > 0 then 
  211.     if (board[xi, yi - 1].val = other) then
  212.       begin
  213.         wipeMarks;
  214.         libs := 0;
  215.         size := 0;
  216.         spanGroup(other, xi, yi - 1, libs, size);
  217.         if libs = 0 then
  218.           begin
  219.             killGroup(other, xi, yi - 1);
  220.             numDead := numDead + size;
  221.             killX := xi;
  222.             killY := yi - 1;
  223.           end;
  224.       end;
  225.   if yi < maxPoint then
  226.     if (board[xi, yi + 1].val = other) then
  227.       begin
  228.         wipeMarks;
  229.         libs := 0;
  230.         size := 0;
  231.         spanGroup(other, xi, yi + 1, libs, size);
  232.         if libs = 0 then
  233.           begin
  234.             killGroup(other, xi, yi + 1);
  235.             numDead := numDead + size;
  236.             killX := xi;
  237.             killY := yi + 1;
  238.           end;
  239.       end;
  240.   if numDead > 0 then
  241.     beep(die);
  242. end { remDead };
  243.  
  244. function lastPlayAt(bx, by: integer): boolean;
  245. var
  246.   tm: pMRec;
  247. begin { lastPlayAt }
  248.   lastPlayAt := false;
  249.   tm := curMove;
  250.   while tm <> treeRoot do
  251.     with tm^ do
  252.       if id = move then
  253.         begin
  254.           lastPlayAt := (mx = bx) and (my = by);
  255.           exit(lastPlayAt);
  256.         end
  257.       else if id = pass then
  258.         exit(lastPlayAt)
  259.       else if id = hcPlay then
  260.         exit(lastPlayAt)
  261.       else
  262.         tm := tm^.blink;
  263. end { lastPlayAt };
  264.  
  265. procedure findAtari(xi, yi: integer);
  266. var
  267.   i, j, libs, num, size: integer;
  268.   s, other: bVal;
  269. begin { findAtari }
  270.   size := 0;
  271.   s := board[xi, yi].val;
  272.   if s = white then
  273.     other := black
  274.   else
  275.     other := white;
  276.   wipeMarks;
  277.   libs := 0;
  278.   spanGroup(s, xi, yi, libs, size);
  279.   if libs = 1 then
  280.     begin
  281.       beep(atari);
  282.       exit(findAtari);
  283.     end;
  284.   if xi > 0 then
  285.     if (board[xi - 1, yi].val = other) and
  286.        (not board[xi - 1, yi].marked) then
  287.       begin
  288.         wipeMarks;
  289.         libs := 0;
  290.         spanGroup(other, xi - 1, yi, libs, size);
  291.         if libs = 1 then
  292.           begin
  293.             beep(atari);
  294.             exit(findAtari);
  295.           end;
  296.       end;
  297.   if xi < maxPoint then
  298.     if (board[xi + 1, yi].val = other) and
  299.        (not board[xi + 1, yi].marked) then
  300.       begin
  301.         wipeMarks;
  302.         libs := 0;
  303.         spanGroup(other, xi + 1, yi, libs, size);
  304.         if libs = 1 then
  305.           begin
  306.             beep(atari);
  307.             exit(findAtari);
  308.           end;
  309.       end;
  310.   if yi > 0 then 
  311.     if (board[xi, yi - 1].val = other) and
  312.        (not board[xi, yi - 1].marked) then
  313.       begin
  314.         wipeMarks;
  315.         libs := 0;
  316.         spanGroup(other, xi, yi - 1, libs, size);
  317.         if libs = 1 then
  318.           begin
  319.             beep(atari);
  320.             exit(findAtari);
  321.           end;
  322.       end;
  323.   if yi < maxPoint then
  324.     if (board[xi, yi + 1].val = other) and
  325.        (not board[xi, yi + 1].marked) then
  326.       begin
  327.         wipeMarks;
  328.         libs := 0;
  329.         spanGroup(other, xi, yi + 1, libs, size);
  330.         if libs = 1 then
  331.           beep(atari);
  332.       end;
  333. end { findAtari };
  334.  
  335. procedure checkAtari(cm: pMRec);
  336. begin { checkAtari }
  337.   if cm <> treeRoot then
  338.     if cm^.id <> hcPlay then
  339.       if cm^.id <> pass then
  340.         begin
  341.           while cm^.id = remove do
  342.             cm := cm^.blink;
  343.           with cm^ do
  344.             findAtari(mx, my);
  345.       end;
  346. end { checkAtari };
  347.  
  348. procedure restoreDead;
  349. var
  350.   i: integer;
  351.   other: sType;
  352. begin { restoreDead }
  353.   for i := 1 to numEndDead do
  354.     with endDead[i] do
  355.       begin
  356.         placeStone(whoDead, dx, dy, dox, doy, mn);
  357.         if whoDead = white then
  358.           other := black
  359.         else
  360.           other := white;
  361.         captures[other] := captures[other] - 1;
  362.       end;
  363.   numEndDead := 0;
  364.   gameOver := false;
  365. end { restoreDead };
  366.  
  367. procedure backUp1;
  368. var
  369.   moveT: mType;
  370.   prevMove, tm: pMRec;
  371. begin { backUp1 }
  372.   if dotSX >= 0 then
  373.     begin
  374.       dotStone(dotSX, dotSY);
  375.       dotSX := -1;
  376.     end;
  377.   if gameOver then
  378.     restoreDead;
  379.   if curMove <> treeRoot then
  380.     repeat
  381.       with curMove^ do
  382.         begin
  383.           prevMove := blink;
  384.           moveT := id;
  385.           if id = move then
  386.             remStone(mx, my)
  387.           else if id = remove then
  388.             begin 
  389.               placeStone(who, mx, my, ox, oy, moveN);
  390.               if who = black then
  391.                 captures[white] := captures[white] - 1
  392.               else
  393.                 captures[black] := captures[black] - 1;
  394.             end
  395.           else if id = pass then
  396.             remPass
  397.           else { hcPlay }
  398.             clearBoard;
  399.         end;
  400.       curMove := prevMove;
  401.    until (curMove = treeRoot) or (moveT = move) or (moveT = pass); 
  402.    if curMove = treeRoot then
  403.      begin
  404.        koX := -1;
  405.        koY := -1;
  406.        moveNum := 0;
  407.      end
  408.    else if curMove^.id = move then
  409.      with curMove^ do
  410.        begin
  411.          koX := kx;
  412.          koY := ky;
  413.          moveNum := moveN;
  414.        end
  415.    else if curMove^.id = pass then
  416.      with curMove^ do
  417.        begin
  418.          koX := -1;
  419.          koY := -1;
  420.          moveNum := moveN;
  421.          showPass(who);
  422.        end
  423.    else if curMove^.id = hcPlay then
  424.      begin
  425.        koX := -1;
  426.        koY := -1;
  427.        moveNum := 1;
  428.      end
  429.    else
  430.      begin
  431.        tm := curMove^.blink;
  432.        while tm^.id <> move do
  433.          tm := tm^.blink;
  434.        with tm^ do
  435.          begin
  436.            koX := kx;
  437.            koY := ky;
  438.            moveNum := moveN;
  439.          end;
  440.      end;
  441. end { backUp1 };
  442.  
  443. procedure doMove(which: sType; ix, iy, pox, poy: integer);
  444. var
  445.   numDead: integer;
  446.   cm: pMRec;
  447. begin { doMove }
  448.   if dotSX >= 0 then
  449.     begin
  450.       dotStone(dotSX, dotSY);
  451.       dotSX := -1;
  452.     end;
  453.   if gameOver then
  454.     restoreDead;
  455.   curMove := newMove(curMove);
  456.   moveNum := moveNum + 1;
  457.   with curMove^ do
  458.     begin
  459.       mx := ix;
  460.       my := iy;
  461.       ox := pox;
  462.       oy := poy;
  463.       kx := koX;
  464.       ky := koY;
  465.       who := which;
  466.       id := move;
  467.       moveN := moveNum;
  468.     end;
  469.   curMove := mergeMove(curMove);
  470.   cm := curMove;
  471.   placeStone(which, ix, iy, pox, poy, moveNum);
  472.   remDead(ix, iy, numDead);
  473.   if libertyCount(ix, iy) < 1 then
  474.     begin
  475.       curMove := delBranch(curMove);
  476.       moveNum := moveNum + 1;
  477.       remStone(ix, iy);
  478.       beep(error);
  479.     end
  480.   else
  481.     begin
  482.       captures[which] := captures[which] + numDead;
  483.       if (numDead = 1) and (groupSize(ix, iy) = 1) then
  484.         begin
  485.           koX := killX;
  486.           koY := killY;
  487.         end
  488.       else
  489.         begin
  490.           koX := -1;
  491.           koY := -1;
  492.         end;  
  493.       with cm^ do
  494.         begin
  495.           kx := koX;
  496.           ky := koY;
  497.         end;
  498.     end;
  499. end { doMove };
  500.  
  501. procedure doPass(which: sType);
  502. begin { doPass }
  503.   if dotSX >= 0 then
  504.     begin
  505.       dotStone(dotSX, dotSY);
  506.       dotSX := -1;
  507.     end;
  508.   if gameOver then
  509.     restoreDead;
  510.   curMove := newMove(curMove);
  511.   moveNum := moveNum + 1;
  512.   with curMove^ do
  513.     begin
  514.       who := which;
  515.       id := pass;
  516.       moveN := moveNum;
  517.     end;
  518.   curMove := mergeMove(curMove);
  519.   showPass(which);
  520. end { doPass };
  521.  
  522. procedure doHCPlay(num: integer);
  523. begin { doHCPlay }
  524.   moveNum := 1;
  525.   curMove := newMove(treeRoot);
  526.   with curMove^ do
  527.     begin
  528.       who := black;
  529.       id := hcPlay;
  530.       hcNum := num;
  531.     end;
  532.   addHCStones(num);
  533. end { doHCPlay };
  534.  
  535. procedure forwardTo(m: pMRec);
  536. begin { forwardTo }
  537.   if dotSX >= 0 then
  538.     begin
  539.       dotStone(dotSX, dotSY);
  540.       dotSX := -1;
  541.     end;
  542.   curMove := m;
  543.   if passShowing then
  544.     remPass;
  545.   with curMove^ do
  546.     if id = hcPlay then
  547.       begin
  548.         addHCStones(hcNum);
  549.         moveNum := 1;
  550.       end
  551.     else if id = pass then
  552.       begin
  553.         moveNum := moveN;
  554.         koX := -1;
  555.         koY := -1;
  556.         showPass(who);
  557.       end
  558.     else
  559.       begin
  560.         moveNum := moveN;
  561.         placeStone(who, mx, my, ox, oy, moveNum);
  562.         koX := kx;
  563.         koY := ky;
  564.         while curMove^.flink <> nil do
  565.           if curMove^.flink^.id = remove then
  566.             begin
  567.               curMove := curMove^.flink;
  568.               with curMove^ do
  569.                 remStone(mx, my);
  570.               if curMove^.who = white then
  571.                 captures[black] := captures[black] + 1
  572.               else
  573.                 captures[white] := captures[white] + 1
  574.             end
  575.           else
  576.             exit(forwardTo);
  577.       end;
  578. end { forwardTo };
  579.  
  580. procedure forwToBr;
  581. var
  582.   atBr: boolean;
  583. begin { forwToBr }
  584.   if dotSX >= 0 then
  585.     begin
  586.       dotStone(dotSX, dotSY);
  587.       dotSX := -1;
  588.     end;
  589.   atBr := false;
  590.   repeat
  591.     if curMove^.flink = nil then
  592.       atBr := true
  593.     else if curMove^.flink^.slink <> nil then
  594.       atBr := true
  595.     else
  596.       forwardTo(curMove^.flink);
  597.   until atBr;
  598. end { forwToBr };
  599.  
  600. procedure backToBr;
  601. var
  602.   na: integer;
  603.   tm: pMRec;
  604.   endLoop: boolean;
  605. begin { backToBr }
  606.   if dotSX >= 0 then
  607.     begin
  608.       dotStone(dotSX, dotSY);
  609.       dotSX := -1;
  610.     end;
  611.   if curMove <> treeRoot then
  612.     begin
  613.       if not hasAlts(curMove) then
  614.         repeat
  615.           backUp1;
  616.           if curMove = treeRoot then
  617.             endLoop := true
  618.           else
  619.             endLoop := hasAlts(curMove);
  620.         until endLoop;
  621.       if curMove <> treeRoot then
  622.         backUp1;
  623.     end
  624.   else
  625.     beep(error);
  626. end { backToBr };
  627.  
  628. function atBranch(cm: pMRec): boolean;
  629. begin { atBranch }
  630.   if cm^.flink <> nil then
  631.     atBranch := cm^.flink^.slink <> nil
  632.   else
  633.     atBranch := false;
  634. end { atBranch };
  635.  
  636. function atLeaf(cm: pMRec): boolean;
  637. begin { atLeaf }
  638.   atLeaf := cm^.flink = nil;
  639. end { atLeaf };
  640.  
  641. procedure showAlts;
  642. var
  643.   tm: pMRec;
  644. begin { showAlts }
  645.   setMenuCursor;
  646.   tm := curMove^.flink;
  647.   passIsAlt := false;
  648.   while tm <> nil do
  649.     begin
  650.       with tm^ do
  651.         begin
  652.           if id = move then
  653.             placeAlt(who, mx, my, ox, oy)
  654.           else if id = pass then
  655.             begin
  656.               SChrFunc(ord(rNot));
  657.               showPass(who);
  658.               SChrFunc(ord(rRpl));
  659.               passIsAlt := true;
  660.             end;
  661.           tm := tm^.slink;
  662.         end;
  663.     end;
  664. end { showAlts };
  665.  
  666. procedure remAlts;
  667. var
  668.   tm: pMRec;
  669. begin { remAlts }
  670.   tm := curMove^.flink;
  671.   while tm <> nil do
  672.     begin
  673.       with tm^ do
  674.         begin
  675.           if id = move then
  676.             remStone(mx, my)
  677.           else if id = pass then
  678.             remPass;
  679.           tm := tm^.slink;
  680.         end;
  681.     end;
  682. end { remAlts };
  683.  
  684. procedure selAlt(lx, ly: integer);
  685. begin { selAlt }
  686.   remAlts;
  687.   curMove := curMove^.flink;
  688.   repeat
  689.     while curMove^.id <> move do
  690.       curMove := curMove^.slink;
  691.     if (curMove^.mx = lx) and (curMove^.my = ly) then
  692.       begin
  693.         forwardTo(curMove);
  694.         exit(selAlt);
  695.       end
  696.     else
  697.       curMove := curMove^.slink;
  698.   until false;
  699. end { selAlt };
  700.  
  701. procedure selPass;
  702. begin { selPass }
  703.   remAlts;
  704.   curMove := curMove^.flink;
  705.   while curMove^.id <> pass do
  706.     curMove := curMove^.slink;
  707.   forwardTo(curMove);
  708. end { selPass };
  709.  
  710. procedure switchBranch(bm: pMRec);
  711. var
  712.   tm: pMRec;
  713. begin { switchBranch }
  714.   if dotSX >= 0 then
  715.     begin
  716.       dotStone(dotSX, dotSY);
  717.       dotSX := -1;
  718.     end;
  719.   if gameOver then
  720.     restoreDead;
  721.   wipeTreeMarks;
  722.   tm := bm;
  723.   while tm <> treeRoot do
  724.     begin
  725.       tm^.mark := true;
  726.       tm := tm^.blink;
  727.     end;
  728.   treeRoot^.mark := true;
  729.   while not curMove^.mark do
  730.     backup1;
  731.   while curMove <> bm do
  732.     begin
  733.       tm := curMove^.flink;
  734.       while not tm^.mark do
  735.         tm := tm^.slink;
  736.       forwardTo(tm);
  737.     end;
  738. end { switchBranch };
  739.  
  740. function stepTagPossible: boolean;
  741. begin { stepTagPossible }
  742.   if treeRoot^.lastTag = nil then
  743.     stepTagPossible := false
  744.   else if stepTag = nil then
  745.     stepTagPossible := true
  746.   else if curMove = treeRoot then
  747.     stepTagPossible := true
  748.   else if curMove^.tag = stepTag then
  749.     stepTagPossible := false
  750.   else
  751.     stepTagPossible := true;
  752. end { stepTagPossible };
  753.  
  754. procedure doStepTag;
  755. var
  756.   tm: pMRec;
  757. begin { doStepTag }
  758.   if stepTag = nil then
  759.     exit(doStepTag);
  760.   if dotSX >= 0 then
  761.     begin
  762.       dotStone(dotSX, dotSY);
  763.       dotSX := -1;
  764.     end;
  765.   if gameOver then
  766.     restoreDead;
  767.   tm := stepTag^.mPtr;
  768.   if curMove = tm then
  769.     exit(doStepTag);
  770.   wipeTreeMarks;
  771.   while tm <> treeRoot do
  772.     begin
  773.       tm^.mark := true;
  774.       tm := tm^.blink;
  775.     end;
  776.   treeRoot^.mark := true;
  777.   if not curMove^.mark then
  778.     begin
  779.       prompt('Backed up to proper branch');
  780.       repeat
  781.         backup1;
  782.       until curMove^.mark;
  783.     end
  784.   else 
  785.     begin
  786.       tm := curMove^.flink;
  787.       while not tm^.mark do
  788.         tm := tm^.slink;
  789.       forwardTo(tm);
  790.     end;
  791. end { doStepTag };
  792.  
  793. procedure scoreGame(var ws, bs: integer);
  794. var
  795.   i, j, size: integer;
  796.   bSeen, wSeen: boolean;
  797.  
  798.   procedure spanEmpties(bx, by: integer);
  799.   begin { spanEmpties }
  800.     if (bx >= 0) and (bx <= maxPoint) and
  801.        (by >= 0) and (by <= maxPoint) then
  802.       begin
  803.         if board[bx, by].val = white then
  804.           wSeen := true
  805.         else if board[bx, by].val = black then
  806.           bSeen := true
  807.         else if not board[bx, by].marked then
  808.           begin
  809.             board[bx, by].marked := true;
  810.             size := size + 1;
  811.             spanEmpties(bx - 1, by);
  812.             spanEmpties(bx + 1, by);
  813.             spanEmpties(bx, by - 1);
  814.             spanEmpties(bx, by + 1);
  815.           end;
  816.       end;
  817.   end { spanEmpties };
  818.  
  819. begin { scoreGame }
  820.   ws := 0;
  821.   bs := 0;
  822.   wipeMarks;
  823.   for j := 0 to maxPoint do
  824.     for i := 0 to maxPoint do
  825.       if (not board[i, j].marked) and
  826.          (board[i, j].val = empty) then
  827.         begin
  828.           bSeen := false;
  829.           wSeen := false;
  830.           size := 0;
  831.           spanEmpties(i, j);
  832.           if bSeen and not wSeen then
  833.             bs := bs + size
  834.           else if wSeen and not bSeen then
  835.             ws := ws + size;
  836.         end;
  837. end { scoreGame };
  838.  
  839. procedure putEnd;
  840. begin { putEnd }
  841.   if not gameOver then
  842.     begin
  843.       gameOver := true;
  844.       numEndDead := 0;
  845.     end;
  846. end { putEnd };
  847.  
  848. procedure delGroup(bx, by: integer);
  849. var
  850.   sto, other: sType;
  851.   size: integer;
  852.  
  853.   procedure dumpDead(bx, by: integer);
  854.   begin { dumpDead }
  855.     if (bx >= 0) and (bx <= maxPoint) and
  856.        (by >= 0) and (by <= maxPoint) then
  857.       if board[bx, by].val = sto then
  858.         begin
  859.           remStone(bx, by);
  860.           numEndDead := numEndDead + 1;
  861.           with endDead[numEndDead] do
  862.             begin
  863.               dx := bx;
  864.               dy := by;
  865.               with board[bx, by] do
  866.                 begin
  867.                   dox := xOfs;
  868.                   doy := yOfs;
  869.                   mn := mNum;
  870.                 end;
  871.               whoDead := sto;
  872.             end;
  873.           size := size + 1;
  874.           dumpDead(bx - 1, by);
  875.           dumpDead(bx + 1, by);
  876.           dumpDead(bx, by - 1);
  877.           dumpDead(bx, by + 1);
  878.         end;
  879.   end { dumpDead };
  880.  
  881. begin { delGroup }
  882.   sto := board[bx, by].val;
  883.   size := 0;
  884.   dumpDead(bx, by);
  885.   if sto = white then
  886.     other := black
  887.   else
  888.     other := white;
  889.   captures[other] := captures[other] + size;
  890. end { delGroup };
  891.  
  892. procedure dotLast;
  893. var
  894.   tm: pMRec;
  895. begin { dotLast }
  896.   if numbEnabled then
  897.     exit(dotLast);
  898.   if dotSX >= 0 then
  899.     dotStone(dotSX, dotSY);
  900.   dotSX := -1;
  901.   tm := curMove;
  902.   while tm <> treeRoot do
  903.     if tm^.id = pass then
  904.       exit(dotLast)
  905.     else if tm^.id = move then
  906.       with tm^ do
  907.         begin
  908.           dotSX := mx;
  909.           dotSY := my;
  910.           dotStone(mx, my);
  911.           exit(dotLast);
  912.         end
  913.     else
  914.       tm := tm^.blink;
  915. end { dotLast };
  916.  
  917. procedure initGoMgr;
  918. begin { initGoMgr }
  919.   moveNum := 0;
  920.   curMove := treeRoot;
  921.   gameOver := false;
  922.   numEndDead := 0;
  923.   dotSX := -1;
  924.   dotSY := -1;
  925.   passShowing := false;
  926. end. { initGoMgr }
  927.