1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
/*
* Atom-4 triboard
* Implementation file
*
* $Id: board4.cc,v 1.3 2003/02/18 22:23:14 hsteoh Exp hsteoh $
*/
#include "board4.h"
board4 &board4::operator= (board4 &b) {
this->triboard::operator= (b);
return *this;
}
board4::~board4() {}
int board4::check_legal(int x, int y) {
int prev_occupied=0; // 1 if cell has any players' marble;
// 0 otherwise
int cur_occupied=0;
color4 cur_ngbr;
int i;
// Check that (x,y) is currently unoccupied
if (getcell(x,y) != EMPTY_CELL)
return 0; // cannot put a marble here
// Check neighbours of (x,y). Here, we loop 7 times and take i%6 so that
// we will automagically compare dir=0 with dir=5 with no additional code
// :-)
for (i=0; i<7; i++) {
cur_ngbr = ngbr_of(x,y,i%6);
cur_occupied = (cur_ngbr.colortype() != -1);
if (cur_occupied && prev_occupied) {
return 1; // found adjacent pair
}
prev_occupied = cur_occupied;
}
return 0; // no neighbouring pairs to attach to
}
void board4::compute_splash(int x, int y, color4 actor,
elist<boardchange> &delta) {
color4 propagator = actor.propagator();
int i;
delta.clear();
if (propagator==BAD_CELL) return; // no propagator found; nothing to do
delta.append(boardchange(x,y,actor));
for (i=0; i<6; i++) {
int ox=x, oy=y, nx, ny;
color4 affected;
// Propagate effect over any propagators in this direction
while (ngbr_coor(ox,oy,i,nx,ny) && getcell(nx,ny)==propagator) {
ox=nx, oy=ny;
}
affected = getcell(nx,ny);
if (affected.colortype() != -1) {
color4 result = actor.mix(affected);
if (result != affected) // only add delta if actually changed
delta.append(boardchange(nx, ny, result));
}
} // endfor
}
void board4::applychanges(elist<boardchange> &delta, elist<boardchange> *undo)
{
elistiter<boardchange> it;
if (undo) undo->clear();
for (it=delta.headp(); it; it++) {
int x=(*it).x, y=(*it).y;
if (undo) undo->append(boardchange(x,y, getcell(x,y)));
setcell(x,y, (*it).cell);
}
}
int board4::count_marbles(color4 marble, int x, int y, int dir, int max) {
int count=0;
while (ngbr_coor(x,y,dir,x,y)) {
if (getcell(x,y)==marble) {
count++;
if (count>=max) return max;
} else break; // stop at first non-matching marble
}
return count;
}
int board4::check_row(color4 piece, int x, int y, int length) {
int nx,ny;
int i;
if (getcell(x,y)!=piece) return 0;
// Check if there is a sufficiently long row of the same color in any of
// the 3 pairs of directions
for (i=0; i<3; i++) {
int ri=(i+3)%6; // reverse direction of i
// Scan forwards and backwards for consecutive matching marbles.
// The +1 counts the current position (x,y), which is not counted by
// count_marbles().
if (count_marbles(piece,x,y,i,length-1) +
count_marbles(piece,x,y,ri,length-1) + 1 >= length) {
return 1; // found row of at least (length)
}
}
return 0; // no row found
}
int board4::check_win(elist<boardchange> &lastchanges, color4 piece, int len) {
elistiter<boardchange> it;
for (it=lastchanges.headp(); it; it++) {
if (check_row(piece, (*it).x, (*it).y, len))
return 1;
}
return 0;
}
|