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:
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
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
24 #include "abstractboard.h"
28 BoardError::BoardError() {}
36 // coordinates used here: top left = (0,0) - bottom right = (boardsize-1,boardsize-1)
37 MoveNC::MoveNC(char X
, char Y
, char COLOR
) {
43 bool MoveNC::operator==(const MoveNC
& mnc
) const {
44 if (x
== mnc
.x
&& y
== mnc
.y
&& color
== mnc
.color
) return true;
48 Move::Move(char xx
, char yy
, char cc
) : MoveNC(xx
, yy
, cc
) {
52 Move::Move(const Move
& m
) : MoveNC(m
.x
, m
.y
, m
.color
) {
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
);
63 if (captures
) delete captures
;
66 Move
& Move::operator=(const Move
& m
) {
71 if (captures
) delete 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
);
83 abstractBoard::abstractBoard(int bs
) throw(BoardError
) {
85 if (boardsize
< 1) throw BoardError();
86 status
= new char[boardsize
*boardsize
+1];
87 for (int i
= 0; i
< boardsize
*boardsize
; 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
) {
103 boardsize
= ab
.boardsize
;
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
);
114 abstractBoard::~abstractBoard() {
118 // abstractBoard& abstractBoard::copy(const abstractBoard& ab) {
119 // printf("copy assignment operator\n");
120 // if (this != &ab) {
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;
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();
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;
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
] != ' ') {
175 vector
<p_cc
>* captures
= legal(x
, y
, color
[0]);
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
;
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
);
203 setStatus(x
,y
,color
);
206 vector
<p_cc
>* captures
= new vector
<p_cc
>();
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
) {
217 if (!contained
) captures
->push_back(ctop
);
218 c
->erase(c
->begin());
224 vector
<p_cc
>* d
= hasNoLibExcP(x
, y
);
227 status
[boardsize
*x
+ y
] = ' ';
232 vector
<p_cc
>* ret
= new vector
<p_cc
>();
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
));
246 n
= new vector
<p_cc
>;
247 vector
<p_cc
>::iterator it1
;
248 for(it1
=newlyFound
->begin(); it1
!=newlyFound
->end(); it1
++) {
251 int* nbs
= neighbors(x
,y
);
252 for (int j
=1; j
<= nbs
[0]; j
++) {
254 if (status
[yy1
] == ' ' && yy1
!= exc
) {
259 return new vector
<p_cc
>;
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
) {
273 for(it
= st
->begin(); it
!=st
->end(); it
++) {
274 if (it
->first
==yy
.first
&& it
->second
==yy
.second
) {
290 vector
<p_cc
>::iterator it
;
291 for(it
=newlyFound
->begin(); it
!=newlyFound
->end(); it
++) {
301 void abstractBoard::undo(int n
) {
302 for(int i
=0; i
<n
; i
++) {
303 if (undostack
.size()) {
304 Move tuple
= undostack
.top();
307 char color
= tuple
.color
;
308 vector
<p_cc
>* captures
= tuple
.captures
;
312 status
[x
*boardsize
+y
] = ' ';
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';