File: board4.cc

package info (click to toggle)
atom4 4.1-6
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 656 kB
  • ctags: 947
  • sloc: cpp: 4,461; makefile: 54; sh: 21; perl: 6
file content (126 lines) | stat: -rw-r--r-- 3,289 bytes parent folder | download | duplicates (6)
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;
}