author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /noncore/games/go/goplayer.c | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
-rw-r--r-- | noncore/games/go/goplayer.c | 1499 |
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: | ||
4 | Go Move Generator | ||
5 | Copyright (c) 1983 by Three Rivers Computer Corp. | ||
6 | |||
7 | Written: January 17, 1983 by Stoney Ballard | ||
8 | Edit History: | ||
9 | */ | ||
10 | |||
11 | #include "go.h" | ||
12 | #include "goplayutils.h" | ||
13 | #include "amigo.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 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 | |||
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 | 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 | |||
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 | |||