home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 288.lha / AmiGo_v1.0 / goplayer.c < prev    next >
C/C++ Source or Header  |  1989-08-22  |  53KB  |  1,519 lines

  1. /* The go player */
  2. /* Ported from Pascal to C by Todd R. Johnson 4/17/88 */
  3. /* From the original pascal file:
  4. Go Move Generator
  5. Copyright (c) 1983 by Three Rivers Computer Corp.
  6.  
  7. Written: January 17, 1983 by Stoney Ballard
  8. Edit History:
  9. */
  10.  
  11. #include "go.h"
  12. #include "goplayutils.h"
  13.  
  14. #define BIGGEST 32767    /* maximum value for short */
  15.  
  16. /* From go.c */
  17. extern struct bRec goboard[19][19];
  18. extern short ko, koX, koY;
  19.  
  20. /* From goplayutils.c */
  21. extern intBoard bord;
  22. extern intBoard ndbord;
  23. extern intBoard claim;
  24. extern intBoard legal;
  25. extern intBoard connectMap;
  26. extern intBoard threatBord;
  27. extern short maxGroupID;
  28. extern short treeLibLim;
  29. extern short killFlag;
  30. extern short depthLimit;
  31. extern short showTrees;
  32. extern short utilPlayLevel;
  33. extern groupRec gList[maxGroup];
  34. extern short sGlist[maxGroup + 1];
  35. extern pointList pList;
  36. extern pointList pList1;
  37. extern pointList plist2;
  38. extern pointList plist3;
  39. extern intBoard groupIDs;
  40. extern intBoard protPoints;
  41. extern sType mySType;
  42. extern spanGroup( short, short, pointList * );
  43. extern genState();
  44. extern initGPUtils();
  45.  
  46. /* procedure headers */
  47. genBord(enum bVal);
  48. /* copyArray( (short *) *, (short *) * ); */
  49. short getMove( short *, short * );
  50. short genMove( enum bVal, short *, short * );
  51. short checkPos( short, short, short );
  52. short takeCorner( short *, short * );
  53. short extend( short *, short * );
  54. short noNbrs( short, short );
  55. short extend2( short *, short * );
  56. short lookForSave( short *, short * );
  57. short lookForSaveN( short *, short * );
  58. short lookForKill( short *, short * );
  59. short doubleAtari( short *, short * );
  60. short lookForAttack( short *, short * );
  61. short threaten( short *, short * );
  62. short connectCut( short *, short * );
  63. short heCanCut( short, short );
  64. short safeMove( short, short );
  65. short extendWall( short *, short * );
  66. short findAttack2( short *, short * );
  67. short blockCut( short *, short * );
  68. short cutHim( short *, short * );
  69. short atariAnyway( short *, short * );
  70. short underCut( short *, short * );
  71. short dropToEdge( short *, short * );
  72. short pushWall( short *, short * );
  73. short reduceHisLiberties( short *, short * );
  74. short dropToEdge2( short *, short * );
  75.  
  76. short saveNLibs;
  77. pointList dapList1, dapList2, dapList3;
  78. char *playReason;
  79. short maxPlayLevel = 7;
  80. short playLevel = 7;
  81.  
  82. genBord(color)
  83. enum bVal color;
  84. {
  85.    short x, y, nomoves = TRUE;
  86.    maxPlayLevel = 7;
  87.    utilPlayLevel = playLevel;
  88.    mySType = color;
  89.    if (playLevel < 2)
  90.       treeLibLim = 2;
  91.    else
  92.       treeLibLim = 3;
  93.    depthLimit = 100;
  94.    for (y = 0; y <= 18; y++)
  95.       for (x = 0; x <= 18; x++)
  96.          if (goboard[x][y].Val == color)
  97.      {
  98.         bord[x][y] = 1;
  99.         legal[x][y] = FALSE;
  100.             nomoves = FALSE;
  101.      }
  102.      else if (goboard[x][y].Val == EMPTY)
  103.      {
  104.         bord[x][y] = 0;
  105.         legal[x][y] = TRUE;
  106.      }
  107.      else
  108.      {
  109.         bord[x][y] = -1;
  110.         legal[x][y] = FALSE;
  111.             nomoves = FALSE;
  112.      }
  113.      if (ko) legal[koX][koY] = FALSE;
  114.      if (! nomoves) 
  115.         genState();
  116.      else
  117.      {
  118.         initGPUtils();
  119.      }
  120. }
  121.  
  122.  
  123. short getMove( x, y )
  124. short *x, *y;
  125. {
  126.    if (takeCorner(x, y)) return TRUE;
  127.    if (lookForSave(x, y)) return TRUE;
  128.    if (lookForSaveN(x, y)) return TRUE;
  129.    if (extend(x, y)) return TRUE;
  130.    if (lookForKill(x, y)) return TRUE;
  131.    if (doubleAtari(x, y)) return TRUE;
  132.    if (lookForAttack(x, y)) return TRUE;
  133.    if (threaten(x, y)) return TRUE;
  134.    if (extend2(x, y)) return TRUE;
  135.    if (connectCut(x, y)) return TRUE;
  136.    if (blockCut(x, y)) return TRUE;
  137.    if (cutHim(x, y)) return TRUE;
  138.    if (extendWall(x, y)) return TRUE;
  139.    if (findAttack2(x, y)) return TRUE;
  140.    if (atariAnyway(x, y)) return TRUE;
  141.    if (underCut(x, y)) return TRUE;
  142.    if (dropToEdge(x, y)) return TRUE;
  143.    if (pushWall(x, y)) return TRUE;
  144.    if (reduceHisLiberties(x, y)) return TRUE;
  145.    if (dropToEdge2(x, y)) return TRUE;
  146.    return FALSE;
  147. }
  148.  
  149. short genMove( color, x, y )
  150. enum bVal color;
  151. short *x, *y;
  152. {
  153.    if (playLevel > 2)
  154.       saveNLibs = TRUE;
  155.    else
  156.       saveNLibs = FALSE;
  157.    genBord(color);
  158.    if (getMove(x, y)) 
  159.       return TRUE;
  160.    return FALSE;
  161. }
  162.    
  163. short checkPos(x, y, field)
  164. short x, y, field;
  165. {
  166.    short ok;
  167.    ok = (((field == 0) && (claim[x][y] == 0)) ||
  168.          ((field > 0) &&
  169.       (claim[x][y] >= 0) && (claim[x][y] <= field)) ||
  170.      ((field < 0) &&
  171.       (claim[x][y] <= 0) && (claim[x][y] >= field))) &&
  172.      (bord[x-1][y] == 0) &&
  173.      (bord[x+1][y] == 0) &&
  174.      (bord[x][y-1] == 0) &&
  175.      (bord[x][y+1] == 0);
  176.    if (ok) return TRUE; else return FALSE;
  177. }
  178.  
  179. short takeCorner( x, y )
  180. short *x, *y;
  181. {
  182.    short field = -1, i;
  183.    i = 18 - 3;
  184.    playReason = "takeCorner";
  185.    while (field != -4)
  186.    {
  187.       if (field == -1) field = 0;
  188.       else if (field == 0) field = 4;
  189.       else field = -4;
  190.       if (checkPos(2, 3, field)) { *x = 2; *y = 3; return TRUE; }
  191.       if (checkPos(3, 2, field)) { *x = 3; *y = 2; return TRUE; }
  192.       if (checkPos(2, i, field)) { *x = 2; *y = i; return TRUE; }
  193.       if (checkPos(3, i + 1, field)) { *x = 3; *y = i+1; return TRUE; }
  194.       if (checkPos(i, i + 1, field)) { *x = i; *y = i+1; return TRUE; }
  195.       if (checkPos(i + 1, i, field)) { *x = i+1; *y = i; return TRUE; }
  196.       if (checkPos(i, 2, field)) { *x = i; *y = 2; return TRUE; }
  197.       if (checkPos(i + 1, 3, field)) { *x = i+1; *y = 3; return TRUE; }
  198.       if (checkPos(2, 4, field)) { *x = 2; *y = 4; return TRUE; }
  199.       if (checkPos(4, 2, field)) { *x = 4; *y = 2; return TRUE; }
  200.       if (checkPos(2, i - 1, field)) { *x = 2; *y = i-1; return TRUE; }
  201.       if (checkPos(4, i + 1, field)) { *x = 4; *y = i+1; return TRUE; }
  202.       if (checkPos(i - 1, i + 1, field)) { *x = i-1; *y = i+1; return TRUE; }
  203.       if (checkPos(i + 1, i - 1, field)) { *x = i+1; *y = i-1; return TRUE; }
  204.       if (checkPos(i + 1, 4, field)) { *x = i+1; *y = 4; return TRUE; }
  205.       if (checkPos(i - 1, 2, field)) { *x = i-1; *y = 2; return TRUE; }
  206.    }
  207.    return FALSE;
  208. }
  209.  
  210. printBoard(brd, name)
  211. intBoard brd;
  212. char *name;
  213. {
  214.    short x, y;
  215.    printf( "%s\n", name );
  216.    for (y = 0; y <= 18; y++)
  217.    {
  218.       for (x = 0; x <= 18; x++)
  219.          printf("%d ", brd[x][y]);
  220.       printf("\n");
  221.    }
  222. }
  223.  
  224. short noNbrs( x, y )
  225. short x, y;
  226. {
  227.    if (x > 0 && bord[x-1][y] != 0) return FALSE;
  228.    if (x < 18 && bord[x+1][y] != 0) return FALSE;
  229.    if (y > 0 && bord[x][y-1] != 0) return FALSE;
  230.    if (y < 18 && bord[x][y+1] != 0) return FALSE;
  231.    return TRUE;
  232. }
  233.  
  234. short extend(x, y)
  235. short *x, *y;
  236. {
  237.    short i;
  238.    playReason = "extend";
  239.    for (i = 2; i <= 18-2; i++)
  240.       if (claim[2][i] == 0 && noNbrs( 2, i ))
  241.       {
  242.          *x = 2;
  243.      *y = i;
  244.      return TRUE;
  245.       }
  246.    for (i = 2; i <= 18-2; i++)
  247.       if (claim[i][18-2] == 0 && noNbrs( 2, i ))
  248.       {
  249.          *x = i;
  250.      *y = 18-2;
  251.      return TRUE;
  252.       }
  253.    for (i = 18-2; i >= 2; i--)
  254.       if (claim[18-2][i] == 0 && noNbrs( 18-2, i ))
  255.       {
  256.          *x = 18-2;
  257.      *y = i;
  258.      return TRUE;
  259.       }
  260.    for (i = 18-2; i >= 2; i--)
  261.       if (claim[i][2] == 0 && noNbrs( i, 2 ))
  262.       {
  263.          *x = i;
  264.      *y = 2;
  265.      return TRUE;
  266.       }
  267.    return FALSE;
  268. }
  269.  
  270. short extend2( x, y )
  271. short *x, *y;
  272. {
  273.    short i, lowest = BIGGEST, value;
  274.    playReason = "extend2";
  275.    for (i = 3; i <= 18-3; i++)
  276.       if (legal[2][i])         /* if there is nobody there */
  277.       {
  278.           value = claim[2][i];     /* get influence */
  279.           if ((value < 7) &&        /* a reasonable hole in my wall */
  280.              (value > -5) &&       /* or a reasonable gap in his */
  281.              (bord[2][i + 1] == 0) && /* not in contact with any stones */
  282.              (bord[2][i - 1] == 0))
  283.             if (value < lowest) 
  284.               {
  285.                 lowest = value;     /* lowest gets the smallest value */
  286.                 *x = 2;              /* that was seen along all the 3-lines */
  287.                 *y = i;              /* x and y save that location */
  288.               }
  289.         }
  290.    for (i = 3; i <= 18-3; i++)
  291.       if (legal[i][2])
  292.         {
  293.           value = claim[i][2];
  294.           if ((value < 7) &&
  295.              (value > -5) && 
  296.              (bord[i + 1][2] == 0) &&
  297.              (bord[i - 1][2] == 0))
  298.             if (value < lowest) 
  299.               {
  300.                 lowest = value;
  301.                 *x = i;
  302.                 *y = 2;
  303.               }
  304.         }
  305.    for (i = 18-3; i >= 3; i--)
  306.       if (legal[18 - 2][i])
  307.         {
  308.           value = claim[18 - 2][i];
  309.           if ((value < 7) &&
  310.              (value > -5) && 
  311.              (bord[18 - 2][i + 1] == 0) &&
  312.              (bord[18 - 2][i - 1] == 0))
  313.             if (value < lowest) 
  314.               {
  315.                 lowest = value;
  316.                 *x = 18 - 2;
  317.                 *y = i;
  318.               }
  319.         }
  320.    for (i = 3; i <= 18-3; i++)
  321.       if (legal[i][18 - 2])
  322.         {
  323.           value = claim[i][18 - 2];
  324.           if ((value < 7) &&
  325.              (value > -5) && 
  326.              (bord[i + 1][18 - 2] == 0) &&
  327.              (bord[i - 1][18 - 2] == 0))
  328.             if (value < lowest) 
  329.               {
  330.                 lowest = value;
  331.                 *x = i;
  332.                 *y = 18 - 2;
  333.               }
  334.         }
  335.    if (lowest == BIGGEST) return FALSE;
  336.    return TRUE;
  337. }
  338.  
  339.   /*
  340.     check to see if I can save anything in atari
  341.   */
  342. short lookForSave(x, y)
  343. short *x, *y;
  344.   { /* lookForSave */
  345.     short i;
  346.     playReason = "lookForSave";
  347.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  348.         if ((gList[i].libC == 1) &&
  349.            (ndbord[gList[i].lx][gList[i].ly] == 1))
  350.               if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
  351.                 return TRUE;
  352.     return FALSE;
  353.   } /* lookForSave */
  354.  
  355.   /*
  356.     check to see if I can save anything with n libs
  357.   */
  358. short lookForSaveN(x, y)
  359. short *x, *y;
  360.   { /* lookForSaveN */
  361.     short i;
  362.     if (saveNLibs)
  363.       {
  364.         playReason = "lookForSaveN";
  365.         for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  366.             if ((gList[i].libC > 1) &&
  367.                (gList[i].libC <= treeLibLim) &&
  368.                (ndbord[gList[i].lx][gList[i].ly] == 1))
  369.                 {
  370.                   if (killable(gList[i].lx, gList[i].ly, x, y))
  371.                     if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
  372.                       return TRUE;
  373.                 }
  374.       }
  375.     return FALSE;
  376.   } /* lookForSaveN */
  377.  
  378.   /*
  379.     check to see if I can kill anything
  380.   */
  381. short lookForKill(x, y)
  382. short *x, *y;
  383.   { /* lookForKill */
  384.     short i;
  385.     playReason = "lookForKill";
  386.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  387.         if ((gList[i].libC == 1) &&
  388.            (ndbord[gList[i].lx][gList[i].ly] == -1)) 
  389.           {    /* we found a live enemy group with one liberty */
  390.             spanGroup(gList[i].lx, gList[i].ly, &pList); /* find the liberty */
  391.             *x = pList.p[1].px;
  392.             *y = pList.p[1].py;
  393.             if (legal[*x][*y])
  394.               return TRUE;
  395.           }
  396.     return FALSE;
  397.   } /* lookForKill */
  398.  
  399. short doubleAtari(x, y)
  400. short *x, *y;
  401.   { /* doubleAtari */
  402.     short i, j;
  403.     playReason = "doubleAtari";
  404.     for (i = 1; i <= maxGroupID - 1; i++)
  405.         if ((gList[i].libC == 2) &&
  406.            (ndbord[gList[i].lx][gList[i].ly] == -1)) /* found an atariable group of his */
  407.           {
  408.             spanGroup(gList[i].lx, gList[i].ly, &dapList1);
  409.             for (j = i + 1; j <= maxGroupID; j++)
  410.                 if ((gList[j].libC == 2) &&
  411.                    (ndbord[gList[j].lx][gList[j].ly] == -1))
  412.                 {
  413.                   spanGroup(gList[j].lx, gList[j].ly, &dapList2);
  414.                   intersectPlist(&dapList1, &dapList2, &dapList3);
  415.                   if (dapList3.indx > 0)
  416.                       if (legal[dapList3.p[1].px][dapList3.p[1].py])
  417.                         {
  418.                           tryPlay(dapList3.p[1].px, dapList3.p[1].py, 1);
  419.                           if (gList[groupIDs[dapList3.p[1].px][
  420.                 dapList3.p[1].py]].libC > 1)
  421.                             {
  422.                               *x = dapList3.p[1].px;
  423.                               *y = dapList3.p[1].py;
  424.                               restoreState();
  425.                   return TRUE;
  426.                             }
  427.                           restoreState();
  428.                         }
  429.                 }
  430.           } 
  431.     return FALSE;
  432.   } /* doubleAtari */
  433.  
  434. short lookForAttack(x, y)
  435. short *x, *y;
  436.   { /* lookForAttack */
  437.     short tx, ty, i;
  438.     playReason = "lookForAttack";
  439.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  440.         if ((! gList[i].isLive) &&
  441.            (gList[i].libC > 1) &&
  442.            (gList[i].libC <= (treeLibLim + 1)) &&
  443.            (ndbord[gList[i].lx][gList[i].ly] == -1)) 
  444.               {
  445.                 if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
  446.                   {
  447.                     *x = tx;        /* yep - do so */
  448.                     *y = ty;
  449.                     return TRUE;
  450.                   }
  451.               }
  452.     return FALSE;
  453.   } /* lookForAttack */
  454.  
  455.   /*
  456.     Plays a move that requires a response on the opponent's part
  457.   */
  458. short threaten(x, y)
  459. short *x, *y;
  460.   { /* threaten */
  461.     short i, j, gx, gy, tNum;
  462.     playReason = "threaten";
  463.     initArray(threatBord);
  464.     for (i = 1; i <= maxGroupID; i++)
  465.         if ((! gList[i].isLive) &&
  466.            (ndbord[gList[i].lx][gList[i].ly] == -1))
  467.           {
  468.             spanGroup(gList[i].lx, gList[i].ly, &pList);
  469.             for (j = 1; j <= pList.indx; j++)
  470.                 if (legal[pList.p[j].px][pList.p[j].py])
  471.                   {
  472.                     tryPlay(pList.p[j].px, pList.p[j].py, 1);
  473.                     if (gList[groupIDs[pList.p[j].px][pList.p[j].py]].libC > 1)
  474.                       if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
  475.                         threatBord[pList.p[j].px][pList.p[j].py] += 1;
  476.                     restoreState();
  477.                   }
  478.           }
  479.     tNum = 0;
  480.     for (i = 0; i <= maxPoint; i++)
  481.       for (j = 0; j <= maxPoint; j++)
  482.         if ((threatBord[i][j] > tNum) &&
  483.            ((threatBord[i][j] > 1) ||
  484.             (connectMap[i][j] > 0)))
  485.           {
  486.             tNum = threatBord[i][j];
  487.             *x = i;
  488.             *y = j;
  489.           }
  490.     if (tNum > 0) return TRUE;
  491.     else return FALSE;
  492.   } /* threaten */
  493.  
  494.   /*
  495.     connects against enemy cuts
  496.   */
  497. short connectCut(x, y)
  498. short *x, *y;
  499.   { /* connectCut */
  500.     short i, j, nap, gid, infl;
  501.     playReason = "connectCut";
  502.     for (i = 0; i <= maxPoint; i++)
  503.       for (j = 0; j <= maxPoint; j++)
  504.         if (legal[i][j] &&
  505.            (protPoints[i][j] == 0))   /* not a protected point */
  506.           {
  507.             nap = 0;     /* how many of my stones am I adjacent to? */
  508.             if ((i > 0) && (bord[i - 1][j] == 1))
  509.               {
  510.                 nap = nap + 1;
  511.                 pList.p[nap].px = i - 1;
  512.                 pList.p[nap].py = j;
  513.               }
  514.             if ((j > 0) && (bord[i][j - 1] == 1))
  515.               {
  516.                 nap = nap + 1;
  517.                 pList.p[nap].px = i;
  518.                 pList.p[nap].py = j - 1;
  519.               }
  520.             if ((i < maxPoint) && (bord[i + 1][j] == 1))
  521.               {
  522.                 nap = nap + 1;
  523.                 pList.p[nap].px = i + 1;
  524.                 pList.p[nap].py = j;
  525.               }
  526.             if ((j < maxPoint) && (bord[i][j + 1] == 1))
  527.               {
  528.                 nap = nap + 1;
  529.                 pList.p[nap].px = i;
  530.                 pList.p[nap].py = j + 1;
  531.               }
  532.             if (nap == 1) /* possible knight's || 2-point extention */
  533.                 {
  534.                   gid = groupIDs[pList.p[1].px][pList.p[1].py];
  535.                   if ((i > 0) && (i < maxPoint) &&
  536.                      (ndbord[i - 1][j] == 1) &&
  537.                      (ndbord[i + 1][j] == 0)) /* contact on left */
  538.                     {
  539.                       if (((j > 0) && (ndbord[i][j - 1] == -1) &&
  540.                           (ndbord[i + 1][j - 1] == 1) &&
  541.                           (gid != groupIDs[i + 1][j - 1])) ||
  542.                          ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
  543.                           (ndbord[i + 1][j + 1] == 1) &&
  544.                           (gid != groupIDs[i + 1][j + 1])) ||
  545.                          ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
  546.                            ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
  547.                           (i < (maxPoint - 1)) &&
  548.                           (ndbord[i + 2][j] == 1) &&
  549.                           (gid != groupIDs[i + 2][j])))
  550.                         {
  551.                           *x = i;
  552.                           *y = j;
  553.                           if (safeMove(*x, *y))
  554.                             return TRUE;
  555.                         }
  556.                     }
  557.                   else if ((i < maxPoint) && (i > 0) &&
  558.                           (ndbord[i + 1][j] == 1) &&
  559.                           (ndbord[i - 1][j] == 0)) /* r */
  560.                     {
  561.                       if (((j > 0) && (ndbord[i][j - 1] == -1) &&
  562.                           (ndbord[i - 1][j - 1] == 1) &&
  563.                           (gid != groupIDs[i - 1][j - 1])) ||
  564.                          ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
  565.                           (ndbord[i - 1][j + 1] == 1) &&
  566.                           (gid != groupIDs[i - 1][j + 1])) ||
  567.                          ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
  568.                            ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
  569.                           (i > 1) &&
  570.                           (ndbord[i - 2][j] == 1) &&
  571.                           (gid != groupIDs[i - 2][j])))
  572.                         {
  573.                           *x = i;
  574.                           *y = j;
  575.                           if (safeMove(*x, *y))
  576.                             return TRUE;
  577.                         }
  578.                     }
  579.                   else if ((j > 0) && (j < maxPoint) &&
  580.                           (ndbord[i][j - 1] == 1) &&
  581.                           (ndbord[i][j + 1] == 0)) /* top */
  582.                     {
  583.                       if (((i > 0) && (ndbord[i - 1][j] == -1) &&
  584.                           (ndbord[i - 1][j + 1] == 1) &&
  585.                           (gid != groupIDs[i - 1][j + 1])) ||
  586.                          ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
  587.                           (ndbord[i + 1][j + 1] == 1) &&
  588.                           (gid != groupIDs[i + 1][j + 1])) ||
  589.                          ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
  590.                            ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
  591.                           (j < (maxPoint - 1)) &&
  592.                           (ndbord[i][j + 2] == 1) &&
  593.                           (gid != groupIDs[i][j + 2])))
  594.                         {
  595.                           *x = i;
  596.                           *y = j;
  597.                           if (safeMove(*x, *y))
  598.                             return TRUE;
  599.                         }
  600.                     }
  601.                   else if ((j > 0) && (j < maxPoint) &&
  602.                           (ndbord[i][j + 1] == 1) &&
  603.                           (ndbord[i][j - 1] == 0)) /* bottom */
  604.                     {
  605.                       if (((i > 0) && (ndbord[i - 1][j] == -1) &&
  606.                           (ndbord[i - 1][j - 1] == 1) &&
  607.                           (gid != groupIDs[i - 1][j - 1])) ||
  608.                          ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
  609.                           (ndbord[i + 1][j - 1] == 1) &&
  610.                           (gid != groupIDs[i + 1][j - 1])) ||
  611.                          ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
  612.                            ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
  613.                           (j > 1) &&
  614.                           (ndbord[i][j - 2] == 1) &&
  615.                           (gid != groupIDs[i][j - 2])))
  616.                         {
  617.                           *x = i;
  618.                           *y = j;
  619.                           if (safeMove(*x, *y))
  620.                             return TRUE;
  621.                         }
  622.                     }
  623.                 }
  624.             else if (nap == 2) /* diagonal or 1-point extention */
  625.               {
  626.                 if (groupIDs[pList.p[1].px][pList.p[1].py] !=
  627.                    groupIDs[pList.p[2].px][pList.p[2].py])
  628.                   {
  629.                     if ((pList.p[1].px != pList.p[2].px) &&
  630.                        (pList.p[1].py != pList.p[2].py)) /* diag */
  631.                       {
  632.                         spanGroup(pList.p[1].px,
  633.                                   pList.p[1].py, &pList1);
  634.                         spanGroup(pList.p[2].px,
  635.                                   pList.p[2].py, &plist2);
  636.                         intersectPlist(&pList1, &plist2, &plist3);
  637.                         if (plist3.indx == 1)
  638.                           if ((i > 0) && (ndbord[i - 1][j] == -1) ||
  639.                              (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
  640.                              (j > 0) && (ndbord[i][j - 1] == -1) ||
  641.                              (j < maxPoint) && (ndbord[i][j + 1] == -1))
  642.                             { /* must make direct connection */
  643.                               *x = i;
  644.                               *y = j;
  645.                               if (heCanCut(*x, *y))
  646.                                 if (safeMove(*x, *y))
  647.                                   return TRUE;
  648.                             }
  649.                           else if (heCanCut(i, j))
  650.                             {     /* protect point if possible */
  651.                               infl = 1000;
  652.                               if ((i > 0) && legal[i - 1][j] &&
  653.                                  ((i == 1) || (ndbord[i - 2][j] == 0)) &&
  654.                                  ((j == 0) || (ndbord[i - 1][j - 1] == 0)) &&
  655.                                  ((j == maxPoint) ||
  656.                                   (ndbord[i - 1][j + 1] == 0)))
  657.                                 if (safeMove(i - 1, j))
  658.                                   if (claim[i - 1][j] < infl)
  659.                                     {
  660.                                       *x = i - 1;
  661.                                       *y = j;
  662.                                       infl = claim[i - 1][j];
  663.                                     }
  664.                               if ((j > 0) && legal[i][j - 1] &&
  665.                                  ((j == 1) || (ndbord[i][j - 2] == 0)) &&
  666.                                  ((i == 0) || (ndbord[i - 1][j - 1] == 0)) &&
  667.                                  ((i == maxPoint) ||
  668.                                   (ndbord[i + 1][j - 1] == 0)))
  669.                                 if (safeMove(i, j - 1))
  670.                                   if (claim[i][j - 1] < infl)
  671.                                     {
  672.                                       *x = i;
  673.                                       *y = j - 1;
  674.                                       infl = claim[i][j - 1];
  675.                                     }
  676.                               if ((i < maxPoint) && legal[i + 1][j] &&
  677.                                  ((i == (maxPoint - 1)) ||
  678.                                   (ndbord[i + 2][j] == 0)) &&
  679.                                  ((j == 0) || (ndbord[i + 1][j - 1] == 0)) &&
  680.                                  ((j == maxPoint) ||
  681.                                   (ndbord[i + 1][j + 1] == 0)))
  682.                                 if (safeMove(i + 1, j))
  683.                                   if (claim[i + 1][j] < infl)
  684.                                     {
  685.                                       *x = i + 1;
  686.                                       *y = j;
  687.                                       infl = claim[i + 1][j];
  688.                                     }
  689.                               if ((j < maxPoint) && legal[i][j + 1] &&
  690.                                  ((j == (maxPoint - 1)) ||
  691.                                   (ndbord[i][j + 2] == 0)) &&
  692.                                  ((i == 0) || (ndbord[i - 1][j + 1] == 0)) &&
  693.                                  ((i == maxPoint) ||
  694.                                   (ndbord[i + 1][j + 1] == 0)))
  695.                                 if (safeMove(i, j + 1))
  696.                                   if (claim[i][j + 1] < infl)
  697.                                     {
  698.                                       *x = i;
  699.                                       *y = j + 1;
  700.                                       infl = claim[i][j + 1];
  701.                                     }
  702.                               if (infl < 1000)
  703.                                 return TRUE;
  704.                               *x = i;      /* direct connection */
  705.                               *y = j;
  706.                               if (safeMove(*x, *y))
  707.                                 return TRUE;
  708.                             }
  709.                       }
  710.                     else /* 1-point extension, only protect if threatened */
  711.                       {
  712.                         if ((i > 0) && (ndbord[i - 1][j] == -1) ||
  713.                            (j > 0) && (ndbord[i][j - 1] == -1) ||
  714.                            (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
  715.                            (j < maxPoint) && (ndbord[i][j + 1] == -1))
  716.                           {
  717.                             *x = i;
  718.                             *y = j;
  719.                             if (heCanCut(*x, *y))
  720.                               if (safeMove(*x, *y))
  721.                                 return TRUE;
  722.                           }
  723.                       }
  724.                   }
  725.               }
  726.             else if (nap == 3) /* unprotected, but me on 3 sides */
  727.               {
  728.                 if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
  729.                     groupIDs[pList.p[2].px][pList.p[2].py]) ||
  730.                    (groupIDs[pList.p[1].px][pList.p[1].py] !=
  731.                     groupIDs[pList.p[3].px][pList.p[3].py]) ||
  732.                    (groupIDs[pList.p[3].px][pList.p[3].py] !=
  733.                     groupIDs[pList.p[2].px][pList.p[2].py]))
  734.                   {
  735.                     spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
  736.                     spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
  737.                     intersectPlist(&pList1, &plist2, &plist3);
  738.                     spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
  739.                     intersectPlist(&plist2, &plist3, &pList1);
  740.                     if (pList1.indx == 1) /* a common connect point */
  741.                       if (heCanCut(i, j))
  742.                         if (safeMove(i, j))
  743.                           {
  744.                             *x = i;
  745.                             *y = j;
  746.                             return TRUE;
  747.                           }
  748.                   }
  749.               }
  750.           }
  751.     return FALSE;
  752.   } /* connectCut */
  753.  
  754. short heCanCut(x, y)
  755. short x, y;
  756.   { /* heCanCut */
  757.     short gx, gy, result;
  758.     if (playLevel > 3)
  759.       {
  760.         tryPlay(x, y, -1);  /* try his cut */
  761.         result = ! killable(x, y, &gx, &gy);
  762.         restoreState();
  763.         return result;
  764.       }
  765.     else
  766.       return FALSE;
  767.   } /* heCanCut */
  768.  
  769.   /*
  770.     Checks out a move.
  771.     If my stone is not killable then true.
  772.   */
  773. short safeMove(x, y)
  774. short x, y;
  775.   { /* safeMove */
  776.     short gbx, gby, result;
  777.     tryPlay(x, y, 1);              /* try playing at point */
  778.     if (killFlag) /* I shouldn't kill if lookForKill didn't */
  779.       result = FALSE;
  780.     else if (gList[groupIDs[x][y]].libC < 2)
  781.       {                   /* if it is in atari or dead */
  782.         result = FALSE;      /* reject it */
  783.       }
  784.     else if (gList[groupIDs[x][y]].libC <= treeLibLim) /* see if killable */
  785.       if (playLevel > 0)
  786.         result = ! killable(x, y, &gbx, &gby);
  787.       else
  788.         result = TRUE;
  789.     else
  790.       result = TRUE;
  791.     restoreState();
  792.     return result;
  793.   } /* safeMove */
  794.  
  795.   /*
  796.     Extends walls in a connected fashion.
  797.     Finds the lowest influence (mine) point that is connected to one
  798.     of my groups.
  799.     Only looks in the center of the board.
  800.   */
  801. short extendWall(x, y)
  802. short *x, *y;
  803.   { /* extendWall */
  804.     short infl, i, j;
  805.     playReason = "extendWall";
  806.     *x = iNil;
  807.     *y = iNil;
  808.     infl = 11;
  809.     for (i = 2; i <= maxPoint - 2; i++)
  810.       for (j = 2; j <= maxPoint - 2; j++)
  811.         if (legal[i][j])
  812.           if (connectMap[i][j] > 0)
  813.             if ((claim[i][j] < infl) &&
  814.                (ndbord[i - 1][j] < 1) &&
  815.                (ndbord[i + 1][j] < 1) &&
  816.                (ndbord[i][j - 1] < 1) &&
  817.                (ndbord[i][j + 1] < 1) &&
  818.                ((claim[i - 1][j] < 0) ||
  819.                 (claim[i + 1][j] < 0) ||
  820.                 (claim[i][j - 1] < 0) ||
  821.                 (claim[i][j + 1] < 0)))
  822.               if (safeMove(i, j))
  823.                 {
  824.                   infl = claim[i][j];
  825.                   *x = i;
  826.                   *y = j;
  827.                 }
  828.     if (*x != iNil) return TRUE;
  829.     return FALSE;
  830.   } /* extendWall */
  831.  
  832.  
  833.   /*
  834.     check to see if I can attack one of his groups
  835.     uses limited depth search so that it can work on larger lib counts
  836.   */
  837. short findAttack2(x, y)
  838. short *x, *y;
  839.   { /* findAttack2 */
  840.     short tx, ty, i, otll;
  841.     if (playLevel < 7)
  842.       return FALSE;
  843.     playReason = "findAttack2";
  844.     depthLimit = 8;
  845.     otll = treeLibLim;
  846.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  847.         if ((! gList[i].isLive) &&
  848.            (ndbord[gList[i].lx][gList[i].ly] == -1) &&
  849.            (gList[i].libC > 1))
  850.               {
  851.                 treeLibLim = 6;
  852.                 if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
  853.                   {
  854.                     *x = tx;        /* yep - do so */
  855.                     *y = ty;
  856.                     return TRUE;
  857.                   }
  858.                 treeLibLim = otll;
  859.               }
  860.     depthLimit = 100;
  861.     return FALSE;
  862.   } /* findAttack2 */
  863.  
  864.  
  865.   /*
  866.     blocks enemy cuts thru 1-point extensions
  867.   */
  868. short blockCut(x, y)
  869. short *x, *y;
  870.   { /* blockCut */
  871.     short i, j;
  872.     playReason = "blockCut";
  873.     for (i = 0; i <= maxPoint; i++)
  874.       for (j = 0; j <= maxPoint; j++)
  875.         if (legal[i][j])
  876.           {
  877.             if ((i > 0) && (j > 0) && (j < maxPoint))
  878.               {
  879.                 if ((ndbord[i - 1][j] == -1) &&
  880.                    (ndbord[i - 1][j - 1] == 1) &&
  881.                    (ndbord[i - 1][j + 1] == 1) &&
  882.                    (groupIDs[i - 1][j - 1] != groupIDs[i - 1][j + 1]))
  883.                   {
  884.                     *x = i;
  885.                     *y = j;
  886.                     if (heCanCut(*x, *y))
  887.                       if (safeMove(*x, *y))
  888.                         return TRUE;
  889.                   }
  890.               }
  891.             if ((i < maxPoint) && (j > 0) && (j < maxPoint))
  892.               {
  893.                 if ((ndbord[i + 1][j] == -1) &&
  894.                    (ndbord[i + 1][j - 1] == 1) &&
  895.                    (ndbord[i + 1][j + 1] == 1) &&
  896.                    (groupIDs[i + 1][j - 1] != groupIDs[i + 1][j + 1]))
  897.                   {
  898.                     *x = i;
  899.                     *y = j;
  900.                     if (heCanCut(*x, *y))
  901.                       if (safeMove(*x, *y))
  902.                         return TRUE;
  903.                   }
  904.               }
  905.             if ((j > 0) && (i > 0) && (i < maxPoint))
  906.               {
  907.                 if ((ndbord[i][j - 1] == -1) &&
  908.                    (ndbord[i - 1][j - 1] == 1) &&
  909.                    (ndbord[i + 1][j - 1] == 1) &&
  910.                    (groupIDs[i - 1][j - 1] != groupIDs[i + 1][j - 1]))
  911.                   {
  912.                     *x = i;
  913.                     *y = j;
  914.                     if (heCanCut(*x, *y))
  915.                       if (safeMove(*x, *y))
  916.                         return TRUE;
  917.                   }
  918.               }
  919.             if ((j < maxPoint) && (i > 0) && (i < maxPoint))
  920.               {
  921.                 if ((ndbord[i][j + 1] == -1) &&
  922.                    (ndbord[i - 1][j + 1] == 1) &&
  923.                    (ndbord[i + 1][j + 1] == 1) &&
  924.                    (groupIDs[i - 1][j + 1] != groupIDs[i + 1][j + 1]))
  925.                   {
  926.                    *x = i;
  927.                    *y = j;
  928.                     if (heCanCut(*x, *y))
  929.                       if (safeMove(*x, *y))
  930.                         return TRUE;
  931.                   }
  932.               }
  933.           }
  934.     return FALSE;
  935.   } /* blockCut */
  936.  
  937.  
  938.   /*
  939.     cuts the enemy
  940.   */
  941. short cutHim(x, y)
  942. short *x, *y;
  943.   { /* cutHim */
  944.     short i, j, nap, gid;
  945.     playReason = "cutHim";
  946.     for (i = 0; i <= maxPoint; i++)
  947.       for (j = 0; j <= maxPoint; j++)
  948.         if (legal[i][j])
  949.           {
  950.             nap = 0;     /* how many of his stones am I adjacent to? */
  951.             if ((i > 0) && (ndbord[i - 1][j] == -1))
  952.               {
  953.                 nap = nap + 1;
  954.                 pList.p[nap].px = i - 1;
  955.                 pList.p[nap].py = j;
  956.               }
  957.             if ((j > 0) && (ndbord[i][j - 1] == -1))
  958.               {
  959.                 nap = nap + 1;
  960.                 pList.p[nap].px = i;
  961.                 pList.p[nap].py = j - 1;
  962.               }
  963.             if ((i < maxPoint) && (ndbord[i + 1][j] == -1))
  964.               {
  965.                 nap = nap + 1;
  966.                 pList.p[nap].px = i + 1;
  967.                 pList.p[nap].py = j;
  968.               }
  969.             if ((j < maxPoint) && (ndbord[i][j + 1] == -1))
  970.               {
  971.                 nap = nap + 1;
  972.                 pList.p[nap].px = i;
  973.                 pList.p[nap].py = j + 1;
  974.               }
  975.             if (nap == 1) /* possible knight's or 2-point extention */
  976.                 {
  977.                   gid = groupIDs[pList.p[1].px][pList.p[1].py];
  978.                   if ((i > 0) && (i < maxPoint) &&
  979.                      (ndbord[i - 1][j] == -1) &&
  980.                      (connectMap[i][j] > 0)) /* contact on left */
  981.                     {
  982.                       if (((j > 0) &&
  983.                           (ndbord[i + 1][j - 1] == -1) &&
  984.                           (gid != groupIDs[i + 1][j - 1])) ||
  985.                          ((j < maxPoint) &&
  986.                           (ndbord[i + 1][j + 1] == -1) &&
  987.                           (gid != groupIDs[i + 1][j + 1])) ||
  988.                          ((i < (maxPoint - 1)) &&
  989.                           (ndbord[i + 1][j] == 0) &&
  990.                           (ndbord[i + 2][j] == -1) &&
  991.                           (gid != groupIDs[i + 2][j])))
  992.                         {
  993.                           *x = i;
  994.                           *y = j;
  995.                           if (safeMove(*x, *y))
  996.                             return TRUE;
  997.                         }
  998.                     }
  999.                   else if ((i < maxPoint) && (i > 0) &&
  1000.                           (ndbord[i + 1][j] == -1) &&
  1001.                           (connectMap[i][j] > 0)) /* r */
  1002.                     {
  1003.                       if (((j > 0) &&
  1004.                           (ndbord[i - 1][j - 1] == -1) &&
  1005.                           (gid != groupIDs[i - 1][j - 1])) ||
  1006.                          ((j < maxPoint) &&
  1007.                           (ndbord[i - 1][j + 1] == -1) &&
  1008.                           (gid != groupIDs[i - 1][j + 1])) ||
  1009.                          ((i > 1) &&
  1010.                           (ndbord[i - 1][j] == 0) &&
  1011.                           (ndbord[i - 2][j] == -1) &&
  1012.                           (gid != groupIDs[i - 2][j])))
  1013.                         {
  1014.                           *x = i;
  1015.                           *y = j;
  1016.                           if (safeMove(*x, *y))
  1017.                             return TRUE;
  1018.                         }
  1019.                     }
  1020.                   else if ((j > 0) && (j < maxPoint) &&
  1021.                           (ndbord[i][j - 1] == -1) &&
  1022.                           (connectMap[i][j] > 0)) /* top */
  1023.                     {
  1024.                       if (((i > 0) &&
  1025.                           (ndbord[i - 1][j + 1] == -1) &&
  1026.                           (gid != groupIDs[i - 1][j + 1])) ||
  1027.                          ((i < maxPoint) &&
  1028.                           (ndbord[i + 1][j + 1] == -1) &&
  1029.                           (gid != groupIDs[i + 1][j + 1])) ||
  1030.                          ((j < (maxPoint - 1)) &&
  1031.                           (ndbord[i][j + 1] == 0) &&
  1032.                           (ndbord[i][j + 2] == -1) &&
  1033.                           (gid != groupIDs[i][j + 2])))
  1034.                         {
  1035.                           *x = i;
  1036.                           *y = j;
  1037.                           if (safeMove(*x, *y))
  1038.                             return TRUE;
  1039.                         }
  1040.                     }
  1041.                   else if ((j > 0) && (j < maxPoint) &&
  1042.                           (ndbord[i][j + 1] == -1) &&
  1043.                           (connectMap[i][j] > 0)) /* bottom */
  1044.                     {
  1045.                       if (((i > 0) &&
  1046.                           (ndbord[i - 1][j - 1] == -1) &&
  1047.                           (gid != groupIDs[i - 1][j - 1])) ||
  1048.                          ((i < maxPoint) &&
  1049.                           (ndbord[i + 1][j - 1] == -1) &&
  1050.                           (gid != groupIDs[i + 1][j - 1])) ||
  1051.                          ((j > 1) &&
  1052.                           (ndbord[i][j - 1] == 0) &&
  1053.                           (ndbord[i][j - 2] == -1) &&
  1054.                           (gid != groupIDs[i][j - 2])))
  1055.                         {
  1056.                           *x = i;
  1057.                           *y = j;
  1058.                           if (safeMove(*x, *y))
  1059.                             return TRUE;
  1060.                         }
  1061.                     }
  1062.                 }
  1063.             else if (nap == 2) /* diagonal or 1-point extention */
  1064.               {
  1065.                 if (groupIDs[pList.p[1].px][pList.p[1].py] !=
  1066.                    groupIDs[pList.p[2].px][pList.p[2].py])
  1067.                   {
  1068.                     if ((pList.p[1].px != pList.p[2].px) &&
  1069.                        (pList.p[1].py != pList.p[2].py)) /* diag */
  1070.                       {
  1071.                         spanGroup(pList.p[1].px,
  1072.                                   pList.p[1].py, &pList1);
  1073.                         spanGroup(pList.p[2].px,
  1074.                                   pList.p[2].py, &plist2);
  1075.                         intersectPlist(&pList1, &plist2, &plist3);
  1076.                         if (plist3.indx == 1)
  1077.                           {
  1078.                             *x = i;
  1079.                             *y = j;
  1080.                             if (safeMove(*x, *y))
  1081.                               return TRUE;
  1082.                           }
  1083.                       }
  1084.                     else /* 1-point extension, only cut if connected */
  1085.                       {
  1086.                         if (connectMap[i][j] > 0)
  1087.                           {
  1088.                             *x = i;
  1089.                             *y = j;
  1090.                             if (safeMove(*x, *y))
  1091.                               return TRUE;
  1092.                           }
  1093.                       }
  1094.                   }
  1095.               }
  1096.             else if (nap == 3) /* unprotected, but him on 3 sides */
  1097.               {
  1098.                 if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
  1099.                     groupIDs[pList.p[2].px][pList.p[2].py]) ||
  1100.                    (groupIDs[pList.p[1].px][pList.p[1].py] !=
  1101.                     groupIDs[pList.p[3].px][pList.p[3].py]) ||
  1102.                    (groupIDs[pList.p[3].px][pList.p[3].py] !=
  1103.                     groupIDs[pList.p[2].px][pList.p[2].py]))
  1104.                   {
  1105.                     spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
  1106.                     spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
  1107.                     intersectPlist(&pList1, &plist2, &plist3);
  1108.                     spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
  1109.                     intersectPlist(&plist2, &plist3, &pList1);
  1110.                     if (pList1.indx == 1) /* a common connect point */
  1111.                       if (safeMove(i, j))
  1112.                         {
  1113.                           *x = i;
  1114.                           *y = j;
  1115.                           return TRUE;
  1116.                         }
  1117.                   }
  1118.               }
  1119.           }
  1120.     return FALSE;
  1121.   } /* cutHim */
  1122.  
  1123.  
  1124.   /*
  1125.     ataris a group just for the hell of it
  1126.   */
  1127. short atariAnyway(x, y)
  1128. short *x, *y;
  1129.   { /* atariAnyway */
  1130.     short i;
  1131.     playReason = "atariAnyway";
  1132.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  1133.         if ((gList[i].libC == 2) &&
  1134.            (ndbord[gList[i].lx][gList[i].ly] == -1)) 
  1135.               {
  1136.                 spanGroup(gList[i].lx, gList[i].ly, &pList);
  1137.                   if (legal[pList.p[1].px][pList.p[1].py] &&
  1138.                      ((connectMap[pList.p[1].px][pList.p[1].py] > 0) ||
  1139.                       ((pList.p[1].px > 0) &&
  1140.                (connectMap[pList.p[1].px - 1][pList.p[1].py] > 0)) ||
  1141.                       ((pList.p[1].px < maxPoint) &&
  1142.                (connectMap[pList.p[1].px + 1][pList.p[1].py] > 0)) ||
  1143.                       ((pList.p[1].py > 0) &&
  1144.                (connectMap[pList.p[1].px][pList.p[1].py - 1] > 0)) ||
  1145.                       ((pList.p[1].py < maxPoint) &&
  1146.                (connectMap[pList.p[1].px][pList.p[1].py + 1] > 0))))
  1147.                     if (safeMove(pList.p[1].px, pList.p[1].py))
  1148.                       {
  1149.                         *x = pList.p[1].px;
  1150.                         *y = pList.p[1].py;
  1151.                         return TRUE;
  1152.                       }
  1153.                   if (legal[pList.p[2].px][pList.p[2].py] &&
  1154.                      ((connectMap[pList.p[2].px][pList.p[2].py] > 0) ||
  1155.                       ((pList.p[2].px > 0) &&
  1156.                (connectMap[pList.p[2].px - 1][pList.p[2].py] > 0)) ||
  1157.                       ((pList.p[2].px < maxPoint) &&
  1158.                (connectMap[pList.p[2].px + 1][pList.p[2].py] > 0)) ||
  1159.                       ((pList.p[2].py > 0) &&
  1160.                (connectMap[pList.p[2].px][pList.p[2].py - 1] > 0)) ||
  1161.                       ((pList.p[2].py < maxPoint) &&
  1162.                (connectMap[pList.p[2].px][pList.p[2].py + 1] > 0))))
  1163.                     if (safeMove(pList.p[2].px, pList.p[2].py))
  1164.                       {
  1165.                         *x = pList.p[2].px;
  1166.                         *y = pList.p[2].py;
  1167.                         return TRUE;
  1168.                       }
  1169.               }
  1170.     return FALSE;
  1171.   } /* atariAnyway */
  1172.  
  1173.  
  1174.   /*
  1175.     undercuts his groups
  1176.   */
  1177. short underCut(x, y)
  1178. short *x, *y;
  1179.   { /* underCut */
  1180.     short i, j;
  1181.     playReason = "underCut";
  1182.     for (i = 1; i <= maxPoint - 1; i++)
  1183.       {
  1184.         if (legal[0][i])
  1185.           {
  1186.             if (ndbord[1][i] == -1)
  1187.               if (safeMove(0, i))
  1188.                 {
  1189.                   *x = 0;
  1190.                   *y = i;
  1191.                   return TRUE;
  1192.                 }
  1193.           }
  1194.         if (legal[maxPoint][i])
  1195.           {
  1196.             if (ndbord[maxPoint - 1][i] == -1)
  1197.               if (safeMove(maxPoint, i))
  1198.                 {
  1199.                   *x = maxPoint;
  1200.                   *y = i;
  1201.                   return TRUE;
  1202.                 }
  1203.           }
  1204.         if (legal[i][0])
  1205.           {
  1206.             if (ndbord[i][1] == -1)
  1207.               if (safeMove(i, 0))
  1208.                 {
  1209.                   *x = i;
  1210.                   *y = 0;
  1211.                   return TRUE;
  1212.                 }
  1213.           }
  1214.         if (legal[i][maxPoint])
  1215.           {
  1216.             if (ndbord[i][maxPoint - 1] == -1)
  1217.               if (safeMove(i, maxPoint))
  1218.                 {
  1219.                   *x = i;
  1220.                   *y = maxPoint;
  1221.                   return TRUE;
  1222.                 }
  1223.           }
  1224.       }
  1225.     return FALSE;
  1226.   } /* underCut */
  1227.  
  1228.   /*
  1229.     drops to the edge of the board if threatened
  1230.   */
  1231. short dropToEdge(x, y)
  1232. short *x, *y;
  1233.   { /* dropToEdge */
  1234.     short i;
  1235.     playReason = "dropToEdge";
  1236.     for (i = 1; i <= maxPoint - 1; i++)
  1237.       {
  1238.         if (legal[1][i])
  1239.           if ((ndbord[2][i] == 1) &&
  1240.              (ndbord[0][i] == 0) &&
  1241.              (ndbord[1][i - 1] < 1) &&
  1242.              (ndbord[1][i + 1] < 1) &&
  1243.              ((ndbord[2][i - 1] == -1) ||
  1244.               (ndbord[2][i + 1] == -1) ||
  1245.               (ndbord[1][i - 1] == -1) ||
  1246.               (ndbord[1][i + 1] == -1)))
  1247.             {
  1248.               *x = 1;
  1249.               *y = i;
  1250.               if (safeMove(*x, *y))
  1251.                 return TRUE;
  1252.             }
  1253.         if (legal[maxPoint - 1][i])
  1254.           if ((ndbord[maxPoint - 2][i] == 1) &&
  1255.              (ndbord[maxPoint][i] == 0) &&
  1256.              (ndbord[maxPoint - 1][i - 1] < 1) &&
  1257.              (ndbord[maxPoint - 1][i + 1] < 1) &&
  1258.              ((ndbord[maxPoint - 2][i - 1] == -1) ||
  1259.               (ndbord[maxPoint - 2][i + 1] == -1) ||
  1260.               (ndbord[maxPoint - 1][i - 1] == -1) ||
  1261.               (ndbord[maxPoint - 1][i + 1] == -1)))
  1262.             {
  1263.               *x = maxPoint - 1;
  1264.               *y = i;
  1265.               if (safeMove(*x, *y))
  1266.                 return TRUE;
  1267.             }
  1268.         if (legal[i][1])
  1269.           if ((ndbord[i][2] == 1) &&
  1270.              (ndbord[i][0] == 0) &&
  1271.              (ndbord[i - 1][1] < 1) &&
  1272.              (ndbord[i + 1][1] < 1) &&
  1273.              ((ndbord[i - 1][2] == -1) ||
  1274.               (ndbord[i + 1][2] == -1) ||
  1275.               (ndbord[i - 1][1] == -1) ||
  1276.               (ndbord[i + 1][1] == -1)))
  1277.             {
  1278.               *x = i;
  1279.               *y = 1;
  1280.               if (safeMove(*x, *y))
  1281.                 return TRUE;
  1282.             }
  1283.         if (legal[i][maxPoint - 1])
  1284.           if ((ndbord[i][maxPoint - 2] == 1) &&
  1285.              (ndbord[i][maxPoint] == 0) &&
  1286.              (ndbord[i - 1][maxPoint - 1] < 1) &&
  1287.              (ndbord[i + 1][maxPoint - 1] < 1) &&
  1288.              ((ndbord[i - 1][maxPoint - 2] == -1) ||
  1289.               (ndbord[i + 1][maxPoint - 2] == -1) ||
  1290.               (ndbord[i - 1][maxPoint - 1] == -1) ||
  1291.               (ndbord[i + 1][maxPoint - 1] == -1)))
  1292.             {
  1293.               *x = i;
  1294.               *y = maxPoint - 1;
  1295.               if (safeMove(*x, *y))
  1296.                 return TRUE;
  1297.             }
  1298.         if (legal[0][i])
  1299.           if ((ndbord[1][i] == 1) &&
  1300.              (ndbord[0][i - 1] < 1) &&
  1301.              (ndbord[0][i + 1] < 1) &&
  1302.              (((ndbord[1][i - 1] == -1) &&
  1303.                (ndbord[1][i + 1] == -1)) ||
  1304.               (ndbord[0][i - 1] == -1) ||
  1305.               (ndbord[0][i + 1] == -1)))
  1306.             {
  1307.               *x = 0;
  1308.               *y = i;
  1309.               if (safeMove(*x, *y))
  1310.                 return TRUE;
  1311.             }
  1312.         if (legal[maxPoint][i])
  1313.           if ((ndbord[maxPoint - 1][i] == 1) &&
  1314.              (ndbord[maxPoint][i - 1] < 1) &&
  1315.              (ndbord[maxPoint][i + 1] < 1) &&
  1316.              (((ndbord[maxPoint - 1][i - 1] == -1) &&
  1317.                (ndbord[maxPoint - 1][i + 1] == -1)) ||
  1318.               (ndbord[maxPoint][i - 1] == -1) ||
  1319.               (ndbord[maxPoint][i + 1] == -1)))
  1320.             {
  1321.               *x = maxPoint;
  1322.               *y = i;
  1323.               if (safeMove(*x, *y))
  1324.                 return TRUE;
  1325.             }
  1326.         if (legal[i][0])
  1327.           if ((ndbord[i][1] == 1) &&
  1328.              (ndbord[i - 1][0] < 1) &&
  1329.              (ndbord[i + 1][0] < 1) &&
  1330.              (((ndbord[i - 1][1] == -1) &&
  1331.                (ndbord[i + 1][1] == -1)) ||
  1332.               (ndbord[i - 1][0] == -1) ||
  1333.               (ndbord[i + 1][0] == -1)))
  1334.             {
  1335.               *x = i;
  1336.               *y = 0;
  1337.               if (safeMove(*x, *y))
  1338.                 return TRUE;
  1339.             }
  1340.         if (legal[i][maxPoint])
  1341.           if ((ndbord[i][maxPoint - 1] == 1) &&
  1342.              (ndbord[i - 1][maxPoint] < 1) &&
  1343.              (ndbord[i + 1][maxPoint] < 1) &&
  1344.              (((ndbord[i - 1][maxPoint - 1] == -1) &&
  1345.                (ndbord[i + 1][maxPoint - 1] == -1)) ||
  1346.               (ndbord[i - 1][maxPoint] == -1) ||
  1347.               (ndbord[i + 1][maxPoint] == -1)))
  1348.             {
  1349.               *x = i;
  1350.               *y = maxPoint;
  1351.               if (safeMove(*x, *y))
  1352.                 return TRUE;
  1353.             }
  1354.       }
  1355.     return FALSE;
  1356.   } /* dropToEdge */
  1357.  
  1358.   /*
  1359.     Pushes walls in a tightly connected fashion.
  1360.     Finds the lowest influence (mine) point that is connected to one
  1361.     of my groups.
  1362.   */
  1363. short pushWall(x, y)
  1364. short *x, *y;
  1365.   { /* pushWall */
  1366.     short infl, i, j, na;
  1367.     playReason = "pushWall";
  1368.     *x = iNil;
  1369.     *y = iNil;
  1370.     infl = 11;
  1371.     for (i = 0; i <= maxPoint; i++)
  1372.       for (j = 0; j <= maxPoint; j++)
  1373.         if (legal[i][j])
  1374.           if (connectMap[i][j] > 0)
  1375.             if ((claim[i][j] < infl) &&
  1376.                (((i > 0) && (ndbord[i - 1][j] == 1)) ||
  1377.                 ((i < maxPoint) && (ndbord[i + 1][j] == 1)) ||
  1378.                 ((j > 0) && (ndbord[i][j - 1] == 1)) ||
  1379.                 ((j < maxPoint) && (ndbord[i][j + 1] == 1)) ||
  1380.                 ((i > 0) && (j > 0) && (ndbord[i - 1][j - 1] == 1)) ||
  1381.                 ((i < maxPoint) && (j > 0) && (ndbord[i + 1][j - 1] == 1)) ||
  1382.                 ((i > 0) && (j < maxPoint) && (ndbord[i - 1][j + 1] == 1)) ||
  1383.                 ((i < maxPoint) && (j < maxPoint) &&
  1384.                  (ndbord[i + 1][j + 1] == 1))) &&
  1385.                (((i > 0) && (claim[i - 1][j] < 0)) ||
  1386.                 ((i < maxPoint) && (claim[i + 1][j] < 0)) ||
  1387.                 ((j > 0) && (claim[i][j - 1] < 0)) ||
  1388.                 ((j < maxPoint) && (claim[i][j + 1] < 0))))
  1389.               {
  1390.                 na = 0;
  1391.                 if ((i > 0) && (ndbord[i - 1][j] != 0))
  1392.                   na = na + 1;
  1393.                 if ((i < maxPoint) && (ndbord[i + 1][j] != 0))
  1394.                   na = na + 1;
  1395.                 if ((j > 0) && (ndbord[i][j - 1] != 0))
  1396.                   na = na + 1;
  1397.                 if ((j < maxPoint) && (ndbord[i][j + 1] != 0))
  1398.                   na = na + 1;
  1399.                 if (na < 3)
  1400.                   if (safeMove(i, j))
  1401.                     {
  1402.                       infl = claim[i][j];
  1403.                       *x = i;
  1404.                       *y = j;
  1405.                     }
  1406.               }
  1407.     if (*x != iNil) return TRUE;
  1408.     return FALSE;
  1409.   } /* pushWall */
  1410.  
  1411.  
  1412.   /*
  1413.     reduces the liberty count of one of his groups
  1414.   */
  1415. short reduceHisLiberties(x, y)
  1416. short *x, *y;
  1417.   { /* reduceHisLiberties */
  1418.     short i, j;
  1419.     playReason = "reduceHisLiberties";
  1420.     sortLibs();
  1421.     for (i = 1; i <= maxGroupID; i++)
  1422.         if ((! gList[sGlist[i]].isLive) &&
  1423.            (gList[sGlist[i]].libC > 2) &&
  1424.            (ndbord[gList[sGlist[i]].lx][gList[sGlist[i]].ly] == -1))
  1425.           {
  1426.             spanGroup(gList[sGlist[i]].lx, gList[sGlist[i]].ly, &pList);
  1427.             for (j = 1; j <= pList.indx; j++)
  1428.                 if (legal[pList.p[j].px][pList.p[j].py] &&
  1429.                    (connectMap[pList.p[j].px][pList.p[j].py] > 0))
  1430.                   if (safeMove(pList.p[j].px, pList.p[j].py))
  1431.                     {
  1432.                       *x = pList.p[j].px;
  1433.                       *y = pList.p[j].py;
  1434.                       return TRUE;
  1435.                     }
  1436.           }
  1437.     return FALSE;
  1438.   } /* reduceHisLiberties */
  1439.  
  1440.  
  1441.   /*
  1442.     connects a group to the edge
  1443.   */
  1444. short dropToEdge2(x, y)
  1445. short *x, *y;
  1446.   { /* dropToEdge2 */
  1447.     short i;
  1448.     playReason = "dropToEdge2";
  1449.     for (i = 1; i <= maxPoint - 1; i++)
  1450.       {
  1451.         if (legal[i][0])
  1452.           {
  1453.             if ((ndbord[i][1] == 1) &&
  1454.                ((ndbord[i - 1][0] < 1) ||
  1455.                 (groupIDs[i - 1][0] != groupIDs[i][1])) &&
  1456.                ((ndbord[i + 1][0] < 1) ||
  1457.                 (groupIDs[i + 1][0] != groupIDs[i][1])) &&
  1458.                ((ndbord[i - 1][1] == -1) ||
  1459.                 (ndbord[i + 1][1] == -1)))
  1460.               {
  1461.                 *x = i;
  1462.                 *y = 0;
  1463.                 if (safeMove(*x, *y))
  1464.                   return TRUE;
  1465.               }
  1466.           }
  1467.         if (legal[0][i])
  1468.           {
  1469.             if ((ndbord[1][i] == 1) &&
  1470.                ((ndbord[0][i - 1] < 1) ||
  1471.                 (groupIDs[0][i - 1] != groupIDs[1][i])) &&
  1472.                ((ndbord[0][i + 1] < 1) ||
  1473.                 (groupIDs[0][i + 1] != groupIDs[1][i])) &&
  1474.                ((ndbord[1][i - 1] == -1) ||
  1475.                 (ndbord[1][i + 1] == -1)))
  1476.               {
  1477.                 *x = 0;
  1478.                 *y = i;
  1479.                 if (safeMove(*x, *y))
  1480.                   return TRUE;
  1481.               }
  1482.           }
  1483.         if (legal[i][maxPoint])
  1484.           {
  1485.             if ((ndbord[i][maxPoint - 1] == 1) &&
  1486.                ((ndbord[i - 1][maxPoint] < 1) ||
  1487.                 (groupIDs[i - 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
  1488.                ((ndbord[i + 1][maxPoint] < 1) ||
  1489.                 (groupIDs[i + 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
  1490.                ((ndbord[i - 1][maxPoint - 1] == -1) ||
  1491.                 (ndbord[i + 1][maxPoint - 1] == -1)))
  1492.               {
  1493.                 *x = i;
  1494.                 *y = maxPoint;
  1495.                 if (safeMove(*x, *y))
  1496.                   return TRUE;
  1497.               }
  1498.           }
  1499.         if (legal[maxPoint][i])
  1500.           {
  1501.             if ((ndbord[maxPoint - 1][i] == 1) &&
  1502.                ((ndbord[maxPoint][i - 1] < 1) ||
  1503.                 (groupIDs[maxPoint][i - 1] != groupIDs[maxPoint - 1][i])) &&
  1504.                ((ndbord[maxPoint][i + 1] < 1) ||
  1505.                 (groupIDs[maxPoint][i + 1] != groupIDs[maxPoint - 1][i])) &&
  1506.                ((ndbord[maxPoint - 1][i - 1] == -1) ||
  1507.                 (ndbord[maxPoint - 1][i + 1] == -1)))
  1508.               {
  1509.                 *x = maxPoint;
  1510.                 *y = i;
  1511.                 if (safeMove(*x, *y))
  1512.                   return TRUE;
  1513.               }
  1514.           }
  1515.       }
  1516.     return FALSE;
  1517.   } /* dropToEdge2 */
  1518.  
  1519.