1 /* $NetBSD: board.cc,v 1.3 2005/08/09 15:17:41 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * board.C: Board manipulations 41 */ 42 #include "defs.h" 43 RCSID("$NetBSD: board.cc,v 1.3 2005/08/09 15:17:41 christos Exp $") 44 45 #include <stdio.h> 46 #include <string.h> 47 #include <stdarg.h> 48 #include "board.h" 49 #include "gamescreen.h" 50 #include "box.h" 51 #include "player.h" 52 53 BOARD::BOARD(size_t y, size_t x, GAMESCREEN* scrn) : 54 _ny(y), 55 _nx(x), 56 _scrn(scrn) 57 { 58 _ty = 2 * _ny + 1; 59 _tx = 2 * _nx + 1; 60 61 _b = new int*[_ty]; 62 63 for (y = 0; y < _ty; y++) 64 _b[y] = new int[_tx]; 65 66 init(); 67 } 68 69 BOARD::BOARD(const BOARD& b) : 70 _ty(b._ty), 71 _tx(b._tx), 72 _ny(b._ny), 73 _nx(b._nx), 74 _scrn(NULL) 75 { 76 _b = new int*[_ty]; 77 78 for (size_t y = 0; y < _ty; y++) { 79 _b[y] = new int[_tx]; 80 static_cast<void>(memcpy(_b[y], b._b[y], _tx * sizeof(int))); 81 } 82 } 83 84 BOARD::~BOARD() 85 { 86 size_t y; 87 88 for (y = 0; y < _ty; y++) 89 delete[] _b[y]; 90 91 delete[] _b; 92 } 93 94 // Clear all boxes and reset state for a new game 95 void BOARD::init(void) 96 { 97 size_t x, y; 98 99 for (y = 0; y < _ny; y++) 100 for (x = 0; x < _nx; x++) { 101 BOX box(y, x, *this); 102 box.reset(); 103 } 104 } 105 106 /* 107 * Make a move for player with initial 'c', adding an edge at box(x, y) 108 * and the specified direction. 109 * returns: 110 * -1: Invalid move 111 * n: Number of closures n E [0..2] 112 */ 113 int BOARD::domove(size_t y, size_t x, int dir, char c) 114 { 115 int closed = 0; 116 117 // Check if out of bounds 118 if (!bounds(y, x)) 119 return -1; 120 121 BOX box1(y, x, *this); 122 123 // Check if the edge is already there 124 if (box1.isset(dir)) 125 return -1; 126 127 box1.set(dir); 128 129 if (box1.count() == 4) { 130 // New box; name it and count it 131 box1.name() = c; 132 closed++; 133 } 134 135 box1.paint(); 136 137 // Check other box 138 x += BOX::edges[dir].x; 139 y += BOX::edges[dir].y; 140 141 if (bounds(y, x)) { 142 BOX box2(y, x, *this); 143 if (box2.count() == 4) { 144 box2.name() = c; 145 box2.paint(); 146 closed++; 147 } 148 } 149 return closed; 150 } 151 152 // Return true if the board is full 153 int BOARD::full(void) const 154 { 155 for (size_t y = 0; y < _ny; y++) 156 for (size_t x = 0; x < _nx; x++) { 157 BOX box(y, x, const_cast<BOARD&>(*this)); 158 if (box.count() != 4) 159 return 0; 160 } 161 return 1; 162 } 163 164 // Return if the coordinates are within bounds; we don't check for < 0, 165 // since size_t is unsigned 166 int BOARD::bounds(size_t y, size_t x) const 167 { 168 return x < _nx && y < _ny; 169 } 170 171 // Paint all boxes, effectively redrawing the board 172 void BOARD::paint(void) const 173 { 174 for (size_t y = 0; y < _ny; y++) 175 for (size_t x = 0; x < _nx; x++) { 176 BOX box(y, x, const_cast<BOARD&>(*this)); 177 box.paint(); 178 } 179 } 180 181 // Clear the screen 182 void BOARD::clean(void) const 183 { 184 if (!_scrn) 185 return; 186 _scrn->clean(); 187 } 188 189 // Move cursor to x, y 190 void BOARD::setpos(size_t y, size_t x) const 191 { 192 if (!_scrn) 193 return; 194 _scrn->moveto(y, x); 195 _scrn->redraw(); 196 } 197 198 // Return character indicating move 199 int BOARD::getmove(void) const 200 { 201 if (!_scrn) 202 return 'q'; 203 _scrn->redraw(); 204 return _scrn->getinput(); 205 } 206 207 // Ring the bell 208 void BOARD::bell(void) const 209 { 210 if (!_scrn) 211 return; 212 _scrn->bell(); 213 } 214 215 // Post the score in the current game for player i 216 void BOARD::score(size_t i, const PLAYER& p) 217 { 218 if (_scrn == NULL) 219 return; 220 _scrn->score(i, p); 221 } 222 223 // Post the number of games won for player i 224 void BOARD::games(size_t i, const PLAYER& p) 225 { 226 if (_scrn == NULL) 227 return; 228 _scrn->games(i, p); 229 } 230 231 // Post the total score for player i 232 void BOARD::total(size_t i, const PLAYER& p) 233 { 234 if (_scrn == NULL) 235 return; 236 _scrn->total(i, p); 237 } 238 239 // Post the total score for player i 240 void BOARD::ties(const PLAYER& p) 241 { 242 if (_scrn == NULL) 243 return; 244 _scrn->ties(p); 245 } 246 247 // Internal algorithm error; post and abort 248 void BOARD::abort(const char* s, ...) const 249 { 250 for (size_t i = 0; i < _ny; i++) 251 fprintf(stderr, "\n"); 252 253 va_list ap; 254 fprintf(stderr, "Algorithm internal error: "); 255 va_start(ap, s); 256 vfprintf(stderr, s, ap); 257 va_end(ap); 258 fprintf(stderr, "\n"); 259 ::abort(); 260 } 261