first-draft of crop feature and problem theme
[eidogo-ojd.git] / kombilo / abstractboard.cpp
blobf9ef582b8e28af68cf6e57b26937d59a074cd627
1 // File: abstractboard.cpp
2 // part of libkombilo, http://www.u-go.net/kombilo/
4 // Copyright (c) 2006-7 Ulrich Goertz <u@g0ertz.de>
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 // this software and associated documentation files (the "Software"), to deal in
8 // the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 // of the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
24 #include "abstractboard.h"
25 using std::stack;
26 using std::vector;
28 BoardError::BoardError() {}
30 MoveNC::MoveNC() {
31 x = -1;
32 y = -1;
33 color = ' ';
36 // coordinates used here: top left = (0,0) - bottom right = (boardsize-1,boardsize-1)
37 MoveNC::MoveNC(char X, char Y, char COLOR) {
38 x = X;
39 y = Y;
40 color = COLOR;
43 bool MoveNC::operator==(const MoveNC& mnc) const {
44 if (x == mnc.x && y == mnc.y && color == mnc.color) return true;
45 else return false;
48 Move::Move(char xx, char yy, char cc) : MoveNC(xx, yy, cc) {
49 captures = 0;
52 Move::Move(const Move& m) : MoveNC(m.x, m.y, m.color) {
53 if (m.captures) {
54 captures = new vector<p_cc>;
55 vector<p_cc>::iterator it;
56 for(it = m.captures->begin(); it != m.captures->end(); it++)
57 captures->push_back(*it);
59 else captures = 0;
62 Move::~Move() {
63 if (captures) delete captures;
66 Move& Move::operator=(const Move& m) {
67 if (this != &m) {
68 x = m.x;
69 y = m.y;
70 color = m.color;
71 if (captures) delete captures;
72 if (m.captures) {
73 captures = new vector<p_cc>;
74 vector<p_cc>::iterator it;
75 for(it = m.captures->begin(); it != m.captures->end(); it++)
76 captures->push_back(*it);
78 else captures = 0;
80 return *this;
83 abstractBoard::abstractBoard(int bs) throw(BoardError) {
84 boardsize = bs;
85 if (boardsize < 1) throw BoardError();
86 status = new char[boardsize*boardsize+1];
87 for (int i = 0; i < boardsize*boardsize; i++)
88 status[i] = ' ';
89 status[boardsize*boardsize] = 0;
92 abstractBoard::abstractBoard(const abstractBoard& ab) {
93 boardsize = ab.boardsize;
94 status = new char[boardsize*boardsize+1];
95 for (int i = 0; i < boardsize*boardsize; i++)
96 status[i] = ab.status[i];
97 status[boardsize*boardsize] = 0;
98 undostack = stack<Move>(ab.undostack);
101 abstractBoard& abstractBoard::operator=(const abstractBoard& ab) {
102 if (this != &ab) {
103 boardsize = ab.boardsize;
104 delete [] status;
105 status = new char[boardsize*boardsize+1];
106 for (int i = 0; i < boardsize*boardsize; i++)
107 status[i] = ab.status[i];
108 status[boardsize*boardsize] = 0;
109 undostack = stack<Move>(ab.undostack);
111 return *this;
114 abstractBoard::~abstractBoard() {
115 delete [] status;
118 // abstractBoard& abstractBoard::copy(const abstractBoard& ab) {
119 // printf("copy assignment operator\n");
120 // if (this != &ab) {
121 // delete status;
122 // boardsize = ab.boardsize;
123 // status = new char[boardsize*boardsize+1];
124 // for (int i = 0; i < boardsize*boardsize; i++)
125 // status[i] = ab.status[i];
126 // status[boardsize*boardsize] = 0;
127 // undostack = ab.undostack;
128 // }
129 // return *this;
130 // }
132 char abstractBoard::getStatus(int x, int y) {
133 return status[boardsize*x + y];
136 void abstractBoard::setStatus(int x, int y, char val) {
137 if (val=='b' || val=='B') status[boardsize*x + y] = 'B';
138 else if (val=='w' || val=='W') status[boardsize*x + y] = 'W';
139 else status[boardsize*x + y] = val;
142 int abstractBoard::len_cap_last() throw(BoardError) {
143 if (!undostack.size()) throw BoardError();
144 Move m = undostack.top();
145 if (m.captures) return m.captures->size();
146 else return 0;
149 void abstractBoard::undostack_append_pass() {
150 undostack.push(Move(19,19,'-'));
153 int* abstractBoard::neighbors(int x, int y) {
154 int* result = new int[5];
155 char resultIndex = 1;
156 if (x-1 >= 0) result[resultIndex++]=(x-1) * boardsize + y;
157 if (x+1 < boardsize) result[resultIndex++]=(x+1) * boardsize + y;
158 if (y-1 >= 0) result[resultIndex++]=x * boardsize + y-1;
159 if (y+1 < boardsize) result[resultIndex++]=x*boardsize + y+1;
160 result[0] = resultIndex-1;
161 return result;
164 void abstractBoard::clear() {
165 for(int i=0; i<boardsize*boardsize; i++) status[i]=' ';
166 undostack = stack<Move>();
169 int abstractBoard::play(int x, int y, char* color) throw (BoardError) {
170 if (x<0 || x>=boardsize || y<0 || y>=boardsize) return 0;
171 if (status[boardsize*x+y] != ' ') {
172 return 0;
175 vector<p_cc>* captures = legal(x, y, color[0]);
176 if (captures) {
177 vector<p_cc>::iterator it;
178 for(it=captures->begin(); it!=captures->end(); it++)
179 status[boardsize*it->first + it->second] = ' '; // remove captured stones, if any
180 Move m(x, y, color[0]);
181 if (captures->size()) m.captures = captures;
182 else delete captures;
183 undostack.push(m);
184 return 1;
186 return 0;
189 vector<p_cc>* abstractBoard::legal(int x, int y, char color) {
190 vector<p_cc>* c = new vector<p_cc>;
191 int* nb = neighbors(x,y);
192 for(int i=1; i<=nb[0]; i++) {
193 int x1 = nb[i] / boardsize;
194 int y1 = nb[i] % boardsize;
195 if (status[boardsize*x1 + y1] == invert(color)) {
196 vector<p_cc>* d = hasNoLibExcP(x1, y1, x*boardsize+y);
197 vector<p_cc>::iterator it;
198 for(it = d->begin(); it != d->end(); it++) c->push_back(*it);
199 delete d;
202 delete [] nb;
203 setStatus(x,y,color);
205 if (c->size()) {
206 vector<p_cc>* captures = new vector<p_cc>();
207 while (c->size()) {
208 p_cc ctop = (*c)[0];
209 bool contained = false;
210 vector<p_cc>::iterator it;
211 for(it = captures->begin(); it != captures->end(); it++) {
212 if (ctop.first == it->first && ctop.second == it->second) {
213 contained = true;
214 break;
217 if (!contained) captures->push_back(ctop);
218 c->erase(c->begin());
220 delete c;
221 return captures;
223 delete c;
224 vector<p_cc>* d = hasNoLibExcP(x, y);
225 if (d->size()) {
226 delete d;
227 status[boardsize*x + y] = ' ';
228 return 0;
230 else {
231 delete d;
232 vector<p_cc>* ret = new vector<p_cc>();
233 return ret;
237 vector<p_cc>* abstractBoard::hasNoLibExcP(int x1, int y1, int exc) {
238 vector<p_cc>* st = new vector<p_cc>;
239 vector<p_cc>* newlyFound = new vector<p_cc>;
240 newlyFound->push_back(p_cc(x1, y1));
241 vector<p_cc>* n;
242 int foundNew = 1;
244 while (foundNew) {
245 foundNew = 0;
246 n = new vector<p_cc>;
247 vector<p_cc>::iterator it1;
248 for(it1=newlyFound->begin(); it1!=newlyFound->end(); it1++) {
249 int x = it1->first;
250 int y = it1->second;
251 int* nbs = neighbors(x,y);
252 for (int j=1; j <= nbs[0]; j++) {
253 int yy1 = nbs[j];
254 if (status[yy1] == ' ' && yy1 != exc) {
255 delete [] nbs;
256 delete st;
257 delete newlyFound;
258 delete n;
259 return new vector<p_cc>;
261 else {
262 if (status[yy1]==status[x*boardsize+y]) {
263 p_cc yy(yy1/boardsize, yy1%boardsize);
264 int foundNewHere = 1;
265 vector<p_cc>::iterator it;
266 for(it=n->begin(); it!=n->end(); it++) {
267 if (it->first==yy.first && it->second==yy.second) {
268 foundNewHere = 0;
269 break;
272 if (foundNewHere) {
273 for(it = st->begin(); it!=st->end(); it++) {
274 if (it->first==yy.first && it->second==yy.second) {
275 foundNewHere = 0;
276 break;
280 if (foundNewHere) {
281 n->push_back(yy);
282 foundNew = 1;
287 delete [] nbs;
290 vector<p_cc>::iterator it;
291 for(it=newlyFound->begin(); it!=newlyFound->end(); it++) {
292 st->push_back(*it);
294 delete newlyFound;
295 newlyFound = n;
297 delete n;
298 return st;
301 void abstractBoard::undo(int n) {
302 for(int i=0; i<n; i++) {
303 if (undostack.size()) {
304 Move tuple = undostack.top();
305 undostack.pop();
307 char color = tuple.color;
308 vector<p_cc>* captures = tuple.captures;
309 int x = tuple.x;
310 int y = tuple.y;
312 status[x*boardsize+y] = ' ';
313 if (captures) {
314 for(unsigned int i=0; i < captures->size(); i++) {
315 p_cc t = (*captures)[i];
316 setStatus(t.first, t.second, invert(color));
323 void abstractBoard::remove(int x, int y) {
324 undostack.push(Move(-1, -1, invert(status[boardsize*x+y])));
325 status[boardsize*x+y] = ' ';
328 char abstractBoard::invert(char color) {
329 if (color == 'B' || color == 'b') return 'W';
330 if (color == 'W' || color == 'w') return 'B';
331 return ' ';