Sync usage with man page.
[netbsd-mini2440.git] / games / gomoku / makemove.c
blob592449ab752ee709d7309eab86aa4f831e8ec016
1 /* $NetBSD: makemove.c,v 1.10 2009/06/04 05:43:29 dholland Exp $ */
3 /*
4 * Copyright (c) 1994
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell.
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.
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.
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 */
44 #include "gomoku.h"
46 /* direction deltas */
47 const int dd[4] = {
48 MRIGHT, MRIGHT+MDOWN, MDOWN, MDOWN+MLEFT
51 static const int weight[5] = { 0, 1, 7, 22, 100 };
53 static void update_overlap(struct spotstr *);
56 * Return values:
57 * MOVEOK everything is OK.
58 * RESIGN Player resigned.
59 * ILLEGAL Illegal move.
60 * WIN The winning move was just played.
61 * TIE The game is a tie.
63 int
64 makemove(int us, int mv)
66 struct spotstr *sp, *fsp;
67 union comboval *cp;
68 struct spotstr *osp;
69 struct combostr *cbp, *cbp1;
70 union comboval *cp1;
71 int i, f, r, d, n;
72 int space, val, bmask;
74 /* check for end of game */
75 if (mv == RESIGN)
76 return(RESIGN);
78 /* check for illegal move */
79 sp = &board[mv];
80 if (sp->s_occ != EMPTY)
81 return(ILLEGAL);
83 /* make move */
84 sp->s_occ = us;
85 movelog[movenum - 1] = mv;
86 if (++movenum == BSZ * BSZ)
87 return(TIE);
89 /* compute new frame values */
90 sp->s_wval = 0;
91 osp = sp;
92 for (r = 4; --r >= 0; ) { /* for each direction */
93 d = dd[r];
94 fsp = osp;
95 bmask = BFLAG << r;
96 for (f = 5; --f >= 0; fsp -= d) { /* for each frame */
97 if (fsp->s_occ == BORDER)
98 goto nextr;
99 if (fsp->s_flags & bmask)
100 continue;
102 /* remove this frame from the sorted list of frames */
103 cbp = fsp->s_frame[r];
104 if (cbp->c_next) {
105 if (sortframes[BLACK] == cbp)
106 sortframes[BLACK] = cbp->c_next;
107 if (sortframes[WHITE] == cbp)
108 sortframes[WHITE] = cbp->c_next;
109 cbp->c_next->c_prev = cbp->c_prev;
110 cbp->c_prev->c_next = cbp->c_next;
113 /* compute old weight value for this frame */
114 cp = &fsp->s_fval[BLACK][r];
115 if (cp->s <= 0x500)
116 val = weight[5 - cp->c.a - cp->c.b];
117 else
118 val = 0;
119 cp = &fsp->s_fval[WHITE][r];
120 if (cp->s <= 0x500)
121 val += weight[5 - cp->c.a - cp->c.b];
123 /* compute new combo value for this frame */
124 sp = fsp;
125 space = sp->s_occ == EMPTY;
126 n = 0;
127 for (i = 5; --i >= 0; sp += d) { /* for each spot */
128 if (sp->s_occ == us)
129 n++;
130 else if (sp->s_occ == EMPTY)
131 sp->s_wval -= val;
132 else {
133 /* this frame is now blocked, adjust values */
134 fsp->s_flags |= bmask;
135 fsp->s_fval[BLACK][r].s = MAXCOMBO;
136 fsp->s_fval[WHITE][r].s = MAXCOMBO;
137 while (--i >= 0) {
138 sp += d;
139 if (sp->s_occ == EMPTY)
140 sp->s_wval -= val;
142 goto nextf;
146 /* check for game over */
147 if (n == 5)
148 return(WIN);
150 /* compute new value & combo number for this frame & color */
151 fsp->s_fval[!us][r].s = MAXCOMBO;
152 cp = &fsp->s_fval[us][r];
153 /* both ends open? */
154 if (space && sp->s_occ == EMPTY) {
155 cp->c.a = 4 - n;
156 cp->c.b = 1;
157 } else {
158 cp->c.a = 5 - n;
159 cp->c.b = 0;
161 val = weight[n];
162 sp = fsp;
163 for (i = 5; --i >= 0; sp += d) /* for each spot */
164 if (sp->s_occ == EMPTY)
165 sp->s_wval += val;
167 /* add this frame to the sorted list of frames by combo value */
168 cbp1 = sortframes[us];
169 if (!cbp1)
170 sortframes[us] = cbp->c_next = cbp->c_prev = cbp;
171 else {
172 cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
173 if (cp->s <= cp1->s) {
174 /* insert at the head of the list */
175 sortframes[us] = cbp;
176 } else {
177 do {
178 cbp1 = cbp1->c_next;
179 cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
180 if (cp->s <= cp1->s)
181 break;
182 } while (cbp1 != sortframes[us]);
184 cbp->c_next = cbp1;
185 cbp->c_prev = cbp1->c_prev;
186 cbp1->c_prev->c_next = cbp;
187 cbp1->c_prev = cbp;
190 nextf:
194 /* both ends open? */
195 if (fsp->s_occ == EMPTY) {
196 cp = &fsp->s_fval[BLACK][r];
197 if (cp->c.b) {
198 cp->c.a += 1;
199 cp->c.b = 0;
201 cp = &fsp->s_fval[WHITE][r];
202 if (cp->c.b) {
203 cp->c.a += 1;
204 cp->c.b = 0;
208 nextr:
212 update_overlap(osp);
214 return(MOVEOK);
218 * fix up the overlap array due to updating spot osp.
220 static void
221 update_overlap(struct spotstr *osp)
223 struct spotstr *sp, *sp1, *sp2;
224 int i, f, r, r1, d, d1, n;
225 int a, b, bmask, bmask1;
226 struct spotstr *esp;
227 u_char *str;
229 esp = NULL;
230 for (r = 4; --r >= 0; ) { /* for each direction */
231 d = dd[r];
232 sp1 = osp;
233 bmask = BFLAG << r;
234 for (f = 0; f < 6; f++, sp1 -= d) { /* for each frame */
235 if (sp1->s_occ == BORDER)
236 break;
237 if (sp1->s_flags & bmask)
238 continue;
240 * Update all other frames that intersect the current one
241 * to indicate whether they still overlap or not.
242 * Since F1 overlap F2 == F2 overlap F1, we only need to
243 * do the rows 0 <= r1 <= r. The r1 == r case is special
244 * since the two frames can overlap at more than one point.
246 str = &overlap[(a = sp1->s_frame[r] - frames) * FAREA];
247 sp2 = sp1 - d;
248 for (i = f + 1; i < 6; i++, sp2 -= d) {
249 if (sp2->s_occ == BORDER)
250 break;
251 if (sp2->s_flags & bmask)
252 continue;
254 * count the number of empty spots to see if there is
255 * still an overlap.
257 n = 0;
258 sp = sp1;
259 for (b = i - f; b < 5; b++, sp += d) {
260 if (sp->s_occ == EMPTY) {
261 esp = sp; /* save the intersection point */
262 n++;
265 b = sp2->s_frame[r] - frames;
266 if (n == 0) {
267 if (sp->s_occ == EMPTY) {
268 str[b] &= 0xA;
269 overlap[b * FAREA + a] &= 0xC;
270 intersect[a * FAREA + b] = n = sp - board;
271 intersect[b * FAREA + a] = n;
272 } else {
273 str[b] = 0;
274 overlap[b * FAREA + a] = 0;
276 } else if (n == 1) {
277 if (sp->s_occ == EMPTY) {
278 str[b] &= 0xAF;
279 overlap[b * FAREA + a] &= 0xCF;
280 } else {
281 str[b] &= 0xF;
282 overlap[b * FAREA + a] &= 0xF;
284 intersect[a * FAREA + b] = n = esp - board;
285 intersect[b * FAREA + a] = n;
287 /* else no change, still multiple overlap */
290 /* the other directions can only intersect at spot osp */
291 for (r1 = r; --r1 >= 0; ) {
292 d1 = dd[r1];
293 bmask1 = BFLAG << r1;
294 sp = osp;
295 for (i = 6; --i >= 0; sp -= d1) { /* for each spot */
296 if (sp->s_occ == BORDER)
297 break;
298 if (sp->s_flags & bmask1)
299 continue;
300 b = sp->s_frame[r1] - frames;
301 str[b] = 0;
302 overlap[b * FAREA + a] = 0;