makemove.c revision 1.8
1/* $NetBSD: makemove.c,v 1.8 2006/05/11 00:17:07 mrg 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 38static char sccsid[] = "@(#)makemove.c 8.2 (Berkeley) 5/3/95"; 39#else 40__RCSID("$NetBSD: makemove.c,v 1.8 2006/05/11 00:17:07 mrg Exp $"); 41#endif 42#endif /* not lint */ 43 44#include "gomoku.h" 45 46 /* direction deltas */ 47const int dd[4] = { 48 MRIGHT, MRIGHT+MDOWN, MDOWN, MDOWN+MLEFT 49}; 50 51const 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 */ 61int 62makemove(us, mv) 63 int us, mv; 64{ 65 struct spotstr *sp, *fsp; 66 union comboval *cp; 67 struct spotstr *osp; 68 struct combostr *cbp, *cbp1; 69 union comboval *cp1; 70 int i, f, r, d, n; 71 int space, val, bmask; 72 73 /* check for end of game */ 74 if (mv == RESIGN) 75 return(RESIGN); 76 77 /* check for illegal move */ 78 sp = &board[mv]; 79 if (sp->s_occ != EMPTY) 80 return(ILLEGAL); 81 82 /* make move */ 83 sp->s_occ = us; 84 movelog[movenum - 1] = mv; 85 if (++movenum == BSZ * BSZ) 86 return(TIE); 87 88 /* compute new frame values */ 89 sp->s_wval = 0; 90 osp = sp; 91 for (r = 4; --r >= 0; ) { /* for each direction */ 92 d = dd[r]; 93 fsp = osp; 94 bmask = BFLAG << r; 95 for (f = 5; --f >= 0; fsp -= d) { /* for each frame */ 96 if (fsp->s_occ == BORDER) 97 goto nextr; 98 if (fsp->s_flg & bmask) 99 continue; 100 101 /* remove this frame from the sorted list of frames */ 102 cbp = fsp->s_frame[r]; 103 if (cbp->c_next) { 104 if (sortframes[BLACK] == cbp) 105 sortframes[BLACK] = cbp->c_next; 106 if (sortframes[WHITE] == cbp) 107 sortframes[WHITE] = cbp->c_next; 108 cbp->c_next->c_prev = cbp->c_prev; 109 cbp->c_prev->c_next = cbp->c_next; 110 } 111 112 /* compute old weight value for this frame */ 113 cp = &fsp->s_fval[BLACK][r]; 114 if (cp->s <= 0x500) 115 val = weight[5 - cp->c.a - cp->c.b]; 116 else 117 val = 0; 118 cp = &fsp->s_fval[WHITE][r]; 119 if (cp->s <= 0x500) 120 val += weight[5 - cp->c.a - cp->c.b]; 121 122 /* compute new combo value for this frame */ 123 sp = fsp; 124 space = sp->s_occ == EMPTY; 125 n = 0; 126 for (i = 5; --i >= 0; sp += d) { /* for each spot */ 127 if (sp->s_occ == us) 128 n++; 129 else if (sp->s_occ == EMPTY) 130 sp->s_wval -= val; 131 else { 132 /* this frame is now blocked, adjust values */ 133 fsp->s_flg |= bmask; 134 fsp->s_fval[BLACK][r].s = MAXCOMBO; 135 fsp->s_fval[WHITE][r].s = MAXCOMBO; 136 while (--i >= 0) { 137 sp += d; 138 if (sp->s_occ == EMPTY) 139 sp->s_wval -= val; 140 } 141 goto nextf; 142 } 143 } 144 145 /* check for game over */ 146 if (n == 5) 147 return(WIN); 148 149 /* compute new value & combo number for this frame & color */ 150 fsp->s_fval[!us][r].s = MAXCOMBO; 151 cp = &fsp->s_fval[us][r]; 152 /* both ends open? */ 153 if (space && sp->s_occ == EMPTY) { 154 cp->c.a = 4 - n; 155 cp->c.b = 1; 156 } else { 157 cp->c.a = 5 - n; 158 cp->c.b = 0; 159 } 160 val = weight[n]; 161 sp = fsp; 162 for (i = 5; --i >= 0; sp += d) /* for each spot */ 163 if (sp->s_occ == EMPTY) 164 sp->s_wval += val; 165 166 /* add this frame to the sorted list of frames by combo value */ 167 cbp1 = sortframes[us]; 168 if (!cbp1) 169 sortframes[us] = cbp->c_next = cbp->c_prev = cbp; 170 else { 171 cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir]; 172 if (cp->s <= cp1->s) { 173 /* insert at the head of the list */ 174 sortframes[us] = cbp; 175 } else { 176 do { 177 cbp1 = cbp1->c_next; 178 cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir]; 179 if (cp->s <= cp1->s) 180 break; 181 } while (cbp1 != sortframes[us]); 182 } 183 cbp->c_next = cbp1; 184 cbp->c_prev = cbp1->c_prev; 185 cbp1->c_prev->c_next = cbp; 186 cbp1->c_prev = cbp; 187 } 188 189 nextf: 190 ; 191 } 192 193 /* both ends open? */ 194 if (fsp->s_occ == EMPTY) { 195 cp = &fsp->s_fval[BLACK][r]; 196 if (cp->c.b) { 197 cp->c.a += 1; 198 cp->c.b = 0; 199 } 200 cp = &fsp->s_fval[WHITE][r]; 201 if (cp->c.b) { 202 cp->c.a += 1; 203 cp->c.b = 0; 204 } 205 } 206 207 nextr: 208 ; 209 } 210 211 update_overlap(osp); 212 213 return(MOVEOK); 214} 215 216/* 217 * fix up the overlap array due to updating spot osp. 218 */ 219void 220update_overlap(osp) 221 struct spotstr *osp; 222{ 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; 228 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_flg & bmask) 238 continue; 239 /* 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. 245 */ 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_flg & bmask) 252 continue; 253 /* 254 * count the number of empty spots to see if there is 255 * still an overlap. 256 */ 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++; 263 } 264 } 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; 275 } 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; 283 } 284 intersect[a * FAREA + b] = n = esp - board; 285 intersect[b * FAREA + a] = n; 286 } 287 /* else no change, still multiple overlap */ 288 } 289 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_flg & bmask1) 299 continue; 300 b = sp->s_frame[r1] - frames; 301 str[b] = 0; 302 overlap[b * FAREA + a] = 0; 303 } 304 } 305 } 306 } 307} 308