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