-rw-r--r-- | noncore/games/go/amigo.c | 656 |
1 files changed, 656 insertions, 0 deletions
diff --git a/noncore/games/go/amigo.c b/noncore/games/go/amigo.c new file mode 100644 index 0000000..cd61013 --- a/dev/null +++ b/noncore/games/go/amigo.c | |||
@@ -0,0 +1,656 @@ | |||
1 | /* Go started 4/17/88 by Todd R. Johnson */ | ||
2 | /* 8/8/89 cleaned up for first release */ | ||
3 | /* Public Domain */ | ||
4 | |||
5 | #include "go.h" | ||
6 | #include "goplayutils.h" | ||
7 | #include "amigo.h" | ||
8 | |||
9 | |||
10 | extern char*playReason; | ||
11 | extern shortplayLevel, showTrees; | ||
12 | |||
13 | struct bRec goboard[19][19]; /*-- The main go board --*/ | ||
14 | |||
15 | struct Group GroupList[MAXGROUPS]; /*-- The list of Groups --*/ | ||
16 | short DeletedGroups[4]; /*-- Codes of deleted groups--*/ | ||
17 | |||
18 | short GroupCount = 0; /*-- The total number of groups--*/ | ||
19 | short DeletedGroupCount; /*-- The total number of groups--*/ | ||
20 | /*-- deleted on a move --*/ | ||
21 | short ko, koX, koY; | ||
22 | short blackTerritory,whiteTerritory; | ||
23 | short blackPrisoners, whitePrisoners; | ||
24 | short showMoveReason= FALSE, | ||
25 | groupInfo= FALSE, | ||
26 | whitePassed= FALSE, | ||
27 | blackPassed= FALSE; | ||
28 | |||
29 | |||
30 | /* Arrays for use when checking around a point */ | ||
31 | short xVec[4] = {0, 1, 0, -1}; | ||
32 | short yVec[4] = {-1, 0, 1, 0}; | ||
33 | |||
34 | short | ||
35 | member(group, grouplist, cnt) | ||
36 | short group; | ||
37 | short grouplist[4]; | ||
38 | short cnt; | ||
39 | { | ||
40 | unsigned shorti; | ||
41 | |||
42 | |||
43 | for (i = 0; i < cnt; i++) | ||
44 | if (grouplist[i] == group) | ||
45 | return TRUE; | ||
46 | return FALSE; | ||
47 | } | ||
48 | |||
49 | /* Does a stone at x, y connect to any groups of color? */ | ||
50 | short | ||
51 | Connect( color, x, y, fGroups, fCnt, eGroups, eCnt) | ||
52 | enum bValcolor; | ||
53 | short x, y; | ||
54 | short fGroups[4], eGroups[4]; | ||
55 | short *fCnt, *eCnt; | ||
56 | { | ||
57 | unsigned shortpoint = 0; | ||
58 | short tx, ty, total = 0; | ||
59 | enum bValopcolor = WHITE; | ||
60 | |||
61 | |||
62 | *fCnt = 0; | ||
63 | *eCnt = 0; | ||
64 | if (color == WHITE) | ||
65 | opcolor = BLACK; | ||
66 | for (point = 0; point <= 3; point++ ) | ||
67 | { | ||
68 | tx = x + xVec[point]; | ||
69 | ty = y + yVec[point]; | ||
70 | if (!LegalPoint(tx,ty)) | ||
71 | continue; | ||
72 | if (goboard[tx][ty].Val == color) | ||
73 | { | ||
74 | total++; | ||
75 | if (!member(goboard[tx][ty].GroupNum, fGroups, *fCnt)) | ||
76 | fGroups[(*fCnt)++] = goboard[tx][ty].GroupNum; | ||
77 | } | ||
78 | else if (goboard[tx][ty].Val == opcolor) | ||
79 | { | ||
80 | total++; | ||
81 | if (!member(goboard[tx][ty].GroupNum, eGroups, *eCnt)) | ||
82 | eGroups[(*eCnt)++] = goboard[tx][ty].GroupNum; | ||
83 | } | ||
84 | } | ||
85 | return total; | ||
86 | } | ||
87 | |||
88 | /* Returns the maximum number of liberties for a given intersection */ | ||
89 | short | ||
90 | Maxlibs(x, y) | ||
91 | shortx, y; | ||
92 | { | ||
93 | shortcnt = 4; | ||
94 | |||
95 | |||
96 | if (x == 0 || x == 18) | ||
97 | cnt--; | ||
98 | if (y == 0 || y == 18) | ||
99 | cnt--; | ||
100 | return cnt; | ||
101 | } | ||
102 | |||
103 | DeleteGroupFromStone(x,y) | ||
104 | shortx,y; | ||
105 | { | ||
106 | if (goboard[x][y].Val != EMPTY) | ||
107 | GroupCapture(goboard[x][y].GroupNum); | ||
108 | } | ||
109 | |||
110 | /* Determine whether x, y is suicide for color */ | ||
111 | short | ||
112 | Suicide(color, x, y) | ||
113 | enum bValcolor; | ||
114 | short x, y; | ||
115 | { | ||
116 | enum bValopcolor = BLACK; | ||
117 | short friendlycnt, friendlygroups[4], | ||
118 | enemycnt, enemygroups[4], | ||
119 | total; | ||
120 | short maxlibs, i, libcnt = 0; | ||
121 | |||
122 | |||
123 | if (color == BLACK) | ||
124 | opcolor = WHITE; | ||
125 | maxlibs = Maxlibs( x, y); | ||
126 | total = Connect(color, x, y, friendlygroups, &friendlycnt, | ||
127 | enemygroups, &enemycnt); | ||
128 | |||
129 | if (total < maxlibs) | ||
130 | return FALSE; | ||
131 | |||
132 | /* Check for a capture */ | ||
133 | for (i = 0; i < enemycnt; i++) | ||
134 | if (GroupList[enemygroups[i]].liberties == 1) | ||
135 | return FALSE; | ||
136 | for (i = 0; i < friendlycnt; i++) | ||
137 | libcnt += (GroupList[friendlygroups[i]].liberties - 1); | ||
138 | if (libcnt != 0) | ||
139 | return FALSE; | ||
140 | return TRUE; | ||
141 | } | ||
142 | |||
143 | /* Returns the number of liberties for x, y */ | ||
144 | short | ||
145 | StoneLibs(x, y) | ||
146 | short x, y; | ||
147 | { | ||
148 | short cnt = 0, tx, ty; | ||
149 | unsigned shortpoint; | ||
150 | |||
151 | |||
152 | for (point = 0; point <= 3; point++) | ||
153 | { | ||
154 | tx = x + xVec[point]; | ||
155 | ty = y + yVec[point]; | ||
156 | if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY) | ||
157 | cnt++; | ||
158 | } | ||
159 | return cnt; | ||
160 | } | ||
161 | |||
162 | void | ||
163 | EraseMarks() | ||
164 | { | ||
165 | register short i; | ||
166 | register struct bRec *gpt= &goboard[0][0]; | ||
167 | |||
168 | |||
169 | for (i=0; i<361; gpt++,i++) | ||
170 | gpt->marked = FALSE; | ||
171 | } | ||
172 | |||
173 | /* Place a stone of color at x, y */ | ||
174 | short | ||
175 | GoPlaceStone(color, x, y) | ||
176 | enum bValcolor; | ||
177 | short x, y; | ||
178 | { | ||
179 | short fgroups[4], egroups[4];/* group codes surrounding stone */ | ||
180 | shortfcnt, ecnt, i; | ||
181 | shortlowest = GroupCount + 1; | ||
182 | |||
183 | |||
184 | DeletedGroupCount = 0; | ||
185 | if (goboard[x][y].Val != EMPTY || Suicide(color,x,y)) | ||
186 | return FALSE; | ||
187 | |||
188 | if (ko && koX == x && koY == y) | ||
189 | return FALSE; | ||
190 | |||
191 | ko = FALSE; | ||
192 | placestone(color, x, y); | ||
193 | goboard[x][y].Val = color; | ||
194 | /* Does the new stone connect to any friendly stone(s)? */ | ||
195 | Connect(color, x, y, fgroups, &fcnt, egroups, &ecnt); | ||
196 | if (fcnt) | ||
197 | { | ||
198 | /* Find the connecting friendly group with the lowest code */ | ||
199 | for (i = 0; i < fcnt; i++) | ||
200 | if (fgroups[i] <= lowest) | ||
201 | lowest = fgroups[i]; | ||
202 | /*-- Renumber resulting group --*/ | ||
203 | /*-- Raise the stone count of the lowest by one to account --*/ | ||
204 | /*-- for new stone --*/ | ||
205 | goboard[x][y].GroupNum = lowest; | ||
206 | GroupList[lowest].count++; | ||
207 | for (i = 0; i < fcnt; i++) | ||
208 | if (fgroups[i] != lowest) | ||
209 | MergeGroups(lowest, fgroups[i]); | ||
210 | /* Fix the liberties of the resulting group */ | ||
211 | CountLiberties(lowest); | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | /* Isolated stone. Create new group. */ | ||
216 | GroupCount++; | ||
217 | lowest = GroupCount; | ||
218 | GroupList[lowest].color = color; | ||
219 | GroupList[lowest].count = 1; | ||
220 | GroupList[lowest].internal = 0; | ||
221 | GroupList[lowest].external = StoneLibs( x, y); | ||
222 | GroupList[lowest].liberties = GroupList[lowest].external; | ||
223 | GroupList[lowest].eyes = 0; | ||
224 | GroupList[lowest].alive = 0; | ||
225 | GroupList[lowest].territory = 0; | ||
226 | goboard[x][y].GroupNum = lowest; | ||
227 | } | ||
228 | /* Now fix the liberties of enemy groups adjacent to played stone */ | ||
229 | FixLibs(color, x, y, PLACED); /* Fix the liberties of opcolor */ | ||
230 | ReEvalGroups(color, x, y, lowest); | ||
231 | RelabelGroups(); | ||
232 | return TRUE; | ||
233 | } | ||
234 | |||
235 | /* Remove a stone from the board */ | ||
236 | void | ||
237 | GoRemoveStone(x, y) | ||
238 | shortx, y; | ||
239 | { | ||
240 | goboard[x][y].Val = EMPTY; | ||
241 | goboard[x][y].GroupNum = 0; | ||
242 | removestone( x, y); | ||
243 | } | ||
244 | |||
245 | /* Merges two groups -- Renumbers stones and deletes second group from | ||
246 | list. Fixes stone count of groups. This does not fix anything else. | ||
247 | FixLibs must be called to fix liberties, etc. */ | ||
248 | void | ||
249 | MergeGroups(g1, g2) | ||
250 | shortg1, g2; | ||
251 | { | ||
252 | shortx, y; | ||
253 | |||
254 | |||
255 | ForeachPoint(y,x) | ||
256 | if (goboard[x][y].GroupNum == g2) | ||
257 | goboard[x][y].GroupNum = g1; | ||
258 | GroupList[g1].count += GroupList[g2].count; | ||
259 | DeleteGroup( g2 ); /* Removes group from GroupList */ | ||
260 | } | ||
261 | |||
262 | /* Stores a group code to be deleted */ | ||
263 | void | ||
264 | DeleteGroup(code) | ||
265 | shortcode; | ||
266 | { | ||
267 | DeletedGroups[DeletedGroupCount++] = code; | ||
268 | } | ||
269 | |||
270 | /* Re-evaluate the groups given the last move. This assumes that the | ||
271 | last move has been merged into adjoining groups and all liberty counts | ||
272 | are correct. Handles capture. Checks for Ko. Keeps track of captured | ||
273 | stones. code is the group number of the stone just played. */ | ||
274 | void | ||
275 | ReEvalGroups(color, x, y, code) | ||
276 | enum bValcolor; | ||
277 | short x, y, code; | ||
278 | { | ||
279 | short fgroups[4], egroups[4], | ||
280 | fcnt, ecnt, i, killcnt = 0, count = 0; | ||
281 | enum bValopcolor = BLACK; | ||
282 | |||
283 | if (color == BLACK) | ||
284 | opcolor = WHITE; | ||
285 | /* Check for capture */ | ||
286 | Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt); | ||
287 | if (ecnt) | ||
288 | { | ||
289 | /* See if any of the groups have no liberties */ | ||
290 | for (i = 0; i < ecnt; i++) | ||
291 | if (GroupList[egroups[i]].liberties == 0) | ||
292 | { | ||
293 | killcnt++; | ||
294 | count = GroupList[egroups[i]].count; | ||
295 | GroupCapture( egroups[i]); | ||
296 | } | ||
297 | } | ||
298 | /* Check for ko. koX and koY are set in GroupCapture above. */ | ||
299 | if (killcnt == 1 && count == 1 && GroupList[ code ].count == 1 | ||
300 | && GroupList[ code ].liberties == 1) | ||
301 | { | ||
302 | ko = TRUE; | ||
303 | } | ||
304 | if (killcnt) | ||
305 | intrPrisonerReport( blackPrisoners, whitePrisoners); | ||
306 | /* Set eye count for groups */ | ||
307 | CountEyes(); | ||
308 | } | ||
309 | |||
310 | /* Remove a captured group from the board and fix the liberties of any | ||
311 | adjacent groups. Fixes prisoner count. Sets KoX and KoY */ | ||
312 | /*-- update display of captured stones -neilb --*/ | ||
313 | void | ||
314 | GroupCapture(code) | ||
315 | shortcode; | ||
316 | { | ||
317 | shortx, y; | ||
318 | |||
319 | if (GroupList[code].color == BLACK) | ||
320 | blackPrisoners += GroupList[code].count; | ||
321 | else | ||
322 | whitePrisoners += GroupList[code].count; | ||
323 | intrPrisonerReport(blackPrisoners, whitePrisoners); | ||
324 | ForeachPoint(y,x) | ||
325 | if (goboard[x][y].GroupNum == code) | ||
326 | { | ||
327 | FixLibs(GroupList[code].color,x,y,REMOVED); | ||
328 | GoRemoveStone(x, y); | ||
329 | koX = x; | ||
330 | koY = y; | ||
331 | } | ||
332 | DeleteGroup( code); | ||
333 | } | ||
334 | |||
335 | /* Fix the liberties of groups adjacent to x, y. move indicates | ||
336 | whether a stone of color was placed or removed at x, y | ||
337 | This does not change liberty counts of friendly groups when a stone | ||
338 | is placed. Does not do captures. */ | ||
339 | void | ||
340 | FixLibs( color, x, y, move) | ||
341 | enumbVal color; | ||
342 | shortx, y, move; | ||
343 | { | ||
344 | shortfgroups[4], fcnt, egroups[4], ecnt, i; | ||
345 | enumbVal opcolor = BLACK; | ||
346 | |||
347 | if (color == BLACK) | ||
348 | opcolor = WHITE; | ||
349 | Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt); | ||
350 | if (move == PLACED) | ||
351 | for (i = 0; i < ecnt; i++) | ||
352 | GroupList[egroups[i]].liberties--; | ||
353 | else /* Stone removed so increment opcolor */ | ||
354 | for (i = 0; i < ecnt; i++) | ||
355 | GroupList[egroups[i]].liberties++; | ||
356 | } | ||
357 | |||
358 | void | ||
359 | goSetHandicap(handicap) | ||
360 | int handicap; | ||
361 | { | ||
362 | if (handicap < 2) | ||
363 | return; | ||
364 | |||
365 | GoPlaceStone(BLACK,3,3); | ||
366 | GoPlaceStone(BLACK,15,15); | ||
367 | |||
368 | if (handicap >= 3) | ||
369 | GoPlaceStone(BLACK,15,3); | ||
370 | if (handicap >= 4) | ||
371 | GoPlaceStone(BLACK,3,15); | ||
372 | if (handicap == 5 || handicap == 7 || handicap == 9) | ||
373 | GoPlaceStone(BLACK,9,9); | ||
374 | if (handicap >= 6) | ||
375 | { | ||
376 | GoPlaceStone(BLACK,15,9); | ||
377 | GoPlaceStone(BLACK,3,9); | ||
378 | } | ||
379 | if (handicap >= 8) | ||
380 | { | ||
381 | GoPlaceStone(BLACK,9,15); | ||
382 | GoPlaceStone(BLACK,9,3); | ||
383 | } | ||
384 | } | ||
385 | |||
386 | void | ||
387 | goRestart(handicap) | ||
388 | inthandicap; | ||
389 | { | ||
390 | register short i; | ||
391 | register struct bRec *gpt= &goboard[0][0]; | ||
392 | |||
393 | |||
394 | GroupCount = 0; | ||
395 | ko = FALSE; | ||
396 | blackPrisoners = whitePrisoners = 0; | ||
397 | intrPrisonerReport(0, 0); | ||
398 | for (i=0; i<361; gpt++,i++) | ||
399 | { | ||
400 | gpt->Val = EMPTY; | ||
401 | gpt->GroupNum = 0; | ||
402 | } | ||
403 | goSetHandicap(handicap); | ||
404 | } | ||
405 | |||
406 | |||
407 | /* if any groups have been deleted as a result of the last move, this | ||
408 | routine will delete the old group numbers from GroupList and | ||
409 | reassign group numbers. */ | ||
410 | void | ||
411 | RelabelGroups() | ||
412 | { | ||
413 | unsignedshort i, j, x, y; | ||
414 | |||
415 | for (i = 0; i < DeletedGroupCount; i++) | ||
416 | { | ||
417 | /* Relabel all higher groups */ | ||
418 | ForeachPoint(y,x) | ||
419 | if (goboard[x][y].GroupNum > DeletedGroups[i]) | ||
420 | goboard[x][y].GroupNum--; | ||
421 | /* Move the groups down */ | ||
422 | for (y = DeletedGroups[i]; y < GroupCount; y++) | ||
423 | GroupList[y] = GroupList[y+1]; | ||
424 | /* fix the group numbers stored in the deleted list */ | ||
425 | for (j = i+1; j < DeletedGroupCount; j++) | ||
426 | if (DeletedGroups[j] > DeletedGroups[i]) | ||
427 | DeletedGroups[j]--; | ||
428 | GroupCount--; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | /* Returns liberty count for x, y intersection. Sets marked to true | ||
433 | for each liberty */ | ||
434 | short | ||
435 | CountAndMarkLibs( x, y) | ||
436 | shortx, y; | ||
437 | { | ||
438 | shorttx,ty,i; | ||
439 | shortcnt = 0; | ||
440 | |||
441 | |||
442 | for (i=0;i<4;i++) | ||
443 | { | ||
444 | tx = x + xVec[i]; | ||
445 | ty = y + yVec[i]; | ||
446 | if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY | ||
447 | && goboard[tx][ty].marked == FALSE) | ||
448 | { | ||
449 | cnt++; | ||
450 | goboard[tx][ty].marked = TRUE; | ||
451 | } | ||
452 | } | ||
453 | return cnt; | ||
454 | } | ||
455 | |||
456 | /* Determine the number of liberties for a group given the group code | ||
457 | num */ | ||
458 | void | ||
459 | CountLiberties( code) | ||
460 | shortcode; | ||
461 | { | ||
462 | shortx, y, libcnt = 0; | ||
463 | |||
464 | ForeachPoint(y,x) | ||
465 | if (goboard[x][y].GroupNum == code) | ||
466 | libcnt += CountAndMarkLibs( x, y); | ||
467 | EraseMarks(); | ||
468 | GroupList[code].liberties = libcnt; | ||
469 | } | ||
470 | |||
471 | void | ||
472 | CheckForEye( x, y, groups, cnt, recheck) | ||
473 | shortx, y, groups[4], cnt, *recheck; | ||
474 | { | ||
475 | shorti; | ||
476 | |||
477 | for (i = 0; i < (cnt-1); i++) | ||
478 | if (groups[i] != groups[i+1]) | ||
479 | { | ||
480 | /* Mark liberty for false eye check */ | ||
481 | goboard[x][y].marked = TRUE; | ||
482 | (*recheck)++; | ||
483 | return; | ||
484 | } | ||
485 | /* It is an eye */ | ||
486 | GroupList[groups[i]].eyes += 1; | ||
487 | } | ||
488 | |||
489 | /* Set the eye count for the groups */ | ||
490 | void CountEyes() | ||
491 | { | ||
492 | shorti, x, y, | ||
493 | wgroups[4], bgroups[4], wcnt, bcnt, max, cnt, recheck = 0, eye; | ||
494 | |||
495 | for (i = 1; i <= GroupCount; i++) | ||
496 | GroupList[i].eyes = 0; | ||
497 | |||
498 | ForeachPoint(y,x) | ||
499 | { | ||
500 | if (goboard[x][y].Val != EMPTY) | ||
501 | continue; | ||
502 | cnt = Connect(WHITE,x,y,wgroups,&wcnt,bgroups,&bcnt); | ||
503 | max = Maxlibs( x, y); | ||
504 | if (cnt == max && wcnt == 1 && bcnt == 0) | ||
505 | GroupList[wgroups[0]].eyes++; | ||
506 | else if (cnt == max && bcnt == 1 && wcnt == 0) | ||
507 | GroupList[bgroups[0]].eyes++; | ||
508 | else if (cnt == max && ( bcnt == 0 || wcnt == 0 )) | ||
509 | { | ||
510 | goboard[x][y].marked = TRUE; | ||
511 | recheck++; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | /*-- Now recheck marked liberties to see if two or more one eye --*/ | ||
516 | /*-- groups contribute to a false eye */ | ||
517 | if (recheck == 0) | ||
518 | return; | ||
519 | |||
520 | ForeachPoint(y,x) | ||
521 | if (goboard[x][y].marked) | ||
522 | { | ||
523 | recheck--; | ||
524 | goboard[x][y].marked = FALSE; | ||
525 | Connect( WHITE, x, y, wgroups, &wcnt, bgroups, &bcnt); | ||
526 | /* If all the groups have at least one eye then all the | ||
527 | groups are safe from capture because of the common | ||
528 | liberty at x, y */ | ||
529 | eye = TRUE; | ||
530 | for (i = 0; i < wcnt; i++) | ||
531 | if (GroupList[wgroups[i]].eyes == 0) | ||
532 | eye = FALSE; | ||
533 | if (eye) | ||
534 | for (i = 0; i < wcnt; i++) | ||
535 | GroupList[wgroups[i]].eyes++; | ||
536 | for (i = 0; i < bcnt; i++) | ||
537 | if (GroupList[bgroups[i]].eyes == 0) | ||
538 | eye = FALSE; | ||
539 | if (eye) | ||
540 | for (i = 0; i < bcnt; i++) | ||
541 | GroupList[bgroups[i]].eyes++; | ||
542 | if (recheck == 0) | ||
543 | return; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | |||
548 | shortfoo[19][19]; | ||
549 | |||
550 | /*---------------------------------------------------------------- | ||
551 | -- CountUp() -- | ||
552 | -- Count up final scores at the end of the game. -- | ||
553 | ----------------------------------------------------------------*/ | ||
554 | CountUp( wtotal, btotal ) | ||
555 | int *wtotal, *btotal; | ||
556 | { | ||
557 | shortx,y; | ||
558 | shortCountFromPoint(); | ||
559 | shortvv; | ||
560 | charbuff[512]; | ||
561 | |||
562 | |||
563 | blackTerritory = whiteTerritory = 0; | ||
564 | ForeachPoint(y,x) | ||
565 | { | ||
566 | goboard[x][y].marked = FALSE; | ||
567 | foo[x][y] = CNT_UNDECIDED; | ||
568 | } | ||
569 | ForeachPoint(y,x) | ||
570 | if (goboard[x][y].Val==EMPTY && foo[x][y]==CNT_UNDECIDED) | ||
571 | { | ||
572 | FillPoints(x,y,CountFromPoint(x,y)); | ||
573 | } | ||
574 | |||
575 | *wtotal = whiteTerritory + blackPrisoners; | ||
576 | *btotal = blackTerritory + whitePrisoners; | ||
577 | /* | ||
578 | sprintf(buff,"White : %3d territory + %3d prisoners = %d\n\ | ||
579 | Black : %3d territory + %3d prisoners = %d\n\n%s.\n", | ||
580 | whiteTerritory,blackPrisoners,*wtotal, | ||
581 | blackTerritory,whitePrisoners,*btotal, | ||
582 | (*btotal>*wtotal?"Black wins":(*wtotal>*btotal?"White wins": | ||
583 | "A draw"))); | ||
584 | |||
585 | |||
586 | |||
587 | XtVaSetValues(message,XtNstring,buff,0); | ||
588 | printf( "CountUp() %s", buff ); | ||
589 | */ | ||
590 | } | ||
591 | |||
592 | FillPoints(x,y,val) | ||
593 | shortx,y,val; | ||
594 | { | ||
595 | inti; | ||
596 | shorttx,ty; | ||
597 | |||
598 | |||
599 | if ((foo[x][y] = val) == CNT_BLACK_TERR) | ||
600 | blackTerritory++; | ||
601 | else if (val == CNT_WHITE_TERR) | ||
602 | whiteTerritory++; | ||
603 | for (i=0;i<4;i++) | ||
604 | { | ||
605 | tx = x + xVec[i]; | ||
606 | ty = y + yVec[i]; | ||
607 | if (!LegalPoint(tx,ty)) | ||
608 | continue; | ||
609 | if (goboard[tx][ty].Val==EMPTY && foo[tx][ty]==CNT_UNDECIDED) | ||
610 | FillPoints(tx,ty,val); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | short | ||
615 | CountFromPoint(x,y) | ||
616 | shortx,y; | ||
617 | { | ||
618 | inti; | ||
619 | shorttx,ty; | ||
620 | shortblkcnt=0,whtcnt=0; | ||
621 | shortbaz; | ||
622 | |||
623 | |||
624 | goboard[x][y].marked = TRUE; | ||
625 | for (i=0;i<4;i++) | ||
626 | { | ||
627 | tx = x + xVec[i]; | ||
628 | ty = y + yVec[i]; | ||
629 | if (!LegalPoint(tx,ty)) | ||
630 | continue; | ||
631 | if (goboard[tx][ty].Val == BLACK) | ||
632 | blkcnt++; | ||
633 | else if (goboard[tx][ty].Val == WHITE) | ||
634 | whtcnt++; | ||
635 | else | ||
636 | { | ||
637 | if (goboard[tx][ty].marked) | ||
638 | continue; | ||
639 | baz = CountFromPoint(tx,ty); | ||
640 | if (baz == CNT_NOONE) | ||
641 | return CNT_NOONE; | ||
642 | else if (baz == CNT_BLACK_TERR) | ||
643 | blkcnt++; | ||
644 | else if (baz == CNT_WHITE_TERR) | ||
645 | whtcnt++; | ||
646 | } | ||
647 | if (blkcnt && whtcnt) | ||
648 | return CNT_NOONE; | ||
649 | } | ||
650 | if (blkcnt && !whtcnt) | ||
651 | return CNT_BLACK_TERR; | ||
652 | else if (whtcnt && !blkcnt) | ||
653 | return CNT_WHITE_TERR; | ||
654 | else | ||
655 | return CNT_UNDECIDED; | ||
656 | } | ||