1 1.37 rillig /* $NetBSD: bdinit.c,v 1.37 2022/06/19 10:33:17 rillig Exp $ */ 2 1.3 cgd 3 1.1 tls /* 4 1.1 tls * Copyright (c) 1994 5 1.1 tls * The Regents of the University of California. All rights reserved. 6 1.1 tls * 7 1.1 tls * This code is derived from software contributed to Berkeley by 8 1.1 tls * Ralph Campbell. 9 1.1 tls * 10 1.1 tls * Redistribution and use in source and binary forms, with or without 11 1.1 tls * modification, are permitted provided that the following conditions 12 1.1 tls * are met: 13 1.1 tls * 1. Redistributions of source code must retain the above copyright 14 1.1 tls * notice, this list of conditions and the following disclaimer. 15 1.1 tls * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 tls * notice, this list of conditions and the following disclaimer in the 17 1.1 tls * documentation and/or other materials provided with the distribution. 18 1.5 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 tls * may be used to endorse or promote products derived from this software 20 1.1 tls * without specific prior written permission. 21 1.1 tls * 22 1.1 tls * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 tls * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 tls * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 tls * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 tls * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 tls * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 tls * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 tls * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 tls * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 tls * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 tls * SUCH DAMAGE. 33 1.1 tls */ 34 1.1 tls 35 1.4 lukem #include <sys/cdefs.h> 36 1.18 rillig /* from: @(#)bdinit.c 8.2 (Berkeley) 5/3/95 */ 37 1.37 rillig __RCSID("$NetBSD: bdinit.c,v 1.37 2022/06/19 10:33:17 rillig Exp $"); 38 1.1 tls 39 1.1 tls #include <string.h> 40 1.1 tls #include "gomoku.h" 41 1.1 tls 42 1.8 dholland static void init_overlap(void); 43 1.8 dholland 44 1.25 rillig static void 45 1.34 rillig init_spot_flags_and_fval(struct spotstr *sp, int col, int row) 46 1.25 rillig { 47 1.25 rillig 48 1.25 rillig sp->s_flags = 0; 49 1.34 rillig if (row < 5) { 50 1.36 rillig set_blocked(sp, DIR_DR); 51 1.36 rillig set_blocked(sp, DIR_D_); 52 1.36 rillig set_blocked(sp, DIR_DL); 53 1.36 rillig sp->s_fval[BLACK][DIR_DR].s = 0x600; 54 1.36 rillig sp->s_fval[BLACK][DIR_D_].s = 0x600; 55 1.36 rillig sp->s_fval[BLACK][DIR_DL].s = 0x600; 56 1.36 rillig sp->s_fval[WHITE][DIR_DR].s = 0x600; 57 1.36 rillig sp->s_fval[WHITE][DIR_D_].s = 0x600; 58 1.36 rillig sp->s_fval[WHITE][DIR_DL].s = 0x600; 59 1.34 rillig } else if (row == 5) { 60 1.25 rillig /* five spaces, blocked on one side */ 61 1.36 rillig sp->s_fval[BLACK][DIR_DR].s = 0x500; 62 1.36 rillig sp->s_fval[BLACK][DIR_D_].s = 0x500; 63 1.36 rillig sp->s_fval[BLACK][DIR_DL].s = 0x500; 64 1.36 rillig sp->s_fval[WHITE][DIR_DR].s = 0x500; 65 1.36 rillig sp->s_fval[WHITE][DIR_D_].s = 0x500; 66 1.36 rillig sp->s_fval[WHITE][DIR_DL].s = 0x500; 67 1.25 rillig } else { 68 1.25 rillig /* six spaces, not blocked */ 69 1.36 rillig sp->s_fval[BLACK][DIR_DR].s = 0x401; 70 1.36 rillig sp->s_fval[BLACK][DIR_D_].s = 0x401; 71 1.36 rillig sp->s_fval[BLACK][DIR_DL].s = 0x401; 72 1.36 rillig sp->s_fval[WHITE][DIR_DR].s = 0x401; 73 1.36 rillig sp->s_fval[WHITE][DIR_D_].s = 0x401; 74 1.36 rillig sp->s_fval[WHITE][DIR_DL].s = 0x401; 75 1.25 rillig } 76 1.37 rillig if (col > BSZ - 4) { 77 1.36 rillig set_blocked(sp, DIR__R); 78 1.36 rillig set_blocked(sp, DIR_DR); 79 1.36 rillig sp->s_fval[BLACK][DIR__R].s = 0x600; 80 1.36 rillig sp->s_fval[BLACK][DIR_DR].s = 0x600; 81 1.36 rillig sp->s_fval[WHITE][DIR__R].s = 0x600; 82 1.36 rillig sp->s_fval[WHITE][DIR_DR].s = 0x600; 83 1.37 rillig } else if (col == BSZ - 4) { 84 1.36 rillig sp->s_fval[BLACK][DIR__R].s = 0x500; 85 1.36 rillig sp->s_fval[WHITE][DIR__R].s = 0x500; 86 1.36 rillig if (!is_blocked(sp, DIR_DR)) { 87 1.36 rillig sp->s_fval[BLACK][DIR_DR].s = 0x500; 88 1.36 rillig sp->s_fval[WHITE][DIR_DR].s = 0x500; 89 1.25 rillig } 90 1.25 rillig } else { 91 1.36 rillig sp->s_fval[BLACK][DIR__R].s = 0x401; 92 1.36 rillig sp->s_fval[WHITE][DIR__R].s = 0x401; 93 1.34 rillig if (col < 5) { 94 1.36 rillig set_blocked(sp, DIR_DL); 95 1.36 rillig sp->s_fval[BLACK][DIR_DL].s = 0x600; 96 1.36 rillig sp->s_fval[WHITE][DIR_DL].s = 0x600; 97 1.36 rillig } else if (col == 5 && !is_blocked(sp, DIR_DL)) { 98 1.36 rillig sp->s_fval[BLACK][DIR_DL].s = 0x500; 99 1.36 rillig sp->s_fval[WHITE][DIR_DL].s = 0x500; 100 1.25 rillig } 101 1.25 rillig } 102 1.25 rillig } 103 1.25 rillig 104 1.25 rillig /* Allocate one of the pre-allocated frames for each non-blocked frame. */ 105 1.25 rillig static void 106 1.30 rillig init_spot_frame(struct spotstr *sp, frame_index *fip) 107 1.25 rillig { 108 1.25 rillig 109 1.32 rillig for (direction r = 4; r-- > 0; ) { 110 1.36 rillig if (is_blocked(sp, r)) 111 1.25 rillig continue; 112 1.25 rillig 113 1.30 rillig frame_index fi = (*fip)++; 114 1.30 rillig sp->s_frame[r] = fi; 115 1.30 rillig 116 1.30 rillig struct combostr *cbp = &frames[fi]; 117 1.25 rillig cbp->c_combo.s = sp->s_fval[BLACK][r].s; 118 1.31 rillig cbp->c_vertex = (spot_index)(sp - board); 119 1.25 rillig cbp->c_nframes = 1; 120 1.25 rillig cbp->c_dir = r; 121 1.25 rillig } 122 1.25 rillig } 123 1.25 rillig 124 1.4 lukem void 125 1.25 rillig init_board(void) 126 1.1 tls { 127 1.1 tls 128 1.23 rillig game.nmoves = 0; 129 1.34 rillig game.win_spot = 0; 130 1.35 rillig game.user_x = 1 + (BSZ - 1) / 2; 131 1.35 rillig game.user_y = 1 + (BSZ - 1) / 2; 132 1.1 tls 133 1.25 rillig struct spotstr *sp = board; 134 1.17 rillig for (int i = 0; i < 1 + BSZ + 1; i++, sp++) { 135 1.25 rillig sp->s_occ = BORDER; /* bottom border and corners */ 136 1.7 dholland sp->s_flags = BFLAGALL; 137 1.1 tls } 138 1.1 tls 139 1.25 rillig /* fill the playing area of the board with EMPTY spots */ 140 1.30 rillig frame_index fi = 0; 141 1.1 tls memset(frames, 0, sizeof(frames)); 142 1.25 rillig for (int row = 1; row <= BSZ; row++, sp++) { 143 1.25 rillig for (int col = 1; col <= BSZ; col++, sp++) { 144 1.1 tls sp->s_occ = EMPTY; 145 1.1 tls sp->s_wval = 0; 146 1.25 rillig init_spot_flags_and_fval(sp, col, row); 147 1.30 rillig init_spot_frame(sp, &fi); 148 1.1 tls } 149 1.25 rillig sp->s_occ = BORDER; /* combined left and right border */ 150 1.7 dholland sp->s_flags = BFLAGALL; 151 1.1 tls } 152 1.1 tls 153 1.17 rillig for (int i = 0; i < BSZ + 1; i++, sp++) { 154 1.25 rillig sp->s_occ = BORDER; /* top border and top-right corner */ 155 1.7 dholland sp->s_flags = BFLAGALL; 156 1.1 tls } 157 1.1 tls 158 1.19 rillig sortframes[BLACK] = NULL; 159 1.19 rillig sortframes[WHITE] = NULL; 160 1.25 rillig 161 1.1 tls init_overlap(); 162 1.1 tls } 163 1.1 tls 164 1.27 rillig /* 165 1.27 rillig * Variable names for frames A and B: 166 1.27 rillig * 167 1.27 rillig * fi index of the frame in the global 'frames' 168 1.27 rillig * d direction delta, difference between adjacent spot indexes 169 1.33 rillig * off index of the spot in the frame, 0 to 5 170 1.27 rillig */ 171 1.27 rillig 172 1.27 rillig /* 173 1.27 rillig * Each entry in the overlap array is a bit mask with eight bits corresponding 174 1.27 rillig * to whether frame B overlaps frame A (as indexed by overlap[A * FAREA + B]). 175 1.27 rillig * 176 1.27 rillig * The eight bits correspond to whether A and B are open-ended (length 6) or 177 1.27 rillig * closed (length 5). 178 1.27 rillig * 179 1.27 rillig * 0 A closed and B closed 180 1.27 rillig * 1 A closed and B open 181 1.27 rillig * 2 A open and B closed 182 1.27 rillig * 3 A open and B open 183 1.27 rillig * 4 A closed and B closed and overlaps in more than one spot 184 1.27 rillig * 5 A closed and B open and overlaps in more than one spot 185 1.27 rillig * 6 A open and B closed and overlaps in more than one spot 186 1.27 rillig * 7 A open and B open and overlaps in more than one spot 187 1.27 rillig * 188 1.27 rillig * As pieces are played during the game, frames that no longer share an empty 189 1.27 rillig * spot will be removed from the overlap array by setting the entry to 0. 190 1.26 rillig */ 191 1.26 rillig static u_char 192 1.33 rillig adjust_overlap(u_char ov, int ra, int offa, int rb, int offb, int mask) 193 1.26 rillig { 194 1.33 rillig ov |= (offb == 5) ? mask & 0xA : mask; 195 1.26 rillig if (rb != ra) 196 1.26 rillig return ov; 197 1.26 rillig 198 1.26 rillig /* compute the multiple spot overlap values */ 199 1.33 rillig switch (offa) { 200 1.26 rillig case 0: 201 1.33 rillig if (offb == 4) 202 1.26 rillig ov |= 0xA0; 203 1.33 rillig else if (offb != 5) 204 1.26 rillig ov |= 0xF0; 205 1.26 rillig break; 206 1.26 rillig case 1: 207 1.33 rillig if (offb == 5) 208 1.26 rillig ov |= 0xA0; 209 1.26 rillig else 210 1.26 rillig ov |= 0xF0; 211 1.26 rillig break; 212 1.26 rillig case 4: 213 1.33 rillig if (offb == 0) 214 1.26 rillig ov |= 0xC0; 215 1.26 rillig else 216 1.26 rillig ov |= 0xF0; 217 1.26 rillig break; 218 1.26 rillig case 5: 219 1.33 rillig if (offb == 1) 220 1.26 rillig ov |= 0xC0; 221 1.33 rillig else if (offb != 0) 222 1.26 rillig ov |= 0xF0; 223 1.26 rillig break; 224 1.26 rillig default: 225 1.26 rillig ov |= 0xF0; 226 1.26 rillig } 227 1.26 rillig 228 1.26 rillig return ov; 229 1.26 rillig } 230 1.26 rillig 231 1.1 tls /* 232 1.27 rillig * Given a single spot 's' of frame A, update the overlap information for 233 1.27 rillig * each frame B that overlaps frame A in that spot. 234 1.1 tls */ 235 1.8 dholland static void 236 1.33 rillig init_overlap_frame(int fia, int ra, int offa, spot_index s, int mask) 237 1.27 rillig { 238 1.27 rillig 239 1.27 rillig for (int rb = 4; --rb >= 0;) { 240 1.27 rillig int db = dd[rb]; 241 1.27 rillig 242 1.33 rillig for (int offb = 0; offb < 6; offb++) { 243 1.27 rillig /* spb0 is the spot where frame B starts. */ 244 1.33 rillig const struct spotstr *spb0 = &board[s - offb * db]; 245 1.27 rillig if (spb0->s_occ == BORDER) 246 1.27 rillig break; 247 1.36 rillig if (is_blocked(spb0, rb)) 248 1.27 rillig continue; 249 1.27 rillig 250 1.30 rillig frame_index fib = spb0->s_frame[rb]; 251 1.29 rillig intersect[fia * FAREA + fib] = s; 252 1.27 rillig u_char *op = &overlap[fia * FAREA + fib]; 253 1.33 rillig *op = adjust_overlap(*op, ra, offa, rb, offb, mask); 254 1.27 rillig } 255 1.27 rillig } 256 1.27 rillig } 257 1.27 rillig 258 1.27 rillig static void 259 1.6 dholland init_overlap(void) 260 1.1 tls { 261 1.1 tls 262 1.1 tls memset(overlap, 0, sizeof(overlap)); 263 1.1 tls memset(intersect, 0, sizeof(intersect)); 264 1.16 rillig 265 1.27 rillig for (int fia = FAREA; fia-- > 0;) { 266 1.27 rillig const struct combostr *fa = &frames[fia]; 267 1.28 rillig spot_index s = fa->c_vertex; 268 1.27 rillig u_char ra = fa->c_dir; 269 1.27 rillig int da = dd[ra]; 270 1.27 rillig 271 1.27 rillig /* 272 1.27 rillig * len = 5 if closed, 6 if open. At this early stage, Black 273 1.27 rillig * and White have the same value for cv_win. 274 1.27 rillig */ 275 1.27 rillig int len = 5 + board[s].s_fval[BLACK][ra].cv_win; 276 1.27 rillig 277 1.33 rillig for (int offa = 0; offa < len; offa++) { 278 1.27 rillig /* spot[5] in frame A only overlaps if it is open */ 279 1.33 rillig int mask = (offa == 5) ? 0xC : 0xF; 280 1.26 rillig 281 1.33 rillig init_overlap_frame(fia, ra, offa, s + offa * da, mask); 282 1.1 tls } 283 1.1 tls } 284 1.1 tls } 285