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