Home | History | Annotate | Line # | Download | only in dab
board.cc revision 1.2
      1 /*	$NetBSD: board.cc,v 1.2 2005/08/09 02:38:32 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.2 2005/08/09 02:38:32 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 	(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