Sat May 28 05:44:41 2022 UTC ()
gomoku: extract separate function update_overlap_same_direction

No functional change.


(rillig)
diff -r1.27 -r1.28 src/games/gomoku/makemove.c

cvs diff -r1.27 -r1.28 src/games/gomoku/makemove.c (expand / switch to unified diff)

--- src/games/gomoku/makemove.c 2022/05/28 05:14:34 1.27
+++ src/games/gomoku/makemove.c 2022/05/28 05:44:41 1.28
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: makemove.c,v 1.27 2022/05/28 05:14:34 rillig Exp $ */ 1/* $NetBSD: makemove.c,v 1.28 2022/05/28 05:44:41 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994 4 * Copyright (c) 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell. 8 * Ralph Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36/* @(#)makemove.c 8.2 (Berkeley) 5/3/95 */ 36/* @(#)makemove.c 8.2 (Berkeley) 5/3/95 */
37__RCSID("$NetBSD: makemove.c,v 1.27 2022/05/28 05:14:34 rillig Exp $"); 37__RCSID("$NetBSD: makemove.c,v 1.28 2022/05/28 05:44:41 rillig Exp $");
38 38
39#include "gomoku.h" 39#include "gomoku.h"
40 40
41 /* direction deltas */ 41 /* direction deltas */
42const int dd[4] = { 42const int dd[4] = {
43 1, /* right */ 43 1, /* right */
44 -(BSZ + 1) + 1, /* down + right */ 44 -(BSZ + 1) + 1, /* down + right */
45 -(BSZ + 1), /* down */ 45 -(BSZ + 1), /* down */
46 -(BSZ + 1) - 1 /* down + left */ 46 -(BSZ + 1) - 1 /* down + left */
47}; 47};
48 48
49static const int weight[5] = { 0, 1, 7, 22, 100 }; 49static const int weight[5] = { 0, 1, 7, 22, 100 };
50 50
@@ -67,30 +67,29 @@ makemove(int us, int mv) @@ -67,30 +67,29 @@ makemove(int us, int mv)
67 return RESIGN; 67 return RESIGN;
68 68
69 /* check for illegal move */ 69 /* check for illegal move */
70 struct spotstr *sp = &board[mv]; 70 struct spotstr *sp = &board[mv];
71 if (sp->s_occ != EMPTY) 71 if (sp->s_occ != EMPTY)
72 return ILLEGAL; 72 return ILLEGAL;
73 73
74 /* make move */ 74 /* make move */
75 sp->s_occ = us; 75 sp->s_occ = us;
76 movelog[nmoves++] = mv; 76 movelog[nmoves++] = mv;
77 77
78 /* compute new frame values */ 78 /* compute new frame values */
79 sp->s_wval = 0; 79 sp->s_wval = 0;
80 struct spotstr *osp = sp; 
81 for (int r = 4; --r >= 0; ) { /* for each direction */ 80 for (int r = 4; --r >= 0; ) { /* for each direction */
82 int d = dd[r]; 81 int d = dd[r];
83 struct spotstr *fsp = osp; 82 struct spotstr *fsp = &board[mv];
84 int bmask = BFLAG << r; 83 int bmask = BFLAG << r;
85 84
86 for (int f = 5; --f >= 0; fsp -= d) { /* for each frame */ 85 for (int f = 5; --f >= 0; fsp -= d) { /* for each frame */
87 if (fsp->s_occ == BORDER) 86 if (fsp->s_occ == BORDER)
88 goto nextr; 87 goto nextr;
89 if ((fsp->s_flags & bmask) != 0) 88 if ((fsp->s_flags & bmask) != 0)
90 continue; 89 continue;
91 90
92 /* remove this frame from the sorted list of frames */ 91 /* remove this frame from the sorted list of frames */
93 struct combostr *cbp = fsp->s_frame[r]; 92 struct combostr *cbp = fsp->s_frame[r];
94 if (cbp->c_next != NULL) { 93 if (cbp->c_next != NULL) {
95 if (sortframes[BLACK] == cbp) 94 if (sortframes[BLACK] == cbp)
96 sortframes[BLACK] = cbp->c_next; 95 sortframes[BLACK] = cbp->c_next;
@@ -188,107 +187,117 @@ makemove(int us, int mv) @@ -188,107 +187,117 @@ makemove(int us, int mv)
188 cp->cv_win = 0; 187 cp->cv_win = 0;
189 } 188 }
190 cp = &fsp->s_fval[WHITE][r]; 189 cp = &fsp->s_fval[WHITE][r];
191 if (cp->cv_win != 0) { 190 if (cp->cv_win != 0) {
192 cp->cv_force++; 191 cp->cv_force++;
193 cp->cv_win = 0; 192 cp->cv_win = 0;
194 } 193 }
195 } 194 }
196 195
197 nextr: 196 nextr:
198 ; 197 ;
199 } 198 }
200 199
201 update_overlap(osp); 200 update_overlap(&board[mv]);
202 201
203 /* 202 /*
204 * TODO: Declare a tie as soon as all frames are blocked. This is 203 * TODO: Declare a tie as soon as all frames are blocked. This is
205 * usually much earlier than when the whole board is filled. 204 * usually much earlier than when the whole board is filled.
206 */ 205 */
207 if (nmoves == BSZ * BSZ) 206 if (nmoves == BSZ * BSZ)
208 return TIE; 207 return TIE;
209 208
210 return MOVEOK; 209 return MOVEOK;
211} 210}
212 211
 212static void
 213update_overlap_same_direction(const struct spotstr *sp1,
 214 const struct spotstr *sp2,
 215 int a, int d, int i_minus_f, int r)
 216{
 217 /*
 218 * count the number of empty spots to see if there is
 219 * still an overlap.
 220 */
 221 int n = 0;
 222 const struct spotstr *sp = sp1;
 223 const struct spotstr *esp = NULL;
 224 for (int b = i_minus_f; b < 5; b++, sp += d) {
 225 if (sp->s_occ == EMPTY) {
 226 esp = sp; /* save the intersection point */
 227 n++;
 228 }
 229 }
 230
 231 int b = (int)(sp2->s_frame[r] - frames);
 232 if (n == 0) {
 233 if (sp->s_occ == EMPTY) {
 234 overlap[a * FAREA + b] &= 0xA;
 235 overlap[b * FAREA + a] &= 0xC;
 236 intersect[a * FAREA + b] = (short)(sp - board);
 237 intersect[b * FAREA + a] = (short)(sp - board);
 238 } else {
 239 overlap[a * FAREA + b] = 0;
 240 overlap[b * FAREA + a] = 0;
 241 }
 242 } else if (n == 1) {
 243 if (sp->s_occ == EMPTY) {
 244 overlap[a * FAREA + b] &= 0xAF;
 245 overlap[b * FAREA + a] &= 0xCF;
 246 } else {
 247 overlap[a * FAREA + b] &= 0xF;
 248 overlap[b * FAREA + a] &= 0xF;
 249 }
 250 intersect[a * FAREA + b] = (short)(esp - board);
 251 intersect[b * FAREA + a] = (short)(esp - board);
 252 }
 253 /* else no change, still multiple overlap */
 254}
 255
213/* 256/*
214 * fix up the overlap array due to updating spot osp. 257 * fix up the overlap array according to the changed 'osp'.
215 */ 258 */
216static void 259static void
217update_overlap(struct spotstr *osp) 260update_overlap(struct spotstr *osp)
218{ 261{
219 262
220 for (int r = 4; --r >= 0; ) { /* for each direction */ 263 for (int r = 4; --r >= 0; ) { /* for each direction */
221 int d = dd[r]; 264 int d = dd[r];
222 struct spotstr *sp1 = osp; 265 struct spotstr *sp1 = osp;
223 266
224 for (int f = 0; f < 6; f++, sp1 -= d) { /* for each frame */ 267 /* for each frame that contains 'osp' */
 268 for (int f = 0; f < 6; f++, sp1 -= d) {
225 if (sp1->s_occ == BORDER) 269 if (sp1->s_occ == BORDER)
226 break; 270 break;
227 if ((sp1->s_flags & BFLAG << r) != 0) 271 if ((sp1->s_flags & BFLAG << r) != 0)
228 continue; 272 continue;
 273
229 /* 274 /*
230 * Update all other frames that intersect the current one 275 * Update all other frames that intersect the current one
231 * to indicate whether they still overlap or not. 276 * to indicate whether they still overlap or not.
232 * Since F1 overlap F2 == F2 overlap F1, we only need to 277 * Since F1 overlap F2 == F2 overlap F1, we only need to
233 * do the rows 0 <= r1 <= r. The r1 == r case is special 278 * do the rows 0 <= r1 <= r. The r1 == r case is special
234 * since the two frames can overlap at more than one point. 279 * since the two frames can overlap at more than one point.
235 */ 280 */
236 int a = (int)(sp1->s_frame[r] - frames); 281 int a = (int)(sp1->s_frame[r] - frames);
237 struct spotstr *sp2 = sp1 - d; 282 struct spotstr *sp2 = sp1 - d;
238 283
239 for (int i = f + 1; i < 6; i++, sp2 -= d) { 284 for (int i = f + 1; i < 6; i++, sp2 -= d) {
240 if (sp2->s_occ == BORDER) 285 if (sp2->s_occ == BORDER)
241 break; 286 break;
242 if ((sp2->s_flags & BFLAG << r) != 0) 287 if ((sp2->s_flags & BFLAG << r) != 0)
243 continue; 288 continue;
244 289
245 /* 290 update_overlap_same_direction(sp1, sp2, a, d, i - f, r);
246 * count the number of empty spots to see if there is 
247 * still an overlap. 
248 */ 
249 int n = 0; 
250 struct spotstr *sp = sp1; 
251 struct spotstr *esp = NULL; 
252 for (int b = i - f; b < 5; b++, sp += d) { 
253 if (sp->s_occ == EMPTY) { 
254 esp = sp; /* save the intersection point */ 
255 n++; 
256 } 
257 } 
258 
259 int b = (int)(sp2->s_frame[r] - frames); 
260 if (n == 0) { 
261 if (sp->s_occ == EMPTY) { 
262 overlap[a * FAREA + b] &= 0xA; 
263 overlap[b * FAREA + a] &= 0xC; 
264 intersect[a * FAREA + b] = (short)(sp - board); 
265 intersect[b * FAREA + a] = (short)(sp - board); 
266 } else { 
267 overlap[a * FAREA + b] = 0; 
268 overlap[b * FAREA + a] = 0; 
269 } 
270 } else if (n == 1) { 
271 if (sp->s_occ == EMPTY) { 
272 overlap[a * FAREA + b] &= 0xAF; 
273 overlap[b * FAREA + a] &= 0xCF; 
274 } else { 
275 overlap[a * FAREA + b] &= 0xF; 
276 overlap[b * FAREA + a] &= 0xF; 
277 } 
278 intersect[a * FAREA + b] = (short)(esp - board); 
279 intersect[b * FAREA + a] = (short)(esp - board); 
280 } 
281 /* else no change, still multiple overlap */ 
282 } 291 }
283 292
284 /* the other directions can only intersect at spot osp */ 293 /* the other directions can only intersect at spot osp */
285 for (int r1 = r; --r1 >= 0; ) { 294 for (int r1 = r; --r1 >= 0; ) {
286 int d1 = dd[r1]; 295 int d1 = dd[r1];
287 struct spotstr *sp = osp; 296 struct spotstr *sp = osp;
288 for (int i = 6; --i >= 0; sp -= d1) { /* for each spot */ 297 for (int i = 6; --i >= 0; sp -= d1) { /* for each spot */
289 if (sp->s_occ == BORDER) 298 if (sp->s_occ == BORDER)
290 break; 299 break;
291 if ((sp->s_flags & BFLAG << r1) != 0) 300 if ((sp->s_flags & BFLAG << r1) != 0)
292 continue; 301 continue;
293 int b = (int)(sp->s_frame[r1] - frames); 302 int b = (int)(sp->s_frame[r1] - frames);
294 overlap[a * FAREA + b] = 0; 303 overlap[a * FAREA + b] = 0;