author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /noncore/games/go | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
-rw-r--r-- | noncore/games/go/.cvsignore | 2 | ||||
-rw-r--r-- | noncore/games/go/Makefile.in | 158 | ||||
-rw-r--r-- | noncore/games/go/README | 3 | ||||
-rw-r--r-- | noncore/games/go/README.AMIGO | 42 | ||||
-rw-r--r-- | noncore/games/go/README.XAMIGO | 26 | ||||
-rw-r--r-- | noncore/games/go/amigo.c | 656 | ||||
-rw-r--r-- | noncore/games/go/amigo.h | 146 | ||||
-rw-r--r-- | noncore/games/go/go.h | 81 | ||||
-rw-r--r-- | noncore/games/go/go.pro | 19 | ||||
-rw-r--r-- | noncore/games/go/goplayer.c | 1499 | ||||
-rw-r--r-- | noncore/games/go/goplayutils.c | 1317 | ||||
-rw-r--r-- | noncore/games/go/goplayutils.h | 85 | ||||
-rw-r--r-- | noncore/games/go/gowidget.cpp | 449 | ||||
-rw-r--r-- | noncore/games/go/gowidget.h | 111 | ||||
-rw-r--r-- | noncore/games/go/killable.c | 373 | ||||
-rw-r--r-- | noncore/games/go/main.cpp | 35 | ||||
-rw-r--r-- | noncore/games/go/qpe-go.control | 9 |
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 @@ | |||
1 | moc_* | ||
2 | Makefile | ||
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 | |||
17 | DESTDIR = ../bin/ | ||
18 | VER_MAJ = 1 | ||
19 | VER_MIN = 0 | ||
20 | VER_PATCH = 0 | ||
21 | TARGET= go | ||
22 | TARGET1 = 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 | ||
42 | INTERFACES = | ||
43 | UICDECLS = | ||
44 | UICIMPLS = | ||
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 | |||
71 | all: $(DESTDIR)$(TARGET) | ||
72 | |||
73 | $(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) | ||
74 | $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) | ||
75 | |||
76 | moc: $(SRCMOC) | ||
77 | |||
78 | tmake: | ||
79 | tmake go.pro | ||
80 | |||
81 | clean: | ||
82 | -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) | ||
83 | -rm -f *~ core | ||
84 | -rm -f allmoc.cpp | ||
85 | |||
86 | ####### Extension Modules | ||
87 | |||
88 | listpromodules: | ||
89 | @echo | ||
90 | |||
91 | listallmodules: | ||
92 | @echo | ||
93 | |||
94 | listaddonpromodules: | ||
95 | @echo | ||
96 | |||
97 | listaddonentmodules: | ||
98 | @echo | ||
99 | |||
100 | |||
101 | REQUIRES= | ||
102 | |||
103 | ####### Sub-libraries | ||
104 | |||
105 | |||
106 | ###### Combined headers | ||
107 | |||
108 | |||
109 | |||
110 | ####### Compile | ||
111 | |||
112 | amigo.o: amigo.c \ | ||
113 | go.h \ | ||
114 | goplayutils.h \ | ||
115 | amigo.h | ||
116 | |||
117 | goplayer.o: goplayer.c \ | ||
118 | go.h \ | ||
119 | goplayutils.h \ | ||
120 | amigo.h | ||
121 | |||
122 | goplayutils.o: goplayutils.c \ | ||
123 | goplayutils.h \ | ||
124 | amigo.h \ | ||
125 | go.h | ||
126 | |||
127 | killable.o: killable.c \ | ||
128 | go.h \ | ||
129 | goplayutils.h \ | ||
130 | amigo.h | ||
131 | |||
132 | gowidget.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 | |||
142 | main.o: main.cpp \ | ||
143 | gowidget.h \ | ||
144 | amigo.h \ | ||
145 | go.h \ | ||
146 | goplayutils.h \ | ||
147 | $(QPEDIR)/include/qpe/qpeapplication.h | ||
148 | |||
149 | moc_gowidget.o: moc_gowidget.cpp \ | ||
150 | gowidget.h \ | ||
151 | amigo.h \ | ||
152 | go.h \ | ||
153 | goplayutils.h | ||
154 | |||
155 | moc_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 @@ | |||
1 | This Go player For Qtopia is based on Xamigo, which in turn was | ||
2 | based on Amigo. The original README files are included as README.XAMIGO | ||
3 | and 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. | ||
2 | The Amiga interface and board manager were written by Todd R. Johnson. | ||
3 | The player is a C port of a Pascal player written by Stoney Ballard. | ||
4 | The interface allows you to play human vs. human, human vs. Amiga, or | ||
5 | Amiga vs. Amiga. | ||
6 | |||
7 | The board manager and player could both use some work. Currently, | ||
8 | you cannot save/load games, take back a move, or automatically score a | ||
9 | game. It is also limited to a 19 by 19 board. I'm releasing AmiGo | ||
10 | now because 1) I'm in the final phases of my dissertation and probably | ||
11 | won't have much time to do any further work on AmiGo, and 2) a lot of | ||
12 | people have been asking for an Amiga Go player. I am also releasing | ||
13 | all of the source code so that others can add to and modify AmiGo. | ||
14 | Note that all of my code in this release is public domain, while the | ||
15 | ported go player retains the original copyright. | ||
16 | |||
17 | If you distribute AmiGo, I urge you to include the source | ||
18 | code. If anyone makes changes, I would appreciate a copy. In fact, I | ||
19 | am willing to act as a clearinghouse for AmiGo changes. | ||
20 | |||
21 | Todd R. Johnson | ||
22 | tj@cis.ohio-state.edu | ||
23 | 8/8/89 | ||
24 | |||
25 | Here is the message attached to the original USENET posting of Stoney | ||
26 | Ballard's Pascal code. Note that the board manager mentioned here is | ||
27 | not included in this distribution. | ||
28 | |||
29 | This go board manager and rudimentary go player was written by | ||
30 | Stoney Ballard at Perq Systems in 1983-1984. It is written in | ||
31 | Perq Pascal and utilizes some Perq libraries for I/O. The code | ||
32 | is offered here if someone is interested to convert it to Unix. | ||
33 | |||
34 | The wonderful part about it is that a game is recorded as a tree | ||
35 | and can be played forward or backward, branching at any point | ||
36 | where there were alternate moves. | ||
37 | |||
38 | For some time, this program was also used to generate the go | ||
39 | boards displayed in the American Go Journal. For this it used | ||
40 | some large font digits which are now lost. | ||
41 | |||
42 | Fred 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 | |||
4 | This is an alpha release of xamigo --- a port (read: quick hack) of the | ||
5 | Amiga Go program AmiGo. I don't have time to get it real nice now, | ||
6 | but will spend some more time on it when my thesis is out of the way. | ||
7 | Sadly this is the second time I've said that :-) | ||
8 | |||
9 | The `readme' from the original distribution is included as README.AMIGO | ||
10 | |||
11 | An Imakefile is included, so you should be able to type | ||
12 | xmkmf | ||
13 | make | ||
14 | to build xamigo. Let me know if you have problems with the Imakefile, | ||
15 | preferably with fixes :-) | ||
16 | |||
17 | You *have* to install the app-defaults file (Xamigo.ad) before you use | ||
18 | xamigo. This should either go in /usr/lib/X11/app-defaults, | ||
19 | or in your own app-defaults directory, as file Xamigo (ie lose the '.ad') | ||
20 | If you do the latter, you have to: | ||
21 | setenv XAPPLRESDIR <full path of your app-defaults directory> | ||
22 | |||
23 | Feel free to mail me any comments and suggestions for improvements. | ||
24 | |||
25 | Neil | ||
26 | neilb@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 | |||
34 | short | ||
35 | member(group, grouplist, cnt) | ||
36 | short group; | ||
37 | short grouplist[4]; | ||
38 | short cnt; | ||
39 | { | ||
40 | unsigned shorti; | ||
41 | |||
42 | |||
43 | for (i = 0; i < cnt; i++) | ||
44 | if (grouplist[i] == group) | ||
45 | return TRUE; | ||
46 | return FALSE; | ||
47 | } | ||
48 | |||
49 | /* Does a stone at x, y connect to any groups of color? */ | ||
50 | short | ||
51 | Connect( color, x, y, fGroups, fCnt, eGroups, eCnt) | ||
52 | enum bValcolor; | ||
53 | short x, y; | ||
54 | short fGroups[4], eGroups[4]; | ||
55 | short *fCnt, *eCnt; | ||
56 | { | ||
57 | unsigned shortpoint = 0; | ||
58 | short tx, ty, total = 0; | ||
59 | enum bValopcolor = WHITE; | ||
60 | |||
61 | |||
62 | *fCnt = 0; | ||
63 | *eCnt = 0; | ||
64 | if (color == WHITE) | ||
65 | opcolor = BLACK; | ||
66 | for (point = 0; point <= 3; point++ ) | ||
67 | { | ||
68 | tx = x + xVec[point]; | ||
69 | ty = y + yVec[point]; | ||
70 | if (!LegalPoint(tx,ty)) | ||
71 | continue; | ||
72 | if (goboard[tx][ty].Val == color) | ||
73 | { | ||
74 | total++; | ||
75 | if (!member(goboard[tx][ty].GroupNum, fGroups, *fCnt)) | ||
76 | fGroups[(*fCnt)++] = goboard[tx][ty].GroupNum; | ||
77 | } | ||
78 | else if (goboard[tx][ty].Val == opcolor) | ||
79 | { | ||
80 | total++; | ||
81 | if (!member(goboard[tx][ty].GroupNum, eGroups, *eCnt)) | ||
82 | eGroups[(*eCnt)++] = goboard[tx][ty].GroupNum; | ||
83 | } | ||
84 | } | ||
85 | return total; | ||
86 | } | ||
87 | |||
88 | /* Returns the maximum number of liberties for a given intersection */ | ||
89 | short | ||
90 | Maxlibs(x, y) | ||
91 | shortx, y; | ||
92 | { | ||
93 | shortcnt = 4; | ||
94 | |||
95 | |||
96 | if (x == 0 || x == 18) | ||
97 | cnt--; | ||
98 | if (y == 0 || y == 18) | ||
99 | cnt--; | ||
100 | return cnt; | ||
101 | } | ||
102 | |||
103 | DeleteGroupFromStone(x,y) | ||
104 | shortx,y; | ||
105 | { | ||
106 | if (goboard[x][y].Val != EMPTY) | ||
107 | GroupCapture(goboard[x][y].GroupNum); | ||
108 | } | ||
109 | |||
110 | /* Determine whether x, y is suicide for color */ | ||
111 | short | ||
112 | Suicide(color, x, y) | ||
113 | enum bValcolor; | ||
114 | short x, y; | ||
115 | { | ||
116 | enum bValopcolor = BLACK; | ||
117 | short friendlycnt, friendlygroups[4], | ||
118 | enemycnt, enemygroups[4], | ||
119 | total; | ||
120 | short maxlibs, i, libcnt = 0; | ||
121 | |||
122 | |||
123 | if (color == BLACK) | ||
124 | opcolor = WHITE; | ||
125 | maxlibs = Maxlibs( x, y); | ||
126 | total = Connect(color, x, y, friendlygroups, &friendlycnt, | ||
127 | enemygroups, &enemycnt); | ||
128 | |||
129 | if (total < maxlibs) | ||
130 | return FALSE; | ||
131 | |||
132 | /* Check for a capture */ | ||
133 | for (i = 0; i < enemycnt; i++) | ||
134 | if (GroupList[enemygroups[i]].liberties == 1) | ||
135 | return FALSE; | ||
136 | for (i = 0; i < friendlycnt; i++) | ||
137 | libcnt += (GroupList[friendlygroups[i]].liberties - 1); | ||
138 | if (libcnt != 0) | ||
139 | return FALSE; | ||
140 | return TRUE; | ||
141 | } | ||
142 | |||
143 | /* Returns the number of liberties for x, y */ | ||
144 | short | ||
145 | StoneLibs(x, y) | ||
146 | short x, y; | ||
147 | { | ||
148 | short cnt = 0, tx, ty; | ||
149 | unsigned shortpoint; | ||
150 | |||
151 | |||
152 | for (point = 0; point <= 3; point++) | ||
153 | { | ||
154 | tx = x + xVec[point]; | ||
155 | ty = y + yVec[point]; | ||
156 | if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY) | ||
157 | cnt++; | ||
158 | } | ||
159 | return cnt; | ||
160 | } | ||
161 | |||
162 | void | ||
163 | EraseMarks() | ||
164 | { | ||
165 | register short i; | ||
166 | register struct bRec *gpt= &goboard[0][0]; | ||
167 | |||
168 | |||
169 | for (i=0; i<361; gpt++,i++) | ||
170 | gpt->marked = FALSE; | ||
171 | } | ||
172 | |||
173 | /* Place a stone of color at x, y */ | ||
174 | short | ||
175 | GoPlaceStone(color, x, y) | ||
176 | enum bValcolor; | ||
177 | short x, y; | ||
178 | { | ||
179 | short fgroups[4], egroups[4];/* group codes surrounding stone */ | ||
180 | shortfcnt, ecnt, i; | ||
181 | shortlowest = GroupCount + 1; | ||
182 | |||
183 | |||
184 | DeletedGroupCount = 0; | ||
185 | if (goboard[x][y].Val != EMPTY || Suicide(color,x,y)) | ||
186 | return FALSE; | ||
187 | |||
188 | if (ko && koX == x && koY == y) | ||
189 | return FALSE; | ||
190 | |||
191 | ko = FALSE; | ||
192 | placestone(color, x, y); | ||
193 | goboard[x][y].Val = color; | ||
194 | /* Does the new stone connect to any friendly stone(s)? */ | ||
195 | Connect(color, x, y, fgroups, &fcnt, egroups, &ecnt); | ||
196 | if (fcnt) | ||
197 | { | ||
198 | /* Find the connecting friendly group with the lowest code */ | ||
199 | for (i = 0; i < fcnt; i++) | ||
200 | if (fgroups[i] <= lowest) | ||
201 | lowest = fgroups[i]; | ||
202 | /*-- Renumber resulting group --*/ | ||
203 | /*-- Raise the stone count of the lowest by one to account --*/ | ||
204 | /*-- for new stone --*/ | ||
205 | goboard[x][y].GroupNum = lowest; | ||
206 | GroupList[lowest].count++; | ||
207 | for (i = 0; i < fcnt; i++) | ||
208 | if (fgroups[i] != lowest) | ||
209 | MergeGroups(lowest, fgroups[i]); | ||
210 | /* Fix the liberties of the resulting group */ | ||
211 | CountLiberties(lowest); | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | /* Isolated stone. Create new group. */ | ||
216 | GroupCount++; | ||
217 | lowest = GroupCount; | ||
218 | GroupList[lowest].color = color; | ||
219 | GroupList[lowest].count = 1; | ||
220 | GroupList[lowest].internal = 0; | ||
221 | GroupList[lowest].external = StoneLibs( x, y); | ||
222 | GroupList[lowest].liberties = GroupList[lowest].external; | ||
223 | GroupList[lowest].eyes = 0; | ||
224 | GroupList[lowest].alive = 0; | ||
225 | GroupList[lowest].territory = 0; | ||
226 | goboard[x][y].GroupNum = lowest; | ||
227 | } | ||
228 | /* Now fix the liberties of enemy groups adjacent to played stone */ | ||
229 | FixLibs(color, x, y, PLACED); /* Fix the liberties of opcolor */ | ||
230 | ReEvalGroups(color, x, y, lowest); | ||
231 | RelabelGroups(); | ||
232 | return TRUE; | ||
233 | } | ||
234 | |||
235 | /* Remove a stone from the board */ | ||
236 | void | ||
237 | GoRemoveStone(x, y) | ||
238 | shortx, y; | ||
239 | { | ||
240 | goboard[x][y].Val = EMPTY; | ||
241 | goboard[x][y].GroupNum = 0; | ||
242 | removestone( x, y); | ||
243 | } | ||
244 | |||
245 | /* Merges two groups -- Renumbers stones and deletes second group from | ||
246 | list. Fixes stone count of groups. This does not fix anything else. | ||
247 | FixLibs must be called to fix liberties, etc. */ | ||
248 | void | ||
249 | MergeGroups(g1, g2) | ||
250 | shortg1, g2; | ||
251 | { | ||
252 | shortx, y; | ||
253 | |||
254 | |||
255 | ForeachPoint(y,x) | ||
256 | if (goboard[x][y].GroupNum == g2) | ||
257 | goboard[x][y].GroupNum = g1; | ||
258 | GroupList[g1].count += GroupList[g2].count; | ||
259 | DeleteGroup( g2 ); /* Removes group from GroupList */ | ||
260 | } | ||
261 | |||
262 | /* Stores a group code to be deleted */ | ||
263 | void | ||
264 | DeleteGroup(code) | ||
265 | shortcode; | ||
266 | { | ||
267 | DeletedGroups[DeletedGroupCount++] = code; | ||
268 | } | ||
269 | |||
270 | /* Re-evaluate the groups given the last move. This assumes that the | ||
271 | last move has been merged into adjoining groups and all liberty counts | ||
272 | are correct. Handles capture. Checks for Ko. Keeps track of captured | ||
273 | stones. code is the group number of the stone just played. */ | ||
274 | void | ||
275 | ReEvalGroups(color, x, y, code) | ||
276 | enum bValcolor; | ||
277 | short x, y, code; | ||
278 | { | ||
279 | short fgroups[4], egroups[4], | ||
280 | fcnt, ecnt, i, killcnt = 0, count = 0; | ||
281 | enum bValopcolor = BLACK; | ||
282 | |||
283 | if (color == BLACK) | ||
284 | opcolor = WHITE; | ||
285 | /* Check for capture */ | ||
286 | Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt); | ||
287 | if (ecnt) | ||
288 | { | ||
289 | /* See if any of the groups have no liberties */ | ||
290 | for (i = 0; i < ecnt; i++) | ||
291 | if (GroupList[egroups[i]].liberties == 0) | ||
292 | { | ||
293 | killcnt++; | ||
294 | count = GroupList[egroups[i]].count; | ||
295 | GroupCapture( egroups[i]); | ||
296 | } | ||
297 | } | ||
298 | /* Check for ko. koX and koY are set in GroupCapture above. */ | ||
299 | if (killcnt == 1 && count == 1 && GroupList[ code ].count == 1 | ||
300 | && GroupList[ code ].liberties == 1) | ||
301 | { | ||
302 | ko = TRUE; | ||
303 | } | ||
304 | if (killcnt) | ||
305 | intrPrisonerReport( blackPrisoners, whitePrisoners); | ||
306 | /* Set eye count for groups */ | ||
307 | CountEyes(); | ||
308 | } | ||
309 | |||
310 | /* Remove a captured group from the board and fix the liberties of any | ||
311 | adjacent groups. Fixes prisoner count. Sets KoX and KoY */ | ||
312 | /*-- update display of captured stones -neilb --*/ | ||
313 | void | ||
314 | GroupCapture(code) | ||
315 | shortcode; | ||
316 | { | ||
317 | shortx, y; | ||
318 | |||
319 | if (GroupList[code].color == BLACK) | ||
320 | blackPrisoners += GroupList[code].count; | ||
321 | else | ||
322 | whitePrisoners += GroupList[code].count; | ||
323 | intrPrisonerReport(blackPrisoners, whitePrisoners); | ||
324 | ForeachPoint(y,x) | ||
325 | if (goboard[x][y].GroupNum == code) | ||
326 | { | ||
327 | FixLibs(GroupList[code].color,x,y,REMOVED); | ||
328 | GoRemoveStone(x, y); | ||
329 | koX = x; | ||
330 | koY = y; | ||
331 | } | ||
332 | DeleteGroup( code); | ||
333 | } | ||
334 | |||
335 | /* Fix the liberties of groups adjacent to x, y. move indicates | ||
336 | whether a stone of color was placed or removed at x, y | ||
337 | This does not change liberty counts of friendly groups when a stone | ||
338 | is placed. Does not do captures. */ | ||
339 | void | ||
340 | FixLibs( color, x, y, move) | ||
341 | enumbVal color; | ||
342 | shortx, y, move; | ||
343 | { | ||
344 | shortfgroups[4], fcnt, egroups[4], ecnt, i; | ||
345 | enumbVal opcolor = BLACK; | ||
346 | |||
347 | if (color == BLACK) | ||
348 | opcolor = WHITE; | ||
349 | Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt); | ||
350 | if (move == PLACED) | ||
351 | for (i = 0; i < ecnt; i++) | ||
352 | GroupList[egroups[i]].liberties--; | ||
353 | else /* Stone removed so increment opcolor */ | ||
354 | for (i = 0; i < ecnt; i++) | ||
355 | GroupList[egroups[i]].liberties++; | ||
356 | } | ||
357 | |||
358 | void | ||
359 | goSetHandicap(handicap) | ||
360 | int handicap; | ||
361 | { | ||
362 | if (handicap < 2) | ||
363 | return; | ||
364 | |||
365 | GoPlaceStone(BLACK,3,3); | ||
366 | GoPlaceStone(BLACK,15,15); | ||
367 | |||
368 | if (handicap >= 3) | ||
369 | GoPlaceStone(BLACK,15,3); | ||
370 | if (handicap >= 4) | ||
371 | GoPlaceStone(BLACK,3,15); | ||
372 | if (handicap == 5 || handicap == 7 || handicap == 9) | ||
373 | GoPlaceStone(BLACK,9,9); | ||
374 | if (handicap >= 6) | ||
375 | { | ||
376 | GoPlaceStone(BLACK,15,9); | ||
377 | GoPlaceStone(BLACK,3,9); | ||
378 | } | ||
379 | if (handicap >= 8) | ||
380 | { | ||
381 | GoPlaceStone(BLACK,9,15); | ||
382 | GoPlaceStone(BLACK,9,3); | ||
383 | } | ||
384 | } | ||
385 | |||
386 | void | ||
387 | goRestart(handicap) | ||
388 | inthandicap; | ||
389 | { | ||
390 | register short i; | ||
391 | register struct bRec *gpt= &goboard[0][0]; | ||
392 | |||
393 | |||
394 | GroupCount = 0; | ||
395 | ko = FALSE; | ||
396 | blackPrisoners = whitePrisoners = 0; | ||
397 | intrPrisonerReport(0, 0); | ||
398 | for (i=0; i<361; gpt++,i++) | ||
399 | { | ||
400 | gpt->Val = EMPTY; | ||
401 | gpt->GroupNum = 0; | ||
402 | } | ||
403 | goSetHandicap(handicap); | ||
404 | } | ||
405 | |||
406 | |||
407 | /* if any groups have been deleted as a result of the last move, this | ||
408 | routine will delete the old group numbers from GroupList and | ||
409 | reassign group numbers. */ | ||
410 | void | ||
411 | RelabelGroups() | ||
412 | { | ||
413 | unsignedshort i, j, x, y; | ||
414 | |||
415 | for (i = 0; i < DeletedGroupCount; i++) | ||
416 | { | ||
417 | /* Relabel all higher groups */ | ||
418 | ForeachPoint(y,x) | ||
419 | if (goboard[x][y].GroupNum > DeletedGroups[i]) | ||
420 | goboard[x][y].GroupNum--; | ||
421 | /* Move the groups down */ | ||
422 | for (y = DeletedGroups[i]; y < GroupCount; y++) | ||
423 | GroupList[y] = GroupList[y+1]; | ||
424 | /* fix the group numbers stored in the deleted list */ | ||
425 | for (j = i+1; j < DeletedGroupCount; j++) | ||
426 | if (DeletedGroups[j] > DeletedGroups[i]) | ||
427 | DeletedGroups[j]--; | ||
428 | GroupCount--; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | /* Returns liberty count for x, y intersection. Sets marked to true | ||
433 | for each liberty */ | ||
434 | short | ||
435 | CountAndMarkLibs( x, y) | ||
436 | shortx, y; | ||
437 | { | ||
438 | shorttx,ty,i; | ||
439 | shortcnt = 0; | ||
440 | |||
441 | |||
442 | for (i=0;i<4;i++) | ||
443 | { | ||
444 | tx = x + xVec[i]; | ||
445 | ty = y + yVec[i]; | ||
446 | if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY | ||
447 | && goboard[tx][ty].marked == FALSE) | ||
448 | { | ||
449 | cnt++; | ||
450 | goboard[tx][ty].marked = TRUE; | ||
451 | } | ||
452 | } | ||
453 | return cnt; | ||
454 | } | ||
455 | |||
456 | /* Determine the number of liberties for a group given the group code | ||
457 | num */ | ||
458 | void | ||
459 | CountLiberties( code) | ||
460 | shortcode; | ||
461 | { | ||
462 | shortx, y, libcnt = 0; | ||
463 | |||
464 | ForeachPoint(y,x) | ||
465 | if (goboard[x][y].GroupNum == code) | ||
466 | libcnt += CountAndMarkLibs( x, y); | ||
467 | EraseMarks(); | ||
468 | GroupList[code].liberties = libcnt; | ||
469 | } | ||
470 | |||
471 | void | ||
472 | CheckForEye( x, y, groups, cnt, recheck) | ||
473 | shortx, y, groups[4], cnt, *recheck; | ||
474 | { | ||
475 | shorti; | ||
476 | |||
477 | for (i = 0; i < (cnt-1); i++) | ||
478 | if (groups[i] != groups[i+1]) | ||
479 | { | ||
480 | /* Mark liberty for false eye check */ | ||
481 | goboard[x][y].marked = TRUE; | ||
482 | (*recheck)++; | ||
483 | return; | ||
484 | } | ||
485 | /* It is an eye */ | ||
486 | GroupList[groups[i]].eyes += 1; | ||
487 | } | ||
488 | |||
489 | /* Set the eye count for the groups */ | ||
490 | void CountEyes() | ||
491 | { | ||
492 | shorti, x, y, | ||
493 | wgroups[4], bgroups[4], wcnt, bcnt, max, cnt, recheck = 0, eye; | ||
494 | |||
495 | for (i = 1; i <= GroupCount; i++) | ||
496 | GroupList[i].eyes = 0; | ||
497 | |||
498 | ForeachPoint(y,x) | ||
499 | { | ||
500 | if (goboard[x][y].Val != EMPTY) | ||
501 | continue; | ||
502 | cnt = Connect(WHITE,x,y,wgroups,&wcnt,bgroups,&bcnt); | ||
503 | max = Maxlibs( x, y); | ||
504 | if (cnt == max && wcnt == 1 && bcnt == 0) | ||
505 | GroupList[wgroups[0]].eyes++; | ||
506 | else if (cnt == max && bcnt == 1 && wcnt == 0) | ||
507 | GroupList[bgroups[0]].eyes++; | ||
508 | else if (cnt == max && ( bcnt == 0 || wcnt == 0 )) | ||
509 | { | ||
510 | goboard[x][y].marked = TRUE; | ||
511 | recheck++; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | /*-- Now recheck marked liberties to see if two or more one eye --*/ | ||
516 | /*-- groups contribute to a false eye */ | ||
517 | if (recheck == 0) | ||
518 | return; | ||
519 | |||
520 | ForeachPoint(y,x) | ||
521 | if (goboard[x][y].marked) | ||
522 | { | ||
523 | recheck--; | ||
524 | goboard[x][y].marked = FALSE; | ||
525 | Connect( WHITE, x, y, wgroups, &wcnt, bgroups, &bcnt); | ||
526 | /* If all the groups have at least one eye then all the | ||
527 | groups are safe from capture because of the common | ||
528 | liberty at x, y */ | ||
529 | eye = TRUE; | ||
530 | for (i = 0; i < wcnt; i++) | ||
531 | if (GroupList[wgroups[i]].eyes == 0) | ||
532 | eye = FALSE; | ||
533 | if (eye) | ||
534 | for (i = 0; i < wcnt; i++) | ||
535 | GroupList[wgroups[i]].eyes++; | ||
536 | for (i = 0; i < bcnt; i++) | ||
537 | if (GroupList[bgroups[i]].eyes == 0) | ||
538 | eye = FALSE; | ||
539 | if (eye) | ||
540 | for (i = 0; i < bcnt; i++) | ||
541 | GroupList[bgroups[i]].eyes++; | ||
542 | if (recheck == 0) | ||
543 | return; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | |||
548 | shortfoo[19][19]; | ||
549 | |||
550 | /*---------------------------------------------------------------- | ||
551 | -- CountUp() -- | ||
552 | -- Count up final scores at the end of the game. -- | ||
553 | ----------------------------------------------------------------*/ | ||
554 | CountUp( wtotal, btotal ) | ||
555 | int *wtotal, *btotal; | ||
556 | { | ||
557 | shortx,y; | ||
558 | shortCountFromPoint(); | ||
559 | shortvv; | ||
560 | charbuff[512]; | ||
561 | |||
562 | |||
563 | blackTerritory = whiteTerritory = 0; | ||
564 | ForeachPoint(y,x) | ||
565 | { | ||
566 | goboard[x][y].marked = FALSE; | ||
567 | foo[x][y] = CNT_UNDECIDED; | ||
568 | } | ||
569 | ForeachPoint(y,x) | ||
570 | if (goboard[x][y].Val==EMPTY && foo[x][y]==CNT_UNDECIDED) | ||
571 | { | ||
572 | FillPoints(x,y,CountFromPoint(x,y)); | ||
573 | } | ||
574 | |||
575 | *wtotal = whiteTerritory + blackPrisoners; | ||
576 | *btotal = blackTerritory + whitePrisoners; | ||
577 | /* | ||
578 | sprintf(buff,"White : %3d territory + %3d prisoners = %d\n\ | ||
579 | Black : %3d territory + %3d prisoners = %d\n\n%s.\n", | ||
580 | whiteTerritory,blackPrisoners,*wtotal, | ||
581 | blackTerritory,whitePrisoners,*btotal, | ||
582 | (*btotal>*wtotal?"Black wins":(*wtotal>*btotal?"White wins": | ||
583 | "A draw"))); | ||
584 | |||
585 | |||
586 | |||
587 | XtVaSetValues(message,XtNstring,buff,0); | ||
588 | printf( "CountUp() %s", buff ); | ||
589 | */ | ||
590 | } | ||
591 | |||
592 | FillPoints(x,y,val) | ||
593 | shortx,y,val; | ||
594 | { | ||
595 | inti; | ||
596 | shorttx,ty; | ||
597 | |||
598 | |||
599 | if ((foo[x][y] = val) == CNT_BLACK_TERR) | ||
600 | blackTerritory++; | ||
601 | else if (val == CNT_WHITE_TERR) | ||
602 | whiteTerritory++; | ||
603 | for (i=0;i<4;i++) | ||
604 | { | ||
605 | tx = x + xVec[i]; | ||
606 | ty = y + yVec[i]; | ||
607 | if (!LegalPoint(tx,ty)) | ||
608 | continue; | ||
609 | if (goboard[tx][ty].Val==EMPTY && foo[tx][ty]==CNT_UNDECIDED) | ||
610 | FillPoints(tx,ty,val); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | short | ||
615 | CountFromPoint(x,y) | ||
616 | shortx,y; | ||
617 | { | ||
618 | inti; | ||
619 | shorttx,ty; | ||
620 | shortblkcnt=0,whtcnt=0; | ||
621 | shortbaz; | ||
622 | |||
623 | |||
624 | goboard[x][y].marked = TRUE; | ||
625 | for (i=0;i<4;i++) | ||
626 | { | ||
627 | tx = x + xVec[i]; | ||
628 | ty = y + yVec[i]; | ||
629 | if (!LegalPoint(tx,ty)) | ||
630 | continue; | ||
631 | if (goboard[tx][ty].Val == BLACK) | ||
632 | blkcnt++; | ||
633 | else if (goboard[tx][ty].Val == WHITE) | ||
634 | whtcnt++; | ||
635 | else | ||
636 | { | ||
637 | if (goboard[tx][ty].marked) | ||
638 | continue; | ||
639 | baz = CountFromPoint(tx,ty); | ||
640 | if (baz == CNT_NOONE) | ||
641 | return CNT_NOONE; | ||
642 | else if (baz == CNT_BLACK_TERR) | ||
643 | blkcnt++; | ||
644 | else if (baz == CNT_WHITE_TERR) | ||
645 | whtcnt++; | ||
646 | } | ||
647 | if (blkcnt && whtcnt) | ||
648 | return CNT_NOONE; | ||
649 | } | ||
650 | if (blkcnt && !whtcnt) | ||
651 | return CNT_BLACK_TERR; | ||
652 | else if (whtcnt && !blkcnt) | ||
653 | return CNT_WHITE_TERR; | ||
654 | else | ||
655 | return CNT_UNDECIDED; | ||
656 | } | ||
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 | ||
43 | extern "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 | |||
56 | enum bVal {BLACK, WHITE, EMPTY}; | ||
57 | typedef enum bVal sType; | ||
58 | struct 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 | |||
71 | struct 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 | ||
14 | INCLUDEPATH += $(QPEDIR)/include | ||
15 | DEPENDPATH+= $(QPEDIR)/include | ||
16 | LIBS += -lqpe | ||
17 | TARGET = go | ||
18 | |||
19 | TRANSLATIONS = ../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: | ||
4 | Go Move Generator | ||
5 | Copyright (c) 1983 by Three Rivers Computer Corp. | ||
6 | |||
7 | Written: January 17, 1983 by Stoney Ballard | ||
8 | Edit History: | ||
9 | */ | ||
10 | |||
11 | #include "go.h" | ||
12 | #include "goplayutils.h" | ||
13 | #include "amigo.h" | ||
14 | |||
15 | #define BIGGEST 32767/* maximum value for short */ | ||
16 | |||
17 | /* From go.c */ | ||
18 | extern struct bRec goboard[19][19]; | ||
19 | extern short ko, koX, koY; | ||
20 | |||
21 | /* From goplayutils.c */ | ||
22 | extern intBoard bord; | ||
23 | extern intBoard ndbord; | ||
24 | extern intBoard claim; | ||
25 | extern intBoard legal; | ||
26 | extern intBoard connectMap; | ||
27 | extern intBoard threatBord; | ||
28 | extern short maxGroupID; | ||
29 | extern short treeLibLim; | ||
30 | extern short killFlag; | ||
31 | extern short depthLimit; | ||
32 | extern short showTrees; | ||
33 | extern short utilPlayLevel; | ||
34 | extern groupRec gList[maxGroup]; | ||
35 | extern short sGlist[maxGroup + 1]; | ||
36 | extern pointList pList; | ||
37 | extern pointList pList1; | ||
38 | extern pointList plist2; | ||
39 | extern pointList plist3; | ||
40 | extern intBoard groupIDs; | ||
41 | extern intBoard protPoints; | ||
42 | extern sType mySType; | ||
43 | |||
44 | |||
45 | short saveNLibs; | ||
46 | pointList dapList1, dapList2, dapList3; | ||
47 | char *playReason; | ||
48 | short maxPlayLevel = 7; | ||
49 | short playLevel = 7; | ||
50 | |||
51 | genBord(color) | ||
52 | enum bValcolor; | ||
53 | { | ||
54 | short x, y, nomoves = TRUE; | ||
55 | char mv[8]; | ||
56 | |||
57 | maxPlayLevel = 7; | ||
58 | utilPlayLevel = playLevel; | ||
59 | mySType = color; | ||
60 | if (playLevel < 2) | ||
61 | treeLibLim = 2; | ||
62 | else | ||
63 | treeLibLim = 3; | ||
64 | depthLimit = 100; | ||
65 | for (y = 0; y <= 18; y++) | ||
66 | for (x = 0; x <= 18; x++) | ||
67 | if (goboard[x][y].Val == color) | ||
68 | { | ||
69 | bord[x][y] = 1; | ||
70 | legal[x][y] = FALSE; | ||
71 | nomoves = FALSE; | ||
72 | } | ||
73 | else if (goboard[x][y].Val == EMPTY) | ||
74 | { | ||
75 | bord[x][y] = 0; | ||
76 | legal[x][y] = TRUE; | ||
77 | } | ||
78 | else | ||
79 | { | ||
80 | bord[x][y] = -1; | ||
81 | legal[x][y] = FALSE; | ||
82 | nomoves = FALSE; | ||
83 | } | ||
84 | if (ko) | ||
85 | { | ||
86 | legal[koX][koY] = FALSE; | ||
87 | } | ||
88 | |||
89 | if (! nomoves) | ||
90 | genState(); | ||
91 | else | ||
92 | initGPUtils(); | ||
93 | } | ||
94 | |||
95 | |||
96 | short getMove( x, y ) | ||
97 | short *x, *y; | ||
98 | { | ||
99 | if (takeCorner(x, y)) return TRUE; | ||
100 | if (lookForSave(x, y)) return TRUE; | ||
101 | if (lookForSaveN(x, y)) return TRUE; | ||
102 | if (extend(x, y)) return TRUE; | ||
103 | if (lookForKill(x, y)) return TRUE; | ||
104 | if (doubleAtari(x, y)) return TRUE; | ||
105 | if (lookForAttack(x, y)) return TRUE; | ||
106 | if (threaten(x, y)) return TRUE; | ||
107 | if (extend2(x, y)) return TRUE; | ||
108 | if (connectCut(x, y)) return TRUE; | ||
109 | if (blockCut(x, y)) return TRUE; | ||
110 | if (cutHim(x, y)) return TRUE; | ||
111 | if (extendWall(x, y)) return TRUE; | ||
112 | if (findAttack2(x, y)) return TRUE; | ||
113 | if (atariAnyway(x, y)) return TRUE; | ||
114 | if (underCut(x, y)) return TRUE; | ||
115 | if (dropToEdge(x, y)) return TRUE; | ||
116 | if (pushWall(x, y)) return TRUE; | ||
117 | if (reduceHisLiberties(x, y)) return TRUE; | ||
118 | if (dropToEdge2(x, y)) return TRUE; | ||
119 | return FALSE; | ||
120 | } | ||
121 | |||
122 | short genMove( color, x, y ) | ||
123 | enum bVal color; | ||
124 | short *x, *y; | ||
125 | { | ||
126 | if (playLevel > 2) | ||
127 | saveNLibs = TRUE; | ||
128 | else | ||
129 | saveNLibs = FALSE; | ||
130 | genBord(color); | ||
131 | if (getMove(x, y)) | ||
132 | return TRUE; | ||
133 | return FALSE; | ||
134 | } | ||
135 | |||
136 | short checkPos(x, y, field) | ||
137 | short x, y, field; | ||
138 | { | ||
139 | short ok; | ||
140 | ok = (((field == 0) && (claim[x][y] == 0)) || | ||
141 | ((field > 0) && | ||
142 | (claim[x][y] >= 0) && (claim[x][y] <= field)) || | ||
143 | ((field < 0) && | ||
144 | (claim[x][y] <= 0) && (claim[x][y] >= field))) && | ||
145 | (bord[x-1][y] == 0) && | ||
146 | (bord[x+1][y] == 0) && | ||
147 | (bord[x][y-1] == 0) && | ||
148 | (bord[x][y+1] == 0); | ||
149 | if (ok) return TRUE; else return FALSE; | ||
150 | } | ||
151 | |||
152 | short takeCorner( x, y ) | ||
153 | short *x, *y; | ||
154 | { | ||
155 | short field = -1, i; | ||
156 | i = 18 - 3; | ||
157 | playReason = "takeCorner"; | ||
158 | while (field != -4) | ||
159 | { | ||
160 | if (field == -1) field = 0; | ||
161 | else if (field == 0) field = 4; | ||
162 | else field = -4; | ||
163 | if (checkPos(2, 3, field)) { *x = 2; *y = 3; return TRUE; } | ||
164 | if (checkPos(3, 2, field)) { *x = 3; *y = 2; return TRUE; } | ||
165 | if (checkPos(2, i, field)) { *x = 2; *y = i; return TRUE; } | ||
166 | if (checkPos(3, i + 1, field)) { *x = 3; *y = i+1; return TRUE; } | ||
167 | if (checkPos(i, i + 1, field)) { *x = i; *y = i+1; return TRUE; } | ||
168 | if (checkPos(i + 1, i, field)) { *x = i+1; *y = i; return TRUE; } | ||
169 | if (checkPos(i, 2, field)) { *x = i; *y = 2; return TRUE; } | ||
170 | if (checkPos(i + 1, 3, field)) { *x = i+1; *y = 3; return TRUE; } | ||
171 | if (checkPos(2, 4, field)) { *x = 2; *y = 4; return TRUE; } | ||
172 | if (checkPos(4, 2, field)) { *x = 4; *y = 2; return TRUE; } | ||
173 | if (checkPos(2, i - 1, field)) { *x = 2; *y = i-1; return TRUE; } | ||
174 | if (checkPos(4, i + 1, field)) { *x = 4; *y = i+1; return TRUE; } | ||
175 | if (checkPos(i - 1, i + 1, field)) { *x = i-1; *y = i+1; return TRUE; } | ||
176 | if (checkPos(i + 1, i - 1, field)) { *x = i+1; *y = i-1; return TRUE; } | ||
177 | if (checkPos(i + 1, 4, field)) { *x = i+1; *y = 4; return TRUE; } | ||
178 | if (checkPos(i - 1, 2, field)) { *x = i-1; *y = 2; return TRUE; } | ||
179 | } | ||
180 | return FALSE; | ||
181 | } | ||
182 | |||
183 | printBoard(brd, name) | ||
184 | intBoard brd; | ||
185 | char *name; | ||
186 | { | ||
187 | short x, y; | ||
188 | printf( "%s\n", name ); | ||
189 | for (y = 0; y <= 18; y++) | ||
190 | { | ||
191 | for (x = 0; x <= 18; x++) | ||
192 | printf("%d ", brd[x][y]); | ||
193 | printf("\n"); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | short noNbrs( x, y ) | ||
198 | short x, y; | ||
199 | { | ||
200 | if (x > 0 && bord[x-1][y] != 0) return FALSE; | ||
201 | if (x < 18 && bord[x+1][y] != 0) return FALSE; | ||
202 | if (y > 0 && bord[x][y-1] != 0) return FALSE; | ||
203 | if (y < 18 && bord[x][y+1] != 0) return FALSE; | ||
204 | return TRUE; | ||
205 | } | ||
206 | |||
207 | short extend(x, y) | ||
208 | short *x, *y; | ||
209 | { | ||
210 | short i; | ||
211 | playReason = "extend"; | ||
212 | for (i = 2; i <= 18-2; i++) | ||
213 | if (claim[2][i] == 0 && noNbrs( 2, i )) | ||
214 | { | ||
215 | *x = 2; | ||
216 | *y = i; | ||
217 | return TRUE; | ||
218 | } | ||
219 | for (i = 2; i <= 18-2; i++) | ||
220 | if (claim[i][18-2] == 0 && noNbrs( 2, i )) | ||
221 | { | ||
222 | *x = i; | ||
223 | *y = 18-2; | ||
224 | return TRUE; | ||
225 | } | ||
226 | for (i = 18-2; i >= 2; i--) | ||
227 | if (claim[18-2][i] == 0 && noNbrs( 18-2, i )) | ||
228 | { | ||
229 | *x = 18-2; | ||
230 | *y = i; | ||
231 | return TRUE; | ||
232 | } | ||
233 | for (i = 18-2; i >= 2; i--) | ||
234 | if (claim[i][2] == 0 && noNbrs( i, 2 )) | ||
235 | { | ||
236 | *x = i; | ||
237 | *y = 2; | ||
238 | return TRUE; | ||
239 | } | ||
240 | return FALSE; | ||
241 | } | ||
242 | |||
243 | short extend2( x, y ) | ||
244 | short *x, *y; | ||
245 | { | ||
246 | short i, lowest = BIGGEST, value; | ||
247 | playReason = "extend2"; | ||
248 | for (i = 3; i <= 18-3; i++) | ||
249 | if (legal[2][i]) /* if there is nobody there */ | ||
250 | { | ||
251 | value = claim[2][i]; /* get influence */ | ||
252 | if ((value < 7) && /* a reasonable hole in my wall */ | ||
253 | (value > -5) && /* or a reasonable gap in his */ | ||
254 | (bord[2][i + 1] == 0) && /* not in contact with any stones */ | ||
255 | (bord[2][i - 1] == 0)) | ||
256 | if (value < lowest) | ||
257 | { | ||
258 | lowest = value; /* lowest gets the smallest value */ | ||
259 | *x = 2; /* that was seen along all the 3-lines */ | ||
260 | *y = i; /* x and y save that location */ | ||
261 | } | ||
262 | } | ||
263 | for (i = 3; i <= 18-3; i++) | ||
264 | if (legal[i][2]) | ||
265 | { | ||
266 | value = claim[i][2]; | ||
267 | if ((value < 7) && | ||
268 | (value > -5) && | ||
269 | (bord[i + 1][2] == 0) && | ||
270 | (bord[i - 1][2] == 0)) | ||
271 | if (value < lowest) | ||
272 | { | ||
273 | lowest = value; | ||
274 | *x = i; | ||
275 | *y = 2; | ||
276 | } | ||
277 | } | ||
278 | for (i = 18-3; i >= 3; i--) | ||
279 | if (legal[18 - 2][i]) | ||
280 | { | ||
281 | value = claim[18 - 2][i]; | ||
282 | if ((value < 7) && | ||
283 | (value > -5) && | ||
284 | (bord[18 - 2][i + 1] == 0) && | ||
285 | (bord[18 - 2][i - 1] == 0)) | ||
286 | if (value < lowest) | ||
287 | { | ||
288 | lowest = value; | ||
289 | *x = 18 - 2; | ||
290 | *y = i; | ||
291 | } | ||
292 | } | ||
293 | for (i = 3; i <= 18-3; i++) | ||
294 | if (legal[i][18 - 2]) | ||
295 | { | ||
296 | value = claim[i][18 - 2]; | ||
297 | if ((value < 7) && | ||
298 | (value > -5) && | ||
299 | (bord[i + 1][18 - 2] == 0) && | ||
300 | (bord[i - 1][18 - 2] == 0)) | ||
301 | if (value < lowest) | ||
302 | { | ||
303 | lowest = value; | ||
304 | *x = i; | ||
305 | *y = 18 - 2; | ||
306 | } | ||
307 | } | ||
308 | if (lowest == BIGGEST) return FALSE; | ||
309 | return TRUE; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | check to see if I can save anything in atari | ||
314 | */ | ||
315 | short lookForSave(x, y) | ||
316 | short *x, *y; | ||
317 | { /* lookForSave */ | ||
318 | short i; | ||
319 | playReason = "lookForSave"; | ||
320 | for (i = 1; i <= maxGroupID; i++) /* scan the group list */ | ||
321 | if ((gList[i].libC == 1) && | ||
322 | (ndbord[gList[i].lx][gList[i].ly] == 1)) | ||
323 | if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */ | ||
324 | return TRUE; | ||
325 | return FALSE; | ||
326 | } /* lookForSave */ | ||
327 | |||
328 | /* | ||
329 | check to see if I can save anything with n libs | ||
330 | */ | ||
331 | short lookForSaveN(x, y) | ||
332 | short *x, *y; | ||
333 | { /* lookForSaveN */ | ||
334 | short i; | ||
335 | if (saveNLibs) | ||
336 | { | ||
337 | playReason = "lookForSaveN"; | ||
338 | for (i = 1; i <= maxGroupID; i++) /* scan the group list */ | ||
339 | if ((gList[i].libC > 1) && | ||
340 | (gList[i].libC <= treeLibLim) && | ||
341 | (ndbord[gList[i].lx][gList[i].ly] == 1)) | ||
342 | { | ||
343 | if (killable(gList[i].lx, gList[i].ly, x, y)) | ||
344 | if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */ | ||
345 | return TRUE; | ||
346 | } | ||
347 | } | ||
348 | return FALSE; | ||
349 | } /* lookForSaveN */ | ||
350 | |||
351 | |||
352 | /*---------------------------------------------------------------- | ||
353 | -- lookForKill() -- | ||
354 | -- check to see if I can kill anything. -- | ||
355 | ----------------------------------------------------------------*/ | ||
356 | short | ||
357 | lookForKill(x, y) | ||
358 | short*x, *y; | ||
359 | { | ||
360 | shorti; | ||
361 | charmv[8]; | ||
362 | |||
363 | playReason = "lookForKill"; | ||
364 | for (i = 1; i <= maxGroupID; i++) /* scan the group list */ | ||
365 | if ((gList[i].libC == 1) && | ||
366 | (ndbord[gList[i].lx][gList[i].ly] == -1)) | ||
367 | { /* we found a live enemy group with one liberty */ | ||
368 | /* find the liberty */ | ||
369 | spanGroup(gList[i].lx, gList[i].ly, &pList); | ||
370 | *x = pList.p[1].px; | ||
371 | *y = pList.p[1].py; | ||
372 | if (legal[*x][*y]) | ||
373 | { | ||
374 | return TRUE; | ||
375 | } | ||
376 | } | ||
377 | return FALSE; | ||
378 | } | ||
379 | |||
380 | short doubleAtari(x, y) | ||
381 | short *x, *y; | ||
382 | { /* doubleAtari */ | ||
383 | short i, j; | ||
384 | playReason = "doubleAtari"; | ||
385 | for (i = 1; i <= maxGroupID - 1; i++) | ||
386 | if ((gList[i].libC == 2) && | ||
387 | (ndbord[gList[i].lx][gList[i].ly] == -1)) /* found an atariable group of his */ | ||
388 | { | ||
389 | spanGroup(gList[i].lx, gList[i].ly, &dapList1); | ||
390 | for (j = i + 1; j <= maxGroupID; j++) | ||
391 | if ((gList[j].libC == 2) && | ||
392 | (ndbord[gList[j].lx][gList[j].ly] == -1)) | ||
393 | { | ||
394 | spanGroup(gList[j].lx, gList[j].ly, &dapList2); | ||
395 | intersectPlist(&dapList1, &dapList2, &dapList3); | ||
396 | if (dapList3.indx > 0) | ||
397 | if (legal[dapList3.p[1].px][dapList3.p[1].py]) | ||
398 | { | ||
399 | tryPlay(dapList3.p[1].px, dapList3.p[1].py, 1); | ||
400 | if (gList[groupIDs[dapList3.p[1].px][ | ||
401 | dapList3.p[1].py]].libC > 1) | ||
402 | { | ||
403 | *x = dapList3.p[1].px; | ||
404 | *y = dapList3.p[1].py; | ||
405 | restoreState(); | ||
406 | return TRUE; | ||
407 | } | ||
408 | restoreState(); | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | return FALSE; | ||
413 | } /* doubleAtari */ | ||
414 | |||
415 | short lookForAttack(x, y) | ||
416 | short *x, *y; | ||
417 | { /* lookForAttack */ | ||
418 | short tx, ty, i; | ||
419 | playReason = "lookForAttack"; | ||
420 | for (i = 1; i <= maxGroupID; i++) /* scan the group list */ | ||
421 | if ((! gList[i].isLive) && | ||
422 | (gList[i].libC > 1) && | ||
423 | (gList[i].libC <= (treeLibLim + 1)) && | ||
424 | (ndbord[gList[i].lx][gList[i].ly] == -1)) | ||
425 | { | ||
426 | if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */ | ||
427 | { | ||
428 | *x = tx; /* yep - do so */ | ||
429 | *y = ty; | ||
430 | return TRUE; | ||
431 | } | ||
432 | } | ||
433 | return FALSE; | ||
434 | } /* lookForAttack */ | ||
435 | |||
436 | /* | ||
437 | Plays a move that requires a response on the opponent's part | ||
438 | */ | ||
439 | short threaten(x, y) | ||
440 | short *x, *y; | ||
441 | { /* threaten */ | ||
442 | short i, j, gx, gy, tNum; | ||
443 | playReason = "threaten"; | ||
444 | initArray(threatBord); | ||
445 | for (i = 1; i <= maxGroupID; i++) | ||
446 | if ((! gList[i].isLive) && | ||
447 | (ndbord[gList[i].lx][gList[i].ly] == -1)) | ||
448 | { | ||
449 | spanGroup(gList[i].lx, gList[i].ly, &pList); | ||
450 | for (j = 1; j <= pList.indx; j++) | ||
451 | if (legal[pList.p[j].px][pList.p[j].py]) | ||
452 | { | ||
453 | tryPlay(pList.p[j].px, pList.p[j].py, 1); | ||
454 | if (gList[groupIDs[pList.p[j].px][pList.p[j].py]].libC > 1) | ||
455 | if (killable(gList[i].lx, gList[i].ly, &gx, &gy)) | ||
456 | threatBord[pList.p[j].px][pList.p[j].py] += 1; | ||
457 | restoreState(); | ||
458 | } | ||
459 | } | ||
460 | tNum = 0; | ||
461 | for (i = 0; i <= maxPoint; i++) | ||
462 | for (j = 0; j <= maxPoint; j++) | ||
463 | if ((threatBord[i][j] > tNum) && | ||
464 | ((threatBord[i][j] > 1) || | ||
465 | (connectMap[i][j] > 0))) | ||
466 | { | ||
467 | tNum = threatBord[i][j]; | ||
468 | *x = i; | ||
469 | *y = j; | ||
470 | } | ||
471 | if (tNum > 0) return TRUE; | ||
472 | else return FALSE; | ||
473 | } /* threaten */ | ||
474 | |||
475 | /* | ||
476 | connects against enemy cuts | ||
477 | */ | ||
478 | short connectCut(x, y) | ||
479 | short *x, *y; | ||
480 | { /* connectCut */ | ||
481 | short i, j, nap, gid, infl; | ||
482 | playReason = "connectCut"; | ||
483 | for (i = 0; i <= maxPoint; i++) | ||
484 | for (j = 0; j <= maxPoint; j++) | ||
485 | if (legal[i][j] && | ||
486 | (protPoints[i][j] == 0)) /* not a protected point */ | ||
487 | { | ||
488 | nap = 0; /* how many of my stones am I adjacent to? */ | ||
489 | if ((i > 0) && (bord[i - 1][j] == 1)) | ||
490 | { | ||
491 | nap = nap + 1; | ||
492 | pList.p[nap].px = i - 1; | ||
493 | pList.p[nap].py = j; | ||
494 | } | ||
495 | if ((j > 0) && (bord[i][j - 1] == 1)) | ||
496 | { | ||
497 | nap = nap + 1; | ||
498 | pList.p[nap].px = i; | ||
499 | pList.p[nap].py = j - 1; | ||
500 | } | ||
501 | if ((i < maxPoint) && (bord[i + 1][j] == 1)) | ||
502 | { | ||
503 | nap = nap + 1; | ||
504 | pList.p[nap].px = i + 1; | ||
505 | pList.p[nap].py = j; | ||
506 | } | ||
507 | if ((j < maxPoint) && (bord[i][j + 1] == 1)) | ||
508 | { | ||
509 | nap = nap + 1; | ||
510 | pList.p[nap].px = i; | ||
511 | pList.p[nap].py = j + 1; | ||
512 | } | ||
513 | if (nap == 1) /* possible knight's || 2-point extention */ | ||
514 | { | ||
515 | gid = groupIDs[pList.p[1].px][pList.p[1].py]; | ||
516 | if ((i > 0) && (i < maxPoint) && | ||
517 | (ndbord[i - 1][j] == 1) && | ||
518 | (ndbord[i + 1][j] == 0)) /* contact on left */ | ||
519 | { | ||
520 | if (((j > 0) && (ndbord[i][j - 1] == -1) && | ||
521 | (ndbord[i + 1][j - 1] == 1) && | ||
522 | (gid != groupIDs[i + 1][j - 1])) || | ||
523 | ((j < maxPoint) && (ndbord[i][j + 1] == -1) && | ||
524 | (ndbord[i + 1][j + 1] == 1) && | ||
525 | (gid != groupIDs[i + 1][j + 1])) || | ||
526 | ((((j > 0) && (ndbord[i][j - 1] == -1)) || | ||
527 | ((j < maxPoint) && (ndbord[i][j + 1] == -1))) && | ||
528 | (i < (maxPoint - 1)) && | ||
529 | (ndbord[i + 2][j] == 1) && | ||
530 | (gid != groupIDs[i + 2][j]))) | ||
531 | { | ||
532 | *x = i; | ||
533 | *y = j; | ||
534 | if (safeMove(*x, *y)) | ||
535 | return TRUE; | ||
536 | } | ||
537 | } | ||
538 | else if ((i < maxPoint) && (i > 0) && | ||
539 | (ndbord[i + 1][j] == 1) && | ||
540 | (ndbord[i - 1][j] == 0)) /* r */ | ||
541 | { | ||
542 | if (((j > 0) && (ndbord[i][j - 1] == -1) && | ||
543 | (ndbord[i - 1][j - 1] == 1) && | ||
544 | (gid != groupIDs[i - 1][j - 1])) || | ||
545 | ((j < maxPoint) && (ndbord[i][j + 1] == -1) && | ||
546 | (ndbord[i - 1][j + 1] == 1) && | ||
547 | (gid != groupIDs[i - 1][j + 1])) || | ||
548 | ((((j > 0) && (ndbord[i][j - 1] == -1)) || | ||
549 | ((j < maxPoint) && (ndbord[i][j + 1] == -1))) && | ||
550 | (i > 1) && | ||
551 | (ndbord[i - 2][j] == 1) && | ||
552 | (gid != groupIDs[i - 2][j]))) | ||
553 | { | ||
554 | *x = i; | ||
555 | *y = j; | ||
556 | if (safeMove(*x, *y)) | ||
557 | return TRUE; | ||
558 | } | ||
559 | } | ||
560 | else if ((j > 0) && (j < maxPoint) && | ||
561 | (ndbord[i][j - 1] == 1) && | ||
562 | (ndbord[i][j + 1] == 0)) /* top */ | ||
563 | { | ||
564 | if (((i > 0) && (ndbord[i - 1][j] == -1) && | ||
565 | (ndbord[i - 1][j + 1] == 1) && | ||
566 | (gid != groupIDs[i - 1][j + 1])) || | ||
567 | ((i < maxPoint) && (ndbord[i + 1][j] == -1) && | ||
568 | (ndbord[i + 1][j + 1] == 1) && | ||
569 | (gid != groupIDs[i + 1][j + 1])) || | ||
570 | ((((i > 0) && (ndbord[i - 1][j] == -1)) || | ||
571 | ((i < maxPoint) && (ndbord[i + 1][j] == -1))) && | ||
572 | (j < (maxPoint - 1)) && | ||
573 | (ndbord[i][j + 2] == 1) && | ||
574 | (gid != groupIDs[i][j + 2]))) | ||
575 | { | ||
576 | *x = i; | ||
577 | *y = j; | ||
578 | if (safeMove(*x, *y)) | ||
579 | return TRUE; | ||
580 | } | ||
581 | } | ||
582 | else if ((j > 0) && (j < maxPoint) && | ||
583 | (ndbord[i][j + 1] == 1) && | ||
584 | (ndbord[i][j - 1] == 0)) /* bottom */ | ||
585 | { | ||
586 | if (((i > 0) && (ndbord[i - 1][j] == -1) && | ||
587 | (ndbord[i - 1][j - 1] == 1) && | ||
588 | (gid != groupIDs[i - 1][j - 1])) || | ||
589 | ((i < maxPoint) && (ndbord[i + 1][j] == -1) && | ||
590 | (ndbord[i + 1][j - 1] == 1) && | ||
591 | (gid != groupIDs[i + 1][j - 1])) || | ||
592 | ((((i > 0) && (ndbord[i - 1][j] == -1)) || | ||
593 | ((i < maxPoint) && (ndbord[i + 1][j] == -1))) && | ||
594 | (j > 1) && | ||
595 | (ndbord[i][j - 2] == 1) && | ||
596 | (gid != groupIDs[i][j - 2]))) | ||
597 | { | ||
598 | *x = i; | ||
599 | *y = j; | ||
600 | if (safeMove(*x, *y)) | ||
601 | return TRUE; | ||
602 | } | ||
603 | } | ||
604 | } | ||
605 | else if (nap == 2) /* diagonal or 1-point extention */ | ||
606 | { | ||
607 | if (groupIDs[pList.p[1].px][pList.p[1].py] != | ||
608 | groupIDs[pList.p[2].px][pList.p[2].py]) | ||
609 | { | ||
610 | if ((pList.p[1].px != pList.p[2].px) && | ||
611 | (pList.p[1].py != pList.p[2].py)) /* diag */ | ||
612 | { | ||
613 | spanGroup(pList.p[1].px, | ||
614 | pList.p[1].py, &pList1); | ||
615 | spanGroup(pList.p[2].px, | ||
616 | pList.p[2].py, &plist2); | ||
617 | intersectPlist(&pList1, &plist2, &plist3); | ||
618 | if (plist3.indx == 1) | ||
619 | if ((i > 0) && (ndbord[i - 1][j] == -1) || | ||
620 | (i < maxPoint) && (ndbord[i + 1][j] == -1) || | ||
621 | (j > 0) && (ndbord[i][j - 1] == -1) || | ||
622 | (j < maxPoint) && (ndbord[i][j + 1] == -1)) | ||
623 | { /* must make direct connection */ | ||
624 | *x = i; | ||
625 | *y = j; | ||
626 | if (heCanCut(*x, *y)) | ||
627 | if (safeMove(*x, *y)) | ||
628 | return TRUE; | ||
629 | } | ||
630 | else if (heCanCut(i, j)) | ||
631 | { /* protect point if possible */ | ||
632 | infl = 1000; | ||
633 | if ((i > 0) && legal[i - 1][j] && | ||
634 | ((i == 1) || (ndbord[i - 2][j] == 0)) && | ||
635 | ((j == 0) || (ndbord[i - 1][j - 1] == 0)) && | ||
636 | ((j == maxPoint) || | ||
637 | (ndbord[i - 1][j + 1] == 0))) | ||
638 | if (safeMove(i - 1, j)) | ||
639 | if (claim[i - 1][j] < infl) | ||
640 | { | ||
641 | *x = i - 1; | ||
642 | *y = j; | ||
643 | infl = claim[i - 1][j]; | ||
644 | } | ||
645 | if ((j > 0) && legal[i][j - 1] && | ||
646 | ((j == 1) || (ndbord[i][j - 2] == 0)) && | ||
647 | ((i == 0) || (ndbord[i - 1][j - 1] == 0)) && | ||
648 | ((i == maxPoint) || | ||
649 | (ndbord[i + 1][j - 1] == 0))) | ||
650 | if (safeMove(i, j - 1)) | ||
651 | if (claim[i][j - 1] < infl) | ||
652 | { | ||
653 | *x = i; | ||
654 | *y = j - 1; | ||
655 | infl = claim[i][j - 1]; | ||
656 | } | ||
657 | if ((i < maxPoint) && legal[i + 1][j] && | ||
658 | ((i == (maxPoint - 1)) || | ||
659 | (ndbord[i + 2][j] == 0)) && | ||
660 | ((j == 0) || (ndbord[i + 1][j - 1] == 0)) && | ||
661 | ((j == maxPoint) || | ||
662 | (ndbord[i + 1][j + 1] == 0))) | ||
663 | if (safeMove(i + 1, j)) | ||
664 | if (claim[i + 1][j] < infl) | ||
665 | { | ||
666 | *x = i + 1; | ||
667 | *y = j; | ||
668 | infl = claim[i + 1][j]; | ||
669 | } | ||
670 | if ((j < maxPoint) && legal[i][j + 1] && | ||
671 | ((j == (maxPoint - 1)) || | ||
672 | (ndbord[i][j + 2] == 0)) && | ||
673 | ((i == 0) || (ndbord[i - 1][j + 1] == 0)) && | ||
674 | ((i == maxPoint) || | ||
675 | (ndbord[i + 1][j + 1] == 0))) | ||
676 | if (safeMove(i, j + 1)) | ||
677 | if (claim[i][j + 1] < infl) | ||
678 | { | ||
679 | *x = i; | ||
680 | *y = j + 1; | ||
681 | infl = claim[i][j + 1]; | ||
682 | } | ||
683 | if (infl < 1000) | ||
684 | return TRUE; | ||
685 | *x = i; /* direct connection */ | ||
686 | *y = j; | ||
687 | if (safeMove(*x, *y)) | ||
688 | return TRUE; | ||
689 | } | ||
690 | } | ||
691 | else /* 1-point extension, only protect if threatened */ | ||
692 | { | ||
693 | if ((i > 0) && (ndbord[i - 1][j] == -1) || | ||
694 | (j > 0) && (ndbord[i][j - 1] == -1) || | ||
695 | (i < maxPoint) && (ndbord[i + 1][j] == -1) || | ||
696 | (j < maxPoint) && (ndbord[i][j + 1] == -1)) | ||
697 | { | ||
698 | *x = i; | ||
699 | *y = j; | ||
700 | if (heCanCut(*x, *y)) | ||
701 | if (safeMove(*x, *y)) | ||
702 | return TRUE; | ||
703 | } | ||
704 | } | ||
705 | } | ||
706 | } | ||
707 | else if (nap == 3) /* unprotected, but me on 3 sides */ | ||
708 | { | ||
709 | if ((groupIDs[pList.p[1].px][pList.p[1].py] != | ||
710 | groupIDs[pList.p[2].px][pList.p[2].py]) || | ||
711 | (groupIDs[pList.p[1].px][pList.p[1].py] != | ||
712 | groupIDs[pList.p[3].px][pList.p[3].py]) || | ||
713 | (groupIDs[pList.p[3].px][pList.p[3].py] != | ||
714 | groupIDs[pList.p[2].px][pList.p[2].py])) | ||
715 | { | ||
716 | spanGroup(pList.p[1].px, pList.p[1].py, &pList1); | ||
717 | spanGroup(pList.p[2].px, pList.p[2].py, &plist2); | ||
718 | intersectPlist(&pList1, &plist2, &plist3); | ||
719 | spanGroup(pList.p[3].px, pList.p[3].py, &plist2); | ||
720 | intersectPlist(&plist2, &plist3, &pList1); | ||
721 | if (pList1.indx == 1) /* a common connect point */ | ||
722 | if (heCanCut(i, j)) | ||
723 | if (safeMove(i, j)) | ||
724 | { | ||
725 | *x = i; | ||
726 | *y = j; | ||
727 | return TRUE; | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | } | ||
732 | return FALSE; | ||
733 | } /* connectCut */ | ||
734 | |||
735 | short heCanCut(x, y) | ||
736 | short x, y; | ||
737 | { /* heCanCut */ | ||
738 | short gx, gy, result; | ||
739 | if (playLevel > 3) | ||
740 | { | ||
741 | tryPlay(x, y, -1); /* try his cut */ | ||
742 | result = ! killable(x, y, &gx, &gy); | ||
743 | restoreState(); | ||
744 | return result; | ||
745 | } | ||
746 | else | ||
747 | return FALSE; | ||
748 | } /* heCanCut */ | ||
749 | |||
750 | /* | ||
751 | Checks out a move. | ||
752 | If my stone is not killable then true. | ||
753 | */ | ||
754 | short safeMove(x, y) | ||
755 | short x, y; | ||
756 | { /* safeMove */ | ||
757 | short gbx, gby, result; | ||
758 | tryPlay(x, y, 1); /* try playing at point */ | ||
759 | if (killFlag) /* I shouldn't kill if lookForKill didn't */ | ||
760 | result = FALSE; | ||
761 | else if (gList[groupIDs[x][y]].libC < 2) | ||
762 | { /* if it is in atari or dead */ | ||
763 | result = FALSE; /* reject it */ | ||
764 | } | ||
765 | else if (gList[groupIDs[x][y]].libC <= treeLibLim) /* see if killable */ | ||
766 | if (playLevel > 0) | ||
767 | result = ! killable(x, y, &gbx, &gby); | ||
768 | else | ||
769 | result = TRUE; | ||
770 | else | ||
771 | result = TRUE; | ||
772 | restoreState(); | ||
773 | return result; | ||
774 | } /* safeMove */ | ||
775 | |||
776 | /* | ||
777 | Extends walls in a connected fashion. | ||
778 | Finds the lowest influence (mine) point that is connected to one | ||
779 | of my groups. | ||
780 | Only looks in the center of the board. | ||
781 | */ | ||
782 | short extendWall(x, y) | ||
783 | short *x, *y; | ||
784 | { /* extendWall */ | ||
785 | short infl, i, j; | ||
786 | playReason = "extendWall"; | ||
787 | *x = iNil; | ||
788 | *y = iNil; | ||
789 | infl = 11; | ||
790 | for (i = 2; i <= maxPoint - 2; i++) | ||
791 | for (j = 2; j <= maxPoint - 2; j++) | ||
792 | if (legal[i][j]) | ||
793 | if (connectMap[i][j] > 0) | ||
794 | if ((claim[i][j] < infl) && | ||
795 | (ndbord[i - 1][j] < 1) && | ||
796 | (ndbord[i + 1][j] < 1) && | ||
797 | (ndbord[i][j - 1] < 1) && | ||
798 | (ndbord[i][j + 1] < 1) && | ||
799 | ((claim[i - 1][j] < 0) || | ||
800 | (claim[i + 1][j] < 0) || | ||
801 | (claim[i][j - 1] < 0) || | ||
802 | (claim[i][j + 1] < 0))) | ||
803 | if (safeMove(i, j)) | ||
804 | { | ||
805 | infl = claim[i][j]; | ||
806 | *x = i; | ||
807 | *y = j; | ||
808 | } | ||
809 | if (*x != iNil) return TRUE; | ||
810 | return FALSE; | ||
811 | } /* extendWall */ | ||
812 | |||
813 | |||
814 | /* | ||
815 | check to see if I can attack one of his groups | ||
816 | uses limited depth search so that it can work on larger lib counts | ||
817 | */ | ||
818 | short findAttack2(x, y) | ||
819 | short *x, *y; | ||
820 | { /* findAttack2 */ | ||
821 | short tx, ty, i, otll; | ||
822 | if (playLevel < 7) | ||
823 | return FALSE; | ||
824 | playReason = "findAttack2"; | ||
825 | depthLimit = 8; | ||
826 | otll = treeLibLim; | ||
827 | for (i = 1; i <= maxGroupID; i++) /* scan the group list */ | ||
828 | if ((! gList[i].isLive) && | ||
829 | (ndbord[gList[i].lx][gList[i].ly] == -1) && | ||
830 | (gList[i].libC > 1)) | ||
831 | { | ||
832 | treeLibLim = 6; | ||
833 | if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */ | ||
834 | { | ||
835 | *x = tx; /* yep - do so */ | ||
836 | *y = ty; | ||
837 | return TRUE; | ||
838 | } | ||
839 | treeLibLim = otll; | ||
840 | } | ||
841 | depthLimit = 100; | ||
842 | return FALSE; | ||
843 | } /* findAttack2 */ | ||
844 | |||
845 | |||
846 | /* | ||
847 | blocks enemy cuts thru 1-point extensions | ||
848 | */ | ||
849 | short blockCut(x, y) | ||
850 | short *x, *y; | ||
851 | { /* blockCut */ | ||
852 | short i, j; | ||
853 | playReason = "blockCut"; | ||
854 | for (i = 0; i <= maxPoint; i++) | ||
855 | for (j = 0; j <= maxPoint; j++) | ||
856 | if (legal[i][j]) | ||
857 | { | ||
858 | if ((i > 0) && (j > 0) && (j < maxPoint)) | ||
859 | { | ||
860 | if ((ndbord[i - 1][j] == -1) && | ||
861 | (ndbord[i - 1][j - 1] == 1) && | ||
862 | (ndbord[i - 1][j + 1] == 1) && | ||
863 | (groupIDs[i - 1][j - 1] != groupIDs[i - 1][j + 1])) | ||
864 | { | ||
865 | *x = i; | ||
866 | *y = j; | ||
867 | if (heCanCut(*x, *y)) | ||
868 | if (safeMove(*x, *y)) | ||
869 | return TRUE; | ||
870 | } | ||
871 | } | ||
872 | if ((i < maxPoint) && (j > 0) && (j < maxPoint)) | ||
873 | { | ||
874 | if ((ndbord[i + 1][j] == -1) && | ||
875 | (ndbord[i + 1][j - 1] == 1) && | ||
876 | (ndbord[i + 1][j + 1] == 1) && | ||
877 | (groupIDs[i + 1][j - 1] != groupIDs[i + 1][j + 1])) | ||
878 | { | ||
879 | *x = i; | ||
880 | *y = j; | ||
881 | if (heCanCut(*x, *y)) | ||
882 | if (safeMove(*x, *y)) | ||
883 | return TRUE; | ||
884 | } | ||
885 | } | ||
886 | if ((j > 0) && (i > 0) && (i < maxPoint)) | ||
887 | { | ||
888 | if ((ndbord[i][j - 1] == -1) && | ||
889 | (ndbord[i - 1][j - 1] == 1) && | ||
890 | (ndbord[i + 1][j - 1] == 1) && | ||
891 | (groupIDs[i - 1][j - 1] != groupIDs[i + 1][j - 1])) | ||
892 | { | ||
893 | *x = i; | ||
894 | *y = j; | ||
895 | if (heCanCut(*x, *y)) | ||
896 | if (safeMove(*x, *y)) | ||
897 | return TRUE; | ||
898 | } | ||
899 | } | ||
900 | if ((j < maxPoint) && (i > 0) && (i < maxPoint)) | ||
901 | { | ||
902 | if ((ndbord[i][j + 1] == -1) && | ||
903 | (ndbord[i - 1][j + 1] == 1) && | ||
904 | (ndbord[i + 1][j + 1] == 1) && | ||
905 | (groupIDs[i - 1][j + 1] != groupIDs[i + 1][j + 1])) | ||
906 | { | ||
907 | *x = i; | ||
908 | *y = j; | ||
909 | if (heCanCut(*x, *y)) | ||
910 | if (safeMove(*x, *y)) | ||
911 | return TRUE; | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | return FALSE; | ||
916 | } /* blockCut */ | ||
917 | |||
918 | |||
919 | /* | ||
920 | cuts the enemy | ||
921 | */ | ||
922 | short cutHim(x, y) | ||
923 | short *x, *y; | ||
924 | { /* cutHim */ | ||
925 | short i, j, nap, gid; | ||
926 | playReason = "cutHim"; | ||
927 | for (i = 0; i <= maxPoint; i++) | ||
928 | for (j = 0; j <= maxPoint; j++) | ||
929 | if (legal[i][j]) | ||
930 | { | ||
931 | nap = 0; /* how many of his stones am I adjacent to? */ | ||
932 | if ((i > 0) && (ndbord[i - 1][j] == -1)) | ||
933 | { | ||
934 | nap = nap + 1; | ||
935 | pList.p[nap].px = i - 1; | ||
936 | pList.p[nap].py = j; | ||
937 | } | ||
938 | if ((j > 0) && (ndbord[i][j - 1] == -1)) | ||
939 | { | ||
940 | nap = nap + 1; | ||
941 | pList.p[nap].px = i; | ||
942 | pList.p[nap].py = j - 1; | ||
943 | } | ||
944 | if ((i < maxPoint) && (ndbord[i + 1][j] == -1)) | ||
945 | { | ||
946 | nap = nap + 1; | ||
947 | pList.p[nap].px = i + 1; | ||
948 | pList.p[nap].py = j; | ||
949 | } | ||
950 | if ((j < maxPoint) && (ndbord[i][j + 1] == -1)) | ||
951 | { | ||
952 | nap = nap + 1; | ||
953 | pList.p[nap].px = i; | ||
954 | pList.p[nap].py = j + 1; | ||
955 | } | ||
956 | if (nap == 1) /* possible knight's or 2-point extention */ | ||
957 | { | ||
958 | gid = groupIDs[pList.p[1].px][pList.p[1].py]; | ||
959 | if ((i > 0) && (i < maxPoint) && | ||
960 | (ndbord[i - 1][j] == -1) && | ||
961 | (connectMap[i][j] > 0)) /* contact on left */ | ||
962 | { | ||
963 | if (((j > 0) && | ||
964 | (ndbord[i + 1][j - 1] == -1) && | ||
965 | (gid != groupIDs[i + 1][j - 1])) || | ||
966 | ((j < maxPoint) && | ||
967 | (ndbord[i + 1][j + 1] == -1) && | ||
968 | (gid != groupIDs[i + 1][j + 1])) || | ||
969 | ((i < (maxPoint - 1)) && | ||
970 | (ndbord[i + 1][j] == 0) && | ||
971 | (ndbord[i + 2][j] == -1) && | ||
972 | (gid != groupIDs[i + 2][j]))) | ||
973 | { | ||
974 | *x = i; | ||
975 | *y = j; | ||
976 | if (safeMove(*x, *y)) | ||
977 | return TRUE; | ||
978 | } | ||
979 | } | ||
980 | else if ((i < maxPoint) && (i > 0) && | ||
981 | (ndbord[i + 1][j] == -1) && | ||
982 | (connectMap[i][j] > 0)) /* r */ | ||
983 | { | ||
984 | if (((j > 0) && | ||
985 | (ndbord[i - 1][j - 1] == -1) && | ||
986 | (gid != groupIDs[i - 1][j - 1])) || | ||
987 | ((j < maxPoint) && | ||
988 | (ndbord[i - 1][j + 1] == -1) && | ||
989 | (gid != groupIDs[i - 1][j + 1])) || | ||
990 | ((i > 1) && | ||
991 | (ndbord[i - 1][j] == 0) && | ||
992 | (ndbord[i - 2][j] == -1) && | ||
993 | (gid != groupIDs[i - 2][j]))) | ||
994 | { | ||
995 | *x = i; | ||
996 | *y = j; | ||
997 | if (safeMove(*x, *y)) | ||
998 | return TRUE; | ||
999 | } | ||
1000 | } | ||
1001 | else if ((j > 0) && (j < maxPoint) && | ||
1002 | (ndbord[i][j - 1] == -1) && | ||
1003 | (connectMap[i][j] > 0)) /* top */ | ||
1004 | { | ||
1005 | if (((i > 0) && | ||
1006 | (ndbord[i - 1][j + 1] == -1) && | ||
1007 | (gid != groupIDs[i - 1][j + 1])) || | ||
1008 | ((i < maxPoint) && | ||
1009 | (ndbord[i + 1][j + 1] == -1) && | ||
1010 | (gid != groupIDs[i + 1][j + 1])) || | ||
1011 | ((j < (maxPoint - 1)) && | ||
1012 | (ndbord[i][j + 1] == 0) && | ||
1013 | (ndbord[i][j + 2] == -1) && | ||
1014 | (gid != groupIDs[i][j + 2]))) | ||
1015 | { | ||
1016 | *x = i; | ||
1017 | *y = j; | ||
1018 | if (safeMove(*x, *y)) | ||
1019 | return TRUE; | ||
1020 | } | ||
1021 | } | ||
1022 | else if ((j > 0) && (j < maxPoint) && | ||
1023 | (ndbord[i][j + 1] == -1) && | ||
1024 | (connectMap[i][j] > 0)) /* bottom */ | ||
1025 | { | ||
1026 | if (((i > 0) && | ||
1027 | (ndbord[i - 1][j - 1] == -1) && | ||
1028 | (gid != groupIDs[i - 1][j - 1])) || | ||
1029 | ((i < maxPoint) && | ||
1030 | (ndbord[i + 1][j - 1] == -1) && | ||
1031 | (gid != groupIDs[i + 1][j - 1])) || | ||
1032 | ((j > 1) && | ||
1033 | (ndbord[i][j - 1] == 0) && | ||
1034 | (ndbord[i][j - 2] == -1) && | ||
1035 | (gid != groupIDs[i][j - 2]))) | ||
1036 | { | ||
1037 | *x = i; | ||
1038 | *y = j; | ||
1039 | if (safeMove(*x, *y)) | ||
1040 | return TRUE; | ||
1041 | } | ||
1042 | } | ||
1043 | } | ||
1044 | else if (nap == 2) /* diagonal or 1-point extention */ | ||
1045 | { | ||
1046 | if (groupIDs[pList.p[1].px][pList.p[1].py] != | ||
1047 | groupIDs[pList.p[2].px][pList.p[2].py]) | ||
1048 | { | ||
1049 | if ((pList.p[1].px != pList.p[2].px) && | ||
1050 | (pList.p[1].py != pList.p[2].py)) /* diag */ | ||
1051 | { | ||
1052 | spanGroup(pList.p[1].px, | ||
1053 | pList.p[1].py, &pList1); | ||
1054 | spanGroup(pList.p[2].px, | ||
1055 | pList.p[2].py, &plist2); | ||
1056 | intersectPlist(&pList1, &plist2, &plist3); | ||
1057 | if (plist3.indx == 1) | ||
1058 | { | ||
1059 | *x = i; | ||
1060 | *y = j; | ||
1061 | if (safeMove(*x, *y)) | ||
1062 | return TRUE; | ||
1063 | } | ||
1064 | } | ||
1065 | else /* 1-point extension, only cut if connected */ | ||
1066 | { | ||
1067 | if (connectMap[i][j] > 0) | ||
1068 | { | ||
1069 | *x = i; | ||
1070 | *y = j; | ||
1071 | if (safeMove(*x, *y)) | ||
1072 | return TRUE; | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | } | ||
1077 | else if (nap == 3) /* unprotected, but him on 3 sides */ | ||
1078 | { | ||
1079 | if ((groupIDs[pList.p[1].px][pList.p[1].py] != | ||
1080 | groupIDs[pList.p[2].px][pList.p[2].py]) || | ||
1081 | (groupIDs[pList.p[1].px][pList.p[1].py] != | ||
1082 | groupIDs[pList.p[3].px][pList.p[3].py]) || | ||
1083 | (groupIDs[pList.p[3].px][pList.p[3].py] != | ||
1084 | groupIDs[pList.p[2].px][pList.p[2].py])) | ||
1085 | { | ||
1086 | spanGroup(pList.p[1].px, pList.p[1].py, &pList1); | ||
1087 | spanGroup(pList.p[2].px, pList.p[2].py, &plist2); | ||
1088 | intersectPlist(&pList1, &plist2, &plist3); | ||
1089 | spanGroup(pList.p[3].px, pList.p[3].py, &plist2); | ||
1090 | intersectPlist(&plist2, &plist3, &pList1); | ||
1091 | if (pList1.indx == 1) /* a common connect point */ | ||
1092 | if (safeMove(i, j)) | ||
1093 | { | ||
1094 | *x = i; | ||
1095 | *y = j; | ||
1096 | return TRUE; | ||
1097 | } | ||
1098 | } | ||
1099 | } | ||
1100 | } | ||
1101 | return FALSE; | ||
1102 | } /* cutHim */ | ||
1103 | |||
1104 | |||
1105 | /* | ||
1106 | ataris a group just for the hell of it | ||
1107 | */ | ||
1108 | short atariAnyway(x, y) | ||
1109 | short *x, *y; | ||
1110 | { /* atariAnyway */ | ||
1111 | short i; | ||
1112 | playReason = "atariAnyway"; | ||
1113 | for (i = 1; i <= maxGroupID; i++) /* scan the group list */ | ||
1114 | if ((gList[i].libC == 2) && | ||
1115 | (ndbord[gList[i].lx][gList[i].ly] == -1)) | ||
1116 | { | ||
1117 | spanGroup(gList[i].lx, gList[i].ly, &pList); | ||
1118 | if (legal[pList.p[1].px][pList.p[1].py] && | ||
1119 | ((connectMap[pList.p[1].px][pList.p[1].py] > 0) || | ||
1120 | ((pList.p[1].px > 0) && | ||
1121 | (connectMap[pList.p[1].px - 1][pList.p[1].py] > 0)) || | ||
1122 | ((pList.p[1].px < maxPoint) && | ||
1123 | (connectMap[pList.p[1].px + 1][pList.p[1].py] > 0)) || | ||
1124 | ((pList.p[1].py > 0) && | ||
1125 | (connectMap[pList.p[1].px][pList.p[1].py - 1] > 0)) || | ||
1126 | ((pList.p[1].py < maxPoint) && | ||
1127 | (connectMap[pList.p[1].px][pList.p[1].py + 1] > 0)))) | ||
1128 | if (safeMove(pList.p[1].px, pList.p[1].py)) | ||
1129 | { | ||
1130 | *x = pList.p[1].px; | ||
1131 | *y = pList.p[1].py; | ||
1132 | return TRUE; | ||
1133 | } | ||
1134 | if (legal[pList.p[2].px][pList.p[2].py] && | ||
1135 | ((connectMap[pList.p[2].px][pList.p[2].py] > 0) || | ||
1136 | ((pList.p[2].px > 0) && | ||
1137 | (connectMap[pList.p[2].px - 1][pList.p[2].py] > 0)) || | ||
1138 | ((pList.p[2].px < maxPoint) && | ||
1139 | (connectMap[pList.p[2].px + 1][pList.p[2].py] > 0)) || | ||
1140 | ((pList.p[2].py > 0) && | ||
1141 | (connectMap[pList.p[2].px][pList.p[2].py - 1] > 0)) || | ||
1142 | ((pList.p[2].py < maxPoint) && | ||
1143 | (connectMap[pList.p[2].px][pList.p[2].py + 1] > 0)))) | ||
1144 | if (safeMove(pList.p[2].px, pList.p[2].py)) | ||
1145 | { | ||
1146 | *x = pList.p[2].px; | ||
1147 | *y = pList.p[2].py; | ||
1148 | return TRUE; | ||
1149 | } | ||
1150 | } | ||
1151 | return FALSE; | ||
1152 | } /* atariAnyway */ | ||
1153 | |||
1154 | |||
1155 | /* | ||
1156 | undercuts his groups | ||
1157 | */ | ||
1158 | short underCut(x, y) | ||
1159 | short *x, *y; | ||
1160 | { /* underCut */ | ||
1161 | short i, j; | ||
1162 | playReason = "underCut"; | ||
1163 | for (i = 1; i <= maxPoint - 1; i++) | ||
1164 | { | ||
1165 | if (legal[0][i]) | ||
1166 | { | ||
1167 | if (ndbord[1][i] == -1) | ||
1168 | if (safeMove(0, i)) | ||
1169 | { | ||
1170 | *x = 0; | ||
1171 | *y = i; | ||
1172 | return TRUE; | ||
1173 | } | ||
1174 | } | ||
1175 | if (legal[maxPoint][i]) | ||
1176 | { | ||
1177 | if (ndbord[maxPoint - 1][i] == -1) | ||
1178 | if (safeMove(maxPoint, i)) | ||
1179 | { | ||
1180 | *x = maxPoint; | ||
1181 | *y = i; | ||
1182 | return TRUE; | ||
1183 | } | ||
1184 | } | ||
1185 | if (legal[i][0]) | ||
1186 | { | ||
1187 | if (ndbord[i][1] == -1) | ||
1188 | if (safeMove(i, 0)) | ||
1189 | { | ||
1190 | *x = i; | ||
1191 | *y = 0; | ||
1192 | return TRUE; | ||
1193 | } | ||
1194 | } | ||
1195 | if (legal[i][maxPoint]) | ||
1196 | { | ||
1197 | if (ndbord[i][maxPoint - 1] == -1) | ||
1198 | if (safeMove(i, maxPoint)) | ||
1199 | { | ||
1200 | *x = i; | ||
1201 | *y = maxPoint; | ||
1202 | return TRUE; | ||
1203 | } | ||
1204 | } | ||
1205 | } | ||
1206 | return FALSE; | ||
1207 | } /* underCut */ | ||
1208 | |||
1209 | /* | ||
1210 | drops to the edge of the board if threatened | ||
1211 | */ | ||
1212 | short dropToEdge(x, y) | ||
1213 | short *x, *y; | ||
1214 | { /* dropToEdge */ | ||
1215 | short i; | ||
1216 | playReason = "dropToEdge"; | ||
1217 | for (i = 1; i <= maxPoint - 1; i++) | ||
1218 | { | ||
1219 | if (legal[1][i]) | ||
1220 | if ((ndbord[2][i] == 1) && | ||
1221 | (ndbord[0][i] == 0) && | ||
1222 | (ndbord[1][i - 1] < 1) && | ||
1223 | (ndbord[1][i + 1] < 1) && | ||
1224 | ((ndbord[2][i - 1] == -1) || | ||
1225 | (ndbord[2][i + 1] == -1) || | ||
1226 | (ndbord[1][i - 1] == -1) || | ||
1227 | (ndbord[1][i + 1] == -1))) | ||
1228 | { | ||
1229 | *x = 1; | ||
1230 | *y = i; | ||
1231 | if (safeMove(*x, *y)) | ||
1232 | return TRUE; | ||
1233 | } | ||
1234 | if (legal[maxPoint - 1][i]) | ||
1235 | if ((ndbord[maxPoint - 2][i] == 1) && | ||
1236 | (ndbord[maxPoint][i] == 0) && | ||
1237 | (ndbord[maxPoint - 1][i - 1] < 1) && | ||
1238 | (ndbord[maxPoint - 1][i + 1] < 1) && | ||
1239 | ((ndbord[maxPoint - 2][i - 1] == -1) || | ||
1240 | (ndbord[maxPoint - 2][i + 1] == -1) || | ||
1241 | (ndbord[maxPoint - 1][i - 1] == -1) || | ||
1242 | (ndbord[maxPoint - 1][i + 1] == -1))) | ||
1243 | { | ||
1244 | *x = maxPoint - 1; | ||
1245 | *y = i; | ||
1246 | if (safeMove(*x, *y)) | ||
1247 | return TRUE; | ||
1248 | } | ||
1249 | if (legal[i][1]) | ||
1250 | if ((ndbord[i][2] == 1) && | ||
1251 | (ndbord[i][0] == 0) && | ||
1252 | (ndbord[i - 1][1] < 1) && | ||
1253 | (ndbord[i + 1][1] < 1) && | ||
1254 | ((ndbord[i - 1][2] == -1) || | ||
1255 | (ndbord[i + 1][2] == -1) || | ||
1256 | (ndbord[i - 1][1] == -1) || | ||
1257 | (ndbord[i + 1][1] == -1))) | ||
1258 | { | ||
1259 | *x = i; | ||
1260 | *y = 1; | ||
1261 | if (safeMove(*x, *y)) | ||
1262 | return TRUE; | ||
1263 | } | ||
1264 | if (legal[i][maxPoint - 1]) | ||
1265 | if ((ndbord[i][maxPoint - 2] == 1) && | ||
1266 | (ndbord[i][maxPoint] == 0) && | ||
1267 | (ndbord[i - 1][maxPoint - 1] < 1) && | ||
1268 | (ndbord[i + 1][maxPoint - 1] < 1) && | ||
1269 | ((ndbord[i - 1][maxPoint - 2] == -1) || | ||
1270 | (ndbord[i + 1][maxPoint - 2] == -1) || | ||
1271 | (ndbord[i - 1][maxPoint - 1] == -1) || | ||
1272 | (ndbord[i + 1][maxPoint - 1] == -1))) | ||
1273 | { | ||
1274 | *x = i; | ||
1275 | *y = maxPoint - 1; | ||
1276 | if (safeMove(*x, *y)) | ||
1277 | return TRUE; | ||
1278 | } | ||
1279 | if (legal[0][i]) | ||
1280 | if ((ndbord[1][i] == 1) && | ||
1281 | (ndbord[0][i - 1] < 1) && | ||
1282 | (ndbord[0][i + 1] < 1) && | ||
1283 | (((ndbord[1][i - 1] == -1) && | ||
1284 | (ndbord[1][i + 1] == -1)) || | ||
1285 | (ndbord[0][i - 1] == -1) || | ||
1286 | (ndbord[0][i + 1] == -1))) | ||
1287 | { | ||
1288 | *x = 0; | ||
1289 | *y = i; | ||
1290 | if (safeMove(*x, *y)) | ||
1291 | return TRUE; | ||
1292 | } | ||
1293 | if (legal[maxPoint][i]) | ||
1294 | if ((ndbord[maxPoint - 1][i] == 1) && | ||
1295 | (ndbord[maxPoint][i - 1] < 1) && | ||
1296 | (ndbord[maxPoint][i + 1] < 1) && | ||
1297 | (((ndbord[maxPoint - 1][i - 1] == -1) && | ||
1298 | (ndbord[maxPoint - 1][i + 1] == -1)) || | ||
1299 | (ndbord[maxPoint][i - 1] == -1) || | ||
1300 | (ndbord[maxPoint][i + 1] == -1))) | ||
1301 | { | ||
1302 | *x = maxPoint; | ||
1303 | *y = i; | ||
1304 | if (safeMove(*x, *y)) | ||
1305 | return TRUE; | ||
1306 | } | ||
1307 | if (legal[i][0]) | ||
1308 | if ((ndbord[i][1] == 1) && | ||
1309 | (ndbord[i - 1][0] < 1) && | ||
1310 | (ndbord[i + 1][0] < 1) && | ||
1311 | (((ndbord[i - 1][1] == -1) && | ||
1312 | (ndbord[i + 1][1] == -1)) || | ||
1313 | (ndbord[i - 1][0] == -1) || | ||
1314 | (ndbord[i + 1][0] == -1))) | ||
1315 | { | ||
1316 | *x = i; | ||
1317 | *y = 0; | ||
1318 | if (safeMove(*x, *y)) | ||
1319 | return TRUE; | ||
1320 | } | ||
1321 | if (legal[i][maxPoint]) | ||
1322 | if ((ndbord[i][maxPoint - 1] == 1) && | ||
1323 | (ndbord[i - 1][maxPoint] < 1) && | ||
1324 | (ndbord[i + 1][maxPoint] < 1) && | ||
1325 | (((ndbord[i - 1][maxPoint - 1] == -1) && | ||
1326 | (ndbord[i + 1][maxPoint - 1] == -1)) || | ||
1327 | (ndbord[i - 1][maxPoint] == -1) || | ||
1328 | (ndbord[i + 1][maxPoint] == -1))) | ||
1329 | { | ||
1330 | *x = i; | ||
1331 | *y = maxPoint; | ||
1332 | if (safeMove(*x, *y)) | ||
1333 | return TRUE; | ||
1334 | } | ||
1335 | } | ||
1336 | return FALSE; | ||
1337 | } /* dropToEdge */ | ||
1338 | |||
1339 | /* | ||
1340 | Pushes walls in a tightly connected fashion. | ||
1341 | Finds the lowest influence (mine) point that is connected to one | ||
1342 | of my groups. | ||
1343 | */ | ||
1344 | short pushWall(x, y) | ||
1345 | short *x, *y; | ||
1346 | { /* pushWall */ | ||
1347 | short infl, i, j, na; | ||
1348 | playReason = "pushWall"; | ||
1349 | *x = iNil; | ||
1350 | *y = iNil; | ||
1351 | infl = 11; | ||
1352 | for (i = 0; i <= maxPoint; i++) | ||
1353 | for (j = 0; j <= maxPoint; j++) | ||
1354 | if (legal[i][j]) | ||
1355 | if (connectMap[i][j] > 0) | ||
1356 | if ((claim[i][j] < infl) && | ||
1357 | (((i > 0) && (ndbord[i - 1][j] == 1)) || | ||
1358 | ((i < maxPoint) && (ndbord[i + 1][j] == 1)) || | ||
1359 | ((j > 0) && (ndbord[i][j - 1] == 1)) || | ||
1360 | ((j < maxPoint) && (ndbord[i][j + 1] == 1)) || | ||
1361 | ((i > 0) && (j > 0) && (ndbord[i - 1][j - 1] == 1)) || | ||
1362 | ((i < maxPoint) && (j > 0) && (ndbord[i + 1][j - 1] == 1)) || | ||
1363 | ((i > 0) && (j < maxPoint) && (ndbord[i - 1][j + 1] == 1)) || | ||
1364 | ((i < maxPoint) && (j < maxPoint) && | ||
1365 | (ndbord[i + 1][j + 1] == 1))) && | ||
1366 | (((i > 0) && (claim[i - 1][j] < 0)) || | ||
1367 | ((i < maxPoint) && (claim[i + 1][j] < 0)) || | ||
1368 | ((j > 0) && (claim[i][j - 1] < 0)) || | ||
1369 | ((j < maxPoint) && (claim[i][j + 1] < 0)))) | ||
1370 | { | ||
1371 | na = 0; | ||
1372 | if ((i > 0) && (ndbord[i - 1][j] != 0)) | ||
1373 | na = na + 1; | ||
1374 | if ((i < maxPoint) && (ndbord[i + 1][j] != 0)) | ||
1375 | na = na + 1; | ||
1376 | if ((j > 0) && (ndbord[i][j - 1] != 0)) | ||
1377 | na = na + 1; | ||
1378 | if ((j < maxPoint) && (ndbord[i][j + 1] != 0)) | ||
1379 | na = na + 1; | ||
1380 | if (na < 3) | ||
1381 | if (safeMove(i, j)) | ||
1382 | { | ||
1383 | infl = claim[i][j]; | ||
1384 | *x = i; | ||
1385 | *y = j; | ||
1386 | } | ||
1387 | } | ||
1388 | if (*x != iNil) return TRUE; | ||
1389 | return FALSE; | ||
1390 | } /* pushWall */ | ||
1391 | |||
1392 | |||
1393 | /* | ||
1394 | reduces the liberty count of one of his groups | ||
1395 | */ | ||
1396 | short reduceHisLiberties(x, y) | ||
1397 | short *x, *y; | ||
1398 | { /* reduceHisLiberties */ | ||
1399 | short i, j; | ||
1400 | playReason = "reduceHisLiberties"; | ||
1401 | sortLibs(); | ||
1402 | for (i = 1; i <= maxGroupID; i++) | ||
1403 | if ((! gList[sGlist[i]].isLive) && | ||
1404 | (gList[sGlist[i]].libC > 2) && | ||
1405 | (ndbord[gList[sGlist[i]].lx][gList[sGlist[i]].ly] == -1)) | ||
1406 | { | ||
1407 | spanGroup(gList[sGlist[i]].lx, gList[sGlist[i]].ly, &pList); | ||
1408 | for (j = 1; j <= pList.indx; j++) | ||
1409 | if (legal[pList.p[j].px][pList.p[j].py] && | ||
1410 | (connectMap[pList.p[j].px][pList.p[j].py] > 0)) | ||
1411 | if (safeMove(pList.p[j].px, pList.p[j].py)) | ||
1412 | { | ||
1413 | *x = pList.p[j].px; | ||
1414 | *y = pList.p[j].py; | ||
1415 | return TRUE; | ||
1416 | } | ||
1417 | } | ||
1418 | return FALSE; | ||
1419 | } /* reduceHisLiberties */ | ||
1420 | |||
1421 | |||
1422 | /* | ||
1423 | connects a group to the edge | ||
1424 | */ | ||
1425 | short dropToEdge2(x, y) | ||
1426 | short *x, *y; | ||
1427 | { /* dropToEdge2 */ | ||
1428 | short i; | ||
1429 | playReason = "dropToEdge2"; | ||
1430 | for (i = 1; i <= maxPoint - 1; i++) | ||
1431 | { | ||
1432 | if (legal[i][0]) | ||
1433 | { | ||
1434 | if ((ndbord[i][1] == 1) && | ||
1435 | ((ndbord[i - 1][0] < 1) || | ||
1436 | (groupIDs[i - 1][0] != groupIDs[i][1])) && | ||
1437 | ((ndbord[i + 1][0] < 1) || | ||
1438 | (groupIDs[i + 1][0] != groupIDs[i][1])) && | ||
1439 | ((ndbord[i - 1][1] == -1) || | ||
1440 | (ndbord[i + 1][1] == -1))) | ||
1441 | { | ||
1442 | *x = i; | ||
1443 | *y = 0; | ||
1444 | if (safeMove(*x, *y)) | ||
1445 | return TRUE; | ||
1446 | } | ||
1447 | } | ||
1448 | if (legal[0][i]) | ||
1449 | { | ||
1450 | if ((ndbord[1][i] == 1) && | ||
1451 | ((ndbord[0][i - 1] < 1) || | ||
1452 | (groupIDs[0][i - 1] != groupIDs[1][i])) && | ||
1453 | ((ndbord[0][i + 1] < 1) || | ||
1454 | (groupIDs[0][i + 1] != groupIDs[1][i])) && | ||
1455 | ((ndbord[1][i - 1] == -1) || | ||
1456 | (ndbord[1][i + 1] == -1))) | ||
1457 | { | ||
1458 | *x = 0; | ||
1459 | *y = i; | ||
1460 | if (safeMove(*x, *y)) | ||
1461 | return TRUE; | ||
1462 | } | ||
1463 | } | ||
1464 | if (legal[i][maxPoint]) | ||
1465 | { | ||
1466 | if ((ndbord[i][maxPoint - 1] == 1) && | ||
1467 | ((ndbord[i - 1][maxPoint] < 1) || | ||
1468 | (groupIDs[i - 1][maxPoint] != groupIDs[i][maxPoint - 1])) && | ||
1469 | ((ndbord[i + 1][maxPoint] < 1) || | ||
1470 | (groupIDs[i + 1][maxPoint] != groupIDs[i][maxPoint - 1])) && | ||
1471 | ((ndbord[i - 1][maxPoint - 1] == -1) || | ||
1472 | (ndbord[i + 1][maxPoint - 1] == -1))) | ||
1473 | { | ||
1474 | *x = i; | ||
1475 | *y = maxPoint; | ||
1476 | if (safeMove(*x, *y)) | ||
1477 | return TRUE; | ||
1478 | } | ||
1479 | } | ||
1480 | if (legal[maxPoint][i]) | ||
1481 | { | ||
1482 | if ((ndbord[maxPoint - 1][i] == 1) && | ||
1483 | ((ndbord[maxPoint][i - 1] < 1) || | ||
1484 | (groupIDs[maxPoint][i - 1] != groupIDs[maxPoint - 1][i])) && | ||
1485 | ((ndbord[maxPoint][i + 1] < 1) || | ||
1486 | (groupIDs[maxPoint][i + 1] != groupIDs[maxPoint - 1][i])) && | ||
1487 | ((ndbord[maxPoint - 1][i - 1] == -1) || | ||
1488 | (ndbord[maxPoint - 1][i + 1] == -1))) | ||
1489 | { | ||
1490 | *x = maxPoint; | ||
1491 | *y = i; | ||
1492 | if (safeMove(*x, *y)) | ||
1493 | return TRUE; | ||
1494 | } | ||
1495 | } | ||
1496 | } | ||
1497 | return FALSE; | ||
1498 | } /* dropToEdge2 */ | ||
1499 | |||
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: | ||
4 | Copyright (c) 1983 by Three Rivers Computer Corp. | ||
5 | |||
6 | Written: January 17, 1983 by Stoney Ballard | ||
7 | */ | ||
8 | |||
9 | #include "goplayutils.h" | ||
10 | #include "amigo.h" | ||
11 | #include "go.h" | ||
12 | |||
13 | extern struct bRec goboard[19][19]; | ||
14 | |||
15 | intBoard claim, extra, bord, ndbord, sGroups, threatBord, | ||
16 | groupIDs, connectMap, protPoints; | ||
17 | boolBoard groupSeen, legal; | ||
18 | short maxGroupID; | ||
19 | pointList pList, pList1, plist2, plist3, pPlist; | ||
20 | intList nlcGroup, aList; | ||
21 | sgRec sList[401]; | ||
22 | groupRec gList[maxGroup]; | ||
23 | short killFlag, | ||
24 | numCapt, | ||
25 | utilPlayLevel, | ||
26 | treeLibLim; | ||
27 | sType mySType; | ||
28 | short showTrees; | ||
29 | short sGlist[maxGroup+1]; | ||
30 | short depthLimit; | ||
31 | intBoard markBoard; | ||
32 | short marker; | ||
33 | |||
34 | short adjInAtari, adj2Libs, | ||
35 | intersectNum, spanNum, libMark; | ||
36 | playRec playStack[1025]; | ||
37 | short playMark, | ||
38 | newGID, | ||
39 | tryLevel, | ||
40 | grpMark, | ||
41 | gMap[maxGroup]; | ||
42 | short 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 | |||
56 | sstone(w, x, y, numb) | ||
57 | short 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 | |||
67 | rstone(x, y) | ||
68 | short x, y; | ||
69 | { /* rstone */ | ||
70 | removestone(x, y); | ||
71 | } /* rstone */ | ||
72 | |||
73 | initBoolBoard(bb) | ||
74 | boolBoard 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 | |||
85 | sortLibs() | ||
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 | |||
103 | spanGroupspan(x, y, libs, lookFor) | ||
104 | short x, y, lookFor; | ||
105 | pointList *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 | |||
133 | spanGroup(x, y, libs) | ||
134 | short x, y; | ||
135 | pointList *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 | |||
154 | sSpanGroupspan(x, y, libs, lookFor) | ||
155 | short x, y, lookFor; | ||
156 | sPointList *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 | |||
187 | sSpanGroup(x, y, libs) | ||
188 | short x, y; | ||
189 | sPointList *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 | |||
208 | LAspan(x, y, me, him, iL) | ||
209 | short x, y, me, him; | ||
210 | intList *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 | |||
236 | listAdjacents(x, y, iL) | ||
237 | short x, y; | ||
238 | intList *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 | |||
257 | LDspan(x, y, me, diags) | ||
258 | short x, y, me; | ||
259 | sPointList *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 | |||
335 | listDiags(x, y, diags) | ||
336 | short x, y; | ||
337 | sPointList *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 | |||
354 | intersectPlist(p1, p2, pr) | ||
355 | pointList *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 | |||
380 | initArray(ary) | ||
381 | intBoard 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 | |||
389 | initState() | ||
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 | |||
403 | copyArray( dest, src ) | ||
404 | intBoard 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 | */ | ||
428 | stake() | ||
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 | */ | ||
457 | spread() | ||
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 | */ | ||
473 | Resspan(x, y, gID, gSize, libCount, who) | ||
474 | short 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 | |||
498 | respreicen() | ||
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 | */ | ||
544 | killGroup(x, y, me, him) | ||
545 | short 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 | |||
605 | mergeGroup(sGID, myGID) | ||
606 | short 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 | |||
623 | tryPlay(x, y, z) | ||
624 | short 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 | |||
758 | saveState() | ||
759 | { /* saveState */ | ||
760 | playMark = 0; | ||
761 | tryLevel = 0; | ||
762 | newGID = maxGroupID; | ||
763 | } /* saveState */ | ||
764 | |||
765 | /* | ||
766 | undoes a move sequence back to uMark | ||
767 | */ | ||
768 | undoTo(uMark) | ||
769 | short 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 | */ | ||
810 | restoreState() | ||
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 | */ | ||
830 | short saveable(gx, gy, savex, savey) | ||
831 | short 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; | ||
938 | one: | ||
939 | restoreState(); | ||
940 | /* sClearChar(sChar, rXor); */ | ||
941 | return result; | ||
942 | } /* saveable */ | ||
943 | |||
944 | /* | ||
945 | marks unsavable groups as dead | ||
946 | */ | ||
947 | markDead() | ||
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 | */ | ||
971 | MLspan(x, y, saw1, sawm1, size, sMark) | ||
972 | short 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 | |||
993 | short CLspan(x, y, numEyes, who) | ||
994 | short 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 | |||
1028 | short checkLive(x, y) | ||
1029 | short 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 | |||
1041 | markLive() | ||
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 | */ | ||
1079 | genConnects() | ||
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 | */ | ||
1205 | genState() | ||
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 | */ | ||
1232 | short tencen(x, y) | ||
1233 | short 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 | |||
1297 | initGPUtils() | ||
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 | |||
28 | typedef short intBoard[19][19]; /* these were -2 to maxPoint + 2 */ | ||
29 | |||
30 | typedef short boolBoard[19][19]; | ||
31 | |||
32 | typedef struct | ||
33 | { | ||
34 | short px, py; | ||
35 | } point; | ||
36 | |||
37 | typedef struct | ||
38 | { | ||
39 | point p[401]; | ||
40 | short indx; | ||
41 | } pointList; | ||
42 | |||
43 | typedef struct | ||
44 | { | ||
45 | point p[maxSPoint+1]; | ||
46 | short indx; | ||
47 | } sPointList; | ||
48 | |||
49 | typedef struct | ||
50 | { | ||
51 | short indx, | ||
52 | v[401]; | ||
53 | } intList; | ||
54 | |||
55 | typedef struct { short w, s, sm; } sgRec; | ||
56 | |||
57 | typedef struct | ||
58 | { | ||
59 | short groupMark, | ||
60 | atLevel, | ||
61 | isLive, | ||
62 | isDead, | ||
63 | libC, | ||
64 | numEyes, | ||
65 | size, | ||
66 | lx, ly; | ||
67 | } groupRec; | ||
68 | |||
69 | typedef enum {rem, add, chLib, reMap} playType; | ||
70 | |||
71 | typedef struct { short who, xl, yl, nextGID, sNumber; } remAddRec; | ||
72 | typedef struct { short oldLC, oldLevel; } chLibRec; | ||
73 | typedef struct { short oldGID; } reMapRec; | ||
74 | typedef 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 | |||
40 | static const enum bVal computer_color = BLACK; | ||
41 | |||
42 | static int current_handicap = 1; | ||
43 | |||
44 | static QBrush *goBrush; | ||
45 | //static QImage *newBlackStone; | ||
46 | //static QImage *blackStone; | ||
47 | //static QImage *whiteStone; | ||
48 | static QPixmap *newBlackStone; | ||
49 | static QPixmap *blackStone; | ||
50 | static QPixmap *whiteStone; | ||
51 | |||
52 | GoMainWidget::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 | |||
104 | void 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 | |||
115 | GoWidget *GoWidget::self = 0; | ||
116 | |||
117 | GoWidget::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 | |||
145 | GoWidget::~GoWidget() | ||
146 | { | ||
147 | writeConfig(); | ||
148 | } | ||
149 | |||
150 | void 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 | |||
169 | void 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 | |||
194 | void 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 | |||
202 | void 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 | |||
221 | void 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 | |||
265 | void 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 | |||
283 | void GoWidget::pass() | ||
284 | { | ||
285 | if ( !gameActive ) | ||
286 | return; | ||
287 | nPassed++; | ||
288 | if ( nPassed >= 2 ) | ||
289 | endGame(); | ||
290 | else if ( !twoplayer ) | ||
291 | doComputerMove(); | ||
292 | } | ||
293 | |||
294 | void GoWidget::resign() | ||
295 | { | ||
296 | if ( gameActive ) | ||
297 | endGame(); | ||
298 | } | ||
299 | |||
300 | |||
301 | void GoWidget::newGame() | ||
302 | { | ||
303 | init(); | ||
304 | update(); | ||
305 | } | ||
306 | |||
307 | |||
308 | void 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 | |||
324 | void 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 | |||
347 | void 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 | |||
356 | void 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 | |||
366 | void 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 | |||
385 | void GoWidget::mouseReleaseEvent( QMouseEvent * ) | ||
386 | { | ||
387 | if ( gameActive && newX > -1 ) | ||
388 | doMove( newX, newY ); | ||
389 | newX = newY = -1; | ||
390 | } | ||
391 | |||
392 | void 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 | |||
397 | void GoWidget::removeStone(short x, short y) | ||
398 | { | ||
399 | board[x][y]=-1; | ||
400 | refresh( x, y ); | ||
401 | } | ||
402 | |||
403 | void GoWidget::placeStone (enum bVal c, short x, short y ) | ||
404 | { | ||
405 | board[x][y]=c; | ||
406 | refresh( x, y ); | ||
407 | } | ||
408 | |||
409 | void 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 | |||
415 | void GoWidget::setTwoplayer( bool b ) | ||
416 | { | ||
417 | twoplayer = b; | ||
418 | } | ||
419 | |||
420 | void GoWidget::setHandicap( int h ) | ||
421 | { | ||
422 | current_handicap = h; | ||
423 | } | ||
424 | |||
425 | |||
426 | extern "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 | |||
28 | class QToolBar; | ||
29 | |||
30 | class GoMainWidget : public QMainWindow | ||
31 | { | ||
32 | Q_OBJECT | ||
33 | public: | ||
34 | GoMainWidget( QWidget *parent=0, const char* name=0); | ||
35 | protected: | ||
36 | void resizeEvent( QResizeEvent * ); | ||
37 | private: | ||
38 | QToolBar *toolbar; | ||
39 | |||
40 | }; | ||
41 | |||
42 | |||
43 | class QLabel; | ||
44 | class GoWidget : public QWidget | ||
45 | { | ||
46 | Q_OBJECT | ||
47 | public: | ||
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 | |||
57 | public slots: | ||
58 | void pass(); | ||
59 | void resign(); | ||
60 | void newGame(); | ||
61 | void setTwoplayer( bool ); | ||
62 | void setHandicap( int ); | ||
63 | signals: | ||
64 | void showScore( const QString& ); | ||
65 | void showTurn( const QPixmap& ); | ||
66 | |||
67 | protected: | ||
68 | void paintEvent( QPaintEvent * ); | ||
69 | void mousePressEvent( QMouseEvent * ); | ||
70 | void mouseMoveEvent( QMouseEvent * ); | ||
71 | void mouseReleaseEvent( QMouseEvent * ); | ||
72 | void resizeEvent( QResizeEvent * ); | ||
73 | private: | ||
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 | |||
8 | extern intBoard bord, groupIDs; | ||
9 | extern boolBoard legal; | ||
10 | extern groupRec gList[maxGroup]; | ||
11 | extern short gMap[maxGroup], adjInAtari, adj2Libs, playMark, treeLibLim, | ||
12 | utilPlayLevel, killFlag, depthLimit, dbStop, showTrees; | ||
13 | extern 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 | |||
27 | short mtNbrs(x, y) | ||
28 | short 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 | |||
42 | short killTree(tx, ty, gx, gy, escape, tkMark) | ||
43 | short 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 | |||
263 | short tKillTree(tx, ty, gx, gy) | ||
264 | short 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 | |||
272 | short killable(gx, gy, killx, killy) | ||
273 | short 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 | |||
27 | int 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 @@ | |||
1 | Files: bin/go apps/Games/go.desktop | ||
2 | Priority: optional | ||
3 | Section: qpe/games | ||
4 | Maintainer: Warwick Allison <warwick@trolltech.com> | ||
5 | Architecture: arm | ||
6 | Version: $QPE_VERSION-3 | ||
7 | Depends: qpe-base ($QPE_VERSION) | ||
8 | Description: The game of Go | ||
9 | A game for the Qtopia environment. | ||