summaryrefslogtreecommitdiff
path: root/noncore/games/go
Unidiff
Diffstat (limited to 'noncore/games/go') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/go/.cvsignore2
-rw-r--r--noncore/games/go/Makefile.in158
-rw-r--r--noncore/games/go/README3
-rw-r--r--noncore/games/go/README.AMIGO42
-rw-r--r--noncore/games/go/README.XAMIGO26
-rw-r--r--noncore/games/go/amigo.c656
-rw-r--r--noncore/games/go/amigo.h146
-rw-r--r--noncore/games/go/go.h81
-rw-r--r--noncore/games/go/go.pro19
-rw-r--r--noncore/games/go/goplayer.c1499
-rw-r--r--noncore/games/go/goplayutils.c1317
-rw-r--r--noncore/games/go/goplayutils.h85
-rw-r--r--noncore/games/go/gowidget.cpp449
-rw-r--r--noncore/games/go/gowidget.h111
-rw-r--r--noncore/games/go/killable.c373
-rw-r--r--noncore/games/go/main.cpp35
-rw-r--r--noncore/games/go/qpe-go.control9
17 files changed, 5011 insertions, 0 deletions
diff --git a/noncore/games/go/.cvsignore b/noncore/games/go/.cvsignore
new file mode 100644
index 0000000..6fe2396
--- a/dev/null
+++ b/noncore/games/go/.cvsignore
@@ -0,0 +1,2 @@
1moc_*
2Makefile
diff --git a/noncore/games/go/Makefile.in b/noncore/games/go/Makefile.in
new file mode 100644
index 0000000..27304f1
--- a/dev/null
+++ b/noncore/games/go/Makefile.in
@@ -0,0 +1,158 @@
1#############################################################################
2
3####### Compiler, tools and options
4
5 CXX =$(SYSCONF_CXX) $(QT_CXX_MT)
6 CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
7 CC =$(SYSCONF_CC) $(QT_C_MT)
8 CFLAGS =$(SYSCONF_CFLAGS)
9 INCPATH =-I$(QPEDIR)/include
10 LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
11 LIBS =$(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
12 MOC =$(SYSCONF_MOC)
13 UIC =$(SYSCONF_UIC)
14
15####### Target
16
17DESTDIR = ../bin/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= go
22TARGET1 = lib$(TARGET).so.$(VER_MAJ)
23
24####### Files
25
26 HEADERS =amigo.h \
27 go.h \
28 goplayutils.h \
29 gowidget.h
30 SOURCES =amigo.c \
31 goplayer.c \
32 goplayutils.c \
33 killable.c \
34 gowidget.cpp \
35 main.cpp
36 OBJECTS =amigo.o \
37 goplayer.o \
38 goplayutils.o \
39 killable.o \
40 gowidget.o \
41 main.o
42INTERFACES =
43UICDECLS =
44UICIMPLS =
45 SRCMOC =moc_gowidget.cpp
46 OBJMOC =moc_gowidget.o
47
48
49####### Implicit rules
50
51.SUFFIXES: .cpp .cxx .cc .C .c
52
53.cpp.o:
54 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
55
56.cxx.o:
57 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
58
59.cc.o:
60 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
61
62.C.o:
63 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
64
65.c.o:
66 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
67
68####### Build rules
69
70
71all: $(DESTDIR)$(TARGET)
72
73$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
74 $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
75
76moc: $(SRCMOC)
77
78tmake:
79 tmake go.pro
80
81clean:
82 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
83 -rm -f *~ core
84 -rm -f allmoc.cpp
85
86####### Extension Modules
87
88listpromodules:
89 @echo
90
91listallmodules:
92 @echo
93
94listaddonpromodules:
95 @echo
96
97listaddonentmodules:
98 @echo
99
100
101REQUIRES=
102
103####### Sub-libraries
104
105
106###### Combined headers
107
108
109
110####### Compile
111
112amigo.o: amigo.c \
113 go.h \
114 goplayutils.h \
115 amigo.h
116
117goplayer.o: goplayer.c \
118 go.h \
119 goplayutils.h \
120 amigo.h
121
122goplayutils.o: goplayutils.c \
123 goplayutils.h \
124 amigo.h \
125 go.h
126
127killable.o: killable.c \
128 go.h \
129 goplayutils.h \
130 amigo.h
131
132gowidget.o: gowidget.cpp \
133 gowidget.h \
134 amigo.h \
135 go.h \
136 goplayutils.h \
137 $(QPEDIR)/include/qpe/config.h \
138 $(QPEDIR)/include/qpe/resource.h \
139 $(QPEDIR)/include/qpe/qpetoolbar.h \
140 $(QPEDIR)/include/qpe/qpemenubar.h
141
142main.o: main.cpp \
143 gowidget.h \
144 amigo.h \
145 go.h \
146 goplayutils.h \
147 $(QPEDIR)/include/qpe/qpeapplication.h
148
149moc_gowidget.o: moc_gowidget.cpp \
150 gowidget.h \
151 amigo.h \
152 go.h \
153 goplayutils.h
154
155moc_gowidget.cpp: gowidget.h
156 $(MOC) gowidget.h -o moc_gowidget.cpp
157
158
diff --git a/noncore/games/go/README b/noncore/games/go/README
new file mode 100644
index 0000000..c6fa1f5
--- a/dev/null
+++ b/noncore/games/go/README
@@ -0,0 +1,3 @@
1This Go player For Qtopia is based on Xamigo, which in turn was
2based on Amigo. The original README files are included as README.XAMIGO
3and README.AMIGO.
diff --git a/noncore/games/go/README.AMIGO b/noncore/games/go/README.AMIGO
new file mode 100644
index 0000000..03978e7
--- a/dev/null
+++ b/noncore/games/go/README.AMIGO
@@ -0,0 +1,42 @@
1 This is version 1.0 of AmiGo --- a Go board and player for the Amiga.
2The Amiga interface and board manager were written by Todd R. Johnson.
3The player is a C port of a Pascal player written by Stoney Ballard.
4The interface allows you to play human vs. human, human vs. Amiga, or
5Amiga vs. Amiga.
6
7 The board manager and player could both use some work. Currently,
8you cannot save/load games, take back a move, or automatically score a
9game. It is also limited to a 19 by 19 board. I'm releasing AmiGo
10now because 1) I'm in the final phases of my dissertation and probably
11won't have much time to do any further work on AmiGo, and 2) a lot of
12people have been asking for an Amiga Go player. I am also releasing
13all of the source code so that others can add to and modify AmiGo.
14Note that all of my code in this release is public domain, while the
15ported go player retains the original copyright.
16
17 If you distribute AmiGo, I urge you to include the source
18code. If anyone makes changes, I would appreciate a copy. In fact, I
19am willing to act as a clearinghouse for AmiGo changes.
20
21Todd R. Johnson
22tj@cis.ohio-state.edu
238/8/89
24
25Here is the message attached to the original USENET posting of Stoney
26Ballard's Pascal code. Note that the board manager mentioned here is
27not included in this distribution.
28
29This go board manager and rudimentary go player was written by
30Stoney Ballard at Perq Systems in 1983-1984. It is written in
31Perq Pascal and utilizes some Perq libraries for I/O. The code
32is offered here if someone is interested to convert it to Unix.
33
34The wonderful part about it is that a game is recorded as a tree
35and can be played forward or backward, branching at any point
36where there were alternate moves.
37
38For some time, this program was also used to generate the go
39boards displayed in the American Go Journal. For this it used
40some large font digits which are now lost.
41
42Fred Hansen
diff --git a/noncore/games/go/README.XAMIGO b/noncore/games/go/README.XAMIGO
new file mode 100644
index 0000000..219b25f
--- a/dev/null
+++ b/noncore/games/go/README.XAMIGO
@@ -0,0 +1,26 @@
1
2 Xamigo 1.1
3
4This is an alpha release of xamigo --- a port (read: quick hack) of the
5Amiga Go program AmiGo. I don't have time to get it real nice now,
6but will spend some more time on it when my thesis is out of the way.
7Sadly this is the second time I've said that :-)
8
9The `readme' from the original distribution is included as README.AMIGO
10
11An Imakefile is included, so you should be able to type
12 xmkmf
13 make
14to build xamigo. Let me know if you have problems with the Imakefile,
15preferably with fixes :-)
16
17You *have* to install the app-defaults file (Xamigo.ad) before you use
18xamigo. This should either go in /usr/lib/X11/app-defaults,
19or in your own app-defaults directory, as file Xamigo (ie lose the '.ad')
20If you do the latter, you have to:
21 setenv XAPPLRESDIR <full path of your app-defaults directory>
22
23Feel free to mail me any comments and suggestions for improvements.
24
25Neil
26neilb@scs.leeds.ac.uk
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
34short
35member(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? */
50short
51Connect( 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 */
89short
90Maxlibs(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
103DeleteGroupFromStone(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 */
111short
112Suicide(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 */
144short
145StoneLibs(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
162void
163EraseMarks()
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 */
174short
175GoPlaceStone(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 */
236void
237GoRemoveStone(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
246list. Fixes stone count of groups. This does not fix anything else.
247FixLibs must be called to fix liberties, etc. */
248void
249MergeGroups(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 */
263void
264DeleteGroup(code)
265 shortcode;
266{
267 DeletedGroups[DeletedGroupCount++] = code;
268}
269
270/* Re-evaluate the groups given the last move. This assumes that the
271last move has been merged into adjoining groups and all liberty counts
272are correct. Handles capture. Checks for Ko. Keeps track of captured
273stones. code is the group number of the stone just played. */
274void
275ReEvalGroups(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 --*/
313void
314GroupCapture(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. */
339void
340FixLibs( 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
358void
359goSetHandicap(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
386void
387goRestart(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. */
410void
411RelabelGroups()
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 */
434short
435CountAndMarkLibs( 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 */
458void
459CountLiberties( 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
471void
472CheckForEye( 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 */
490void 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----------------------------------------------------------------*/
554CountUp( 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\
579Black : %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
592FillPoints(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
614short
615CountFromPoint(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}
diff --git a/noncore/games/go/amigo.h b/noncore/games/go/amigo.h
new file mode 100644
index 0000000..5150ac0
--- a/dev/null
+++ b/noncore/games/go/amigo.h
@@ -0,0 +1,146 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20/*=========================================================================
21 === ===
22 === FILE amigo.h ===
23 === ===
24 === CONTENTS prototypes for the various AmiGo routines. ===
25 === added by neilb ===
26 === ===
27=========================================================================*/
28
29#ifndef __amigo_h
30#define __amigo_h
31
32#include "go.h"
33#include "goplayutils.h"
34
35#ifdef __STDC__
36 #define PROTO(fp)fp
37#else
38 #define PROTO(fp)()
39#endif
40
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/* From goplayer.c */
47
48
49
50/* Procedures from amigo.c */
51
52 shortConnect PROTO((enum bVal, short, short, short[4], short[4], short *, short * ));
53 shortMaxlibs PROTO((short, short));
54 shortSuicide PROTO((enum bVal, short, short));
55 shortStoneLibs PROTO((short, short));
56 voidEraseMarks PROTO(());
57 shortGoPlaceStone PROTO((enum bVal, short, short));
58 voidGoRemoveStone PROTO((short, short));
59 voidMergeGroups PROTO((short, short));
60 voidDeleteGroup PROTO((short));
61 voidReEvalGroups PROTO((enum bVal, short, short, short));
62 voidGroupCapture PROTO((short));
63 voidFixLibs PROTO((enum bVal, short, short, short));
64 intCountUp PROTO((int*, int*));
65 /*voidmain PROTO(());*/
66 voidgoRestart PROTO((int));
67 voidRelabelGroups PROTO(());
68 shortCountAndMarkLibs PROTO((short, short));
69 voidCountLiberties PROTO((short));
70 voidCheckForEye PROTO((short, short, short[4], short, short *));
71 voidCountEyes PROTO(());
72 voidprintGroupReport PROTO((short, short));
73
74
75/* killable.c */
76
77 inttryPlay PROTO(( short, short, short ));
78 intsSpanGroup PROTO(( short, short, sPointList * ));
79 intspanGroup PROTO(( short, short, pointList *));
80 intpause PROTO(());
81
82 intgenState PROTO(());
83 intinitGPUtils PROTO(());
84 intgenBord PROTO((enum bVal));
85
86 shortgenMove PROTO(( enum bVal, short *, short * ));
87 shortcheckPos PROTO(( short, short, short ));
88 shorttakeCorner PROTO(( short *, short * ));
89 shortextend PROTO(( short *, short * ));
90 shortnoNbrs PROTO(( short, short ));
91 shortextend2 PROTO(( short *, short * ));
92 shortlookForSave PROTO(( short *, short * ));
93 shortlookForSaveN PROTO(( short *, short * ));
94 shortlookForKill PROTO(( short *, short * ));
95 shortdoubleAtari PROTO(( short *, short * ));
96 shortlookForAttack PROTO(( short *, short * ));
97 shortthreaten PROTO(( short *, short * ));
98 shortconnectCut PROTO(( short *, short * ));
99 shortheCanCut PROTO(( short, short ));
100 shortsafeMove PROTO(( short, short ));
101 shortextendWall PROTO(( short *, short * ));
102 shortfindAttack2 PROTO(( short *, short * ));
103 shortblockCut PROTO(( short *, short * ));
104 shortcutHim PROTO(( short *, short * ));
105 shortatariAnyway PROTO(( short *, short * ));
106 shortunderCut PROTO(( short *, short * ));
107 shortdropToEdge PROTO(( short *, short * ));
108 shortpushWall PROTO(( short *, short * ));
109 shortreduceHisLiberties PROTO(( short *, short * ));
110 shortdropToEdge2 PROTO(( short *, short * ));
111
112
113/* goplayutils.c */
114
115 shortsaveable PROTO((short, short, short *, short *));
116 shortkillable PROTO((short, short, short *, short *));
117 intinitBoolBoard PROTO((boolBoard));
118 intintersectPlist PROTO((pointList *, pointList *, pointList *));
119 intinitArray PROTO((intBoard));
120 intinitState PROTO(());
121 intcopyArray PROTO((intBoard, intBoard));
122 intstake PROTO(());
123 intspread PROTO(());
124 intrespreicen PROTO(());
125 inttryPlay PROTO((short, short, short));
126 intsaveState PROTO(());
127 intrestoreState PROTO(());
128 shorttencen PROTO((short, short));
129 intgenConnects PROTO(());
130 intsortLibs PROTO(());
131
132
133/*-- from xinterface.c --*/
134 voidremovestone PROTO((short, short));
135 voidplacestone PROTO((enum bVal, short, short));
136
137 voidintrMoveReport PROTO((enum bVal,char *,char *));
138 voidintrPrisonerReport PROTO(( short, short ));
139
140
141#ifdef __cplusplus
142}
143#endif
144
145
146#endif
diff --git a/noncore/games/go/go.h b/noncore/games/go/go.h
new file mode 100644
index 0000000..9aa644b
--- a/dev/null
+++ b/noncore/games/go/go.h
@@ -0,0 +1,81 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20/* AmiGo Include */
21/* MSG types for getinput() */
22
23#ifndef __go_h
24#define __go_h
25
26
27 #define INTERSECTIONMSG 1/* User buttoned an intersection */
28 #define QUITMSG 2 /* User buttoned QUIT icon */
29#define PLAYMSG 3
30#define RESTARTMSG 4
31#define PASSMSG 5
32
33#define TRUE 1
34#define FALSE 0
35
36#define MAXGROUPS 100
37
38#define PLACED 0
39#define REMOVED 1
40
41#define numPoints 19
42#define maxPoint numPoints - 1
43
44/*-- definitions used when counting up --*/
45
46 #define CNT_UNDECIDED0
47 #define CNT_BLACK_TERR1
48 #define CNT_WHITE_TERR2
49 #define CNT_NOONE3
50
51/*-- macro functions --*/
52
53 #define LegalPoint(x,y) (x>=0 && x<=18 && y>=0 && y<=18)
54 #define ForeachPoint(a,b)for(a=0;a<19;a++) for (b=0;b<19;b++)
55
56enum bVal {BLACK, WHITE, EMPTY};
57typedef enum bVal sType;
58struct Group
59{
60 enum bVal color;/* The color of the group */
61 short code, /* The code used to mark stones in the group */
62 count, /* The number of stones in the group */
63 internal,/* The number of internal liberties */
64 external,/* The number of external liberties */
65 liberties,/* The total number of liberties */
66 eyes, /* The number of eyes */
67 alive, /* A judgement of how alive this group is */
68 territory;/* The territory this group controls */
69};
70
71struct bRec
72{
73 enum bVal Val;/* What is at this intersection */
74 short xOfs,
75 yOfs;
76 short mNum;
77 short GroupNum;/* What group the stone belongs to */
78 short marked;/* TRUE or FALSE */
79};
80
81#endif
diff --git a/noncore/games/go/go.pro b/noncore/games/go/go.pro
new file mode 100644
index 0000000..deb90c5
--- a/dev/null
+++ b/noncore/games/go/go.pro
@@ -0,0 +1,19 @@
1 DESTDIR = ../bin
2 TEMPLATE= app
3 CONFIG = qt warn_on release
4 HEADERS = amigo.h \
5 go.h \
6 goplayutils.h \
7 gowidget.h
8 SOURCES = amigo.c \
9 goplayer.c \
10 goplayutils.c \
11 killable.c \
12 gowidget.cpp \
13 main.cpp
14INCLUDEPATH += $(QPEDIR)/include
15 DEPENDPATH+= $(QPEDIR)/include
16LIBS += -lqpe
17 TARGET = go
18
19TRANSLATIONS = ../i18n/de/go.ts \ No newline at end of file
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
diff --git a/noncore/games/go/goplayutils.c b/noncore/games/go/goplayutils.c
new file mode 100644
index 0000000..9e2ce4c
--- a/dev/null
+++ b/noncore/games/go/goplayutils.c
@@ -0,0 +1,1317 @@
1/* The go player utilities */
2/* Ported from Pascal to C by Todd R. Johnson */
3/* From the original Pascal file:
4Copyright (c) 1983 by Three Rivers Computer Corp.
5
6Written: January 17, 1983 by Stoney Ballard
7*/
8
9#include "goplayutils.h"
10#include "amigo.h"
11#include "go.h"
12
13extern struct bRec goboard[19][19];
14
15intBoard claim, extra, bord, ndbord, sGroups, threatBord,
16 groupIDs, connectMap, protPoints;
17boolBoard groupSeen, legal;
18short maxGroupID;
19pointList pList, pList1, plist2, plist3, pPlist;
20intList nlcGroup, aList;
21sgRec sList[401];
22groupRec gList[maxGroup];
23short killFlag,
24 numCapt,
25 utilPlayLevel,
26 treeLibLim;
27sType mySType;
28short showTrees;
29short sGlist[maxGroup+1];
30short depthLimit;
31intBoard markBoard;
32short marker;
33
34short adjInAtari, adj2Libs,
35 intersectNum, spanNum, libMark;
36playRec playStack[1025];
37short playMark,
38 newGID,
39 tryLevel,
40 grpMark,
41 gMap[maxGroup];
42short dbStop, inGenState;
43
44 pause()
45{ /* pause */
46/* if (dbStop and ! inGenState)
47 {
48 while ! tabswitch do;
49 repeat
50 if (tabYellow)
51 dbStop = false;
52 until ! tabswitch;
53 } */
54} /* pause */
55
56sstone(w, x, y, numb)
57short w, x, y, numb;
58{ /* sstone */
59 if (w == 1)
60 placestone(mySType, x, y);
61 else if (mySType == WHITE)
62 placestone(BLACK, x, y);
63 else
64 placestone(WHITE, x, y);
65} /* sstone */
66
67rstone(x, y)
68short x, y;
69{ /* rstone */
70 removestone(x, y);
71} /* rstone */
72
73initBoolBoard(bb)
74boolBoard bb;
75{ /* initBoolBoard */
76 short i, j;
77#ifdef DEBUG
78 printf( "initBoolBoard\n" );
79#endif
80 for (i = 0; i <= maxPoint; i++)
81 for (j = 0; j <= maxPoint; j++)
82 bb[i][j] = FALSE;
83} /* initBoolBoard */
84
85sortLibs()
86{ /* sortLibs */
87 short i, j, t;
88#ifdef DEBUG
89 printf( "sortLibs\n" );
90#endif
91 for (i = 1; i <= maxGroupID; i++)
92 sGlist[i] = i;
93 for (i = 1; i < maxGroupID; i++)
94 for (j = i + 1; j <= maxGroupID; j++)
95 if (gList[sGlist[i]].libC > gList[sGlist[j]].libC)
96 {
97 t = sGlist[i];
98 sGlist[i] = sGlist[j];
99 sGlist[j] = t;
100 }
101} /* sortLibs */
102
103spanGroupspan(x, y, libs, lookFor)
104short x, y, lookFor;
105pointList *libs;
106 { /* span */
107 markBoard[x][y] = marker;
108 if (bord[x][y] == 0)
109 {
110 libs->indx = libs->indx + 1;
111 libs->p[libs->indx].px = x;
112 libs->p[libs->indx].py = y;
113 }
114 else if (bord[x][y] == lookFor)
115 {
116 groupSeen[x][y] = TRUE;
117 if ((x > 0) && (markBoard[x - 1][y] != marker))
118 spanGroupspan(x - 1, y, libs, lookFor);
119 if ((y > 0) && (markBoard[x][y - 1] != marker))
120 spanGroupspan(x, y - 1, libs, lookFor);
121 if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
122 spanGroupspan(x + 1, y, libs, lookFor);
123 if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
124 spanGroupspan(x, y + 1, libs, lookFor);
125 }
126 else if (gList[gMap[groupIDs[x][y]]].libC == 1)
127 adjInAtari = TRUE;
128 else if ((gList[gMap[groupIDs[x][y]]].libC == 2) &&
129 (! gList[gMap[groupIDs[x][y]]].isLive))
130 adj2Libs = TRUE;
131 } /* span */
132
133spanGroup(x, y, libs)
134short x, y;
135pointList *libs;
136{ /* spanGroup */
137 short lookFor;
138#ifdef DEBUG
139 printf( "spanGroup\n" );
140#endif
141 marker = marker + 1;
142 if (marker == 0)
143 {
144 initArray(markBoard);
145 marker = 1;
146 }
147 adjInAtari = FALSE;
148 adj2Libs = FALSE;
149 lookFor = bord[x][y];
150 libs->indx = 0;
151 spanGroupspan(x, y, libs, lookFor);
152} /* spanGroup */
153
154sSpanGroupspan(x, y, libs, lookFor)
155short x, y, lookFor;
156sPointList *libs;
157 { /* span */
158 markBoard[x][y] = marker;
159 if (bord[x][y] == 0)
160 {
161 libs->indx += 1;
162 if (libs->indx <= maxSPoint)
163 {
164 libs->p[libs->indx].px = x;
165 libs->p[libs->indx].py = y;
166 }
167 }
168 else if (bord[x][y] == lookFor)
169 {
170 groupSeen[x][y] = TRUE;
171 if ((x > 0) && (markBoard[x - 1][y] != marker))
172 sSpanGroupspan(x - 1, y, libs, lookFor);
173 if ((y > 0) && (markBoard[x][y - 1] != marker))
174 sSpanGroupspan(x, y - 1, libs, lookFor);
175 if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
176 sSpanGroupspan(x + 1, y, libs, lookFor);
177 if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
178 sSpanGroupspan(x, y + 1, libs, lookFor);
179 }
180 else if (gList[gMap[groupIDs[x][y]]].libC == 1)
181 adjInAtari = TRUE;
182 else if ((gList[gMap[groupIDs[x][y]]].libC == 2) &&
183 (! gList[gMap[groupIDs[x][y]]].isLive))
184 adj2Libs = TRUE;
185 } /* span */
186
187sSpanGroup(x, y, libs)
188short x, y;
189sPointList *libs;
190{ /* sSpanGroup */
191 short lookFor;
192#ifdef DEBUG
193 printf( "sSpanGroup\n" );
194#endif
195 marker = marker + 1;
196 if (marker == 0)
197 {
198 initArray(markBoard);
199 marker = 1;
200 }
201 adjInAtari = FALSE;
202 adj2Libs = FALSE;
203 lookFor = bord[x][y];
204 libs->indx = 0;
205 sSpanGroupspan(x, y, libs, lookFor);
206} /* sSpanGroup */
207
208LAspan(x, y, me, him, iL)
209short x, y, me, him;
210intList *iL;
211 { /* span */
212#ifdef DEBUG
213 printf( "LAspan\n" );
214#endif
215 markBoard[x][y] = marker;
216 if (bord[x][y] == me)
217 {
218 if ((x > 0) && (markBoard[x - 1][y] != marker))
219 LAspan(x - 1, y, me, him, iL);
220 if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
221 LAspan(x + 1, y, me, him, iL);
222 if ((y > 0) && (markBoard[x][y - 1] != marker))
223 LAspan(x, y - 1, me, him, iL);
224 if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
225 LAspan(x, y + 1, me, him, iL);
226 }
227 else if (bord[x][y] == him)
228 if (gList[gMap[groupIDs[x][y]]].groupMark != grpMark)
229 {
230 gList[gMap[groupIDs[x][y]]].groupMark = grpMark;
231 iL->indx = iL->indx + 1;
232 iL->v[iL->indx] = gMap[groupIDs[x][y]];
233 }
234 } /* span */
235
236listAdjacents(x, y, iL)
237short x, y;
238intList *iL;
239{ /* listAdjacents */
240 short me, him;
241#ifdef DEBUG
242 printf( "listAdjacents\n" );
243#endif
244 grpMark = grpMark + 1;
245 marker = marker + 1;
246 if (marker == 0)
247 {
248 initArray(markBoard);
249 marker = 1;
250 }
251 iL->indx = 0;
252 me = bord[x][y];
253 him = -me;
254 LAspan(x, y, me , him, iL);
255} /* listAdjacents */
256
257LDspan(x, y, me, diags)
258short x, y, me;
259sPointList *diags;
260 { /* span */
261#ifdef DEBUG
262 printf( "LDspan\n" );
263#endif
264 markBoard[x][y] = marker;
265 if ((x > 0) && (y > 0) &&
266 (bord[x - 1][y - 1] == 0) &&
267 (bord[x][y - 1] != me) &&
268 (bord[x - 1][y] != me) &&
269 (markBoard[x - 1][y - 1] != marker))
270 {
271 markBoard[x - 1][y - 1] = marker;
272 diags->indx = diags->indx + 1;
273 if (diags->indx <= maxSPoint)
274 {
275 diags->p[diags->indx].px = x - 1;
276 diags->p[diags->indx].py = y - 1;
277 }
278 }
279 if ((x < maxPoint) && (y > 0) &&
280 (bord[x + 1][y - 1] == 0) &&
281 (bord[x][y - 1] != me) &&
282 (bord[x + 1][y] != me) &&
283 (markBoard[x + 1][y - 1] != marker))
284 {
285 markBoard[x + 1][y - 1] = marker;
286 diags->indx = diags->indx + 1;
287 if (diags->indx <= maxSPoint)
288 {
289 diags->p[diags->indx].px = x + 1;
290 diags->p[diags->indx].py = y - 1;
291 }
292 }
293 if ((x > 0) && (y < maxPoint) &&
294 (bord[x - 1][y + 1] == 0) &&
295 (bord[x][y + 1] != me) &&
296 (bord[x - 1][y] != me) &&
297 (markBoard[x - 1][y + 1] != marker))
298 {
299 markBoard[x - 1][y + 1] = marker;
300 diags->indx = diags->indx + 1;
301 if (diags->indx <= maxSPoint)
302 {
303 diags->p[diags->indx].px = x - 1;
304 diags->p[diags->indx].py = y + 1;
305 }
306 }
307 if ((x < maxPoint) && (y < maxPoint) &&
308 (bord[x + 1][y + 1] == 0) &&
309 (bord[x][y + 1] != me) &&
310 (bord[x + 1][y] != me) &&
311 (markBoard[x + 1][y + 1] != marker))
312 {
313 markBoard[x + 1][y + 1] = marker;
314 diags->indx = diags->indx + 1;
315 if (diags->indx <= maxSPoint)
316 {
317 diags->p[diags->indx].px = x + 1;
318 diags->p[diags->indx].py = y + 1;
319 }
320 }
321 if ((x > 0) && (bord[x - 1][y] == me) &&
322 (markBoard[x - 1][y] != marker))
323 LDspan(x - 1, y, me, diags);
324 if ((x < maxPoint) && (bord[x + 1][y] == me) &&
325 (markBoard[x + 1][y] != marker))
326 LDspan(x + 1, y, me, diags);
327 if ((y > 0) && (bord[x][y - 1] == me) &&
328 (markBoard[x][y - 1] != marker))
329 LDspan(x, y - 1, me, diags);
330 if ((y < maxPoint) && (bord[x][y + 1] == me) &&
331 (markBoard[x][y + 1] != marker))
332 LDspan(x, y + 1, me , diags);
333} /* span */
334
335listDiags(x, y, diags)
336short x, y;
337sPointList *diags;
338{ /* listDiags */
339 short me;
340#ifdef DEBUG
341 printf( "listDiags\n" );
342#endif
343 me = bord[x][y];
344 diags->indx = 0;
345 marker = marker + 1;
346 if (marker == 0)
347 {
348 initArray(markBoard);
349 marker = 1;
350 }
351 LDspan(x, y, me, diags);
352} /* listDiags */
353
354intersectPlist(p1, p2, pr)
355pointList *p1, *p2, *pr;
356{ /* intersectPlist */
357 short i, j, k;
358#ifdef DEBUG
359 printf( "intersectPlist\n" );
360#endif
361 marker = marker + 1;
362 if (marker == 0)
363 {
364 initArray(markBoard);
365 marker = 1;
366 }
367 pr->indx = 0;
368 for (i = 1; i <= p1->indx; i++)
369 markBoard[p1->p[i].px][p1->p[i].py] = marker;
370 j = 0;
371 for (i = 1; i <= p2->indx; i++)
372 if (markBoard[p2->p[i].px][p2->p[i].py] == marker)
373 {
374 j = j + 1;
375 pr->p[j] = p2->p[i];
376 }
377 pr->indx = j;
378} /* intersectPlist */
379
380initArray(ary)
381intBoard ary;
382{ /* initArray */
383 short i, j;
384 for (i = 0; i <= maxPoint; i++)
385 for (j = 0; j <= maxPoint; j++)
386 ary[i][j] = 0;
387} /* initArray */
388
389initState()
390{ /* initState */
391 short i, j;
392 for (i = 0; i <= maxPoint; i++)
393 for (j = 0; j <= maxPoint; j++)
394 {
395 extra[i][j] = 0;
396 claim[i][j] = 0;
397 groupIDs[i][j] = 0;
398 connectMap[i][j] = 0;
399 protPoints[i][j] = 0;
400 }
401} /* initState */
402
403copyArray( dest, src )
404intBoard dest, src;
405{
406 short x, y;
407 for (y = 0; y <= maxPoint; y++)
408 for (x = 0; x <= maxPoint; x++)
409 dest[x][y] = src[x][y];
410}
411
412/*
413 generates a one-point spread in the force field array (claim)
414
415 the spread from a single point after four calls is:
416
417 1
418 2 2 2
419 2 4 6 4 2
420 2 4 8 10 8 4 2
421 1 2 6 10 62 10 6 2 1
422 2 4 8 10 8 4 2
423 2 4 6 4 2
424 2 2 2
425 1
426
427*/
428stake()
429{
430 short x, y;
431 initArray( extra );
432 for (y = 0; y <= maxPoint; y++)
433 for (x = 0; x <= maxPoint; x++)
434 {
435 extra[x][y] = extra[x][y] + claim[x][y];
436 if (claim[x][y] > 0)
437 {
438 if (x > 0) extra[x-1][y] += 1;
439 if (y > 0) extra[x][y-1] += 1;
440 if (x < maxPoint) extra[x+1][y] += 1;
441 if (y < maxPoint) extra[x][y+1] += 1;
442 }
443 else if (claim[x][y] < 0)
444 {
445 if (x > 0) extra[x-1][y] -= 1;
446 if (y > 0) extra[x][y-1] -= 1;
447 if (x < maxPoint) extra[x+1][y] -= 1;
448 if (y < maxPoint) extra[x][y+1] -= 1;
449 }
450 }
451 copyArray( claim, extra );
452} /* stake */
453
454/*
455 sets up claim from the current board position
456*/
457spread()
458{
459 short x, y;
460 for (y = 0; y <= maxPoint; y++)
461 for (x = 0; x <= maxPoint; x++)
462 claim[x][y] = ndbord[x][y] * 50;
463 stake();
464 stake();
465 stake();
466 stake();
467} /* spread */
468
469/*
470 gList is initialized with the size, loc, and libCount of each group
471 groupIDs contains the serial numbers of the groups.
472*/
473Resspan(x, y, gID, gSize, libCount, who)
474short x, y, gID, *gSize, *libCount, who;
475 { /* span */
476 if ((bord[x][y] == 0) &&
477 (markBoard[x][y] != marker)) /* a liberty */
478 {
479 markBoard[x][y] = marker;
480 *libCount = *libCount + 1;
481 }
482 else if ((bord[x][y] == who) &&
483 (groupIDs[x][y] == 0))
484 {
485 groupIDs[x][y] = gID;
486 *gSize = *gSize + 1;
487 if (x > 0)
488 Resspan(x - 1, y, gID, gSize, libCount, who);
489 if (x < maxPoint)
490 Resspan(x + 1, y, gID, gSize, libCount, who);
491 if (y > 0)
492 Resspan(x, y - 1, gID, gSize, libCount, who);
493 if (y < maxPoint)
494 Resspan(x, y + 1, gID, gSize, libCount, who);
495 }
496 } /* span */
497
498respreicen()
499{ /* respreicen */
500 short i, j, gID, libCount, gSize, who;
501 gID = 0;
502#ifdef DEBUG
503 printf( "respreicen\n" );
504#endif
505 for (i = 0; i <= maxPoint; i++)
506 for (j = 0; j <= maxPoint; j++)
507 groupIDs[i][j] = 0;
508 for (i = 0; i <= maxPoint; i++)
509 for (j = 0; j <= maxPoint; j++)
510 if ((bord[i][j] != 0) && /* a stone there */
511 (groupIDs[i][j] == 0)) /* not seen yet */
512 {
513 marker = marker + 1;
514 if (marker == 0)
515 {
516 initArray(markBoard);
517 marker = 1;
518 }
519 gID = gID + 1;
520 libCount = 0;
521 gSize = 0;
522 who = bord[i][j];
523 Resspan(i, j, gID, &gSize, &libCount, who); /* span the group, collecting info */
524 gList[gID].groupMark = 0;
525 gList[gID].atLevel = 0;
526 gList[gID].isLive = FALSE; /* we don't know yet */
527 gList[gID].isDead = FALSE;
528 gList[gID].numEyes = -1;
529 gList[gID].size = gSize;
530 gList[gID].libC = libCount;
531 gList[gID].lx = i;
532 gList[gID].ly = j;
533 gMap[gID] = gID; /* set up identity map */
534 }
535 maxGroupID = gID;
536 newGID = gID;
537 grpMark = 0;
538} /* respreicen */
539
540/*
541 play z at [x, y].
542 killFlag is set true if anything is killed.
543*/
544killGroup(x, y, me, him)
545short x, y, me, him;
546 { /* killGroup */
547#ifdef DEBUG
548 printf( "killGroup\n" );
549#endif
550 playMark = playMark + 1;
551 /* record this kill */
552 playStack[playMark].kind = rem;
553 playStack[playMark].uval.rem.who = him;
554 playStack[playMark].uval.rem.xl = x;
555 playStack[playMark].uval.rem.yl = y;
556 playStack[playMark].gID = groupIDs[x][y];
557 playStack[playMark].uval.rem.sNumber = goboard[x][y].mNum;
558 if (showTrees)
559 rstone(x, y);
560 numCapt = numCapt + 1;
561 bord[x][y] = 0;
562 groupIDs[x][y] = 0;
563 if (x > 0)
564 {
565 if (bord[x - 1][y] == me)
566 {
567 nlcGroup.indx = nlcGroup.indx + 1;
568 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]];
569 }
570 else if (bord[x - 1][y] == him)
571 killGroup(x - 1, y, me , him);
572 }
573 if (x < maxPoint)
574 {
575 if (bord[x + 1][y] == me)
576 {
577 nlcGroup.indx = nlcGroup.indx + 1;
578 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]];
579 }
580 else if (bord[x + 1][y] == him)
581 killGroup(x + 1, y, me, him);
582 }
583 if (y > 0)
584 {
585 if (bord[x][y - 1] == me)
586 {
587 nlcGroup.indx = nlcGroup.indx + 1;
588 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]];
589 }
590 else if (bord[x][y - 1] == him)
591 killGroup(x, y - 1, me, him);
592 }
593 if (y < maxPoint)
594 {
595 if (bord[x][y + 1] == me)
596 {
597 nlcGroup.indx = nlcGroup.indx + 1;
598 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]];
599 }
600 else if (bord[x][y + 1] == him)
601 killGroup(x, y + 1, me, him);
602 }
603 } /* killGroup */
604
605mergeGroup(sGID, myGID)
606short sGID, myGID;
607 { /* mergeGroup */
608 short i;
609#ifdef DEBUG
610 printf( "mergeGroup\n" );
611#endif
612 for (i = 1; i <= newGID; i++)
613 if (gMap[i] == sGID)
614 {
615 playMark = playMark + 1;
616 playStack[playMark].kind = reMap;
617 playStack[playMark].gID = i;
618 playStack[playMark].uval.reMap.oldGID = sGID;
619 gMap[i] = myGID;
620 }
621 } /* mergeGroup */
622
623tryPlay(x, y, z)
624short x, y, z;
625{ /* plei */
626 short i, me, him, myGID;
627 short isNew;
628#ifdef DEBUG
629 printf( "tryPlay\n" );
630#endif
631 me = z;
632 him = -me;
633 killFlag = FALSE; /* set true if something is killed */
634 numCapt = 0;
635 tryLevel = tryLevel + 1;
636 isNew = FALSE;
637 bord[x][y] = z; /* play the stone */
638 if ((x > 0) && (bord[x - 1][y] == me)) /* connect to adjacent group */
639 myGID = gMap[groupIDs[x - 1][y]];
640 else if ((x < maxPoint) && (bord[x + 1][y] == me))
641 myGID = gMap[groupIDs[x + 1][y]];
642 else if ((y > 0) && (bord[x][y - 1] == me))
643 myGID = gMap[groupIDs[x][y - 1]];
644 else if ((y < maxPoint) && (bord[x][y + 1] == me))
645 myGID = gMap[groupIDs[x][y + 1]];
646 else /* nobody to connect to */
647 {
648 newGID = newGID + 1;
649 isNew = TRUE;
650 myGID = newGID;
651 gList[myGID].groupMark = 0;
652 gList[myGID].atLevel = tryLevel;
653 gList[myGID].isLive = FALSE;
654 gList[myGID].numEyes = -1;
655 gList[myGID].size = -1;
656 gList[myGID].lx = x;
657 gList[myGID].ly = y;
658 gMap[myGID] = myGID;
659 }
660 groupIDs[x][y] = myGID;
661 playMark = playMark + 1;
662 /* record this move */
663 playStack[playMark].kind = add;
664 playStack[playMark].uval.add.who = me;
665 playStack[playMark].uval.add.xl = x;
666 playStack[playMark].uval.add.yl = y;
667 playStack[playMark].gID = myGID;
668 playStack[playMark].uval.add.sNumber = 0;
669 if (isNew)
670 playStack[playMark].uval.add.nextGID = newGID - 1;
671 else
672 playStack[playMark].uval.add.nextGID = newGID;
673 if (showTrees)
674 sstone(me, x, y, 0);
675 /* merge adjacent groups */
676 if ((x > 0) && (bord[x - 1][y] == me) &&
677 (gMap[groupIDs[x - 1][y]] != myGID))
678 mergeGroup(gMap[groupIDs[x - 1][y]], myGID);
679 if ((x < maxPoint) && (bord[x + 1][y] == me) &&
680 (gMap[groupIDs[x + 1][y]] != myGID))
681 mergeGroup(gMap[groupIDs[x + 1][y]], myGID);
682 if ((y > 0) && (bord[x][y - 1] == me) &&
683 (gMap[groupIDs[x][y - 1]] != myGID))
684 mergeGroup(gMap[groupIDs[x][y - 1]], myGID);
685 if ((y < maxPoint) && (bord[x][y + 1] == me) &&
686 (gMap[groupIDs[x][y + 1]] != myGID))
687 mergeGroup(gMap[groupIDs[x][y + 1]], myGID);
688 /* kill opposing groups, listing affected groups */
689 nlcGroup.indx = 1;
690 nlcGroup.v[1] = myGID; /* init list to include me */
691 if ((x > 0) && (bord[x - 1][y] == him) &&
692 (gList[gMap[groupIDs[x - 1][y]]].libC == 1))
693 {
694 killFlag = TRUE;
695 killGroup(x - 1, y, me, him);
696 }
697 if ((x < maxPoint) && (bord[x + 1][y] == him) &&
698 (gList[gMap[groupIDs[x + 1][y]]].libC == 1))
699 {
700 killFlag = TRUE;
701 killGroup(x + 1, y, me, him);
702 }
703 if ((y > 0) && (bord[x][y - 1] == him) &&
704 (gList[gMap[groupIDs[x][y - 1]]].libC == 1))
705 {
706 killFlag = TRUE;
707 killGroup(x, y - 1, me, him);
708 }
709 if ((y < maxPoint) && (bord[x][y + 1] == him) &&
710 (gList[gMap[groupIDs[x][y + 1]]].libC == 1))
711 {
712 killFlag = TRUE;
713 killGroup(x, y + 1, me, him);
714 }
715 /* list groups adjacent to me */
716 if ((x > 0) && (bord[x - 1][y] == him))
717 {
718 nlcGroup.indx = nlcGroup.indx + 1;
719 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]];
720 }
721 if ((x < maxPoint) && (bord[x + 1][y] == him))
722 {
723 nlcGroup.indx = nlcGroup.indx + 1;
724 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]];
725 }
726 if ((y > 0) && (bord[x][y - 1] == him))
727 {
728 nlcGroup.indx = nlcGroup.indx + 1;
729 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]];
730 }
731 if ((y < maxPoint) && (bord[x][y + 1] == him))
732 {
733 nlcGroup.indx = nlcGroup.indx + 1;
734 nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]];
735 }
736 /* fix liberty count for affected groups */
737 grpMark = grpMark + 1;
738 for (i = 1; i <= nlcGroup.indx; i++)
739 if (gList[nlcGroup.v[i]].groupMark != grpMark)
740 {
741 if (gList[nlcGroup.v[i]].atLevel != tryLevel)
742 {
743 playMark = playMark + 1;
744 playStack[playMark].kind = chLib;
745 playStack[playMark].gID = nlcGroup.v[i];
746 playStack[playMark].uval.chLib.oldLevel =
747 gList[nlcGroup.v[i]].atLevel;
748 playStack[playMark].uval.chLib.oldLC =
749 gList[nlcGroup.v[i]].libC;
750 }
751 gList[nlcGroup.v[i]].groupMark = grpMark;
752 gList[nlcGroup.v[i]].atLevel = tryLevel;
753 spanGroup(gList[nlcGroup.v[i]].lx, gList[nlcGroup.v[i]].ly, &pPlist);
754 gList[nlcGroup.v[i]].libC = pPlist.indx;
755 }
756} /* plei */
757
758saveState()
759{ /* saveState */
760 playMark = 0;
761 tryLevel = 0;
762 newGID = maxGroupID;
763} /* saveState */
764
765/*
766 undoes a move sequence back to uMark
767*/
768undoTo(uMark)
769short uMark;
770{ /* undoTo */
771 short i, xl, yl;
772#ifdef DEBUG
773 printf( "undoTo\n" );
774#endif
775 for (i = playMark; i >= uMark + 1; i--)
776 if (playStack[i].kind == rem)
777 {
778 xl = playStack[i].uval.rem.xl;
779 yl = playStack[i].uval.rem.yl;
780 bord[xl][yl] = playStack[i].uval.rem.who;
781 groupIDs[xl][yl] = playStack[i].gID;
782 if (showTrees)
783 sstone(playStack[i].uval.rem.who, xl, yl,
784 playStack[i].uval.rem.sNumber);
785 }
786 else if (playStack[i].kind == add)
787 {
788 xl = playStack[i].uval.add.xl;
789 yl = playStack[i].uval.add.yl;
790 bord[xl][yl] = 0;
791 groupIDs[xl][yl] = 0;
792 tryLevel = tryLevel - 1;
793 newGID = playStack[i].uval.add.nextGID;
794 if (showTrees)
795 rstone(xl, yl);
796 }
797 else if (playStack[i].kind == reMap)
798 gMap[playStack[i].gID] = playStack[i].uval.reMap.oldGID;
799 else /* change libs of group - gID is pre-mapped */
800 {
801 gList[playStack[i].gID].libC = playStack[i].uval.chLib.oldLC;
802 gList[playStack[i].gID].atLevel = playStack[i].uval.chLib.oldLevel;
803 }
804 playMark = uMark;
805} /* undoTo */
806
807/*
808 restores the state of the world after trying a move sequence
809*/
810restoreState()
811{ /* restoreState */
812#ifdef DEBUG
813 printf( "restoreState\n" );
814#endif
815 if (playMark > 0)
816 {
817 undoTo(0);
818 playMark = 0;
819 tryLevel = 0;
820 }
821} /* restoreState */
822
823/* exception bpt; */
824
825
826/*
827 returns true if (the group (at gx, gy) is saveable.
828 if so, returns the point to play at in savex, savey
829*/
830short saveable(gx, gy, savex, savey)
831short gx, gy, *savex, *savey;
832{ /* saveable */
833 short me, him, gx1, gx2, i, j, smark, mark2, tl, result;
834 char sChar;
835 sPointList dList;
836 point tp;
837 short libList[maxSPoint+1];
838#ifdef DEBUG
839 printf( "saveable\n" );
840#endif
841 dbStop = TRUE;
842 me = bord[gx][gy];
843 him = -me;
844 if (me == 1)
845 sChar = '|';
846 else
847 sChar = '>';
848/* write(sChar); */
849 spanGroup(gx, gy, &plist3); /* find my liberties */
850 if (adjInAtari) /* one of my options is to kill */
851 {
852 listAdjacents(gx, gy, &aList);
853 for (i = 1; i <= aList.indx; i++)
854 if (gList[aList.v[i]].libC == 1)
855 {
856 spanGroup(gList[aList.v[i]].lx, gList[aList.v[i]].ly,
857 &pList1); /* find it's liberty */
858 plist3.indx = plist3.indx + 1;
859 plist3.p[plist3.indx].px = pList1.p[1].px;
860 plist3.p[plist3.indx].py = pList1.p[1].py;
861 }
862 }
863 for (i = 1; i <= maxSPoint; i++)
864 libList[i] = -1;
865 if ((utilPlayLevel > 4) &&
866 (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* account for diags */
867 {
868 listDiags(gx, gy, &dList);
869 j = 0;
870 i = plist3.indx;
871 while ((j < dList.indx) &&
872 (i < maxSPoint))
873 {
874 j = j + 1;
875 i = i + 1;
876 libList[i] = 100;
877 plist3.p[i].px = dList.p[j].px;
878 plist3.p[i].py = dList.p[j].py;
879 }
880 plist3.indx = i;
881 }
882 if (plist3.indx > 1) /* sort by decreasing lib count */
883 {
884 for (i = 1; i <= plist3.indx; i++)
885 if (libList[i] != 100)
886 {
887 mark2 = playMark;
888 tryPlay(plist3.p[i].px, plist3.p[i].py, me);
889 libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
890 if (libList[i] > treeLibLim) /* i'm safe */
891 {
892 *savex = plist3.p[i].px;
893 *savey = plist3.p[i].py;
894 result = TRUE;
895 goto one;
896 }
897 undoTo(mark2);
898 }
899 for (i = 1; i <= plist3.indx - 1; i++)
900 for (j = i + 1; j <= plist3.indx; j++)
901 if (libList[i] < libList[j])
902 {
903 tl = libList[i];
904 libList[i] = libList[j];
905 libList[j] = tl;
906 tp = plist3.p[i];
907 plist3.p[i] = plist3.p[j];
908 plist3.p[j] = tp;
909 }
910 }
911 for (i = 1; i <= plist3.indx; i++)
912 {
913 *savex = plist3.p[i].px;
914 *savey = plist3.p[i].py;
915 if (legal[*savex][*savey])
916 {
917 smark = playMark;
918 tryPlay(*savex, *savey, me);
919 pause();
920 if (gList[gMap[groupIDs[*savex][*savey]]].libC > 1)
921 if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
922 {
923 restoreState();
924/* sClearChar(sChar, rXor); */
925 return TRUE;
926 }
927 else if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
928 if (! killable(gx, gy, &gx1, &gx2))
929 {
930 restoreState();
931/* sClearChar(sChar, rXor); */
932 return TRUE;
933 }
934 undoTo(smark);
935 }
936 }
937 result = FALSE;
938one:
939 restoreState();
940/* sClearChar(sChar, rXor); */
941 return result;
942} /* saveable */
943
944/*
945 marks unsavable groups as dead
946*/
947markDead()
948{ /* markDead */
949 short i, j, gx, gy, result;
950#ifdef DEBUG
951 printf( "markDead\n" );
952#endif
953 for (i = 1; i <= maxGroupID; i++)
954 if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
955 result = ! saveable(gList[i].lx, gList[i].ly, &gx, &gy);
956 else
957 result = FALSE;
958 for (i = 0; i <= maxPoint; i++)
959 for (j = 0; j <= maxPoint; j++)
960 if (bord[i][j] == 0)
961 ndbord[i][j] = 0;
962 else if (gList[groupIDs[i][j]].isDead)
963 ndbord[i][j] = 0;
964 else
965 ndbord[i][j] = bord[i][j];
966} /* markDead */
967
968/*
969 marks groups with two eyes as live
970*/
971MLspan(x, y, saw1, sawm1, size, sMark)
972short x, y, *saw1, *sawm1, *size, sMark;
973 { /* span */
974 if (ndbord[x][y] == 1)
975 *saw1 = TRUE;
976 else if (ndbord[x][y] == -1)
977 *sawm1 = TRUE;
978 else if (sGroups[x][y] == 0)
979 {
980 sGroups[x][y] = sMark;
981 *size = *size + 1;
982 if (x > 0)
983 MLspan(x - 1, y, saw1, sawm1, size, sMark);
984 if (x < maxPoint)
985 MLspan(x + 1, y, saw1, sawm1, size, sMark);
986 if (y > 0)
987 MLspan(x, y - 1, saw1, sawm1, size, sMark);
988 if (y < maxPoint)
989 MLspan(x, y + 1, saw1, sawm1, size, sMark);
990 }
991 } /* span */
992
993short CLspan(x, y, numEyes, who)
994short x, y, *numEyes, who;
995 { /* span */
996 markBoard[x][y] = marker;
997 if (ndbord[x][y] == 0)
998 {
999 if ((sList[sGroups[x][y]].sm != marker) &&
1000 (sList[sGroups[x][y]].w == who))
1001 {
1002 sList[sGroups[x][y]].sm = marker;
1003 if (sList[sGroups[x][y]].s > 6)
1004 return TRUE;
1005 *numEyes = *numEyes + 1;
1006 if (*numEyes > 1)
1007 return TRUE;
1008 }
1009 }
1010 else if (bord[x][y] == who)
1011 {
1012 if ((x > 0) &&
1013 (markBoard[x - 1][y] != marker))
1014 if (CLspan(x - 1, y, numEyes, who)) return TRUE;
1015 if ((x < maxPoint) &&
1016 (markBoard[x + 1][y] != marker))
1017 if (CLspan(x + 1, y, numEyes, who)) return TRUE;
1018 if ((y > 0) &&
1019 (markBoard[x][y - 1] != marker))
1020 if (CLspan(x, y - 1, numEyes, who)) return TRUE;
1021 if ((y < maxPoint) &&
1022 (markBoard[x][y + 1] != marker))
1023 if (CLspan(x, y + 1, numEyes, who)) return TRUE;
1024 }
1025 return FALSE;
1026 } /* span */
1027
1028short checkLive(x, y)
1029short x, y;
1030 { /* checkLive */
1031 short numEyes, who;
1032#ifdef DEBUG
1033 printf( "checkLive\n" );
1034#endif
1035 numEyes = 0;
1036 who = bord[x][y];
1037 marker = marker + 1;
1038 return CLspan(x, y, &numEyes, who);
1039 } /* checkLive */
1040
1041markLive()
1042{ /* markLive */
1043 short i, j, size, sMark = 0;
1044 short saw1, sawm1;
1045#ifdef DEBUG
1046 printf( "markLive\n" );
1047#endif
1048 initArray(sGroups);
1049 for (i = 0; i <= maxPoint; i++)
1050 for (j = 0; j <= maxPoint; j++)
1051 if ((sGroups[i][j] == 0) &&
1052 (ndbord[i][j] == 0))
1053 {
1054 size = 0;
1055 sMark = sMark + 1;
1056 sawm1 = FALSE;
1057 saw1 = FALSE;
1058 MLspan(i, j, &saw1, &sawm1, &size, sMark);
1059 sList[sMark].s = size;
1060 sList[sMark].sm = 0;
1061 if (sawm1)
1062 if (saw1)
1063 sList[sMark].w = 0;
1064 else
1065 sList[sMark].w = -1;
1066 else if (saw1)
1067 sList[sMark].w = 1;
1068 else
1069 sList[sMark].w = 0;
1070 }
1071 for (i = 1; i <= maxGroupID; i++)
1072 if (! gList[i].isDead)
1073 gList[i].isLive = checkLive(gList[i].lx, gList[i].ly);
1074} /* markLive */
1075
1076/*
1077 generates the connection map and the protected point map.
1078*/
1079genConnects()
1080{ /* genConnects */
1081 short x, y, numStones;
1082#ifdef DEBUG
1083 printf( "genConnects\n" );
1084#endif
1085 for (x = 0; x <= maxPoint; x++)
1086 for (y = 0; y <= maxPoint; y++)
1087 {
1088 connectMap[x][y] = 0;
1089 protPoints[x][y] = 0;
1090 }
1091 for (x = 0; x <= maxPoint; x++)
1092 for (y = 0; y <= maxPoint; y++)
1093 if (bord[x][y] == 1) /* map connections to this stone */
1094 {
1095 if (x > 0) /* direct connection */
1096 connectMap[x - 1][y] += 1;
1097 if (x < maxPoint)
1098 connectMap[x + 1][y] += 1;
1099 if (y > 0)
1100 connectMap[x][y - 1] += 1;
1101 if (y < maxPoint)
1102 connectMap[x][y + 1] += 1;
1103 if ((x > 0) && (y > 0) && /* diagonal connection */
1104 (bord[x - 1][y] == 0) && (bord[x][y - 1] == 0))
1105 connectMap[x - 1][y - 1] += 1;
1106 if ((x < maxPoint) && (y > 0) &&
1107 (bord[x + 1][y] == 0) && (bord[x][y - 1] == 0))
1108 connectMap[x + 1][y - 1] += 1;
1109 if ((x < maxPoint) && (y < maxPoint) &&
1110 (bord[x + 1][y] == 0) && (bord[x][y + 1] == 0))
1111 connectMap[x + 1][y + 1] += 1;
1112 if ((x > 0) && (y < maxPoint) &&
1113 (bord[x - 1][y] == 0) && (bord[x][y + 1] == 0))
1114 connectMap[x - 1][y + 1] += 1;
1115 if ((x > 1) && (claim[x - 1][y] > 3)) /* one point jump */
1116 connectMap[x - 2][y] += 1;
1117 if ((x < (maxPoint - 1)) && (claim[x + 1][y] > 3))
1118 connectMap[x + 2][y] += 1;
1119 if ((y > 1) && (claim[x][y - 1] > 3))
1120 connectMap[x][y - 2] += 1;
1121 if ((y < (maxPoint - 1)) && (claim[x][y + 1] > 3))
1122 connectMap[x][y + 2] += 1;
1123 if ((x > 1) && (y > 0) && /* knight's move */
1124 (claim[x - 1][y] > 3) && (claim[x - 1][y - 1] > 3))
1125 connectMap[x - 2][y - 1] += 1;
1126 if ((x > 0) && (y > 1) &&
1127 (claim[x][y - 1] > 3) && (claim[x - 1][y - 1] > 3))
1128 connectMap[x - 1][y - 2] += 1;
1129 if ((x < (maxPoint - 1)) && (y > 0) &&
1130 (claim[x + 1][y] > 3) && (claim[x + 1][y - 1] > 3))
1131 connectMap[x + 2][y - 1] += 1;
1132 if ((x < maxPoint) && (y > 1) &&
1133 (claim[x][y - 1] > 3) && (claim[x + 1][y - 1] > 3))
1134 connectMap[x + 1][y - 2] += 1;
1135 if ((x > 1) && (y < maxPoint) &&
1136 (claim[x - 1][y] > 3) && (claim[x - 1][y + 1] > 3))
1137 connectMap[x - 2][y + 1] += 1;
1138 if ((x > 0) && (y < (maxPoint - 1)) &&
1139 (claim[x][y + 1] > 3) && (claim[x - 1][y + 1] > 3))
1140 connectMap[x - 1][y + 2] += 1;
1141 if ((x < (maxPoint - 1)) && (y < maxPoint) &&
1142 (claim[x + 1][y] > 3) && (claim[x + 1][y + 1] > 3))
1143 connectMap[x + 2][y + 1] += 1;
1144 if ((x < maxPoint) && (y < (maxPoint - 1)) &&
1145 (claim[x][y + 1] > 3) && (claim[x + 1][y + 1] > 3))
1146 connectMap[x + 1][y + 2] += 1;
1147 }
1148 else if (bord[x][y] == 0) /* see if protected point */
1149 {
1150 numStones = 0;
1151 if (x == 0)
1152 numStones = numStones + 1;
1153 if (y == 0)
1154 numStones = numStones + 1;
1155 if (x == maxPoint)
1156 numStones = numStones + 1;
1157 if (y == maxPoint)
1158 numStones = numStones + 1;
1159 if ((x > 0) && (bord[x - 1][y] == 1))
1160 numStones = numStones + 1;
1161 if ((y > 0) && (bord[x][y - 1] == 1))
1162 numStones = numStones + 1;
1163 if ((x < maxPoint) && (bord[x + 1][y] == 1))
1164 numStones = numStones + 1;
1165 if ((y < maxPoint) && (bord[x][y + 1] == 1))
1166 numStones = numStones + 1;
1167 if (numStones == 4)
1168 protPoints[x][y] = 1;
1169 else if (numStones == 3)
1170 {
1171 if ((x > 0) &&
1172 ((bord[x - 1][y] == 0) ||
1173 ((bord[x - 1][y] == -1) &&
1174 (gList[groupIDs[x - 1][y]].libC == 1))))
1175 protPoints[x][y] = 1;
1176 else if ((x < maxPoint) &&
1177 ((bord[x + 1][y] == 0) ||
1178 ((bord[x + 1][y] == -1) &&
1179 (gList[groupIDs[x + 1][y]].libC == 1))))
1180 protPoints[x][y] = 1;
1181 else if ((y > 0) &&
1182 ((bord[x][y - 1] == 0) ||
1183 ((bord[x][y - 1] == -1) &&
1184 (gList[groupIDs[x][y - 1]].libC == 1))))
1185 protPoints[x][y] = 1;
1186 else if ((y < maxPoint) &&
1187 ((bord[x][y + 1] == 0) ||
1188 ((bord[x][y + 1] == -1) &&
1189 (gList[groupIDs[x][y + 1]].libC == 1))))
1190 protPoints[x][y] = 1;
1191 }
1192 }
1193 for (x = 0; x <= maxPoint; x++)
1194 for (y = 0; y <= maxPoint; y++)
1195 if (bord[x][y] != 0)
1196 {
1197 connectMap[x][y] = 0;
1198 protPoints[x][y] = 0;
1199 }
1200} /* genConnects */
1201
1202/*
1203 generates the whole state of the game.
1204*/
1205genState()
1206{ /* genState */
1207#ifdef DEBUG
1208 printf( "genState\n" );
1209#endif
1210 inGenState = TRUE;
1211 respreicen();
1212 markDead();
1213 markLive();
1214 spread();
1215 genConnects();
1216#ifdef DEBUG
1217/* printBoard( claim, "claim" ); */
1218/* printBoard( bord, "bord" ); */
1219/* printBoard( ndbord, "ndbord" );
1220 printBoard( sGroups, "sGroups" );
1221 printBoard( groupIDs, "groupIDs" );
1222 printBoard( connectMap, "connectMap" );
1223 printBoard( protPoints, "protPoints" ); */
1224#endif
1225 inGenState = FALSE;
1226} /* genState */
1227
1228/*
1229 generates a value for the [x, y] location that appears to get larger
1230 for points that are saddle points in the influence graph (klein)
1231*/
1232short tencen(x, y)
1233short x, y;
1234{ /* tencen */
1235 short a, b, c, d, w, z;
1236#ifdef DEBUG
1237 printf( "tencen\n" );
1238#endif
1239 if (claim[x][y] > -1) /* if (he does not influence this area, return 50 */
1240 {
1241 return 50;
1242 }
1243 w = claim[x][y]; /* w <= -1 */
1244 a = iNil;
1245 if (x > 0)
1246 if (claim[x - 1][y] > -1) /* if (neighbor is not influenced by him */
1247 a = claim[x - 1][y] - w; /* score is sum of his influence on central */
1248 b = iNil; /* point and my influence on this neighbor */
1249 if (y > 0)
1250 if (claim[x][y - 1] > -1)
1251 b = claim[x][y - 1] - w;
1252 c = iNil;
1253 if (x < maxPoint)
1254 if (claim[x + 1][y] > -1)
1255 c = claim[x + 1][y] - w;
1256 d = iNil;
1257 if (y < maxPoint)
1258 if (claim[x][y + 1] > -1)
1259 d = claim[x][y + 1] - w;
1260 z = a; /* z = max(a, b, c, d) */
1261 if (z != iNil)
1262 {
1263 if ((b != iNil) &&
1264 (b > z))
1265 z = b;
1266 }
1267 else
1268 z = b;
1269 if (z != iNil)
1270 {
1271 if ((c != iNil) &&
1272 (c > z))
1273 z = c;
1274 }
1275 else
1276 z = c;
1277 if (z != iNil)
1278 {
1279 if ((d != iNil) &&
1280 (d > z))
1281 z = d;
1282 }
1283 else
1284 z = d;
1285 if ((z != iNil) &&
1286 ((x == 0) ||
1287 (y == 0) ||
1288 (x == maxPoint) ||
1289 (y == maxPoint)))
1290 z = z * 2; /* double z if (on the edge of the board ?? */
1291 if (z != iNil)
1292 return z;
1293 else
1294 return 50;
1295} /* tencen */
1296
1297initGPUtils()
1298{ /* initGPUtils */
1299#ifdef DEBUG
1300 printf( "initGPUtils\n" );
1301#endif
1302 initArray(markBoard);
1303 initState();
1304 marker = 0;
1305 playMark = 0;
1306 gList[0].isLive = FALSE;
1307 gList[0].isDead = FALSE;
1308 gList[0].libC = 0;
1309 gList[0].size = 0;
1310 gList[0].numEyes = 0;
1311 gList[0].lx = -1;
1312 gList[0].ly = -1;
1313 gMap[0] = 0;
1314 dbStop = FALSE;
1315 inGenState = FALSE;
1316} /* initGPUtils */
1317
diff --git a/noncore/games/go/goplayutils.h b/noncore/games/go/goplayutils.h
new file mode 100644
index 0000000..11ab658
--- a/dev/null
+++ b/noncore/games/go/goplayutils.h
@@ -0,0 +1,85 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef __goplayutils_h
21#define __goplayutils_h
22
23#define iNil 32767 /* a distinguished value like nil */
24#define maxGroup 512
25#define maxSPoint 16
26#define tryLimit 300
27
28typedef short intBoard[19][19]; /* these were -2 to maxPoint + 2 */
29
30typedef short boolBoard[19][19];
31
32typedef struct
33{
34 short px, py;
35} point;
36
37typedef struct
38{
39 point p[401];
40 short indx;
41} pointList;
42
43typedef struct
44{
45 point p[maxSPoint+1];
46 short indx;
47} sPointList;
48
49typedef struct
50{
51 short indx,
52 v[401];
53} intList;
54
55typedef struct { short w, s, sm; } sgRec;
56
57typedef struct
58{
59 short groupMark,
60 atLevel,
61 isLive,
62 isDead,
63 libC,
64 numEyes,
65 size,
66 lx, ly;
67} groupRec;
68
69typedef enum {rem, add, chLib, reMap} playType;
70
71typedef struct { short who, xl, yl, nextGID, sNumber; } remAddRec;
72typedef struct { short oldLC, oldLevel; } chLibRec;
73typedef struct { short oldGID; } reMapRec;
74typedef struct
75{
76 short gID;
77 playType kind;
78 union {
79 remAddRec rem, add;
80 chLibRec chLib;
81 reMapRec reMap;
82 } uval;
83} playRec;
84
85#endif
diff --git a/noncore/games/go/gowidget.cpp b/noncore/games/go/gowidget.cpp
new file mode 100644
index 0000000..fca9797
--- a/dev/null
+++ b/noncore/games/go/gowidget.cpp
@@ -0,0 +1,449 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "gowidget.h"
22
23#include <qpe/config.h>
24#include <qpe/resource.h>
25
26#include <qpainter.h>
27#include <qpixmap.h>
28#include <qpe/qpetoolbar.h>
29#include <qpe/qpemenubar.h>
30#include <qpopupmenu.h>
31#include <qaction.h>
32#include <qapplication.h> //processEvents()
33#include <qlabel.h>
34
35//#include <stdio.h>
36
37#include "amigo.h"
38#include "goplayutils.h"
39
40static const enum bVal computer_color = BLACK;
41
42static int current_handicap = 1;
43
44static QBrush *goBrush;
45//static QImage *newBlackStone;
46//static QImage *blackStone;
47//static QImage *whiteStone;
48static QPixmap *newBlackStone;
49static QPixmap *blackStone;
50static QPixmap *whiteStone;
51
52GoMainWidget::GoMainWidget( QWidget *parent, const char* name) :
53 QMainWindow( parent, name )
54{
55 setToolBarsMovable( FALSE );
56 GoWidget *go = new GoWidget(this);
57
58 setCentralWidget(go);
59 toolbar = new QPEToolBar(this);
60 toolbar->setHorizontalStretchable( TRUE );
61 addToolBar(toolbar);
62
63 QPEMenuBar *mb = new QPEMenuBar( toolbar );
64 mb->setMargin(0);
65 QPopupMenu *file = new QPopupMenu( this );
66
67 QAction *a = new QAction( tr( "New Game" ), QString::null, 0, this, 0 );
68 connect( a, SIGNAL( activated() ), go, SLOT( newGame() ) );
69 a->addTo( file );
70
71 a = new QAction( tr( "Pass" ), Resource::loadPixmap( "pass" ), QString::null, 0, this, 0 );
72 connect( a, SIGNAL( activated() ), go, SLOT( pass() ) );
73 a->addTo( file );
74 a->addTo( toolbar );
75
76
77 a = new QAction( tr( "Resign" ), Resource::loadPixmap( "reset" ), QString::null, 0, this, 0 );
78 connect( a, SIGNAL( activated() ), go, SLOT( resign() ) );
79 a->addTo( file );
80
81 a = new QAction( tr( "Two player option" ), QString::null, 0, this, 0 );
82 a->setToggleAction( TRUE );
83 connect( a, SIGNAL( toggled(bool) ), go, SLOT( setTwoplayer(bool) ) );
84 a->addTo( file );
85
86 mb->insertItem( tr( "Game" ), file );
87
88 QLabel *turnLabel = new QLabel( toolbar );
89 turnLabel->setBackgroundMode( PaletteButton );
90 connect( go, SIGNAL(showTurn(const QPixmap&)),
91 turnLabel, SLOT(setPixmap(const QPixmap&)) );
92
93
94 QLabel * scoreLabel = new QLabel( toolbar );
95 scoreLabel->setBackgroundMode( PaletteButton );
96 connect( go, SIGNAL(showScore(const QString&)),
97 scoreLabel, SLOT(setText(const QString&)) );
98
99 toolbar->setStretchableWidget( scoreLabel );
100
101 go->readConfig();
102}
103
104void GoMainWidget::resizeEvent( QResizeEvent * )
105{
106 //### this won't work because of the text label...
107 /*
108 if ( width() > height() )
109 moveToolBar( toolbar, Left );
110 else
111 moveToolBar( toolbar, Top );
112 */
113}
114
115GoWidget *GoWidget::self = 0;
116
117GoWidget::GoWidget( QWidget *parent, const char* name) :
118 QWidget( parent, name )
119{
120 if ( self )
121 fatal( "Only one Go widget allowed" );
122 self = this;
123 twoplayer = FALSE;
124
125
126 d = bx = by = 1;
127
128 QPixmap pix = Resource::loadPixmap( "pine" );
129 goBrush = new QBrush( black, pix );
130 /*
131 QString fn = Resource::findPixmap("Go-black");
132 blackStone = new QImage( fn );
133 fn = Resource::findPixmap("Go-black-highlight");
134 newBlackStone = new QImage( fn );
135 fn = Resource::findPixmap("Go-white");
136 whiteStone = new QImage( fn );
137 */
138 blackStone = new QPixmap(Resource::loadPixmap( "Go-black" ));
139 whiteStone = new QPixmap(Resource::loadPixmap( "Go-white" ));
140 newBlackStone = new QPixmap(Resource::loadPixmap( "Go-black-highlight" ));
141
142 init();
143}
144
145GoWidget::~GoWidget()
146{
147 writeConfig();
148}
149
150void GoWidget::writeConfig()
151{
152 Config cfg("Go");
153 cfg.setGroup("Game");
154 cfg.writeEntry("TwoPlayer", twoplayer);
155 cfg.writeEntry("CurrentPlayer", currentPlayer);
156 cfg.writeEntry("NPassed", nPassed);
157 QString b;
158 for (int i=0; i<19; i++)
159 for (int j=0; j<19; j++)
160 b += board[i][j] == BLACK ? 'B' : board[i][j] == WHITE ? 'W' : '.';
161 cfg.writeEntry("Board", b);
162 cfg.writeEntry("LastX", lastX);
163 cfg.writeEntry("LastY", lastY);
164 extern int blackPrisoners, whitePrisoners;
165 cfg.writeEntry("BlackPrisoners", blackPrisoners);
166 cfg.writeEntry("WhitePrisoners", whitePrisoners);
167}
168
169void GoWidget::readConfig()
170{
171 init();
172 Config cfg("Go");
173 cfg.setGroup("Game");
174 twoplayer = cfg.readBoolEntry("TwoPlayer");
175 currentPlayer = (bVal)cfg.readNumEntry("CurrentPlayer",1);
176 nPassed = cfg.readNumEntry("NPassed",0);
177 QString b = cfg.readEntry("Board");
178 if ( b.length() == 19*19 )
179 for (int i=0; i<19; i++)
180 for (int j=0; j<19; j++) {
181 QChar ch = b[j+19*i];
182 if ( ch != '.' )
183 GoPlaceStone( ch == 'B' ? BLACK : WHITE, i, j );
184 }
185 lastX = cfg.readNumEntry("LastX");
186 lastY = cfg.readNumEntry("LastY");
187 extern int blackPrisoners, whitePrisoners;
188 blackPrisoners = cfg.readNumEntry("BlackPrisoners",0);
189 whitePrisoners = cfg.readNumEntry("WhitePrisoners",0);
190 reportPrisoners(blackPrisoners,whitePrisoners);
191 emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
192}
193
194void GoWidget::resizeEvent( QResizeEvent * )
195{
196 d = QMIN(width(),height())/19;
197 // int r = (d/2-1);
198 bx = (width() - 18*d)/2 ;
199 by = (height() - 18*d)/2 ;
200}
201
202void GoWidget::init()
203{
204 lastX = lastY = newX = newY = -1;
205 nPassed = 0;
206 for ( int i = 0; i < 19; i++ )
207 for ( int j = 0; j < 19; j++ )
208 board[i][j]=-1;
209 gameActive = TRUE;
210 goRestart(current_handicap);
211
212 if ( twoplayer ) {
213 currentPlayer = BLACK;
214 } else {
215 doComputerMove();
216 currentPlayer = WHITE;
217 }
218 emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
219}
220
221void GoWidget::paintEvent( QPaintEvent *e )
222{
223 int i,j;
224
225 int r = whiteStone->width()/2;
226
227 QPainter p(this);
228 p.fillRect( bx - d/2, by - d/2, 19*d, 19*d, *goBrush );
229
230 int xMin = QMAX( x2board(e->rect().left()), 0 );
231 int xMax = QMIN( x2board(e->rect().right()), 18 );
232 int yMin = QMAX( y2board(e->rect().top()), 0 );
233 int yMax = QMIN( y2board(e->rect().bottom()), 18 );
234
235 QColor pine( 255, 186, 89 );
236 p.setPen( pine.dark() );
237
238 for ( i = xMin; i < xMax+1 ; i ++ ) {
239 p.drawLine( bx+i*d, by, bx+i*d, by+18*d );
240 }
241 for ( j = yMin; j < yMax+1 ; j ++ ) {
242 p.drawLine( bx, by+j*d, bx+18*d, by+j*d);
243 }
244
245 // dots are at (3,3), (3,9), (3,15) and so on
246 p.setBrush( black );
247 for ( i = 3; i < xMax+1; i+=6 )
248 for ( j = 3; j < yMax+1; j+=6 )
249 p.drawEllipse( bx+i*d-2, by+j*d-2, 5, 5 );
250
251
252 for ( i = xMin; i < xMax+1; i++ )
253 for ( j = yMin; j < yMax+1; j++ ) {
254 if ( board[i][j] == WHITE ||
255 currentPlayer==WHITE && newX == i && newY == j )
256 p.drawPixmap( bx+i*d - r, by+j*d - r, *whiteStone );
257 else if ( i == lastX && j == lastY )
258 p.drawPixmap( bx+i*d - r, by+j*d - r, *newBlackStone );
259 else if ( board[i][j] == BLACK ||
260 currentPlayer==BLACK && newX == i && newY == j)
261 p.drawPixmap( bx+i*d - r, by+j*d - r, *blackStone );
262 }
263}
264
265void GoWidget::doMove( int x, int y )
266{
267
268 if ( !GoPlaceStone( currentPlayer, x, y ) ) {
269 //printf( "Illegal move (%d,%d)\n", x, y );
270 return;
271 }
272 //printf( "you do (%d,%d)\n", x, y );
273 nPassed = 0;
274 if ( twoplayer )
275 currentPlayer = (currentPlayer==WHITE) ? BLACK : WHITE;
276 else
277 doComputerMove();
278
279 emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
280
281}
282
283void GoWidget::pass()
284{
285 if ( !gameActive )
286 return;
287 nPassed++;
288 if ( nPassed >= 2 )
289 endGame();
290 else if ( !twoplayer )
291 doComputerMove();
292}
293
294void GoWidget::resign()
295{
296 if ( gameActive )
297 endGame();
298}
299
300
301void GoWidget::newGame()
302{
303 init();
304 update();
305}
306
307
308void GoWidget::endGame()
309{
310 gameActive = FALSE;
311
312 int w,b;
313 CountUp( &w, &b);
314 QString s = tr("White %1, Black %2. ").arg(w).arg(b);
315 if ( w > b )
316 s += tr("White wins.");
317 else if ( w < b )
318 s += tr("Black wins.");
319 else
320 s += tr("A draw.");
321 emit showScore( s );
322}
323
324void GoWidget::doComputerMove()
325{
326 int ox = lastX;
327 int oy = lastY;
328 lastX = lastY = -1;
329 emit showTurn( *blackStone );
330 refresh( ox, oy);
331 qApp->processEvents();
332 short int x,y;
333 if ( genMove( computer_color, &x, &y ) ) {
334 lastX = x;
335 lastY = y;
336 //printf( "I do (%d,%d)\n", x, y );
337 GoPlaceStone(computer_color,x,y);
338 nPassed = 0;
339 } else {
340 emit showScore( tr("I pass") );
341 nPassed++;
342 if ( nPassed >= 2 )
343 endGame();
344 }
345}
346
347void GoWidget::mousePressEvent( QMouseEvent *me )
348{
349 if ( !gameActive )
350 return;
351 int x = x2board(me->x());
352 int y = y2board(me->y());
353 showStone(x,y,currentPlayer);
354}
355
356void GoWidget::mouseMoveEvent( QMouseEvent *me )
357{
358 if ( !gameActive )
359 return;
360 int x = x2board(me->x());
361 int y = y2board(me->y());
362 if ( x != newX || y != newY )
363 showStone(x,y,currentPlayer);
364}
365
366void GoWidget::showStone( int x, int y, enum bVal c )
367{
368
369 if ( newX > -1 ) {
370 refresh( newX, newY );
371 newY = newX = -1;
372 }
373 if ( x < 0 || x > 18 || y < 0 || y > 18 ) {
374 newX = newY = -1;
375 return;
376 }
377 if ( board[x][y] == -1 && !Suicide( c, x, y ) ) {
378 newX = x;
379 newY = y;
380 refresh(x,y);
381 }
382
383}
384
385void GoWidget::mouseReleaseEvent( QMouseEvent * )
386{
387 if ( gameActive && newX > -1 )
388 doMove( newX, newY );
389 newX = newY = -1;
390}
391
392void GoWidget::refresh( int x, int y )
393{
394 update( bx+d*x-d/2-1, by+d*y-d/2-1, d+2, d+2 );
395}
396
397void GoWidget::removeStone(short x, short y)
398{
399 board[x][y]=-1;
400 refresh( x, y );
401}
402
403void GoWidget::placeStone (enum bVal c, short x, short y )
404{
405 board[x][y]=c;
406 refresh( x, y );
407}
408
409void GoWidget::reportPrisoners( int blackcnt, int whitecnt )
410{
411 QString s = tr( "Prisoners: black %1, white %2" ).arg(blackcnt).arg(whitecnt);
412 emit showScore( s );
413}
414
415void GoWidget::setTwoplayer( bool b )
416{
417 twoplayer = b;
418}
419
420void GoWidget::setHandicap( int h )
421{
422 current_handicap = h;
423}
424
425
426extern "C" {
427
428 voidremovestone(short x, short y)
429{
430 GoWidget::self->removeStone(x,y);
431}
432
433 voidplacestone (enum bVal c, short x, short y )
434{
435 GoWidget::self->placeStone(c,x,y);
436}
437
438 voidintrMoveReport(enum bVal c ,char *coord ,char *reason )
439{
440 qDebug( "intrMoveReport colour %d, %s %s", c, coord, reason );
441}
442
443 voidintrPrisonerReport( short blackcnt, short whitecnt )
444{
445 GoWidget::self->reportPrisoners(blackcnt,whitecnt);
446}
447
448}
449
diff --git a/noncore/games/go/gowidget.h b/noncore/games/go/gowidget.h
new file mode 100644
index 0000000..94de2cc
--- a/dev/null
+++ b/noncore/games/go/gowidget.h
@@ -0,0 +1,111 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef GOWIDGET_H
22#define GOWIDGET_H
23
24#include <qmainwindow.h>
25#include "amigo.h"
26
27
28class QToolBar;
29
30class GoMainWidget : public QMainWindow
31{
32 Q_OBJECT
33public:
34 GoMainWidget( QWidget *parent=0, const char* name=0);
35protected:
36 void resizeEvent( QResizeEvent * );
37private:
38 QToolBar *toolbar;
39
40};
41
42
43class QLabel;
44class GoWidget : public QWidget
45{
46 Q_OBJECT
47public:
48 GoWidget( QWidget *parent=0, const char* name=0);
49 ~GoWidget();
50
51 void doMove( int x, int y );
52 void doComputerMove();
53
54 void readConfig();
55 void writeConfig();
56
57public slots:
58 void pass();
59 void resign();
60 void newGame();
61 void setTwoplayer( bool );
62 void setHandicap( int );
63signals:
64 void showScore( const QString& );
65 void showTurn( const QPixmap& );
66
67protected:
68 void paintEvent( QPaintEvent * );
69 void mousePressEvent( QMouseEvent * );
70 void mouseMoveEvent( QMouseEvent * );
71 void mouseReleaseEvent( QMouseEvent * );
72 void resizeEvent( QResizeEvent * );
73private:
74 void init();
75 void removeStone(short x, short y);
76 void placeStone (enum bVal c, short x, short y );
77
78 void refresh( int x, int y );
79 void showStone( int x, int y, enum bVal );
80 void reportPrisoners(int,int);
81
82 inline int x2board( int x ) { return (x-bx+d/2)/d; }
83 inline int y2board( int y ) { return (y-by+d/2)/d; }
84
85 void endGame();
86
87 bool twoplayer;
88 enum bVal currentPlayer;
89 bool gameActive;
90 int nPassed;
91 signed char board[19][19];
92
93 int d; //distance between lines
94 int bx; //vertical baseline
95 int by; //horizontal baseline
96
97 int lastX,lastY;
98 int newX,newY;
99
100 static GoWidget *self;
101
102 friend void removestone(short x, short y);
103 friend voidintrPrisonerReport( short, short );
104 friend void placestone(enum bVal c, short x, short y );
105};
106
107
108
109
110
111#endif
diff --git a/noncore/games/go/killable.c b/noncore/games/go/killable.c
new file mode 100644
index 0000000..3ed2d2e
--- a/dev/null
+++ b/noncore/games/go/killable.c
@@ -0,0 +1,373 @@
1/* By Stoney Ballard */
2/* Ported from Pascal to C by Todd R. Johnson */
3
4#include "go.h"
5#include "goplayutils.h"
6#include "amigo.h"
7
8extern intBoard bord, groupIDs;
9extern boolBoard legal;
10extern groupRec gList[maxGroup];
11extern short gMap[maxGroup], adjInAtari, adj2Libs, playMark, treeLibLim,
12 utilPlayLevel, killFlag, depthLimit, dbStop, showTrees;
13extern pointList plist2;
14
15/*
16 returns true if the group (at x, y) is killable.
17 if so, returns the point to play at in killx, killy.
18*/
19
20 short me, him, depth, i, j, tryCount, tl, topMark, tkMark, mark2;
21 char sChar;
22 sPointList lList, dList;
23 point tp;
24 short libList[maxSPoint+1];
25 short esc;
26
27short mtNbrs(x, y)
28short x, y;
29 { /* mtNbrs */
30 short n = 0;
31 if ((x > 0) && (bord[x - 1][y] == 0))
32 n = n + 1;
33 if ((x < maxPoint) && (bord[x + 1][y] == 0))
34 n = n + 1;
35 if ((y > 0) && (bord[x][y - 1] == 0))
36 n = n + 1;
37 if ((y < maxPoint) && (bord[x][y + 1] == 0))
38 n = n + 1;
39 return n;
40 } /* mtNbrs */
41
42short killTree(tx, ty, gx, gy, escape, tkMark)
43short tx, ty, gx, gy, *escape, tkMark;
44 { /* killTree */
45 short curMark, mark2, mark3, i, j, k, tl, dStart, result;
46 sPointList lList1, lList2;
47 short libList[maxSPoint+1];
48 point tp;
49 short esc = FALSE;
50 tryCount = tryCount + 1;
51 if (tryCount > tryLimit)
52 {
53 undoTo(tkMark);
54/* for (i = 1; i <= depth - 1; i++)
55 {
56 sClearChar(sChar, rXor);
57 } */
58 depth = 1;
59 return FALSE;
60 }
61/* write(sChar); */
62 depth = depth + 1;
63 curMark = playMark;
64 tryPlay(tx, ty, me); /* try my move */
65 pause();
66 if (gList[gMap[groupIDs[tx][ty]]].libC == 0) /* I'm dead */
67 {
68 result = FALSE;
69 goto one;
70 }
71 else if (killFlag) /* I killed something of his */
72 {
73 result = TRUE;
74 goto one;
75 }
76 else if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim) /* safe */
77 {
78 result = FALSE;
79 goto one;
80 }
81 else
82 {
83 sSpanGroup(gx, gy, &lList1); /* find his liberties */
84 if (gList[gMap[groupIDs[tx][ty]]].libC == 1) /* he can kill me */
85 {
86 if (lList1.indx < maxSPoint) /* add that option to his list */
87 {
88 lList1.indx = lList1.indx + 1;
89 spanGroup(tx, ty, &plist2); /* find my liberty */
90 lList1.p[lList1.indx].px = plist2.p[1].px;
91 lList1.p[lList1.indx].py = plist2.p[1].py;
92 }
93 else
94 {
95 result = FALSE;
96 goto one;
97 }
98 }
99 for (i = 1; i <= maxSPoint; i++) /* init liblist so diags can be marked */
100 libList[i] = -1;
101 if ((utilPlayLevel > 4) &&
102 (lList1.indx > 1) &&
103 (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* try diags */
104 {
105 listDiags(gx, gy, &dList);
106 j = 0;
107 i = lList1.indx;
108 while ((j < dList.indx) &&
109 (i < maxSPoint))
110 {
111 j = j + 1;
112 i = i + 1;
113 libList[i] = 0; /* mark this as a diag */
114 lList1.p[i].px = dList.p[j].px;
115 lList1.p[i].py = dList.p[j].py;
116 }
117 lList1.indx = i;
118 }
119 if (lList1.indx > 1) /* sort by decreasing lib count */
120 {
121 for (i = 1; i <= lList1.indx; i++)
122 if (libList[i] != 0) /* diags are tried last */
123 {
124 mark2 = playMark;
125 tryPlay(lList1.p[i].px, lList1.p[i].py, him);
126 libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
127 if ((libList[i] > treeLibLim) ||
128 ((libList[i] > (depthLimit - depth)) &&
129 (libList[i] > 2)))
130 {
131 *escape = TRUE;
132 result = FALSE;
133 goto one;
134 }
135 undoTo(mark2);
136 }
137 for (i = 1; i <= lList1.indx - 1; i++)
138 for (j = i + 1; j <= lList1.indx; j++)
139 if (libList[i] < libList[j])
140 {
141 tl = libList[i];
142 libList[i] = libList[j];
143 libList[j] = tl;
144 tp = lList1.p[i];
145 lList1.p[i] = lList1.p[j];
146 lList1.p[j] = tp;
147 }
148 }
149 for (i = 1; i <= lList1.indx + 1; i++) /* try his responses */
150 {
151 mark2 = playMark;
152 if (i <= lList1.indx) /* try his move */
153 {
154 tryPlay(lList1.p[i].px, lList1.p[i].py, him); /* play his response */
155 pause();
156 if (gList[gMap[groupIDs[lList1.p[i].px]
157 [lList1.p[i].py]]].libC < 2)
158 goto two; /* a bogus move */
159 }
160 else if (gList[gMap[groupIDs[gx][gy]]].libC <= 1)
161 {
162 result = TRUE;
163 goto one;
164 }
165 if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
166 {
167 *escape = TRUE;
168 result = FALSE;
169 goto one;
170 }
171 if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
172 { /* look at my responses */
173 sSpanGroup(gx, gy, &lList2); /* list his liberties */
174 dStart = lList2.indx + 1;
175 if (adjInAtari) /* he wins */
176 {
177 result = FALSE;
178 goto one;
179 }
180 if ((lList2.indx > 2) && adj2Libs) /* he wins */
181 {
182 result = FALSE;
183 goto one;
184 }
185 for (k = 1; k <= maxSPoint; k++)
186 libList[k] = -1;
187 if (utilPlayLevel > 4) /* account for diagonal moves */
188 {
189 listDiags(gx, gy, &dList);
190 j = 0;
191 k = lList2.indx;
192 while ((j < dList.indx) &&
193 (k < maxSPoint))
194 {
195 j = j + 1;
196 k = k + 1;
197 libList[k] = 100;
198 lList2.p[k].px = dList.p[j].px;
199 lList2.p[k].py = dList.p[j].py;
200 }
201 lList2.indx = k;
202 }
203 if (lList2.indx > 1) /* sort by increasing lib count */
204 {
205 for (k = 1; k <= lList2.indx; k++)
206 if (libList[k] != 100) /* diags go last */
207 {
208 mark3 = playMark;
209 tryPlay(lList2.p[k].px, lList2.p[k].py, me);
210 libList[k] = gList[gMap[groupIDs[gx][gy]]].libC;
211 undoTo(mark3);
212 }
213 for (k = 1; k <= lList2.indx - 1; k++)
214 for (j = k + 1; j <= lList2.indx; j++)
215 if (libList[k] > libList[j])
216 {
217 tl = libList[k];
218 libList[k] = libList[j];
219 libList[j] = tl;
220 tp = lList2.p[k];
221 lList2.p[k] = lList2.p[j];
222 lList2.p[j] = tp;
223 }
224 else if ((libList[k] == libList[j]) &&
225 (libList[k] == 1))
226 if (mtNbrs(lList2.p[k].px, lList2.p[k].py) <
227 mtNbrs(lList2.p[j].px, lList2.p[j].py))
228 {
229 tl = libList[k];
230 libList[k] = libList[j];
231 libList[j] = tl;
232 tp = lList2.p[k];
233 lList2.p[k] = lList2.p[j];
234 lList2.p[j] = tp;
235 }
236 }
237 for (j = 1; j <= lList2.indx; j++)
238 {
239 if (killTree(lList2.p[j].px, lList2.p[j].py, gx,
240 gy, &esc, tkMark))
241 goto two; /* this kills him */
242 if (esc && (j >= dStart))
243 {
244 result = FALSE;
245 goto one; /* don't bother with more diags if escapes */
246 }
247 }
248 result = FALSE; /* none of my responses kills him */
249 goto one;
250 }
251 two:
252 undoTo(mark2);
253 }
254 result = TRUE; /* none of his responses saves him */
255 }
256 one:
257 undoTo(curMark);
258/* sClearChar(sChar, rXor); */
259 depth = depth - 1;
260 return result;
261 } /* killTree */
262
263short tKillTree(tx, ty, gx, gy)
264short tx, ty, gx, gy;
265 { /* tKillTree */
266 short tkMark, escape;
267 tryCount = 0;
268 tkMark = playMark;
269 return killTree(tx, ty, gx, gy, &escape, tkMark);
270 } /* tKillTree */
271
272short killable(gx, gy, killx, killy)
273short gx, gy, *killx, *killy;
274{ /* killable */
275#ifdef DEBUG
276 printf( "killable\n" );
277 showTrees = TRUE;
278#endif
279 dbStop = TRUE;
280 him = bord[gx][gy]; /* find out who I am */
281 me = -him;
282/* if (me == 1)
283 sChar = '>';
284 else
285 sChar = '|'; */
286/* write(sChar); */
287 depth = 1;
288 topMark = playMark;
289 sSpanGroup(gx, gy, &lList); /* find his liberties */
290 if (lList.indx == 1)
291 {
292 *killx = lList.p[1].px;
293 *killy = lList.p[1].py;
294 return TRUE;
295 }
296 else if (lList.indx > treeLibLim)
297 return FALSE;
298 else if (adjInAtari)
299 return FALSE;
300 else if ((lList.indx > 2) && adj2Libs)
301 return FALSE;
302 else
303 {
304 for (i = 1; i <= maxSPoint; i++)
305 libList[i] = -1;
306 if (utilPlayLevel > 4) /* account for diagonal moves */
307 {
308 listDiags(gx, gy, &dList);
309 j = 0;
310 i = lList.indx;
311 while ((j < dList.indx) &&
312 (i < maxSPoint))
313 {
314 j = j + 1;
315 i = i + 1;
316 libList[i] = 100;
317 lList.p[i].px = dList.p[j].px;
318 lList.p[i].py = dList.p[j].py;
319 }
320 lList.indx = i;
321 }
322 if (lList.indx > 1) /* sort by increasing lib count */
323 {
324 for (i = 1; i <= lList.indx; i++)
325 if (libList[i] != 100) /* diags go last */
326 {
327 mark2 = playMark;
328 tryPlay(lList.p[i].px, lList.p[i].py, me);
329 libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
330 undoTo(mark2);
331 }
332 for (i = 1; i <= lList.indx - 1; i++)
333 for (j = i + 1; j <= lList.indx; j++)
334 if (libList[i] > libList[j])
335 {
336 tl = libList[i];
337 libList[i] = libList[j];
338 libList[j] = tl;
339 tp = lList.p[i];
340 lList.p[i] = lList.p[j];
341 lList.p[j] = tp;
342 }
343 else if ((libList[i] == libList[j]) &&
344 (libList[i] == 1))
345 if (mtNbrs(lList.p[i].px, lList.p[i].py) <
346 mtNbrs(lList.p[j].px, lList.p[j].py))
347 {
348 tl = libList[i];
349 libList[i] = libList[j];
350 libList[j] = tl;
351 tp = lList.p[i];
352 lList.p[i] = lList.p[j];
353 lList.p[j] = tp;
354 }
355 }
356 for (i = 1; i <= lList.indx; i++)
357 {
358 if (legal[lList.p[i].px][lList.p[i].py])
359 {
360 *killx = lList.p[i].px;
361 *killy = lList.p[i].py;
362 if (tKillTree(*killx, *killy, gx, gy))
363 {
364/* sClearChar(sChar, rXor); */
365 return TRUE;
366 }
367 }
368 }
369 return FALSE;
370 }
371/* sClearChar(sChar, rXor); */
372} /* killable */
373
diff --git a/noncore/games/go/main.cpp b/noncore/games/go/main.cpp
new file mode 100644
index 0000000..c7e2669
--- a/dev/null
+++ b/noncore/games/go/main.cpp
@@ -0,0 +1,35 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "gowidget.h"
22
23#include <qpe/qpeapplication.h>
24
25#include <stdio.h>
26
27int main( int argc, char ** argv)
28{
29 QPEApplication app( argc, argv );
30
31 GoMainWidget m;
32 m.setCaption( GoWidget::tr("Go") );
33 app.showMainWidget( &m );
34 return app.exec();
35}
diff --git a/noncore/games/go/qpe-go.control b/noncore/games/go/qpe-go.control
new file mode 100644
index 0000000..edc106b
--- a/dev/null
+++ b/noncore/games/go/qpe-go.control
@@ -0,0 +1,9 @@
1Files: bin/go apps/Games/go.desktop
2Priority: optional
3Section: qpe/games
4Maintainer: Warwick Allison <warwick@trolltech.com>
5Architecture: arm
6Version: $QPE_VERSION-3
7Depends: qpe-base ($QPE_VERSION)
8Description: The game of Go
9 A game for the Qtopia environment.