summaryrefslogtreecommitdiff
path: root/noncore/games/go/goplayer.c
Unidiff
Diffstat (limited to 'noncore/games/go/goplayer.c') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/go/goplayer.c1499
1 files changed, 1499 insertions, 0 deletions
diff --git a/noncore/games/go/goplayer.c b/noncore/games/go/goplayer.c
new file mode 100644
index 0000000..88c0f61
--- a/dev/null
+++ b/noncore/games/go/goplayer.c
@@ -0,0 +1,1499 @@
1/* The go player */
2/* Ported from Pascal to C by Todd R. Johnson 4/17/88 */
3/* From the original pascal file:
4Go Move Generator
5Copyright (c) 1983 by Three Rivers Computer Corp.
6
7Written: January 17, 1983 by Stoney Ballard
8Edit History:
9*/
10
11#include "go.h"
12#include "goplayutils.h"
13#include "amigo.h"
14
15 #define BIGGEST 32767/* maximum value for short */
16
17/* From go.c */
18extern struct bRec goboard[19][19];
19extern short ko, koX, koY;
20
21/* From goplayutils.c */
22extern intBoard bord;
23extern intBoard ndbord;
24extern intBoard claim;
25extern intBoard legal;
26extern intBoard connectMap;
27extern intBoard threatBord;
28extern short maxGroupID;
29extern short treeLibLim;
30extern short killFlag;
31extern short depthLimit;
32extern short showTrees;
33extern short utilPlayLevel;
34extern groupRec gList[maxGroup];
35extern short sGlist[maxGroup + 1];
36extern pointList pList;
37extern pointList pList1;
38extern pointList plist2;
39extern pointList plist3;
40extern intBoard groupIDs;
41extern intBoard protPoints;
42extern sType mySType;
43
44
45short saveNLibs;
46pointList dapList1, dapList2, dapList3;
47char *playReason;
48short maxPlayLevel = 7;
49short playLevel = 7;
50
51genBord(color)
52 enum bValcolor;
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
96short getMove( x, y )
97short *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
122short genMove( color, x, y )
123enum bVal color;
124short *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
136short checkPos(x, y, field)
137short 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
152short takeCorner( x, y )
153short *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
183printBoard(brd, name)
184intBoard brd;
185char *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
197short noNbrs( x, y )
198short 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
207short extend(x, y)
208short *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
243short extend2( x, y )
244short *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 */
315short lookForSave(x, y)
316short *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 */
331short lookForSaveN(x, y)
332short *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----------------------------------------------------------------*/
356short
357lookForKill(x, y)
358 short*x, *y;
359{
360 shorti;
361 charmv[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
380short doubleAtari(x, y)
381short *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
415short lookForAttack(x, y)
416short *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 */
439short threaten(x, y)
440short *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 */
478short connectCut(x, y)
479short *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
735short heCanCut(x, y)
736short 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 */
754short safeMove(x, y)
755short 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 */
782short extendWall(x, y)
783short *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 */
818short findAttack2(x, y)
819short *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 */
849short blockCut(x, y)
850short *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 */
922short cutHim(x, y)
923short *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 */
1108short atariAnyway(x, y)
1109short *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 */
1158short underCut(x, y)
1159short *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 */
1212short dropToEdge(x, y)
1213short *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 */
1344short pushWall(x, y)
1345short *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 */
1396short reduceHisLiberties(x, y)
1397short *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 */
1425short dropToEdge2(x, y)
1426short *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