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