[comp.sources.games] v03i098: go - go board manager sources, Part02/05

games-request@tekred.TEK.COM (03/10/88)

Submitted by: Fred Hansen <wjh+@andrew.cmu.edu>
Comp.sources.games: Volume 3, Issue 98
Archive-name: go/Part02


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 5)."
# Contents:  goPlayer.pas
# Wrapped by billr@saab on Wed Mar  9 09:14:44 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f goPlayer.pas -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"goPlayer.pas\"
else
echo shar: Extracting \"goPlayer.pas\" \(58639 characters\)
sed "s/^X//" >goPlayer.pas <<'END_OF_goPlayer.pas'
X{---------------------------------------------------------------}
X{ GoPlayer.Pas                                                  }
X{                                                               }
X{ Go Move Generator                                             }
X{ Copyright (c) 1983 by Three Rivers Computer Corp.             }
X{                                                               }
X{ Written: January 17, 1983 by Stoney Ballard                   }
X{ Edit History:                                                 }
X{---------------------------------------------------------------}
X
Xmodule goPlayer;
X
Xexports
X
Ximports goCom from goCom;
X
X{ returns true if a move was generated, false for a pass }
Xfunction playMove(who: sType; var xLoc, yLoc: integer): boolean;
Xprocedure showPlayState(who: sType);
Xprocedure initGoPlayer;
X
Xvar
X  playReason: string;
X  playLevel: integer;
X  maxPlayLevel: integer;
X
Xprivate
X
Ximports goPlayUtils from goPlayUtils;
Ximports popUp from popUp;
Ximports goBoard from goBoard;
Ximports perq_string from perq_string;
Ximports io_others from io_others;
X
Xvar
X  saveNLibs: boolean;
X  stateMenu: pNameDesc;
X
Xexception broken;
X
Xprocedure blek(var moveX, moveY: integer);
Xlabel
X  1; { done }
X
Xvar
X  x, y: integer;
X  dapList1, dapList2, dapList3: pointList;
X
X  {
X    Checks out a move.
X    If my stone is not killable then true.
X  }
X  function safeMove(x, y: integer): boolean;
X  var
X    gbx, gby: integer;
X  begin { safeMove }
X    plei(x, y, 1);              { try playing at point }
X    if killFlag then { I shouldn't kill if lookForKill didn't }
X      safeMove := false
X    else if gList[groupIDs[x, y]].libC < 2 then
X      begin                   { if it is in atari or dead }
X        safeMove := false;      { reject it }
X      end
X    else if gList[groupIDs[x, y]].libC <= treeLibLim then { see if killable }
X      if playLevel > 0 then
X        safeMove := not killable(x, y, gbx, gby)
X      else
X        safeMove := true
X    else
X      safeMove := true;
X    restoreState;
X  end { safeMove };
X
X  function heCanCut(x, y: integer): boolean;
X  var
X    gx, gy: integer;
X  begin { heCanCut }
X    if playLevel > 3 then
X      begin
X        plei(x, y, -1);  { try his cut }
X        heCanCut := not killable(x, y, gx, gy);
X        restoreState;
X      end
X    else
X      heCanCut := true;
X  end { heCanCut };
X
X  {
X    Plays on a corner point if possible
X    returns true if so
X  }
X  function takeCorner(var x, y: integer): boolean;
X  var
X    field, i: integer;
X
X    {
X      checks a point for no influence and no neighbors
X      sets up return vars and exits takeCorner if ok
X    }
X    procedure checkPos(tx, ty, field: integer);
X    var
X      ok: boolean;
X    begin { checkPos }
X      ok := (((field = 0) and (kleim[tx, ty] = 0)) or  { if in field limits }
X             ((field > 0) and
X              (kleim[tx, ty] >= 0) and (kleim[tx, ty] <= field)) or
X             ((field < 0) and
X              (kleim[tx, ty] <= 0) and (kleim[tx, ty] >= field))) and
X            (bord[tx - 1, ty] = 0) and { and no neighbors }
X            (bord[tx + 1, ty] = 0) and
X            (bord[tx, ty - 1] = 0) and  
X            (bord[tx, ty + 1] = 0);
X      if ok then
X        begin
X          x := tx;
X          y := ty;
X          takeCorner := true;
X          exit(takeCorner);
X        end;
X    end { checkPos };
X
X  begin { takeCorner }
X    playReason := 'takeCorner';
X    i := maxPoint - 3;
X    field := -1;
X    repeat
X      if field = -1 then
X        field := 0
X      else if field = 0 then
X        field := 4
X      else
X        field := -4;
X      checkPos(2, 3, field);
X      checkPos(3, 2, field);
X      checkPos(2, i, field);
X      checkPos(3, i + 1, field);
X      checkPos(i, i + 1, field);
X      checkPos(i + 1, i, field);
X      checkPos(i, 2, field);
X      checkPos(i + 1, 3, field);
X      checkPos(2, 4, field);
X      checkPos(4, 2, field);
X      checkPos(2, i - 1, field);
X      checkPos(4, i + 1, field);
X      checkPos(i - 1, i + 1, field);
X      checkPos(i + 1, i - 1, field);
X      checkPos(i + 1, 4, field);
X      checkPos(i - 1, 2, field);
X    until field = -4;
X    takeCorner := false;
X  end { takeCorner }; 
X
X  {
X    first phase of 3-line extentions
X  }
X  function extend(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { extend }
X    playReason := 'extend';
X    for i := 2 to maxPoint - 2 do   { look along a three line }
X      if (kleim[2, i] = 0) and
X         (bord[1, i] = 0) and
X         (bord[3, i] = 0) and
X         (bord[2, i - 1] = 0) and
X         (bord[2, i + 1] = 0) then
X        begin
X          x := 2;        { return the first point that there's nothing around }
X          y := i;
X          extend := true;
X          exit(extend);
X        end;
X    for i := 2 to maxPoint - 2 do         { another 3-line extention }
X      if (kleim[i, maxPoint - 2] = 0) and
X         (bord[i - 1, maxPoint - 2] = 0) and
X         (bord[i + 1, maxPoint - 2] = 0) and
X         (bord[i, maxPoint - 1] = 0) and
X         (bord[i, maxPoint - 3] = 0) then
X        begin
X          x := i;
X          y := maxPoint - 2;
X          extend := true;
X          exit(extend);
X        end;
X    for i := maxPoint - 2 downto 2 do     { another 3-line extention }
X      if (kleim[maxPoint - 2, i] = 0) and
X         (bord[maxPoint - 1, i] = 0) and
X         (bord[maxPoint - 3, i] = 0) and
X         (bord[maxPoint - 2, i - 1] = 0) and
X         (bord[maxPoint - 2, i + 1] = 0) then
X        begin
X          x := maxPoint - 2;
X          y := i;
X          extend := true;
X          exit(extend);
X        end;
X    for i := maxPoint - 2 downto 2 do    { another 3-line extention }
X      if (kleim[i, 2] = 0) and
X         (bord[i - 1, 2] = 0) and
X         (bord[i + 1, 2] = 0) and
X         (bord[i, 1] = 0) and
X         (bord[i, 3] = 0) then
X        begin
X          x := i;
X          y := 2;
X          extend := true;
X          exit(extend);
X        end;
X    extend := false;
X  end { extend };
X
X  {
X    second phase of extentions - plays in my lowest influence spots on
X    the 3-lines, so long as they are not touching anything
X  }
X  function extend2(var x, y: integer): boolean;
X  var
X    i, rekrd, veliu: integer;
X  begin { extend2 }
X    playReason := 'extend2';
X    rekrd := iNil;
X    x := iNil;
X    y := iNil;
X    for i := 3 to maxPoint - 3 do    { scan a 3-line }
X      if legal[2, i] then         { if there is nobody there }
X        begin
X          veliu := kleim[2, i];     { get influence }
X          if (veliu < 7) and        { a reasonable hole in my wall }
X             (veliu > -5) and       { or a reasonable gap in his }
X             (bord[2, i + 1] = 0) and { not in contact with any stones }
X             (bord[2, i - 1] = 0) then 
X            if (rekrd <> iNil) and
X               (veliu < rekrd) then
X              begin
X                rekrd := veliu;     { rekrd gets the smallest value }
X                x := 2;              { that was seen along all the 3-lines }
X                y := i;              { x and y save that location }
X              end
X            else if rekrd = iNil then
X              begin
X                rekrd := veliu;
X                x := 2;
X                y := i;
X              end;
X        end;
X    for i := 3 to maxPoint - 3 do
X      if legal[i, 2] then
X        begin
X          veliu := kleim[i, 2];
X          if (veliu < 7) and
X             (veliu > -5) and 
X             (bord[i + 1, 2] = 0) and
X             (bord[i - 1, 2] = 0) then 
X            if (rekrd <> iNil) and
X               (veliu < rekrd) then
X              begin
X                rekrd := veliu;
X                x := i;
X                y := 2;
X              end
X            else if rekrd = iNil then
X              begin
X                rekrd := veliu;
X                x := i;
X                y := 2;
X              end;
X        end;
X    for i := maxPoint - 3 downto 3 do
X      if legal[maxPoint - 2, i] then
X        begin
X          veliu := kleim[maxPoint - 2, i];
X          if (veliu < 7) and
X             (veliu > -5) and 
X             (bord[maxPoint - 2, i + 1] = 0) and
X             (bord[maxPoint - 2, i - 1] = 0) then 
X            if (rekrd <> iNil) and
X               (veliu < rekrd) then
X              begin
X                rekrd := veliu;
X                x := maxPoint - 2;
X                y := i;
X              end
X            else if rekrd = iNil then
X              begin
X                rekrd := veliu;
X                x := maxPoint - 2;
X                y := i;
X              end;
X        end;
X    for i := maxPoint - 3 downto 3 do
X      if legal[i, maxPoint - 2] then
X        begin
X          veliu := kleim[i, maxPoint - 2];
X          if (veliu < 7) and
X             (veliu > -5) and 
X             (bord[i + 1, maxPoint - 2] = 0) and
X             (bord[i - 1, maxPoint - 2] = 0) then 
X            if (rekrd <> iNil) and
X               (veliu < rekrd) then
X              begin
X                rekrd := veliu;
X                x := i;
X                y := maxPoint - 2;
X              end
X            else if rekrd = iNil then
X              begin
X                rekrd := veliu;
X                x := i;
X                y := maxPoint - 2;
X              end;
X        end;
X    extend2 := x <> iNil;
X  end { extend2 };
X
X  {
X    connects against enemy cuts
X  }
X  function connectCut(var x, y: integer): boolean;
X  var
X    i, j, nap, gid, infl: integer;
X
X  begin { connectCut }
X    playreason := 'connectCut';
X    connectCut := true;
X    for i := 0 to maxPoint do
X      for j := 0 to maxPoint do
X        if legal[i, j] and
X           (protPoints[i, j] = 0) then   { not a protected point }
X          begin
X            nap := 0;     { how many of my stones am I adjacent to? }
X            if (i > 0) and (bord[i - 1, j] = 1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i - 1;
X                pList.p[nap].py := j;
X              end;
X            if (j > 0) and (bord[i, j - 1] = 1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i;
X                pList.p[nap].py := j - 1;
X              end;
X            if (i < maxPoint) and (bord[i + 1, j] = 1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i + 1;
X                pList.p[nap].py := j;
X              end;
X            if (j < maxPoint) and (bord[i, j + 1] = 1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i;
X                pList.p[nap].py := j + 1;
X              end;
X            if nap = 1 then { possible knight's or 2-point extention }
X              with pList.p[1] do
X                begin
X                  gid := groupIDs[px, py];
X                  if (i > 0) and (i < maxPoint) and
X                     (ndbord[i - 1, j] = 1) and
X                     (ndbord[i + 1, j] = 0) then { contact on left }
X                    begin
X                      if ((j > 0) and (ndbord[i, j - 1] = -1) and
X                          (ndbord[i + 1, j - 1] = 1) and
X                          (gid <> groupIDs[i + 1, j - 1])) or
X                         ((j < maxPoint) and (ndbord[i, j + 1] = -1) and
X                          (ndbord[i + 1, j + 1] = 1) and
X                          (gid <> groupIDs[i + 1, j + 1])) or
X                         ((((j > 0) and (ndbord[i, j - 1] = -1)) or
X                           ((j < maxPoint) and (ndbord[i, j + 1] = -1))) and
X                          (i < (maxPoint - 1)) and
X                          (ndbord[i + 2, j] = 1) and
X                          (gid <> groupIDs[i + 2, j])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(connectCut);
X                        end;
X                    end
X                  else if (i < maxPoint) and (i > 0) and
X                          (ndbord[i + 1, j] = 1) and
X                          (ndbord[i - 1, j] = 0) then { r }
X                    begin
X                      if ((j > 0) and (ndbord[i, j - 1] = -1) and
X                          (ndbord[i - 1, j - 1] = 1) and
X                          (gid <> groupIDs[i - 1, j - 1])) or
X                         ((j < maxPoint) and (ndbord[i, j + 1] = -1) and
X                          (ndbord[i - 1, j + 1] = 1) and
X                          (gid <> groupIDs[i - 1, j + 1])) or
X                         ((((j > 0) and (ndbord[i, j - 1] = -1)) or
X                           ((j < maxPoint) and (ndbord[i, j + 1] = -1))) and
X                          (i > 1) and
X                          (ndbord[i - 2, j] = 1) and
X                          (gid <> groupIDs[i - 2, j])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(connectCut);
X                        end;
X                    end
X                  else if (j > 0) and (j < maxPoint) and
X                          (ndbord[i, j - 1] = 1) and
X                          (ndbord[i, j + 1] = 0) then { top }
X                    begin
X                      if ((i > 0) and (ndbord[i - 1, j] = -1) and
X                          (ndbord[i - 1, j + 1] = 1) and
X                          (gid <> groupIDs[i - 1, j + 1])) or
X                         ((i < maxPoint) and (ndbord[i + 1, j] = -1) and
X                          (ndbord[i + 1, j + 1] = 1) and
X                          (gid <> groupIDs[i + 1, j + 1])) or
X                         ((((i > 0) and (ndbord[i - 1, j] = -1)) or
X                           ((i < maxPoint) and (ndbord[i + 1, j] = -1))) and
X                          (j < (maxPoint - 1)) and
X                          (ndbord[i, j + 2] = 1) and
X                          (gid <> groupIDs[i, j + 2])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(connectCut);
X                        end;
X                    end
X                  else if (j > 0) and (j < maxPoint) and
X                          (ndbord[i, j + 1] = 1) and
X                          (ndbord[i, j - 1] = 0) then { bottom }
X                    begin
X                      if ((i > 0) and (ndbord[i - 1, j] = -1) and
X                          (ndbord[i - 1, j - 1] = 1) and
X                          (gid <> groupIDs[i - 1, j - 1])) or
X                         ((i < maxPoint) and (ndbord[i + 1, j] = -1) and
X                          (ndbord[i + 1, j - 1] = 1) and
X                          (gid <> groupIDs[i + 1, j - 1])) or
X                         ((((i > 0) and (ndbord[i - 1, j] = -1)) or
X                           ((i < maxPoint) and (ndbord[i + 1, j] = -1))) and
X                          (j > 1) and
X                          (ndbord[i, j - 2] = 1) and
X                          (gid <> groupIDs[i, j - 2])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(connectCut);
X                        end;
X                    end;
X                end
X            else if nap = 2 then { diagonal or 1-point extention }
X              begin
X                if groupIDs[pList.p[1].px, pList.p[1].py] <>
X                   groupIDs[pList.p[2].px, pList.p[2].py] then
X                  begin
X                    if (pList.p[1].px <> pList.p[2].px) and
X                       (pList.p[1].py <> pList.p[2].py) then { diag }
X                      begin
X                        spanGroup(pList.p[1].px,
X                                  pList.p[1].py, pList1);
X                        spanGroup(pList.p[2].px,
X                                  pList.p[2].py, pList2);
X                        intersectPlist(pList1, pList2, pList3);
X                        if pList3.indx = 1 then
X                          if (i > 0) and (ndbord[i - 1, j] = -1) or
X                             (i < maxPoint) and (ndbord[i + 1, j] = -1) or
X                             (j > 0) and (ndbord[i, j - 1] = -1) or
X                             (j < maxPoint) and (ndbord[i, j + 1] = -1) then
X                            begin { must make direct connection }
X                              x := i;
X                              y := j;
X                              if heCanCut(x, y) then
X                                if safeMove(x, y) then
X                                  exit(connectCut);
X                            end
X                          else if heCanCut(i, j) then
X                            begin     { protect point if possible }
X                              infl := 1000;
X                              if (i > 0) and legal[i - 1, j] and
X                                 ((i = 1) or (ndbord[i - 2, j] = 0)) and
X                                 ((j = 0) or (ndbord[i - 1, j - 1] = 0)) and
X                                 ((j = maxPoint) or
X                                  (ndbord[i - 1, j + 1] = 0)) then
X                                if safeMove(i - 1, j) then
X                                  if kleim[i - 1, j] < infl then
X                                    begin
X                                      x := i - 1;
X                                      y := j;
X                                      infl := kleim[i - 1, j];
X                                    end;
X                              if (j > 0) and legal[i, j - 1] and
X                                 ((j = 1) or (ndbord[i, j - 2] = 0)) and
X                                 ((i = 0) or (ndbord[i - 1, j - 1] = 0)) and
X                                 ((i = maxPoint) or
X                                  (ndbord[i + 1, j - 1] = 0)) then
X                                if safeMove(i, j - 1) then
X                                  if kleim[i, j - 1] < infl then
X                                    begin
X                                      x := i;
X                                      y := j - 1;
X                                      infl := kleim[i, j - 1];
X                                    end;
X                              if (i < maxPoint) and legal[i + 1, j] and
X                                 ((i = (maxPoint - 1)) or
X                                  (ndbord[i + 2, j] = 0)) and
X                                 ((j = 0) or (ndbord[i + 1, j - 1] = 0)) and
X                                 ((j = maxPoint) or
X                                  (ndbord[i + 1, j + 1] = 0)) then
X                                if safeMove(i + 1, j) then
X                                  if kleim[i + 1, j] < infl then
X                                    begin
X                                      x := i + 1;
X                                      y := j;
X                                      infl := kleim[i + 1, j];
X                                    end;
X                              if (j < maxPoint) and legal[i, j + 1] and
X                                 ((j = (maxPoint - 1)) or
X                                  (ndbord[i, j + 2] = 0)) and
X                                 ((i = 0) or (ndbord[i - 1, j + 1] = 0)) and
X                                 ((i = maxPoint) or
X                                  (ndbord[i + 1, j + 1] = 0)) then
X                                if safeMove(i, j + 1) then
X                                  if kleim[i, j + 1] < infl then
X                                    begin
X                                      x := i;
X                                      y := j + 1;
X                                      infl := kleim[i, j + 1];
X                                    end;
X                              if infl < 1000 then
X                                exit(connectCut);
X                              x := i;      { direct connection }
X                              y := j;
X                              if safeMove(x, y) then
X                                exit(connectCut);
X                            end;
X                      end
X                    else { 1-point extension, only protect if threatened }
X                      begin
X                        if (i > 0) and (ndbord[i - 1, j] = -1) or
X                           (j > 0) and (ndbord[i, j - 1] = -1) or
X                           (i < maxPoint) and (ndbord[i + 1, j] = -1) or
X                           (j < maxPoint) and (ndbord[i, j + 1] = -1) then
X                          begin
X                            x := i;
X                            y := j;
X                            if heCanCut(x, y) then
X                              if safeMove(x, y) then
X                                exit(connectCut);
X                          end;
X                      end;
X                  end;
X              end
X            else if nap = 3 then { unprotected, but me on 3 sides }
X              begin
X                if (groupIDs[pList.p[1].px, pList.p[1].py] <>
X                    groupIDs[pList.p[2].px, pList.p[2].py]) or
X                   (groupIDs[pList.p[1].px, pList.p[1].py] <>
X                    groupIDs[pList.p[3].px, pList.p[3].py]) or
X                   (groupIDs[pList.p[3].px, pList.p[3].py] <>
X                    groupIDs[pList.p[2].px, pList.p[2].py]) then
X                  begin
X                    spanGroup(pList.p[1].px, pList.p[1].py, pList1);
X                    spanGroup(pList.p[2].px, pList.p[2].py, pList2);
X                    intersectPlist(pList1, pList2, pList3);
X                    spanGroup(pList.p[3].px, pList.p[3].py, pList2);
X                    intersectPlist(pList2, pList3, pList1);
X                    if pList1.indx = 1 then { a common connect point }
X                      if heCanCut(i, j) then
X                        if safeMove(i, j) then
X                          begin
X                            x := i;
X                            y := j;
X                            exit(connectCut);
X                          end;
X                  end;
X              end;
X          end;
X    connectCut := false;
X  end { connectCut };
X
X  {
X    cuts the enemy
X  }
X  function cutHim(var x, y: integer): boolean;
X  var
X    i, j, nap, gid: integer;
X  begin { cutHim }
X    playreason := 'cutHim';
X    cutHim := true;
X    for i := 0 to maxPoint do
X      for j := 0 to maxPoint do
X        if legal[i, j] then
X          begin
X            nap := 0;     { how many of his stones am I adjacent to? }
X            if (i > 0) and (ndbord[i - 1, j] = -1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i - 1;
X                pList.p[nap].py := j;
X              end;
X            if (j > 0) and (ndbord[i, j - 1] = -1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i;
X                pList.p[nap].py := j - 1;
X              end;
X            if (i < maxPoint) and (ndbord[i + 1, j] = -1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i + 1;
X                pList.p[nap].py := j;
X              end;
X            if (j < maxPoint) and (ndbord[i, j + 1] = -1) then
X              begin
X                nap := nap + 1;
X                pList.p[nap].px := i;
X                pList.p[nap].py := j + 1;
X              end;
X            if nap = 1 then { possible knight's or 2-point extention }
X              with pList.p[1] do
X                begin
X                  gid := groupIDs[px, py];
X                  if (i > 0) and (i < maxPoint) and
X                     (ndbord[i - 1, j] = -1) and
X                     (connectMap[i, j] > 0) then { contact on left }
X                    begin
X                      if ((j > 0) and
X                          (ndbord[i + 1, j - 1] = -1) and
X                          (gid <> groupIDs[i + 1, j - 1])) or
X                         ((j < maxPoint) and
X                          (ndbord[i + 1, j + 1] = -1) and
X                          (gid <> groupIDs[i + 1, j + 1])) or
X                         ((i < (maxPoint - 1)) and
X                          (ndbord[i + 1, j] = 0) and
X                          (ndbord[i + 2, j] = -1) and
X                          (gid <> groupIDs[i + 2, j])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(cutHim);
X                        end;
X                    end
X                  else if (i < maxPoint) and (i > 0) and
X                          (ndbord[i + 1, j] = -1) and
X                          (connectMap[i, j] > 0) then { r }
X                    begin
X                      if ((j > 0) and
X                          (ndbord[i - 1, j - 1] = -1) and
X                          (gid <> groupIDs[i - 1, j - 1])) or
X                         ((j < maxPoint) and
X                          (ndbord[i - 1, j + 1] = -1) and
X                          (gid <> groupIDs[i - 1, j + 1])) or
X                         ((i > 1) and
X                          (ndbord[i - 1, j] = 0) and
X                          (ndbord[i - 2, j] = -1) and
X                          (gid <> groupIDs[i - 2, j])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(cutHim);
X                        end;
X                    end
X                  else if (j > 0) and (j < maxPoint) and
X                          (ndbord[i, j - 1] = -1) and
X                          (connectMap[i, j] > 0) then { top }
X                    begin
X                      if ((i > 0) and
X                          (ndbord[i - 1, j + 1] = -1) and
X                          (gid <> groupIDs[i - 1, j + 1])) or
X                         ((i < maxPoint) and
X                          (ndbord[i + 1, j + 1] = -1) and
X                          (gid <> groupIDs[i + 1, j + 1])) or
X                         ((j < (maxPoint - 1)) and
X                          (ndbord[i, j + 1] = 0) and
X                          (ndbord[i, j + 2] = -1) and
X                          (gid <> groupIDs[i, j + 2])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(cutHim);
X                        end;
X                    end
X                  else if (j > 0) and (j < maxPoint) and
X                          (ndbord[i, j + 1] = -1) and
X                          (connectMap[i, j] > 0) then { bottom }
X                    begin
X                      if ((i > 0) and
X                          (ndbord[i - 1, j - 1] = -1) and
X                          (gid <> groupIDs[i - 1, j - 1])) or
X                         ((i < maxPoint) and
X                          (ndbord[i + 1, j - 1] = -1) and
X                          (gid <> groupIDs[i + 1, j - 1])) or
X                         ((j > 1) and
X                          (ndbord[i, j - 1] = 0) and
X                          (ndbord[i, j - 2] = -1) and
X                          (gid <> groupIDs[i, j - 2])) then
X                        begin
X                          x := i;
X                          y := j;
X                          if safeMove(x, y) then
X                            exit(cutHim);
X                        end;
X                    end;
X                end
X            else if nap = 2 then { diagonal or 1-point extention }
X              begin
X                if groupIDs[pList.p[1].px, pList.p[1].py] <>
X                   groupIDs[pList.p[2].px, pList.p[2].py] then
X                  begin
X                    if (pList.p[1].px <> pList.p[2].px) and
X                       (pList.p[1].py <> pList.p[2].py) then { diag }
X                      begin
X                        spanGroup(pList.p[1].px,
X                                  pList.p[1].py, pList1);
X                        spanGroup(pList.p[2].px,
X                                  pList.p[2].py, pList2);
X                        intersectPlist(pList1, pList2, pList3);
X                        if pList3.indx = 1 then
X                          begin
X                            x := i;
X                            y := j;
X                            if safeMove(x, y) then
X                              exit(cutHim);
X                          end;
X                      end
X                    else { 1-point extension, only cut if connected }
X                      begin
X                        if connectMap[i, j] > 0 then
X                          begin
X                            x := i;
X                            y := j;
X                            if safeMove(x, y) then
X                              exit(cutHim);
X                          end;
X                      end;
X                  end;
X              end
X            else if nap = 3 then { unprotected, but him on 3 sides }
X              begin
X                if (groupIDs[pList.p[1].px, pList.p[1].py] <>
X                    groupIDs[pList.p[2].px, pList.p[2].py]) or
X                   (groupIDs[pList.p[1].px, pList.p[1].py] <>
X                    groupIDs[pList.p[3].px, pList.p[3].py]) or
X                   (groupIDs[pList.p[3].px, pList.p[3].py] <>
X                    groupIDs[pList.p[2].px, pList.p[2].py]) then
X                  begin
X                    spanGroup(pList.p[1].px, pList.p[1].py, pList1);
X                    spanGroup(pList.p[2].px, pList.p[2].py, pList2);
X                    intersectPlist(pList1, pList2, pList3);
X                    spanGroup(pList.p[3].px, pList.p[3].py, pList2);
X                    intersectPlist(pList2, pList3, pList1);
X                    if pList1.indx = 1 then { a common connect point }
X                      if safeMove(i, j) then
X                        begin
X                          x := i;
X                          y := j;
X                          exit(cutHim);
X                        end;
X                  end;
X              end;
X          end;
X    cutHim := false;
X  end { cutHim };
X
X  {
X    blocks enemy cuts thru 1-point extensions
X  }
X  function blockCut(var x, y: integer): boolean;
X  var
X    i, j: integer;
X  begin { blockCut }
X    playReason := 'blockCut';
X    blockCut := true;
X    for i := 0 to maxPoint do
X      for j := 0 to maxPoint do
X        if legal[i, j] then
X          begin
X            if (i > 0) and (j > 0) and (j < maxPoint) then
X              begin
X                if (ndbord[i - 1, j] = -1) and
X                   (ndbord[i - 1, j - 1] = 1) and
X                   (ndbord[i - 1, j + 1] = 1) and
X                   (groupIDs[i - 1, j - 1] <> groupIDs[i - 1, j + 1]) then
X                  begin
X                    x := i;
X                    y := j;
X                    if heCanCut(x, y) then
X                      if safeMove(x, y) then
X                        exit(blockCut);
X                  end;
X              end;
X            if (i < maxPoint) and (j > 0) and (j < maxPoint) then
X              begin
X                if (ndbord[i + 1, j] = -1) and
X                   (ndbord[i + 1, j - 1] = 1) and
X                   (ndbord[i + 1, j + 1] = 1) and
X                   (groupIDs[i + 1, j - 1] <> groupIDs[i + 1, j + 1]) then
X                  begin
X                    x := i;
X                    y := j;
X                    if heCanCut(x, y) then
X                      if safeMove(x, y) then
X                        exit(blockCut);
X                  end;
X              end;
X            if (j > 0) and (i > 0) and (i < maxPoint) then
X              begin
X                if (ndbord[i, j - 1] = -1) and
X                   (ndbord[i - 1, j - 1] = 1) and
X                   (ndbord[i + 1, j - 1] = 1) and
X                   (groupIDs[i - 1, j - 1] <> groupIDs[i + 1, j - 1]) then
X                  begin
X                    x := i;
X                    y := j;
X                    if heCanCut(x, y) then
X                      if safeMove(x, y) then
X                        exit(blockCut);
X                  end;
X              end;
X            if (j < maxPoint) and (i > 0) and (i < maxPoint) then
X              begin
X                if (ndbord[i, j + 1] = -1) and
X                   (ndbord[i - 1, j + 1] = 1) and
X                   (ndbord[i + 1, j + 1] = 1) and
X                   (groupIDs[i - 1, j + 1] <> groupIDs[i + 1, j + 1]) then
X                  begin
X                    x := i;
X                    y := j;
X                    if heCanCut(x, y) then
X                      if safeMove(x, y) then
X                        exit(blockCut);
X                  end;
X              end;
X          end;
X    blockCut := false;
X  end { blockCut };
X
X  {
X    drops to the edge of the board if threatened
X  }
X  function dropToEdge(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { dropToEdge }
X    dropToEdge := true;
X    playReason := 'dropToEdge';
X    for i := 1 to maxPoint - 1 do
X      begin
X        if legal[1, i] then
X          if (ndbord[2, i] = 1) and
X             (ndbord[0, i] = 0) and
X             (ndbord[1, i - 1] < 1) and
X             (ndbord[1, i + 1] < 1) and
X             ((ndbord[2, i - 1] = -1) or
X              (ndbord[2, i + 1] = -1) or
X              (ndbord[1, i - 1] = -1) or
X              (ndbord[1, i + 1] = -1)) then
X            begin
X              x := 1;
X              y := i;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[maxPoint - 1, i] then
X          if (ndbord[maxPoint - 2, i] = 1) and
X             (ndbord[maxPoint, i] = 0) and
X             (ndbord[maxPoint - 1, i - 1] < 1) and
X             (ndbord[maxPoint - 1, i + 1] < 1) and
X             ((ndbord[maxPoint - 2, i - 1] = -1) or
X              (ndbord[maxPoint - 2, i + 1] = -1) or
X              (ndbord[maxPoint - 1, i - 1] = -1) or
X              (ndbord[maxPoint - 1, i + 1] = -1)) then
X            begin
X              x := maxPoint - 1;
X              y := i;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[i, 1] then
X          if (ndbord[i, 2] = 1) and
X             (ndbord[i, 0] = 0) and
X             (ndbord[i - 1, 1] < 1) and
X             (ndbord[i + 1, 1] < 1) and
X             ((ndbord[i - 1, 2] = -1) or
X              (ndbord[i + 1, 2] = -1) or
X              (ndbord[i - 1, 1] = -1) or
X              (ndbord[i + 1, 1] = -1)) then
X            begin
X              x := i;
X              y := 1;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[i, maxPoint - 1] then
X          if (ndbord[i, maxPoint - 2] = 1) and
X             (ndbord[i, maxPoint] = 0) and
X             (ndbord[i - 1, maxPoint - 1] < 1) and
X             (ndbord[i + 1, maxPoint - 1] < 1) and
X             ((ndbord[i - 1, maxPoint - 2] = -1) or
X              (ndbord[i + 1, maxPoint - 2] = -1) or
X              (ndbord[i - 1, maxPoint - 1] = -1) or
X              (ndbord[i + 1, maxPoint - 1] = -1)) then
X            begin
X              x := i;
X              y := maxPoint - 1;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[0, i] then
X          if (ndbord[1, i] = 1) and
X             (ndbord[0, i - 1] < 1) and
X             (ndbord[0, i + 1] < 1) and
X             (((ndbord[1, i - 1] = -1) and
X               (ndbord[1, i + 1] = -1)) or
X              (ndbord[0, i - 1] = -1) or
X              (ndbord[0, i + 1] = -1)) then
X            begin
X              x := 0;
X              y := i;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[maxPoint, i] then
X          if (ndbord[maxPoint - 1, i] = 1) and
X             (ndbord[maxPoint, i - 1] < 1) and
X             (ndbord[maxPoint, i + 1] < 1) and
X             (((ndbord[maxPoint - 1, i - 1] = -1) and
X               (ndbord[maxPoint - 1, i + 1] = -1)) or
X              (ndbord[maxPoint, i - 1] = -1) or
X              (ndbord[maxPoint, i + 1] = -1)) then
X            begin
X              x := maxPoint;
X              y := i;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[i, 0] then
X          if (ndbord[i, 1] = 1) and
X             (ndbord[i - 1, 0] < 1) and
X             (ndbord[i + 1, 0] < 1) and
X             (((ndbord[i - 1, 1] = -1) and
X               (ndbord[i + 1, 1] = -1)) or
X              (ndbord[i - 1, 0] = -1) or
X              (ndbord[i + 1, 0] = -1)) then
X            begin
X              x := i;
X              y := 0;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X        if legal[i, maxPoint] then
X          if (ndbord[i, maxPoint - 1] = 1) and
X             (ndbord[i - 1, maxPoint] < 1) and
X             (ndbord[i + 1, maxPoint] < 1) and
X             (((ndbord[i - 1, maxPoint - 1] = -1) and
X               (ndbord[i + 1, maxPoint - 1] = -1)) or
X              (ndbord[i - 1, maxPoint] = -1) or
X              (ndbord[i + 1, maxPoint] = -1)) then
X            begin
X              x := i;
X              y := maxPoint;
X              if safeMove(x, y) then
X                exit(dropToEdge);
X            end;
X      end;
X    dropToEdge := false;
X  end { dropToEdge };
X
X  {
X    Plays a move that requires a response on the opponent's part
X  }
X  function threaten(var x, y: integer): boolean;
X  var
X    i, j, gx, gy, tNum: integer;
X  begin { threaten }
X    playReason := 'threaten';
X    initArray(threatBord);
X    for i := 1 to maxGroupID do
X      with gList[i] do
X        if (not isLive) and
X           (ndBord[lx, ly] = -1) then
X          begin
X            spanGroup(lx, ly, pList);
X            for j := 1 to pList.indx do
X              with pList.p[j] do
X                if legal[px, py] then
X                  begin
X                    plei(px, py, 1);
X                    if gList[groupIDs[px, py]].libC > 1 then
X                      if killable(lx, ly, gx, gy) then
X                        threatBord[px, py] := threatBord[px, py] + 1;
X                    restoreState;
X                  end;
X          end;
X    tNum := 0;
X    for i := 0 to maxPoint do
X      for j := 0 to maxPoint do
X        if (threatBord[i, j] > tNum) and
X           ((threatBord[i, j] > 1) or
X            (connectMap[i, j] > 0)) then
X          begin
X            tNum := threatBord[i, j];
X            x := i;
X            y := j;
X          end;
X    threaten := tNum > 0;
X  end { threaten };
X
X  {
X    Extends walls in a connected fashion.
X    Finds the lowest influence (mine) point that is connected to one
X    of my groups.
X    Only looks in the center of the board.
X  }
X  function extendWall(var x, y: integer): boolean;
X  var
X    infl, i, j: integer;
X  begin { extendWall }
X    playReason := 'extendWall';
X    x := iNil;
X    y := iNil;
X    infl := 11;
X    for i := 2 to maxPoint - 2 do
X      for j := 2 to maxPoint - 2 do
X        if legal[i, j] then
X          if connectMap[i, j] > 0 then
X            if (kleim[i, j] < infl) and
X               (ndbord[i - 1, j] < 1) and
X               (ndbord[i + 1, j] < 1) and
X               (ndbord[i, j - 1] < 1) and
X               (ndbord[i, j + 1] < 1) and
X               ((kleim[i - 1, j] < 0) or
X                (kleim[i + 1, j] < 0) or
X                (kleim[i, j - 1] < 0) or
X                (kleim[i, j + 1] < 0)) then
X              if safeMove(i, j) then
X                begin
X                  infl := kleim[i, j];
X                  x := i;
X                  y := j;
X                end;
X    extendWall := x <> iNil;
X  end { extendWall };
X
X  {
X    Pushes walls in a tightly connected fashion.
X    Finds the lowest influence (mine) point that is connected to one
X    of my groups.
X  }
X  function pushWall(var x, y: integer): boolean;
X  var
X    infl, i, j, na: integer;
X  begin { pushWall }
X    playReason := 'pushWall';
X    x := iNil;
X    y := iNil;
X    infl := 11;
X    for i := 0 to maxPoint do
X      for j := 0 to maxPoint do
X        if legal[i, j] then
X          if connectMap[i, j] > 0 then
X            if (kleim[i, j] < infl) and
X               (((i > 0) and (ndbord[i - 1, j] = 1)) or
X                ((i < maxPoint) and (ndbord[i + 1, j] = 1)) or
X                ((j > 0) and (ndbord[i, j - 1] = 1)) or
X                ((j < maxPoint) and (ndbord[i, j + 1] = 1)) or
X                ((i > 0) and (j > 0) and (ndbord[i - 1, j - 1] = 1)) or
X                ((i < maxPoint) and (j > 0) and (ndbord[i + 1, j - 1] = 1)) or
X                ((i > 0) and (j < maxPoint) and (ndbord[i - 1, j + 1] = 1)) or
X                ((i < maxPoint) and (j < maxPoint) and
X                 (ndbord[i + 1, j + 1] = 1))) and
X               (((i > 0) and (kleim[i - 1, j] < 0)) or
X                ((i < maxPoint) and (kleim[i + 1, j] < 0)) or
X                ((j > 0) and (kleim[i, j - 1] < 0)) or
X                ((j < maxPoint) and (kleim[i, j + 1] < 0))) then
X              begin
X                na := 0;
X                if (i > 0) and (ndbord[i - 1, j] <> 0) then
X                  na := na + 1;
X                if (i < maxPoint) and (ndbord[i + 1, j] <> 0) then
X                  na := na + 1;
X                if (j > 0) and (ndbord[i, j - 1] <> 0) then
X                  na := na + 1;
X                if (j < maxPoint) and (ndbord[i, j + 1] <> 0) then
X                  na := na + 1;
X                if na < 3 then
X                  if safeMove(i, j) then
X                    begin
X                      infl := kleim[i, j];
X                      x := i;
X                      y := j;
X                    end;
X              end;
X    pushWall := x <> iNil;
X  end { pushWall };
X
X  {
X    check to see if I can kill anything
X  }
X  function lookForKill(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { lookForKill }
X    playReason := 'lookForKill';
X    lookForKill := true;
X    for i := 1 to maxGroupID do       { scan the group list }
X      with gList[i] do
X        if (libC = 1) and
X           (ndbord[lx, ly] = -1) then 
X          begin    { we found a live enemy group with one liberty }
X            spanGroup(lx, ly, pList); { find the liberty }
X            x := pList.p[1].px;
X            y := pList.p[1].py;
X            if legal[x, y] then
X              exit(lookForKill);
X          end;
X    lookForKill := false;
X  end { lookForKill };
X
X  {
X    check to see if I can save anything in atari
X  }
X  function lookForSave(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { lookForSave }
X    playReason := 'lookForSave';
X    lookForSave := true;
X    for i := 1 to maxGroupID do       { scan the group list }
X      with gList[i] do
X        if (libC = 1) and
X           (ndbord[lx, ly] = 1) then 
X            begin
X              if saveable(lx, ly, x, y) then { see if I can save it }
X                exit(lookForSave);
X            end;
X    lookForSave := false;
X  end { lookForSave };
X
X  {
X    check to see if I can save anything with n libs
X  }
X  function lookForSaveN(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { lookForSaveN }
X    if saveNLibs then
X      begin
X        playReason := 'lookForSaveN';
X        lookForSaveN := true;
X        for i := 1 to maxGroupID do       { scan the group list }
X          with gList[i] do
X            if (libC > 1) and
X               (libC <= treeLibLim) and
X               (ndbord[lx, ly] = 1) then 
X                begin
X                  if killable(lx, ly, x, y) then
X                    if saveable(lx, ly, x, y) then { see if I can save it }
X                      exit(lookForSaveN);
X                end;
X      end;
X    lookForSaveN := false;
X  end { lookForSaveN };
X
X  {
X    check to see if I can attack one of his groups
X  }
X  function lookForAttack(var x, y: integer): boolean;
X  var
X    tx, ty, i: integer;
X  begin { lookForAttack }
X    playReason := 'lookForAttack';
X    lookForAttack := true;
X    for i := 1 to maxGroupID do       { scan the group list }
X      with gList[i] do
X        if (not isLive) and
X           (libC > 1) and
X           (libC <= (treeLibLim + 1)) and
X           (ndbord[lx, ly] = -1) then 
X              begin
X                if killable(lx, ly, tx, ty) then { can we kill it? }
X                  begin
X                    x := tx;        { yep - do so }
X                    y := ty;
X                    exit(lookForAttack);
X                  end;
X              end;
X    lookForAttack := false;
X  end { lookForAttack };
X
X  {
X    check to see if I can attack one of his groups
X    uses limited depth search so that it can work on larger lib counts
X  }
X  function findAttack2(var x, y: integer): boolean;
X  var
X    tx, ty, i, otll: integer;
X  begin { findAttack2 }
X    if playLevel < 7 then
X      begin
X        findAttack2 := false;
X        exit(findAttack2);
X      end;
X    playReason := 'findAttack2';
X    findAttack2 := true;
X    depthLimit := 8;
X    otll := treeLibLim;
X    for i := 1 to maxGroupID do       { scan the group list }
X      with gList[i] do
X        if (not isLive) and
X           (ndBord[lx, ly] = -1) and
X           (libC > 1) then
X              begin
X                treeLibLim := 6;
X                if killable(lx, ly, tx, ty) then { can we kill it? }
X                  begin
X                    x := tx;        { yep - do so }
X                    y := ty;
X                    exit(findAttack2);
X                  end;
X                treeLibLim := otll;
X              end;
X    findAttack2 := false;
X    depthLimit := 100;
X  end { findAttack2 };
X
X  function doubleAtari(var x, y: integer): boolean;
X  var
X    i, j: integer;
X  begin { doubleAtari }
X    playReason := 'doubleAtari';
X    doubleAtari := true;
X    for i := 1 to maxGroupID - 1 do
X      with gList[i] do
X        if (libC = 2) and
X           (ndbord[lx, ly] = -1) then { found an atariable group of his }
X          begin
X            spanGroup(lx, ly, dapList1);
X            for j := i + 1 to maxGroupID do
X              with gList[j] do
X                if (libC = 2) and
X                   (ndbord[lx, ly] = -1) then
X                begin
X                  spanGroup(lx, ly, dapList2);
X                  intersectPlist(dapList1, dapList2, dapList3);
X                  if dapList3.indx > 0 then
X                    with dapList3.p[1] do
X                      if legal[px, py] then
X                        begin
X                          plei(px, py, 1);
X                          if gList[groupIDs[px, py]].libC > 1 then
X                            begin
X                              x := px;
X                              y := py;
X                              restoreState;
X                              exit(doubleAtari);
X                            end;
X                          restoreState;
X                        end;
X                end;
X          end; 
X    doubleAtari := false;
X  end { doubleAtari };
X
X  {
X    ataris a group just for the hell of it
X  }
X  function atariAnyway(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { atariAnyway }
X    playReason := 'atariAnyway';
X    atariAnyway := true;
X    for i := 1 to maxGroupID do       { scan the group list }
X      with gList[i] do
X        if (libC = 2) and
X           (ndbord[lx, ly] = -1) then 
X              begin
X                spanGroup(lx, ly, pList);
X                with pList.p[1] do
X                  if legal[px, py] and
X                     ((connectMap[px, py] > 0) or
X                      ((px > 0) and (connectMap[px - 1, py] > 0)) or
X                      ((px < maxPoint) and (connectMap[px + 1, py] > 0)) or
X                      ((py > 0) and (connectMap[px, py - 1] > 0)) or
X                      ((py < maxPoint) and (connectMap[px, py + 1] > 0))) then
X                    if safeMove(px, py) then
X                      begin
X                        x := px;
X                        y := py;
X                        exit(atariAnyway);
X                      end;
X                with pList.p[2] do
X                  if legal[px, py] and
X                     ((connectMap[px, py] > 0) or
X                      ((px > 0) and (connectMap[px - 1, py] > 0)) or
X                      ((px < maxPoint) and (connectMap[px + 1, py] > 0)) or
X                      ((py > 0) and (connectMap[px, py - 1] > 0)) or
X                      ((py < maxPoint) and (connectMap[px, py + 1] > 0))) then
X                    if safeMove(px, py) then
X                      begin
X                        x := px;
X                        y := py;
X                        exit(atariAnyway);
X                      end;
X              end;
X    atariAnyway := false;
X  end { atariAnyway };
X
X  {
X    undercuts his groups
X  }
X  function underCut(var x, y: integer): boolean;
X  var
X    i, j: integer;
X  begin { underCut }
X    playReason := 'underCut';
X    underCut := true;
X    for i := 1 to maxPoint - 1 do
X      begin
X        if legal[0, i] then
X          begin
X            if ndbord[1, i] = -1 then
X              if safeMove(0, i) then
X                begin
X                  x := 0;
X                  y := i;
X                  exit(underCut);
X                end;
X          end;
X        if legal[maxPoint, i] then
X          begin
X            if ndbord[maxPoint - 1, i] = -1 then
X              if safeMove(maxPoint, i) then
X                begin
X                  x := maxPoint;
X                  y := i;
X                  exit(underCut);
X                end;
X          end;
X        if legal[i, 0] then
X          begin
X            if ndbord[i, 1] = -1 then
X              if safeMove(i, 0) then
X                begin
X                  x := i;
X                  y := 0;
X                  exit(underCut);
X                end;
X          end;
X        if legal[i, maxPoint] then
X          begin
X            if ndbord[i, maxPoint - 1] = -1 then
X              if safeMove(i, maxPoint) then
X                begin
X                  x := i;
X                  y := maxPoint;
X                  exit(underCut);
X                end;
X          end;
X      end;
X    underCut := false;
X  end { underCut };
X
X  {
X    reduces the liberty count of one of his groups
X  }
X  function reduceHisLiberties(var x, y: integer): boolean;
X  var
X    i, j: integer;
X  begin { reduceHisLiberties }
X    playReason := 'reduceHisLiberties';
X    reduceHisLiberties := true;
X    sortLibs;
X    for i := 1 to maxGroupID do
X      with gList[sGList[i]] do
X        if (not isLive) and
X           (libC > 2) and
X           (ndbord[lx, ly] = -1) then
X          begin
X            spanGroup(lx, ly, pList);
X            for j := 1 to pList.indx do
X              with pList.p[j] do
X                if legal[px, py] and
X                   (connectMap[px, py] > 0) then
X                  if safeMove(px, py) then
X                    begin
X                      x := px;
X                      y := py;
X                      exit(reduceHisLiberties);
X                    end;
X          end;
X    reduceHisLiberties := false;
X  end { reduceHisLiberties };
X
X  {
X    connects a group to the edge
X  }
X  function dropToEdge2(var x, y: integer): boolean;
X  var
X    i: integer;
X  begin { dropToEdge2 }
X    playReason := 'dropToEdge2';
X    dropToEdge2 := true;
X    for i := 1 to maxPoint - 1 do
X      begin
X        if legal[i, 0] then
X          begin
X            if (ndbord[i, 1] = 1) and
X               ((ndbord[i - 1, 0] < 1) or
X                (groupIDs[i - 1, 0] <> groupIDs[i, 1])) and
X               ((ndbord[i + 1, 0] < 1) or
X                (groupIDs[i + 1, 0] <> groupIDs[i, 1])) and
X               ((ndbord[i - 1, 1] = -1) or
X                (ndbord[i + 1, 1] = -1)) then
X              begin
X                x := i;
X                y := 0;
X                if safeMove(x, y) then
X                  exit(dropToEdge2);
X              end;
X          end;
X        if legal[0, i] then
X          begin
X            if (ndbord[1, i] = 1) and
X               ((ndbord[0, i - 1] < 1) or
X                (groupIDs[0, i - 1] <> groupIDs[1, i])) and
X               ((ndbord[0, i + 1] < 1) or
X                (groupIDs[0, i + 1] <> groupIDs[1, i])) and
X               ((ndbord[1, i - 1] = -1) or
X                (ndbord[1, i + 1] = -1)) then
X              begin
X                x := 0;
X                y := i;
X                if safeMove(x, y) then
X                  exit(dropToEdge2);
X              end;
X          end;
X        if legal[i, maxPoint] then
X          begin
X            if (ndbord[i, maxPoint - 1] = 1) and
X               ((ndbord[i - 1, maxPoint] < 1) or
X                (groupIDs[i - 1, maxPoint] <> groupIDs[i, maxPoint - 1])) and
X               ((ndbord[i + 1, maxPoint] < 1) or
X                (groupIDs[i + 1, maxPoint] <> groupIDs[i, maxPoint - 1])) and
X               ((ndbord[i - 1, maxPoint - 1] = -1) or
X                (ndbord[i + 1, maxPoint - 1] = -1)) then
X              begin
X                x := i;
X                y := maxPoint;
X                if safeMove(x, y) then
X                  exit(dropToEdge2);
X              end;
X          end;
X        if legal[maxPoint, i] then
X          begin
X            if (ndbord[maxPoint - 1, i] = 1) and
X               ((ndbord[maxPoint, i - 1] < 1) or
X                (groupIDs[maxPoint, i - 1] <> groupIDs[maxPoint - 1, i])) and
X               ((ndbord[maxPoint, i + 1] < 1) or
X                (groupIDs[maxPoint, i + 1] <> groupIDs[maxPoint - 1, i])) and
X               ((ndbord[maxPoint - 1, i - 1] = -1) or
X                (ndbord[maxPoint - 1, i + 1] = -1)) then
X              begin
X                x := maxPoint;
X                y := i;
X                if safeMove(x, y) then
X                  exit(dropToEdge2);
X              end;
X          end;
X      end;
X    dropToEdge2 := false;
X  end { dropToEdge2 };
X
Xbegin { blek }
X  saveState;                    { save state of the world }
X  if takeCorner(x, y) then
X    goto 1;
X  if lookForSave(x, y) then
X    goto 1;
X  if lookForSaveN(x, y) then
X    goto 1;
X  if extend(x, y) then         { check for possible 3-line extentions }
X    goto 1;
X  if lookForKill(x, y) then
X    goto 1;
X  if doubleAtari(x, y) then
X    goto 1;
X  if lookForAttack(x, y) then
X    goto 1;
X  if threaten(x, y) then
X    goto 1;
X  if extend2(x, y) then
X    goto 1; 
X  if connectCut(x, y) then
X    goto 1;
X  if blockCut(x, y) then
X    goto 1;
X  if cutHim(x, y) then
X    goto 1;
X  if extendWall(x, y) then
X    goto 1; 
X  if findAttack2(x, y) then
X    goto 1;
X  if atariAnyway(x, y) then
X    goto 1;
X  if underCut(x, y) then
X    goto 1;
X  if dropToEdge(x, y) then
X    goto 1;
X  if pushWall(x, y) then
X    goto 1;
X  if reduceHisLiberties(x, y) then
X    goto 1;
X  if dropToEdge2(x, y) then
X    goto 1;
X  moveX := iNil; { pass }
X  moveY := iNil;
X  exit(blek);
X1: { done }
X  moveX := x;
X  moveY := y;   
Xend { blek };
X
Xprocedure genBord(who: sType);
Xvar
X  i, j: integer;
X  noMoves: boolean;
Xbegin { genBord }
X  utilPlayLevel := playLevel;
X  showTrees := debug;
X  depthLimit := 100;
X  mySType := who;
X  if playLevel < 2 then
X    treeLibLim := 2
X  else
X    treeLibLim := 3;
X  noMoves := true;
X  for i := 0 to maxPoint do
X    for j := 0 to maxPoint do
X      if board[i, j].val = who then
X        begin
X          bord[i, j] := 1;
X          legal[i, j] := false;
X          noMoves := false;
X        end
X      else if board[i, j].val = empty then
X        begin
X          bord[i, j] := 0;
X          legal[i, j] := true;
X        end
X      else
X        begin
X          bord[i, j] := -1;
X          legal[i, j] := false;
X          noMoves := false;
X        end;
X  if koX >= 0 then
X    legal[koX, koY] := false;
X  if noMoves then
X    initState
X  else
X    genState;
Xend { genBord };
X
Xfunction playMove(who: sType; var xLoc, yLoc: integer): boolean;
Xvar
X  i, j: integer;
X  noMoves: boolean;
Xbegin { playMove }
X  saveNLibs := playLevel > 2;
X  genBord(who);
X  blek(xLoc, yLoc);
X  playMove := xLoc <> iNil;
Xend { playMove };
X
Xprocedure showPlayState(who: sType);
Xvar
X  res: resres;
X  shown: boolean;
X  cx, cy: integer;
X
X  handler outside;
X  begin { outside }
X    write(''); {control-G}
X    if shown then
X      refreshBoard;
X    exit(showPlayState);
X  end { outside };
X
X  procedure showIntBord(ib: intBoard);
X  var
X    i, j: integer;
X    s: string;
X  begin { showIntBord }
X    for i := 0 to maxPoint do
X      for j := 0 to maxPoint do
X        if ib[i, j] <> 0 then
X          begin
X            s := intToStr(ib[i, j]);
X            putBString(i, j, s);
X          end;
X  end { showIntBord };
X
X  procedure showGroupState(sn: integer);
X  var
X    g: integer;
X    s: string;
X
X    procedure span(x, y: integer);
X    begin { span }
X      markBoard[x, y] := marker;
X      putBString(x, y, s);
X      if (x > 0) and
X         (groupIDs[x - 1, y] = g) and
X         (markBoard[x - 1, y] <> marker) then
X        span(x - 1, y);
X      if (x < maxPoint) and
X         (groupIDs[x + 1, y] = g) and
X         (markBoard[x + 1, y] <> marker) then
X        span(x + 1, y);
X      if (y > 0) and
X         (groupIDs[x, y - 1] = g) and
X         (markBoard[x, y - 1] <> marker) then
X        span(x, y - 1);
X      if (y < maxPoint) and
X         (groupIDs[x, y + 1] = g) and
X         (markBoard[x, y + 1] <> marker) then
X        span(x, y + 1);
X    end { span };
X
X  begin { showGroupState }
X    marker := marker + 1;
X    if marker = 0 then
X      begin
X        initArray(markBoard);
X        marker := 1;
X      end;
X    if sn < 3 then
X      s := '*';
X    for g := 1 to maxGroupID do
X      with gList[g] do
X        begin
X          case sn of
X            1: { isLive }
X              if isLive then
X                span(lx, ly);
X            2: { isDead }
X              if isDead then
X                span(lx, ly);
X            3: { libertyCount }
X              begin
X                s := intToStr(libC);
X                span(lx, ly);
X              end;
X          end; { case }
X        end;
X  end { showGroupState };
X
Xbegin { showPlayState }
X  genBord(who);
X  shown := false;
X  cx := tabRelX;
X  cy := tabRelY;
X  repeat
X    menu(stateMenu, false, 1, 11, cx, cy, -1, res);
X    if shown then
X      refreshBoard;
X    case res^.indices[1] of
X      1: { bord }
X        showIntBord(bord);
X      2: { ndBord }
X        showIntBord(ndBord);
X      3: { kleim }
X        showIntBord(kleim);
X      4: { sGroups }
X        showIntBord(sGroups);
X      5: { groupIDs }
X        showIntBord(groupIDs);
X      6: { connectMap }
X        showIntBord(connectMap);
X      7: { protPoints }
X        showIntBord(protPoints);
X      8: { isLive }
X        showGroupState(1);
X      9: { isDead }
X        showGroupState(2);
X      10: { libC }
X        showGroupState(3);
X      11: { done }
X        exit(showPlayState);
X    end; { case }
X    shown := true;
X    destroyRes(res);
X  until false;
Xend { showPlayState };
X
Xprocedure initGoPlayer;
Xbegin { initGoPlayer }
X  initGPUtils;
X  maxPlayLevel := 7;
X  allocNameDesc(11, 0, stateMenu);
X  with stateMenu^ do
X    begin
X      header := 'State to Display?';
X{$R-}
X      commands[1] := 'Bord';
X      commands[2] := 'NdBord';
X      commands[3] := 'Influence';
X      commands[4] := 'Space Groups';
X      commands[5] := 'Group IDs';
X      commands[6] := 'Connect Map';
X      commands[7] := 'Protected Points';
X      commands[8] := 'Live Groups';
X      commands[9] := 'Dead Groups';
X      commands[10] := 'Liberty Counts';
X      commands[11] := 'Done';
X{$R=}
X    end;
Xend. { initGoPlayer }
END_OF_goPlayer.pas
echo shar: 1 control character may be missing from \"goPlayer.pas\"
if test 58639 -ne `wc -c <goPlayer.pas`; then
    echo shar: \"goPlayer.pas\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 5\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0