root/06/libkombilo-branches/hash_center_makedb/search.cpp

Revision 236, 159.6 kB (checked in by ug, 23 months ago)

Fixed some issues with creating the frequency db.

Line 
1// File: search.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 "sgfparser.h"
25#include "abstractboard.h"
26#include "search.h"
27#include <stdio.h>
28#include <string>
29#include <cstring>
30
31using std::min;
32using std::max;
33using std::string;
34using std::vector;
35using std::map;
36using std::pair;
37using std::make_pair;
38using std::stack;
39
40#if defined(_MSC_VER)
41#include <algorithm>
42#else
43using std::sort;
44#endif
45
46PatternError::PatternError() {}
47
48Continuation::Continuation() {
49  B  = 0;
50  W  = 0;
51  tB = 0;
52  tW = 0;
53  wB = 0;
54  lB = 0;
55  wW = 0;
56  lW = 0;
57}
58
59Symmetries::Symmetries(char sX, char sY) {
60  sizeX = sX;
61  sizeY = sY;
62  dataX = new char[sizeX*sizeY];
63  dataY = new char[sizeX*sizeY];
64  dataCS = new char[sizeX*sizeY];
65  for(int i=0; i<sizeX*sizeY; i++) {
66    dataX[i] = -1;
67    dataY[i] = -1;
68    dataCS[i] = -1;
69  }
70}
71
72Symmetries::~Symmetries() {
73  delete [] dataX;
74  delete [] dataY;
75  delete [] dataCS;
76}
77
78Symmetries::Symmetries(const Symmetries& s) {
79  sizeX = s.sizeX;
80  sizeY = s.sizeY;
81  dataX = new char[sizeX*sizeY];
82  dataY = new char[sizeX*sizeY];
83  dataCS = new char[sizeX*sizeY];
84  for(int i=0; i<sizeX*sizeY; i++) {
85    dataX[i] = s.dataX[i];
86    dataY[i] = s.dataY[i];
87    dataCS[i] = s.dataCS[i];
88  }
89}
90
91Symmetries& Symmetries::operator=(const Symmetries& s) {
92  if (&s != this) {
93    sizeX = s.sizeX;
94    sizeY = s.sizeY;
95    delete [] dataX;
96    delete [] dataY;
97    delete [] dataCS;
98    dataX = new char[sizeX*sizeY];
99    dataY = new char[sizeX*sizeY];
100    dataCS = new char[sizeX*sizeY];
101    for(int i=0; i<sizeX*sizeY; i++) {
102      dataX[i] = s.dataX[i];
103      dataY[i] = s.dataY[i];
104      dataCS[i] = s.dataCS[i];
105    }
106  }
107  return *this;
108}
109
110void Symmetries::set(char i, char j, char k, char l, char cs) throw(PatternError) {
111  if (0 <= i && i < sizeX && 0 <= j && j < sizeY) {
112    dataX[i + j*sizeX] = k;
113    dataY[i + j*sizeX] = l;
114    dataCS[i + j*sizeX] = cs;
115  }
116  else throw PatternError();
117}
118
119char Symmetries::getX(char i, char j) throw(PatternError) {
120  if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataX[i + j*sizeX];
121  else throw PatternError();
122  return -1;
123}
124
125char Symmetries::getY(char i, char j) throw(PatternError) {
126  if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataY[i + j*sizeX];
127  else throw PatternError();
128  return -1;
129}
130
131char Symmetries::getCS(char i, char j) throw(PatternError) {
132  if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataCS[i + j*sizeX];
133  else throw PatternError();
134  return -1;
135}
136
137char Symmetries::has_key(char i, char j) throw(PatternError) {
138  if (0 <= i && i < sizeX && 0 <= j && j < sizeY) {
139    if (dataX[i + j*sizeX] == -1) return 0;
140    else return 1;
141  }
142  else throw PatternError();
143  return 0;
144}
145
146
147
148// ----------- class Pattern -----------------------------------------------
149
150int Pattern::operator==(const Pattern& p) {
151  if (boardsize != p.boardsize) return 0;
152  if (sizeX != p.sizeX || sizeY != p.sizeY) return 0;
153  if (left != p.left || right != p.right || top != p.top || bottom != p.bottom) return 0; 
154  for(int i=0; i < sizeX*sizeY; i++)
155    if (initialPos[i] != p.initialPos[i]) return 0;
156  if (contList != p.contList) return 0;
157  return 1;
158}
159
160
161char Pattern::BW2XO(char c) {
162  if (c == 'B') return 'X';
163  if (c == 'W') return 'O';
164  return c;
165}
166
167char Pattern::getInitial(int i, int j) {
168  return initialPos[i + sizeX*j];
169}
170 
171char Pattern::getFinal(int i, int j) {
172  return finalPos[i + sizeX*j];
173}
174 
175
176Pattern::Pattern() {
177  initialPos = 0;
178  finalPos = 0;
179  flip = 0;
180  colorSwitch = 0;
181  sizeX = 0;
182  sizeY = 0;
183  boardsize = 0;
184  contLabels = 0;
185}
186
187
188Pattern::Pattern(int type, int BOARDSIZE, int sX, int sY, char* iPos, char* CONTLABELS) {
189  flip = 0;
190  colorSwitch = 0;
191  sizeX = sX;
192  sizeY = sY;
193  boardsize = BOARDSIZE;
194  if (CONTLABELS) {
195    contLabels = new char[sizeX * sizeY];
196    for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
197  } else contLabels = 0;
198
199  if (type == CORNER_NW_PATTERN || type == FULLBOARD_PATTERN) {
200    left = right = top = bottom = 0;
201  } else if (type == CORNER_NE_PATTERN) {
202    top = bottom = 0;
203    left = right = boardsize - sizeX;
204  } else if (type == CORNER_SE_PATTERN) {
205    top = bottom = boardsize - sizeY;
206    left = right = boardsize - sizeX;
207  } else if (type == CORNER_SW_PATTERN) {
208    top = bottom = boardsize - sizeY;
209    left = right = 0;
210  } else if (type == SIDE_N_PATTERN) {
211    top = bottom = 0;
212    left = 1;
213    right = boardsize -1 - sizeX;
214  } else if (type == SIDE_E_PATTERN) {
215    left = right = boardsize - sizeX;
216    top = 1;
217    bottom = boardsize -1 - sizeY;
218  } else if (type == SIDE_W_PATTERN) {
219    left = right = 0;
220    top = 1;
221    bottom = boardsize -1 - sizeY;
222  } else if (type == SIDE_S_PATTERN) {
223    top = bottom = boardsize - sizeY;
224    left = 1;
225    right = boardsize -1 - sizeX;
226  } else if (type == CENTER_PATTERN) {
227    left = top = 1;
228    right = boardsize -1 - sizeX;
229    bottom = boardsize -1 - sizeY;
230  }
231
232  initialPos = new char[sizeX * sizeY];
233  finalPos = new char[sizeX*sizeY];
234  for(int i=0; i<sizeX*sizeY; i++) {
235    initialPos[i] = iPos[i];
236    finalPos[i] = iPos[i];
237  }
238}
239
240Pattern::Pattern(int type, int BOARDSIZE, int sX, int sY, char* iPos, vector<MoveNC> CONTLIST, char* CONTLABELS) {
241  flip = 0;
242  colorSwitch = 0;
243  sizeX = sX;
244  sizeY = sY;
245  boardsize = BOARDSIZE;
246  if (CONTLABELS) {
247    contLabels = new char[sizeX * sizeY];
248    for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
249  } else contLabels = 0;
250
251  if (type == CORNER_NW_PATTERN || type == FULLBOARD_PATTERN) {
252    left = right = top = bottom = 0;
253  } else if (type == CORNER_NE_PATTERN) {
254    top = bottom = 0;
255    left = right = boardsize - sizeX;
256  } else if (type == CORNER_SE_PATTERN) {
257    top = bottom = boardsize - sizeY;
258    left = right = boardsize - sizeX;
259  } else if (type == CORNER_SW_PATTERN) {
260    top = bottom = boardsize - sizeY;
261    left = right = 0;
262  } else if (type == SIDE_N_PATTERN) {
263    top = bottom = 0;
264    left = 1;
265    right = boardsize -1 - sizeX;
266  } else if (type == SIDE_E_PATTERN) {
267    left = right = boardsize - sizeX;
268    top = 1;
269    bottom = boardsize -1 - sizeY;
270  } else if (type == SIDE_W_PATTERN) {
271    left = right = 0;
272    top = 1;
273    bottom = boardsize -1 - sizeY;
274  } else if (type == SIDE_S_PATTERN) {
275    top = bottom = boardsize - sizeY;
276    left = 1;
277    right = boardsize -1 - sizeX;
278  } else if (type == CENTER_PATTERN) {
279    left = top = 1;
280    right = boardsize -1 - sizeX;
281    bottom = boardsize -1 - sizeY;
282  }
283
284  initialPos = new char[sizeX * sizeY];
285  finalPos = new char[sizeX*sizeY];
286  for(int i=0; i<sizeX*sizeY; i++) {
287    initialPos[i] = iPos[i];
288    finalPos[i] = iPos[i];
289  }
290
291  contList = CONTLIST;
292}
293
294Pattern::Pattern(int le, int ri, int to, int bo, int BOARDSIZE, int sX, int sY, char* iPos, const vector<MoveNC>& CONTLIST, char* CONTLABELS) throw(PatternError) {
295  // check whether anchor rectangle is valid
296  if (le < 0 || ri+sX > BOARDSIZE || to < 0 || bo+sY > BOARDSIZE || ri < le || bo < to) throw PatternError();
297
298  flip = 0;
299  colorSwitch = 0;
300       
301  left = le;
302  right = ri;
303  top = to;
304  bottom = bo;
305  boardsize = BOARDSIZE;
306
307  sizeX = sX;
308  sizeY = sY;
309  if (CONTLABELS) {
310    contLabels = new char[sizeX * sizeY];
311    for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
312  } else contLabels = 0;
313
314  initialPos = new char[sizeX * sizeY];
315  finalPos = new char[sizeX*sizeY];
316  for(int i=0; i<sizeX*sizeY; i++) {
317    initialPos[i] = iPos[i];
318    finalPos[i] = iPos[i];
319  }
320
321  contList = CONTLIST;
322}
323
324Pattern::~Pattern() {
325  if (initialPos) delete [] initialPos;
326  if (finalPos) delete [] finalPos;
327  if (contLabels) delete [] contLabels;
328}
329
330Pattern::Pattern(const Pattern& p) {
331  left = p.left;
332  right = p.right;
333  top = p.top;
334  bottom = p.bottom;
335  boardsize = p.boardsize;
336  sizeX = p.sizeX;
337  sizeY = p.sizeY;
338  flip = p.flip;
339  colorSwitch = p.colorSwitch;
340
341  initialPos = new char[sizeX*sizeY];
342  finalPos = new char[sizeX*sizeY];
343  if (p.contLabels) contLabels = new char[sizeX*sizeY];
344  else contLabels = 0;
345  for(int i=0; i<sizeX*sizeY; i++) {
346    initialPos[i] = p.initialPos[i];
347    finalPos[i] = p.finalPos[i];
348    if (p.contLabels) contLabels[i] = p.contLabels[i];
349  }
350  contList = p.contList;
351}
352
353Pattern& Pattern::operator=(const Pattern& p) {
354  if (&p != this) {
355    left = p.left;
356    right = p.right;
357    top = p.top;
358    bottom = p.bottom;
359    boardsize = p.boardsize;
360    sizeX = p.sizeX;
361    sizeY = p.sizeY;
362    flip = p.flip;
363    colorSwitch = p.colorSwitch;
364
365    if (initialPos) delete [] initialPos;
366    if (finalPos) delete [] finalPos;
367    if (contLabels) delete [] contLabels;
368   
369    initialPos = new char[sizeX*sizeY];
370    finalPos = new char[sizeX*sizeY];
371    if (p.contLabels) contLabels = new char[sizeX*sizeY];
372    else contLabels = 0;
373    for(int i=0; i<sizeX*sizeY; i++) {
374      initialPos[i] = p.initialPos[i];
375      finalPos[i] = p.finalPos[i];
376      if (p.contLabels) contLabels[i] = p.contLabels[i];
377    }
378    contList = p.contList;
379  }
380  return *this;
381}
382
383
384Pattern& Pattern::copy(const Pattern& p) {
385  if (&p != this) {
386    left = p.left;
387    right = p.right;
388    top = p.top;
389    bottom = p.bottom;
390    boardsize = p.boardsize;
391    sizeX = p.sizeX;
392    sizeY = p.sizeY;
393    flip = p.flip;
394    colorSwitch = p.colorSwitch;
395
396    if (initialPos) delete [] initialPos;
397    if (finalPos) delete [] finalPos;
398   
399    initialPos = new char[sizeX*sizeY];
400    finalPos = new char[sizeX*sizeY];
401    if (p.contLabels) contLabels = new char[sizeX*sizeY];
402    else contLabels = 0;
403    for(int i=0; i<sizeX*sizeY; i++) {
404      initialPos[i] = p.initialPos[i];
405      finalPos[i] = p.finalPos[i];
406      if (p.contLabels) contLabels[i] = p.contLabels[i];
407    }
408    contList = p.contList;
409  }
410  return *this;
411}
412
413string Pattern::printPattern() {
414  string result;
415  char buf[100];
416  sprintf(buf, "boardsize: %d, area: %d, %d, %d, %d\nsize: %d, %d\n", boardsize, left, right, top, bottom, sizeX, sizeY);
417  result += buf;
418  for(int i=0; i<sizeY; i++) {
419    for(int j=0; j<sizeX; j++) {
420      if (initialPos[i*sizeX + j] == 'X' || initialPos[i*sizeX + j] == 'O' || initialPos[i*sizeX + j] == 'x' || initialPos[i*sizeX + j] == 'x' || initialPos[i*sizeX+j] == '*') result += initialPos[i*sizeX+j];
421      else result += '.';
422    }
423    result += "\n";
424  }
425  result += "\n";
426  return result;
427}
428
429
430int Pattern::flipsX(int i, int x, int y, int XX, int YY) {
431  if (i==0) return x;
432  if (i==1) return XX-x;
433  if (i==2) return x;
434  if (i==3) return XX-x;
435  if (i==4) return y;
436  if (i==5) return YY-y;
437  if (i==6) return y;
438  if (i==7) return YY-y;
439  return -1;
440}
441
442int Pattern::flipsY(int i, int x, int y, int XX, int YY) {
443  if (i==0) return y;
444  if (i==1) return y;
445  if (i==2) return YY-y;
446  if (i==3) return YY-y;
447  if (i==4) return x;
448  if (i==5) return x;
449  if (i==6) return XX-x;
450  if (i==7) return XX-x;
451  return -1;
452}
453
454
455int Pattern::PatternInvFlip(int i) {
456  if (i == 5) return 6;
457  if (i == 6) return 5;
458  return i;
459}
460
461const int composition_table[] = {
462  0, 1, 2, 3, 4, 5, 6, 7,
463  1, 0, 3, 2, 5, 4, 7, 6,
464  2, 3, 0, 1, 6, 7, 4, 5,
465  3, 2, 1, 0, 7, 6, 5, 4,
466  4, 6, 5, 7, 0, 2, 1, 3,
467  5, 7, 4, 6, 1, 3, 0, 2,
468  6, 4, 7, 5, 2, 0, 3, 1,
469  7, 5, 6, 4, 3, 1, 2, 0 };
470
471int Pattern::compose_flips(int i, int j) {
472  return composition_table[j+8*i];
473}
474
475PatternList::PatternList(Pattern& p, int fColor, int nMove) throw(PatternError) {
476  pattern.copy(p);
477  fixedColor = fColor;
478  nextMove = nMove;
479  special = -1;
480  flipTable = new int[16];
481  for(int i=0; i<16; i++) flipTable[i] = -1; // (patternList() relies on this)
482
483  patternList();
484  continuations = new Continuation[pattern.sizeX * pattern.sizeY];
485}
486
487PatternList::~PatternList() {
488  delete [] continuations;
489  delete [] flipTable;
490}
491
492char PatternList::invertColor(char co) {
493  if (co == 'X') return 'O';
494  if (co == 'x') return 'o';
495
496  if (co == 'O') return 'X';
497  if (co == 'o') return 'x';
498
499  return co;
500}
501       
502void PatternList::patternList() {
503       
504  vector<Pattern> lCS;
505  vector<pair<int,int> > sy;
506  int boardsize = pattern.boardsize;
507
508  for(int f = 0; f < 8; f++) {
509    int newSizeX = max(Pattern::flipsX(f,0,0,pattern.sizeX,pattern.sizeY),
510                       Pattern::flipsX(f,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
511    int newSizeY = max(Pattern::flipsY(f,0,0,pattern.sizeX,pattern.sizeY),
512                       Pattern::flipsY(f,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
513
514    int newLeft = min(Pattern::flipsX(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
515                      Pattern::flipsX(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
516                                      boardsize-1,boardsize-1));
517    int newRight = max(Pattern::flipsX(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
518                       Pattern::flipsX(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
519                                       boardsize-1,boardsize-1)) - (newSizeX-1);
520    int newTop = min(Pattern::flipsY(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
521                     Pattern::flipsY(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
522                                     boardsize-1,boardsize-1));
523    int newBottom = max(Pattern::flipsY(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
524                        Pattern::flipsY(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
525                        boardsize-1,boardsize-1)) - (newSizeY - 1);
526
527    // printf("%d, %d, %d, %d, %d, %d, %d\n", f, newSizeX, newSizeY, newLeft, newRight, newTop, newBottom);
528    char* newInitialPos = new char[pattern.sizeX*pattern.sizeY];
529    int i=0;
530    for(i=0; i<pattern.sizeX; i++) {
531      for(int j=0; j<pattern.sizeY; j++) {
532        newInitialPos[Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1) + \
533                      newSizeX*Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1)] = pattern.getInitial(i, j);
534      }
535    }
536
537    vector<MoveNC> newContList;
538    for(i=0; (unsigned int)i<pattern.contList.size(); i++) {
539      newContList.push_back(MoveNC(Pattern::flipsX(f, pattern.contList[i].x, pattern.contList[i].y, 
540                                                      pattern.sizeX-1,pattern.sizeY-1),
541                                  Pattern::flipsY(f, pattern.contList[i].x, pattern.contList[i].y,
542                                                      pattern.sizeX-1,pattern.sizeY-1),
543                                  pattern.contList[i].color));
544    }
545
546    Pattern pNew(newLeft, newRight, newTop, newBottom, pattern.boardsize, newSizeX, newSizeY,
547                 newInitialPos, newContList);
548
549    pNew.flip = f;
550    // printf("new size %d %d\n", pNew.sizeX, pNew.sizeY);
551
552    delete [] newInitialPos;
553
554    vector<Pattern>::iterator it;
555    bool foundNewPattern = true;
556    for(it = data.begin(); it != data.end(); it++) {
557      if (pNew == *it) {
558        foundNewPattern = false;
559        flipTable[f] = flipTable[it->flip];
560        break;
561      }
562    }
563    if (foundNewPattern) {
564      flipTable[f] = data.size();
565      data.push_back(pNew);
566    }
567
568    if (pNew == pattern) sy.push_back(pair<int,int>(f,0));
569
570    if (nextMove || !fixedColor) {
571      char* newInitialPos = new char[pattern.sizeX*pattern.sizeY];
572      for(int i=0; i<pattern.sizeX; i++) {
573        for(int j=0; j<pattern.sizeY; j++) {
574          newInitialPos[Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1) + newSizeX*Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1)] =
575            invertColor(pattern.getInitial(i, j));
576        }
577      }
578      vector<MoveNC> newContList;
579      {
580        for(unsigned int i=0; i<pattern.contList.size(); i++) {
581          newContList.push_back(MoveNC(Pattern::flipsX(f, pattern.contList[i].x, pattern.contList[i].y, 
582                  pattern.sizeX-1,pattern.sizeY-1),
583                Pattern::flipsY(f, pattern.contList[i].x, pattern.contList[i].y,
584                  pattern.sizeX-1,pattern.sizeY-1),
585                invertColor(pattern.contList[i].color)));
586        }
587      }
588
589
590      // printf("new size %d %d", newSizeX, newSizeY);
591      Pattern pNew1(newLeft, newRight, newTop, newBottom, pattern.boardsize, newSizeX, newSizeY,
592                    newInitialPos, newContList);
593      pNew1.flip = f;
594      pNew1.colorSwitch = 1;
595
596      delete [] newInitialPos;
597
598      if (!fixedColor) {
599        bool foundNewPattern = true;
600        int lCS_ctr = 0;
601        for(vector<Pattern>::iterator it = lCS.begin(); it != lCS.end(); it++) {
602          if (pNew1 == *it) {
603            foundNewPattern = false;
604            flipTable[f+8] = lCS_ctr;
605            break;
606          }
607          lCS_ctr++;
608        }
609        if (foundNewPattern) {
610          lCS.push_back(pNew1);
611        }
612      }
613
614      if (pNew1 == pattern) {
615        if (!fixedColor) sy.push_back(pair<int