]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - gomoku/makemove.c
sprinkle static and prune some dead code
[bsdgames-darwin.git] / gomoku / makemove.c
1 /* $NetBSD: makemove.c,v 1.10 2009/06/04 05:43:29 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)makemove.c 8.2 (Berkeley) 5/3/95";
39 #else
40 __RCSID("$NetBSD: makemove.c,v 1.10 2009/06/04 05:43:29 dholland Exp $");
41 #endif
42 #endif /* not lint */
43
44 #include "gomoku.h"
45
46 /* direction deltas */
47 const int dd[4] = {
48 MRIGHT, MRIGHT+MDOWN, MDOWN, MDOWN+MLEFT
49 };
50
51 const int weight[5] = { 0, 1, 7, 22, 100 };
52
53 /*
54 * Return values:
55 * MOVEOK everything is OK.
56 * RESIGN Player resigned.
57 * ILLEGAL Illegal move.
58 * WIN The winning move was just played.
59 * TIE The game is a tie.
60 */
61 int
62 makemove(int us, int mv)
63 {
64 struct spotstr *sp, *fsp;
65 union comboval *cp;
66 struct spotstr *osp;
67 struct combostr *cbp, *cbp1;
68 union comboval *cp1;
69 int i, f, r, d, n;
70 int space, val, bmask;
71
72 /* check for end of game */
73 if (mv == RESIGN)
74 return(RESIGN);
75
76 /* check for illegal move */
77 sp = &board[mv];
78 if (sp->s_occ != EMPTY)
79 return(ILLEGAL);
80
81 /* make move */
82 sp->s_occ = us;
83 movelog[movenum - 1] = mv;
84 if (++movenum == BSZ * BSZ)
85 return(TIE);
86
87 /* compute new frame values */
88 sp->s_wval = 0;
89 osp = sp;
90 for (r = 4; --r >= 0; ) { /* for each direction */
91 d = dd[r];
92 fsp = osp;
93 bmask = BFLAG << r;
94 for (f = 5; --f >= 0; fsp -= d) { /* for each frame */
95 if (fsp->s_occ == BORDER)
96 goto nextr;
97 if (fsp->s_flags & bmask)
98 continue;
99
100 /* remove this frame from the sorted list of frames */
101 cbp = fsp->s_frame[r];
102 if (cbp->c_next) {
103 if (sortframes[BLACK] == cbp)
104 sortframes[BLACK] = cbp->c_next;
105 if (sortframes[WHITE] == cbp)
106 sortframes[WHITE] = cbp->c_next;
107 cbp->c_next->c_prev = cbp->c_prev;
108 cbp->c_prev->c_next = cbp->c_next;
109 }
110
111 /* compute old weight value for this frame */
112 cp = &fsp->s_fval[BLACK][r];
113 if (cp->s <= 0x500)
114 val = weight[5 - cp->c.a - cp->c.b];
115 else
116 val = 0;
117 cp = &fsp->s_fval[WHITE][r];
118 if (cp->s <= 0x500)
119 val += weight[5 - cp->c.a - cp->c.b];
120
121 /* compute new combo value for this frame */
122 sp = fsp;
123 space = sp->s_occ == EMPTY;
124 n = 0;
125 for (i = 5; --i >= 0; sp += d) { /* for each spot */
126 if (sp->s_occ == us)
127 n++;
128 else if (sp->s_occ == EMPTY)
129 sp->s_wval -= val;
130 else {
131 /* this frame is now blocked, adjust values */
132 fsp->s_flags |= bmask;
133 fsp->s_fval[BLACK][r].s = MAXCOMBO;
134 fsp->s_fval[WHITE][r].s = MAXCOMBO;
135 while (--i >= 0) {
136 sp += d;
137 if (sp->s_occ == EMPTY)
138 sp->s_wval -= val;
139 }
140 goto nextf;
141 }
142 }
143
144 /* check for game over */
145 if (n == 5)
146 return(WIN);
147
148 /* compute new value & combo number for this frame & color */
149 fsp->s_fval[!us][r].s = MAXCOMBO;
150 cp = &fsp->s_fval[us][r];
151 /* both ends open? */
152 if (space && sp->s_occ == EMPTY) {
153 cp->c.a = 4 - n;
154 cp->c.b = 1;
155 } else {
156 cp->c.a = 5 - n;
157 cp->c.b = 0;
158 }
159 val = weight[n];
160 sp = fsp;
161 for (i = 5; --i >= 0; sp += d) /* for each spot */
162 if (sp->s_occ == EMPTY)
163 sp->s_wval += val;
164
165 /* add this frame to the sorted list of frames by combo value */
166 cbp1 = sortframes[us];
167 if (!cbp1)
168 sortframes[us] = cbp->c_next = cbp->c_prev = cbp;
169 else {
170 cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
171 if (cp->s <= cp1->s) {
172 /* insert at the head of the list */
173 sortframes[us] = cbp;
174 } else {
175 do {
176 cbp1 = cbp1->c_next;
177 cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
178 if (cp->s <= cp1->s)
179 break;
180 } while (cbp1 != sortframes[us]);
181 }
182 cbp->c_next = cbp1;
183 cbp->c_prev = cbp1->c_prev;
184 cbp1->c_prev->c_next = cbp;
185 cbp1->c_prev = cbp;
186 }
187
188 nextf:
189 ;
190 }
191
192 /* both ends open? */
193 if (fsp->s_occ == EMPTY) {
194 cp = &fsp->s_fval[BLACK][r];
195 if (cp->c.b) {
196 cp->c.a += 1;
197 cp->c.b = 0;
198 }
199 cp = &fsp->s_fval[WHITE][r];
200 if (cp->c.b) {
201 cp->c.a += 1;
202 cp->c.b = 0;
203 }
204 }
205
206 nextr:
207 ;
208 }
209
210 update_overlap(osp);
211
212 return(MOVEOK);
213 }
214
215 /*
216 * fix up the overlap array due to updating spot osp.
217 */
218 void
219 update_overlap(struct spotstr *osp)
220 {
221 struct spotstr *sp, *sp1, *sp2;
222 int i, f, r, r1, d, d1, n;
223 int a, b, bmask, bmask1;
224 struct spotstr *esp;
225 u_char *str;
226
227 esp = NULL;
228 for (r = 4; --r >= 0; ) { /* for each direction */
229 d = dd[r];
230 sp1 = osp;
231 bmask = BFLAG << r;
232 for (f = 0; f < 6; f++, sp1 -= d) { /* for each frame */
233 if (sp1->s_occ == BORDER)
234 break;
235 if (sp1->s_flags & bmask)
236 continue;
237 /*
238 * Update all other frames that intersect the current one
239 * to indicate whether they still overlap or not.
240 * Since F1 overlap F2 == F2 overlap F1, we only need to
241 * do the rows 0 <= r1 <= r. The r1 == r case is special
242 * since the two frames can overlap at more than one point.
243 */
244 str = &overlap[(a = sp1->s_frame[r] - frames) * FAREA];
245 sp2 = sp1 - d;
246 for (i = f + 1; i < 6; i++, sp2 -= d) {
247 if (sp2->s_occ == BORDER)
248 break;
249 if (sp2->s_flags & bmask)
250 continue;
251 /*
252 * count the number of empty spots to see if there is
253 * still an overlap.
254 */
255 n = 0;
256 sp = sp1;
257 for (b = i - f; b < 5; b++, sp += d) {
258 if (sp->s_occ == EMPTY) {
259 esp = sp; /* save the intersection point */
260 n++;
261 }
262 }
263 b = sp2->s_frame[r] - frames;
264 if (n == 0) {
265 if (sp->s_occ == EMPTY) {
266 str[b] &= 0xA;
267 overlap[b * FAREA + a] &= 0xC;
268 intersect[a * FAREA + b] = n = sp - board;
269 intersect[b * FAREA + a] = n;
270 } else {
271 str[b] = 0;
272 overlap[b * FAREA + a] = 0;
273 }
274 } else if (n == 1) {
275 if (sp->s_occ == EMPTY) {
276 str[b] &= 0xAF;
277 overlap[b * FAREA + a] &= 0xCF;
278 } else {
279 str[b] &= 0xF;
280 overlap[b * FAREA + a] &= 0xF;
281 }
282 intersect[a * FAREA + b] = n = esp - board;
283 intersect[b * FAREA + a] = n;
284 }
285 /* else no change, still multiple overlap */
286 }
287
288 /* the other directions can only intersect at spot osp */
289 for (r1 = r; --r1 >= 0; ) {
290 d1 = dd[r1];
291 bmask1 = BFLAG << r1;
292 sp = osp;
293 for (i = 6; --i >= 0; sp -= d1) { /* for each spot */
294 if (sp->s_occ == BORDER)
295 break;
296 if (sp->s_flags & bmask1)
297 continue;
298 b = sp->s_frame[r1] - frames;
299 str[b] = 0;
300 overlap[b * FAREA + a] = 0;
301 }
302 }
303 }
304 }
305 }