root/06/libkombilo-branches/hash_center/abstractboard.cpp

Revision 249, 9.1 kB (checked in by ug, 21 months ago)

Merge -r 246:248 from libkombilo main branch.

Line 
1// File: abstractboard.cpp
2// part of libkombilo, http://www.u-go.net/kombilo/
3
4// Copyright (c) 2006-7 Ulrich Goertz <u@g0ertz.de>
5
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.
23
24#include "abstractboard.h"
25using std::stack;
26using std::vector;
27
28BoardError::BoardError() {}
29
30MoveNC::MoveNC() {
31  x = -1;
32  y = -1;
33  color = ' ';
34}
35
36// coordinates used here: top left = (0,0) - bottom right = (boardsize-1,boardsize-1)
37MoveNC::MoveNC(char X, char Y, char COLOR) {
38  x = X;
39  y = Y;
40  color = COLOR;
41}
42
43bool MoveNC::operator==(const MoveNC& mnc) const {
44  if (x == mnc.x && y == mnc.y && color == mnc.color) return true;
45  else return false;
46}
47
48Move::Move(char xx, char yy, char cc) : MoveNC(xx, yy, cc) {
49  captures = 0;
50}
51
52Move::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);
58  }
59  else captures = 0;
60}
61
62Move::~Move() {
63  if (captures) delete captures;
64}
65
66Move& 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);
77    }
78    else captures = 0;
79  }
80  return *this;
81}
82
83abstractBoard::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;
90}
91
92abstractBoard::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);
99}
100
101abstractBoard& 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);
110  }
111  return *this;
112}
113
114abstractBoard::~abstractBoard() {
115  delete [] status;
116}
117
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// }
131
132char abstractBoard::getStatus(int x, int y) {
133  return status[boardsize*x + y];
134}
135
136void 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;
140}
141
142int 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;
147}
148
149void abstractBoard::undostack_append_pass() {
150  undostack.push(Move(19,19,'-'));
151}
152
153int* 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;
162}
163
164void abstractBoard::clear() {
165  for(int i=0; i<boardsize*boardsize; i++) status[i]=' ';
166  undostack = stack<Move>();
167}
168
169int 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;
173  }
174
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;
185  }
186  return 0;
187}
188
189vector<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;
200    }
201  }
202  delete [] nb;
203  setStatus(x,y,color);
204
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;
215        }
216      }
217      if (!contained) captures->push_back(ctop);
218      c->erase(c->begin());
219    }
220    delete c;
221    return captures;
222  }
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;
229  }
230  else {
231    delete d;
232    vector<p_cc>* ret = new vector<p_cc>();
233    return ret;
234  }
235}
236
237vector<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;
243
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>;
260        }
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;
270              }
271            }
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;
277                }
278              }
279            }
280            if (foundNewHere) {
281              n->push_back(yy);
282              foundNew = 1;
283            }
284          }
285        }
286      }
287      delete [] nbs;
288    }
289
290    vector<p_cc>::iterator it;
291    for(it=newlyFound->begin(); it!=newlyFound->end(); it++) {
292      st->push_back(*it);
293    }
294    delete newlyFound;
295    newlyFound = n;
296  }
297  delete n;
298  return st;
299}
300
301void abstractBoard::undo(int n) {
302  for(int i=0; i<n; i++) {
303    if (undostack.size()) {
304      Move tuple = undostack.top();
305      undostack.pop();
306
307      char color = tuple.color;
308      vector<p_cc>* captures = tuple.captures;
309      int x = tuple.x;
310      int y = tuple.y;
311
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));
317  }
318      }
319    }
320  }
321}
322
323void abstractBoard::remove(int x, int y) {
324  undostack.push(Move(-1, -1, invert(status[boardsize*x+y])));
325  status[boardsize*x+y] = ' ';
326}
327
328char abstractBoard::invert(char color) {
329  if (color == 'B' || color == 'b') return 'W';
330  if (color == 'W' || color == 'w') return 'B';
331  return ' ';
332}
Note: See TracBrowser for help on using the browser.