/kombilo/search.cpp
C++ | 5380 lines | 4166 code | 524 blank | 690 comment | 1777 complexity | 0e1bbdbcb1b0e8ea2618a8bcc476aa52 MD5 | raw file
- // File: search.cpp
- // part of libkombilo, http://www.u-go.net/kombilo/
- // Copyright (c) 2006-7 Ulrich Goertz <u@g0ertz.de>
- // Permission is hereby granted, free of charge, to any person obtaining a copy of
- // this software and associated documentation files (the "Software"), to deal in
- // the Software without restriction, including without limitation the rights to
- // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- // of the Software, and to permit persons to whom the Software is furnished to do
- // so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- #include "sgfparser.h"
- #include "abstractboard.h"
- #include "search.h"
- #include <stdio.h>
- #include <string>
- #include <cstring>
- using std::min;
- using std::max;
- using std::string;
- using std::vector;
- using std::map;
- using std::pair;
- using std::make_pair;
- using std::stack;
- #if defined(_MSC_VER)
- #include <algorithm>
- #else
- using std::sort;
- #endif
- SnapshotVector::SnapshotVector() : vector<unsigned char>() {
- current = begin();
- }
- SnapshotVector::SnapshotVector(char* c, int size) : vector<unsigned char>() {
- for(int i=0; i<size; i++) push_back(c[i]);
- current = begin();
- }
- void SnapshotVector::pb_int(int d) {
- for(int i = 0; i < 4; i++) {
- push_back((unsigned char)(d % 256));
- d = d >> 8;
- }
- }
- void SnapshotVector::pb_charp(char* c, int size) {
- pb_int(size);
- for(int i=0; i<size; i++) push_back(c[i]);
- }
- void SnapshotVector::pb_intp(int* p, int size) {
- pb_int(size);
- for(int i=0; i<size; i++) pb_int(p[i]);
- }
- void SnapshotVector::pb_string(string s) {
- pb_int(s.size()+1);
- for(unsigned int i=0; i<s.size(); i++) push_back(s[i]);
- push_back(0);
- }
- void SnapshotVector::pb_char(char c) {
- push_back(c);
- }
- int SnapshotVector::retrieve_int() {
- int result = 0;
- for(int i=0; i<4; i++) {
- result += *current << (i*8);
- current++;
- }
- return result;
- }
- int* SnapshotVector::retrieve_intp() {
- int sz = retrieve_int();
- int* result = new int[sz];
- for(int i=0; i<sz; i++)
- result[i] = retrieve_int();
- return result;
- }
- char SnapshotVector::retrieve_char() {
- char c = *current;
- current++;
- return c;
- }
- char* SnapshotVector::retrieve_charp() {
- int sz = retrieve_int();
- char* result = new char[sz];
- for(int i=0; i<sz; i++) {
- result[i] = *current;
- current++;
- }
- return result;
- }
- string SnapshotVector::retrieve_string() {
- char* cp = retrieve_charp();
- string s(cp);
- delete [] cp;
- return s;
- }
- char* SnapshotVector::to_charp() {
- char* result = new char[size()];
- int counter = 0;
- for(SnapshotVector::iterator it = begin(); it != end(); it++) result[counter++] = *it;
- return result;
- }
- PatternError::PatternError() {}
- Continuation::Continuation() {
- B = 0;
- W = 0;
- tB = 0;
- tW = 0;
- wB = 0;
- lB = 0;
- wW = 0;
- lW = 0;
- }
- void Continuation::from_snv(SnapshotVector& snv) {
- B = snv.retrieve_int();
- W = snv.retrieve_int();
- tB = snv.retrieve_int();
- tW = snv.retrieve_int();
- wB = snv.retrieve_int();
- lB = snv.retrieve_int();
- wW = snv.retrieve_int();
- lW = snv.retrieve_int();
- }
- void Continuation::to_snv(SnapshotVector& snv) {
- snv.pb_int(B);
- snv.pb_int(W);
- snv.pb_int(tB);
- snv.pb_int(tW);
- snv.pb_int(wB);
- snv.pb_int(lB);
- snv.pb_int(wW);
- snv.pb_int(lW);
- }
- Symmetries::Symmetries(char sX, char sY) {
- sizeX = sX;
- sizeY = sY;
- dataX = new char[sizeX*sizeY];
- dataY = new char[sizeX*sizeY];
- dataCS = new char[sizeX*sizeY];
- for(int i=0; i<sizeX*sizeY; i++) {
- dataX[i] = -1;
- dataY[i] = -1;
- dataCS[i] = -1;
- }
- }
- Symmetries::~Symmetries() {
- delete [] dataX;
- delete [] dataY;
- delete [] dataCS;
- }
- Symmetries::Symmetries(const Symmetries& s) {
- sizeX = s.sizeX;
- sizeY = s.sizeY;
- dataX = new char[sizeX*sizeY];
- dataY = new char[sizeX*sizeY];
- dataCS = new char[sizeX*sizeY];
- for(int i=0; i<sizeX*sizeY; i++) {
- dataX[i] = s.dataX[i];
- dataY[i] = s.dataY[i];
- dataCS[i] = s.dataCS[i];
- }
- }
- Symmetries& Symmetries::operator=(const Symmetries& s) {
- if (&s != this) {
- sizeX = s.sizeX;
- sizeY = s.sizeY;
- delete [] dataX;
- delete [] dataY;
- delete [] dataCS;
- dataX = new char[sizeX*sizeY];
- dataY = new char[sizeX*sizeY];
- dataCS = new char[sizeX*sizeY];
- for(int i=0; i<sizeX*sizeY; i++) {
- dataX[i] = s.dataX[i];
- dataY[i] = s.dataY[i];
- dataCS[i] = s.dataCS[i];
- }
- }
- return *this;
- }
- void Symmetries::set(char i, char j, char k, char l, char cs) throw(PatternError) {
- if (0 <= i && i < sizeX && 0 <= j && j < sizeY) {
- dataX[i + j*sizeX] = k;
- dataY[i + j*sizeX] = l;
- dataCS[i + j*sizeX] = cs;
- }
- else throw PatternError();
- }
- char Symmetries::getX(char i, char j) throw(PatternError) {
- if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataX[i + j*sizeX];
- else throw PatternError();
- return -1;
- }
- char Symmetries::getY(char i, char j) throw(PatternError) {
- if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataY[i + j*sizeX];
- else throw PatternError();
- return -1;
- }
- char Symmetries::getCS(char i, char j) throw(PatternError) {
- if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataCS[i + j*sizeX];
- else throw PatternError();
- return -1;
- }
- char Symmetries::has_key(char i, char j) throw(PatternError) {
- if (0 <= i && i < sizeX && 0 <= j && j < sizeY) {
- if (dataX[i + j*sizeX] == -1) return 0;
- else return 1;
- }
- else throw PatternError();
- return 0;
- }
- // ----------- class Pattern -----------------------------------------------
- int Pattern::operator==(const Pattern& p) {
- if (boardsize != p.boardsize) return 0;
- if (sizeX != p.sizeX || sizeY != p.sizeY) return 0;
- if (left != p.left || right != p.right || top != p.top || bottom != p.bottom) return 0;
- for(int i=0; i < sizeX*sizeY; i++)
- if (initialPos[i] != p.initialPos[i]) return 0;
- if (contList != p.contList) return 0;
- return 1;
- }
- char Pattern::BW2XO(char c) {
- if (c == 'B') return 'X';
- if (c == 'W') return 'O';
- return c;
- }
- char Pattern::getInitial(int i, int j) {
- return initialPos[i + sizeX*j];
- }
-
- char Pattern::getFinal(int i, int j) {
- return finalPos[i + sizeX*j];
- }
-
- Pattern::Pattern() {
- initialPos = 0;
- finalPos = 0;
- flip = 0;
- colorSwitch = 0;
- sizeX = 0;
- sizeY = 0;
- boardsize = 0;
- contLabels = 0;
- }
- Pattern::Pattern(int type, int BOARDSIZE, int sX, int sY, char* iPos, char* CONTLABELS) {
- flip = 0;
- colorSwitch = 0;
- sizeX = sX;
- sizeY = sY;
- boardsize = BOARDSIZE;
- if (CONTLABELS) {
- contLabels = new char[sizeX * sizeY];
- for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
- } else contLabels = 0;
- if (type == CORNER_NW_PATTERN || type == FULLBOARD_PATTERN) {
- left = right = top = bottom = 0;
- } else if (type == CORNER_NE_PATTERN) {
- top = bottom = 0;
- left = right = boardsize - sizeX;
- } else if (type == CORNER_SE_PATTERN) {
- top = bottom = boardsize - sizeY;
- left = right = boardsize - sizeX;
- } else if (type == CORNER_SW_PATTERN) {
- top = bottom = boardsize - sizeY;
- left = right = 0;
- } else if (type == SIDE_N_PATTERN) {
- top = bottom = 0;
- left = 1;
- right = boardsize -1 - sizeX;
- } else if (type == SIDE_E_PATTERN) {
- left = right = boardsize - sizeX;
- top = 1;
- bottom = boardsize -1 - sizeY;
- } else if (type == SIDE_W_PATTERN) {
- left = right = 0;
- top = 1;
- bottom = boardsize -1 - sizeY;
- } else if (type == SIDE_S_PATTERN) {
- top = bottom = boardsize - sizeY;
- left = 1;
- right = boardsize -1 - sizeX;
- } else if (type == CENTER_PATTERN) {
- left = top = 1;
- right = boardsize -1 - sizeX;
- bottom = boardsize -1 - sizeY;
- }
- initialPos = new char[sizeX * sizeY];
- finalPos = new char[sizeX*sizeY];
- for(int i=0; i<sizeX*sizeY; i++) {
- initialPos[i] = iPos[i];
- finalPos[i] = iPos[i];
- }
- }
- Pattern::Pattern(int type, int BOARDSIZE, int sX, int sY,
- char* iPos, vector<MoveNC> CONTLIST, char* CONTLABELS) {
- flip = 0;
- colorSwitch = 0;
- sizeX = sX;
- sizeY = sY;
- boardsize = BOARDSIZE;
- if (CONTLABELS) {
- contLabels = new char[sizeX * sizeY];
- for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
- } else contLabels = 0;
- if (type == CORNER_NW_PATTERN || type == FULLBOARD_PATTERN) {
- left = right = top = bottom = 0;
- } else if (type == CORNER_NE_PATTERN) {
- top = bottom = 0;
- left = right = boardsize - sizeX;
- } else if (type == CORNER_SE_PATTERN) {
- top = bottom = boardsize - sizeY;
- left = right = boardsize - sizeX;
- } else if (type == CORNER_SW_PATTERN) {
- top = bottom = boardsize - sizeY;
- left = right = 0;
- } else if (type == SIDE_N_PATTERN) {
- top = bottom = 0;
- left = 1;
- right = boardsize -1 - sizeX;
- } else if (type == SIDE_E_PATTERN) {
- left = right = boardsize - sizeX;
- top = 1;
- bottom = boardsize -1 - sizeY;
- } else if (type == SIDE_W_PATTERN) {
- left = right = 0;
- top = 1;
- bottom = boardsize -1 - sizeY;
- } else if (type == SIDE_S_PATTERN) {
- top = bottom = boardsize - sizeY;
- left = 1;
- right = boardsize -1 - sizeX;
- } else if (type == CENTER_PATTERN) {
- left = top = 1;
- right = boardsize -1 - sizeX;
- bottom = boardsize -1 - sizeY;
- }
- initialPos = new char[sizeX * sizeY];
- finalPos = new char[sizeX*sizeY];
- for(int i=0; i<sizeX*sizeY; i++) {
- initialPos[i] = iPos[i];
- finalPos[i] = iPos[i];
- }
- contList = CONTLIST;
- }
- Pattern::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) {
- // check whether anchor rectangle is valid
- if (le < 0 || ri+sX > BOARDSIZE || to < 0 || bo+sY > BOARDSIZE || ri < le || bo < to) throw PatternError();
- flip = 0;
- colorSwitch = 0;
- left = le;
- right = ri;
- top = to;
- bottom = bo;
- boardsize = BOARDSIZE;
- sizeX = sX;
- sizeY = sY;
- if (CONTLABELS) {
- contLabels = new char[sizeX * sizeY];
- for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
- } else contLabels = 0;
- initialPos = new char[sizeX * sizeY];
- finalPos = new char[sizeX*sizeY];
- for(int i=0; i<sizeX*sizeY; i++) {
- initialPos[i] = iPos[i];
- finalPos[i] = iPos[i];
- }
- contList = CONTLIST;
- }
- Pattern::Pattern(SnapshotVector& snv) {
- flip = snv.retrieve_int();
- colorSwitch = snv.retrieve_int();
- left = snv.retrieve_int();
- right = snv.retrieve_int();
- top = snv.retrieve_int();
- bottom = snv.retrieve_int();
- boardsize = snv.retrieve_int();
- sizeX = snv.retrieve_int();
- sizeY = snv.retrieve_int();
- if (snv.retrieve_char()) { // contLabels?
- contLabels = snv.retrieve_charp();
- } else contLabels = 0;
- initialPos = snv.retrieve_charp();
- finalPos = snv.retrieve_charp();
- int size = snv.retrieve_int();
- for(int i=0; i<size; i++)
- contList.push_back(MoveNC(snv.retrieve_char(), snv.retrieve_char(), snv.retrieve_char())); // x, y, color
- }
- void Pattern::to_snv(SnapshotVector& snv) {
- snv.pb_int(flip);
- snv.pb_int(colorSwitch);
- snv.pb_int(left);
- snv.pb_int(right);
- snv.pb_int(top);
- snv.pb_int(bottom);
- snv.pb_int(boardsize);
- snv.pb_int(sizeX);
- snv.pb_int(sizeY);
- if (contLabels) {
- snv.pb_char(1);
- snv.pb_charp(contLabels, sizeX*sizeY);
- } else snv.pb_char(0);
- snv.pb_charp(initialPos, sizeX*sizeY);
- snv.pb_charp(finalPos, sizeX*sizeY);
- snv.pb_int(contList.size());
- for(vector<MoveNC>::iterator it = contList.begin(); it != contList.end(); it++) {
- snv.pb_char(it->x);
- snv.pb_char(it->y);
- snv.pb_char(it->color);
- }
- }
- Pattern::~Pattern() {
- if (initialPos) delete [] initialPos;
- if (finalPos) delete [] finalPos;
- if (contLabels) delete [] contLabels;
- }
- Pattern::Pattern(const Pattern& p) {
- left = p.left;
- right = p.right;
- top = p.top;
- bottom = p.bottom;
- boardsize = p.boardsize;
- sizeX = p.sizeX;
- sizeY = p.sizeY;
- flip = p.flip;
- colorSwitch = p.colorSwitch;
- initialPos = new char[sizeX*sizeY];
- finalPos = new char[sizeX*sizeY];
- if (p.contLabels) contLabels = new char[sizeX*sizeY];
- else contLabels = 0;
- for(int i=0; i<sizeX*sizeY; i++) {
- initialPos[i] = p.initialPos[i];
- finalPos[i] = p.finalPos[i];
- if (p.contLabels) contLabels[i] = p.contLabels[i];
- }
- contList = p.contList;
- }
- Pattern& Pattern::operator=(const Pattern& p) {
- if (&p != this) {
- left = p.left;
- right = p.right;
- top = p.top;
- bottom = p.bottom;
- boardsize = p.boardsize;
- sizeX = p.sizeX;
- sizeY = p.sizeY;
- flip = p.flip;
- colorSwitch = p.colorSwitch;
- if (initialPos) delete [] initialPos;
- if (finalPos) delete [] finalPos;
- if (contLabels) delete [] contLabels;
- initialPos = new char[sizeX*sizeY];
- finalPos = new char[sizeX*sizeY];
- if (p.contLabels) contLabels = new char[sizeX*sizeY];
- else contLabels = 0;
- for(int i=0; i<sizeX*sizeY; i++) {
- initialPos[i] = p.initialPos[i];
- finalPos[i] = p.finalPos[i];
- if (p.contLabels) contLabels[i] = p.contLabels[i];
- }
- contList = p.contList;
- }
- return *this;
- }
- Pattern& Pattern::copy(const Pattern& p) {
- if (&p != this) {
- left = p.left;
- right = p.right;
- top = p.top;
- bottom = p.bottom;
- boardsize = p.boardsize;
- sizeX = p.sizeX;
- sizeY = p.sizeY;
- flip = p.flip;
- colorSwitch = p.colorSwitch;
- if (initialPos) delete [] initialPos;
- if (finalPos) delete [] finalPos;
- initialPos = new char[sizeX*sizeY];
- finalPos = new char[sizeX*sizeY];
- if (p.contLabels) contLabels = new char[sizeX*sizeY];
- else contLabels = 0;
- for(int i=0; i<sizeX*sizeY; i++) {
- initialPos[i] = p.initialPos[i];
- finalPos[i] = p.finalPos[i];
- if (p.contLabels) contLabels[i] = p.contLabels[i];
- }
- contList = p.contList;
- }
- return *this;
- }
- string Pattern::printPattern() {
- string result;
- char buf[100];
- sprintf(buf, "boardsize: %d, area: %d, %d, %d, %d\nsize: %d, %d\n", boardsize, left, right, top, bottom, sizeX, sizeY);
- result += buf;
- for(int i=0; i<sizeY; i++) {
- for(int j=0; j<sizeX; j++) {
- 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];
- else result += '.';
- }
- result += "\n";
- }
- result += "\n";
- return result;
- }
- int Pattern::flipsX(int i, int x, int y, int XX, int YY) {
- if (i==0) return x;
- if (i==1) return XX-x;
- if (i==2) return x;
- if (i==3) return XX-x;
- if (i==4) return y;
- if (i==5) return YY-y;
- if (i==6) return y;
- if (i==7) return YY-y;
- return -1;
- }
- int Pattern::flipsY(int i, int x, int y, int XX, int YY) {
- if (i==0) return y;
- if (i==1) return y;
- if (i==2) return YY-y;
- if (i==3) return YY-y;
- if (i==4) return x;
- if (i==5) return x;
- if (i==6) return XX-x;
- if (i==7) return XX-x;
- return -1;
- }
- int Pattern::PatternInvFlip(int i) {
- if (i == 5) return 6;
- if (i == 6) return 5;
- return i;
- }
- const int composition_table[] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 1, 0, 3, 2, 5, 4, 7, 6,
- 2, 3, 0, 1, 6, 7, 4, 5,
- 3, 2, 1, 0, 7, 6, 5, 4,
- 4, 6, 5, 7, 0, 2, 1, 3,
- 5, 7, 4, 6, 1, 3, 0, 2,
- 6, 4, 7, 5, 2, 0, 3, 1,
- 7, 5, 6, 4, 3, 1, 2, 0 };
- int Pattern::compose_flips(int i, int j) {
- return composition_table[j+8*i];
- }
- PatternList::PatternList(Pattern& p, int fColor, int nMove) throw(PatternError) {
- pattern.copy(p);
- fixedColor = fColor;
- nextMove = nMove;
- special = -1;
- flipTable = new int[16];
- for(int i=0; i<16; i++) flipTable[i] = -1; // (patternList() relies on this)
- patternList();
- continuations = new Continuation[pattern.sizeX * pattern.sizeY];
- }
- PatternList::~PatternList() {
- delete [] continuations;
- delete [] flipTable;
- }
- char PatternList::invertColor(char co) {
- if (co == 'X') return 'O';
- if (co == 'x') return 'o';
- if (co == 'O') return 'X';
- if (co == 'o') return 'x';
- return co;
- }
- void PatternList::patternList() {
- vector<Pattern> lCS;
- vector<pair<int,int> > sy;
- int boardsize = pattern.boardsize;
- for(int f = 0; f < 8; f++) {
- int newSizeX = max(Pattern::flipsX(f,0,0,pattern.sizeX,pattern.sizeY),
- Pattern::flipsX(f,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
- int newSizeY = max(Pattern::flipsY(f,0,0,pattern.sizeX,pattern.sizeY),
- Pattern::flipsY(f,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
- int newLeft = min(Pattern::flipsX(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
- Pattern::flipsX(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
- boardsize-1,boardsize-1));
- int newRight = max(Pattern::flipsX(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
- Pattern::flipsX(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
- boardsize-1,boardsize-1)) - (newSizeX-1);
- int newTop = min(Pattern::flipsY(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
- Pattern::flipsY(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
- boardsize-1,boardsize-1));
- int newBottom = max(Pattern::flipsY(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
- Pattern::flipsY(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
- boardsize-1,boardsize-1)) - (newSizeY - 1);
- // printf("%d, %d, %d, %d, %d, %d, %d\n", f, newSizeX, newSizeY, newLeft, newRight, newTop, newBottom);
- char* newInitialPos = new char[pattern.sizeX*pattern.sizeY];
- int i=0;
- for(i=0; i<pattern.sizeX; i++) {
- for(int j=0; j<pattern.sizeY; j++) {
- newInitialPos[Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1) + \
- newSizeX*Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1)] = pattern.getInitial(i, j);
- }
- }
- vector<MoveNC> newContList;
- for(i=0; (unsigned int)i<pattern.contList.size(); i++) {
- newContList.push_back(MoveNC(Pattern::flipsX(f, pattern.contList[i].x, pattern.contList[i].y,
- pattern.sizeX-1,pattern.sizeY-1),
- Pattern::flipsY(f, pattern.contList[i].x, pattern.contList[i].y,
- pattern.sizeX-1,pattern.sizeY-1),
- pattern.contList[i].color));
- }
- Pattern pNew(newLeft, newRight, newTop, newBottom, pattern.boardsize, newSizeX, newSizeY,
- newInitialPos, newContList);
- pNew.flip = f;
- // printf("new size %d %d\n", pNew.sizeX, pNew.sizeY);
- delete [] newInitialPos;
- vector<Pattern>::iterator it;
- bool foundNewPattern = true;
- for(it = data.begin(); it != data.end(); it++) {
- if (pNew == *it) {
- foundNewPattern = false;
- flipTable[f] = flipTable[it->flip];
- break;
- }
- }
- if (foundNewPattern) {
- flipTable[f] = data.size();
- data.push_back(pNew);
- }
- if (pNew == pattern) sy.push_back(pair<int,int>(f,0));
- if (nextMove || !fixedColor) {
- char* newInitialPos = new char[pattern.sizeX*pattern.sizeY];
- for(int i=0; i<pattern.sizeX; i++) {
- for(int j=0; j<pattern.sizeY; j++) {
- newInitialPos[Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1) + newSizeX*Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1)] =
- invertColor(pattern.getInitial(i, j));
- }
- }
- vector<MoveNC> newContList;
- {
- for(unsigned int i=0; i<pattern.contList.size(); i++) {
- newContList.push_back(MoveNC(Pattern::flipsX(f, pattern.contList[i].x, pattern.contList[i].y,
- pattern.sizeX-1,pattern.sizeY-1),
- Pattern::flipsY(f, pattern.contList[i].x, pattern.contList[i].y,
- pattern.sizeX-1,pattern.sizeY-1),
- invertColor(pattern.contList[i].color)));
- }
- }
- // printf("new size %d %d", newSizeX, newSizeY);
- Pattern pNew1(newLeft, newRight, newTop, newBottom, pattern.boardsize, newSizeX, newSizeY,
- newInitialPos, newContList);
- pNew1.flip = f;
- pNew1.colorSwitch = 1;
- delete [] newInitialPos;
- if (!fixedColor) {
- bool foundNewPattern = true;
- int lCS_ctr = 0;
- for(vector<Pattern>::iterator it = lCS.begin(); it != lCS.end(); it++) {
- if (pNew1 == *it) {
- foundNewPattern = false;
- flipTable[f+8] = lCS_ctr;
- break;
- }
- lCS_ctr++;
- }
- if (foundNewPattern) {
- lCS.push_back(pNew1);
- }
- }
- if (pNew1 == pattern) {
- if (!fixedColor) sy.push_back(pair<int,int>(f,1));
- if (nextMove) special = Pattern::PatternInvFlip(f);
- }
- }
- }
- int lCS_ctr = 0;
- for(vector<Pattern>::iterator it = lCS.begin(); it != lCS.end(); it++) {
- bool contained_in_l = false;
- for(vector<Pattern>::iterator it_l = data.begin(); it_l != data.end(); it_l++)
- if (*it == *it_l) {
- contained_in_l = true;
- flipTable[8+it->flip] = flipTable[it_l->flip];
- break;
- }
- if (!contained_in_l) {
- flipTable[8+it->flip] = data.size();
- data.push_back(*it);
- }
- for(int ii=it->flip+1; ii<8; ii++)
- if (flipTable[8+ii] == lCS_ctr) flipTable[8+ii] = flipTable[8+it->flip];
- lCS_ctr++;
- }
- Symmetries symm(pattern.sizeX, pattern.sizeY);
- for(int i=0; i<symm.sizeX; i++)
- for(int j=0; j<symm.sizeY; j++)
- symm.set(i,j, i,j,0);
- for(vector<pair<int,int> >::iterator it_s=sy.begin(); it_s!=sy.end(); it_s++) {
- int s = it_s->first;
- int newSizeX = max(Pattern::flipsX(s,0,0,pattern.sizeX,pattern.sizeY),
- Pattern::flipsX(s,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
- int newSizeY = max(Pattern::flipsY(s,0,0,pattern.sizeX,pattern.sizeY),
- Pattern::flipsY(s,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
- int c = it_s->second;
- Symmetries symm1(newSizeX, newSizeY);
- for(int i=0; i < pattern.sizeX; i++) {
- for(int j=0; j < pattern.sizeY; j++) {
- int fX = Pattern::flipsX(s, i, j, pattern.sizeX-1, pattern.sizeY-1);
- int fY = Pattern::flipsY(s, i, j, pattern.sizeX-1, pattern.sizeY-1);
- if ((i != fX || j != fY) && !symm1.has_key(fX, fY))
- symm1.set(i,j, fX, fY, c);
- }
- }
- {
- int cs;
- for(int i=0; i<symm.sizeX; i++)
- for(int j=0; j<symm.sizeY; j++)
- if (symm1.has_key(symm.getX(i,j), symm.getY(i,j))) {
- if ((symm1.getCS(symm.getX(i,j),symm.getY(i,j)) || symm.getCS(i,j)) &&
- !(symm1.getCS(symm.getX(i,j),symm.getY(i,j)) && symm.getCS(i,j)))
- cs = 1;
- else cs = 0;
- symm.set(i,j,symm1.getX(symm.getX(i,j),symm.getY(i,j)),
- symm1.getY(symm.getX(i,j),symm.getY(i,j)), cs);
- }
- }
- }
- symmetries.push_back(symm);
- {
- vector<Pattern>::iterator it = data.begin();
- it++;
- for(; it != data.end(); it++) {
- // printf("ne %d, %d\n", it->sizeX, it->sizeY);
- int f = it->flip;
- Symmetries s(it->sizeX, it->sizeY);
- for(int i=0; i<pattern.sizeX; i++) {
- for(int j=0; j<pattern.sizeY; j++) {
- if (!it->colorSwitch) {
- s.set(Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
- Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
- symm.getX(i,j), symm.getY(i,j), symm.getCS(i,j));
- } else {
- s.set(Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
- Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
- symm.getX(i,j), symm.getY(i,j), 1-symm.getCS(i,j));
- }
- }
- }
- symmetries.push_back(s);
- }
- }
- }
- Pattern PatternList::get(int i) {
- return data[i];
- }
- int PatternList::size() {
- return data.size();
- }
- char* PatternList::updateContinuations(int index, int x, int y, char co, bool tenuki, char winner) {
- char xx;
- char yy;
- char cSymm;
- char cc;
- xx = symmetries[index].getX(x,y);
- yy = symmetries[index].getY(x,y);
- cSymm = symmetries[index].getCS(x,y);
- if (co == 'X' || co == 'B') {
- if (cSymm) cc = 'W'; else cc = 'B';
- } else {
- if (cSymm) cc = 'B'; else cc = 'W';
- }
- if ((nextMove == 1 && cc == 'W') || (nextMove == 2 && cc == 'B')) {
- if (special != -1) {
- char xx1 = xx;
- // printf("s1 xx %d, yy %d sp %d\n", xx, yy, special);
- xx = Pattern::flipsX(special, xx, yy, pattern.sizeX-1, pattern.sizeY-1);
- yy = Pattern::flipsY(special, xx1, yy, pattern.sizeX-1, pattern.sizeY-1);
- // printf("s2 xx %d, yy %d\n", xx, yy);
- if (cc == 'B') cc = 'W';
- else cc = 'B';
- cSymm = 1-cSymm;
- } else {
- return 0;
- }
- }
- if (cc == 'B') {
- continuations[xx + pattern.sizeX*yy].B++;
- if (tenuki) continuations[xx + pattern.sizeX*yy].tB++;
- if ((winner == 'B' && !cSymm) || (winner == 'W' && cSymm)) continuations[xx + pattern.sizeX*yy].wB++;
- else if ((winner == 'W' && !cSymm) || (winner == 'B' && cSymm)) continuations[xx + pattern.sizeX*yy].lB++;
- } else {
- // printf("xx %d, yy %d\n", xx, yy);
- continuations[xx + pattern.sizeX*yy].W++;
- if (tenuki) continuations[xx + pattern.sizeX*yy].tW++;
- if ((winner == 'B' && !cSymm) || (winner == 'W' && cSymm)) continuations[xx + pattern.sizeX*yy].wW++;
- else if ((winner == 'W' && !cSymm) || (winner ='B' && cSymm)) continuations[xx + pattern.sizeX*yy].lW++;
- }
- char* result = new char[3];
- result[0] = xx;
- result[1] = yy;
- result[2] = cSymm;
- return result;
- }
- char* PatternList::sortContinuations() {
- char* labels = new char[pattern.sizeX*pattern.sizeY+1];
- labels[pattern.sizeX * pattern.sizeY] = 0; // so we can just printf the labels as a string
- for(int i=0; i<pattern.sizeX*pattern.sizeY; i++) {
- if (continuations[i].B || continuations[i].W) labels[i] = '?'; // need to assign label
- else labels[i] = '.';
- }
- string labelList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- unsigned int labelIndex = 0;
- // assign labels which are in the contLabels array passed to the original pattern
- // (these will usually be labels "already present in the SGF file")
-
- if (pattern.contLabels) {
- for(int i=0; i<pattern.sizeX*pattern.sizeY; i++) {
- if (pattern.contLabels[i] != '.') {
- labels[i] = pattern.contLabels[i];
- unsigned int j = labelList.find(pattern.contLabels[i]);
- if (j != string::npos) labelList.erase(j,1);
- }
- }
- }
- // now give labels to the remaining points, starting with the one with
- // most hits
-
- int max_hits = 0;
- int max_hits_index = 0;
- while (max_hits != -1 && labelIndex < labelList.size()) {
- for(int i=0; i<pattern.sizeX*pattern.sizeY; i++) {
- if (labels[i] == '?' && continuations[i].B + continuations[i].W > max_hits) {
- max_hits = continuations[i].B + continuations[i].W;
- max_hits_index = i;
- }
- }
- if (max_hits != 0) { // found another point needing a label
- labels[max_hits_index] = labelList[labelIndex++];
- max_hits = 0;
- } else max_hits = -1; // done
- }
- return labels;
- }
- DBError::DBError() {
- }
- int dbinsert1blob(sqlite3* db, char* sql, int id, char* blob, int size) {
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return rc;
- rc = sqlite3_bind_int(ppStmt, 1, id);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_bind_blob(ppStmt, 2, blob, size, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE) return rc;
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) return rc;
- return 0; // Success
- }
- int dbinsert2blobs(sqlite3* db, char* sql, int id, char* blob1, int size1, char* blob2, int size2) {
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return rc;
- rc = sqlite3_bind_int(ppStmt, 1, id);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_bind_blob(ppStmt, 2, blob1, size1, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_bind_blob(ppStmt, 3, blob2, size2, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE) return rc;
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) return rc;
- return 0; // Success
- }
-
- Algorithm::Algorithm(int bsize) {
- boardsize = bsize;
- db = 0;
- }
- Algorithm::~Algorithm() {}
- void Algorithm::initialize_process(sqlite3* DB) {}
- void Algorithm::newgame_process(int game_id) {}
- void Algorithm::AB_process(int x, int y) {}
- void Algorithm::AW_process(int x, int y) {}
- void Algorithm::AE_process(int x, int y, char removed) {}
- void Algorithm::endOfNode_process() {}
- void Algorithm::move_process(Move m) {}
- void Algorithm::pass_process() {}
- void Algorithm::branchpoint_process() {}
- void Algorithm::endOfVariation_process() {}
- void Algorithm::endgame_process(bool commit) {}
- void Algorithm::finalize_process() {}
- int Algorithm::readDB(sqlite3* DB) { return 0; }
- int Algorithm::search(PatternList& patternList, GameList& gl, SearchOptions& options) {
- return -1;
- }
- Algo_signature::Algo_signature(int bsize) : Algorithm(bsize) {
- main_variation = true;
- }
- Algo_signature::~Algo_signature() {
- }
- void Algo_signature::initialize_process(sqlite3* DB) throw(DBError) {
- db = DB;
- char sql[100];
- sprintf(sql, "create table algo_signature_%d ( id integer primary key, signature varchar(12) );", boardsize);
- int rc = sqlite3_exec(db, sql, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- sprintf(sql, "create index sig_idx on algo_signature_%d(signature);", boardsize);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- }
- void Algo_signature::newgame_process(int game_id) {
- main_variation = true;
- counter = 0;
- gid = game_id;
- signature = new char[12];
- for(int i=0; i<12; i++) signature[i] = '?';
- }
- void Algo_signature::AB_process(int x, int y) {
- }
- void Algo_signature::AW_process(int x, int y) {
- }
- void Algo_signature::AE_process(int x, int y, char removed) {
- }
- void Algo_signature::endOfNode_process() {
- }
- void Algo_signature::move_process(Move m) {
- if (!main_variation) return;
- counter++;
- if (counter==20) {
- signature[0] = m.x + 97;
- signature[1] = m.y + 97;
- }
- if (counter==40) {
- signature[2] = m.x + 97;
- signature[3] = m.y + 97;
- }
- if (counter==60) {
- signature[4] = m.x + 97;
- signature[5] = m.y + 97;
- }
- if (counter==31) {
- signature[6] = m.x + 97;
- signature[7] = m.y + 97;
- }
- if (counter==51) {
- signature[8] = m.x + 97;
- signature[9] = m.y + 97;
- }
- if (counter==71) {
- signature[10] = m.x + 97;
- signature[11] = m.y + 97;
- }
- }
- void Algo_signature::pass_process() {
- if (main_variation) move_process(Move(19,19,'p'));
- }
- void Algo_signature::branchpoint_process() {
- }
- void Algo_signature::endOfVariation_process() {
- main_variation = false;
- }
- char* symmetrize(char* signature, int boardsize) {
- // symmetrize signature
- char* min_signature = new char[12];
- for(int i=0; i<12; i++) min_signature[i] = signature[i];
- for (int f=0; f<8; f++) { // for all flips
- // compute flipped signature
- char* next = new char[12];
- for(int i=0; i<6; i++) {
- if ('a' <= signature[2*i] && signature[2*i] <= 's')
- next[2*i] = Pattern::flipsX(f, signature[2*i]-'a', signature[2*i+1]-'a', boardsize-1, boardsize-1)+'a';
- else next[2*i] = signature[2*i];
- if ('a' <= signature[2*i+1] && signature[2*i+1] <= 's')
- next[2*i+1] = Pattern::flipsY(f, signature[2*i]-'a', signature[2*i+1]-'a', boardsize-1, boardsize-1)+'a';
- else next[2*i+1] = signature[2*i+1];
- }
- // if next < min_signature, then swap
- for(int j=0; j<12; j++) {
- if (next[j] > min_signature[j]) break;
- if (next[j] < min_signature[j]) {
- char* help = next;
- next = min_signature;
- min_signature = help;
- break;
- }
- }
- delete [] next;
- }
- return min_signature;
- }
- void Algo_signature::endgame_process(bool commit) throw(DBError) {
- if (commit) {
- char* min_signature = symmetrize(signature, boardsize);
- char sql[100];
- sprintf(sql, "insert into algo_signature_%d (id, signature) values (?,?);", boardsize);
- if (dbinsert1blob(db, sql, gid, min_signature, 12)) throw DBError();
- // for(int i=0; i<12; i++) printf("%c", min_signature[i]); printf("\n");
- delete [] min_signature;
- }
- delete [] signature;
- }
- void Algo_signature::finalize_process() {
- }
- char* Algo_signature::get_current_signature() {
- return symmetrize(signature, boardsize);
- }
- vector<int> Algo_signature::search_signature(char* sig) {
- // to be used during processing! (because we need the db)
- char sql[100];
- sprintf(sql, "select id from algo_signature_%d where signature=? order by id", boardsize);
- sqlite3_stmt *ppStmt=0;
- vector<int> result;
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) throw DBError();
- rc = sqlite3_bind_blob(ppStmt, 1, sig, 12, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK || ppStmt==0) throw DBError();
- do {
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE && rc != SQLITE_ROW) throw DBError();
- if (rc == SQLITE_ROW) {
- result.push_back(sqlite3_column_int(ppStmt, 0));
- }
- } while (rc == SQLITE_ROW);
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) throw DBError();
- return result;
- }
- Algo_finalpos::Algo_finalpos(int bsize) : Algorithm(bsize) {
- fp = 0;
- fpIndex = -1;
- data = 0;
- }
- Algo_finalpos::~Algo_finalpos() {
- if (data) {
- for(map<int, char* >::iterator it = data->begin(); it != data->end(); it++) delete [] it->second;
- delete data;
- }
- }
- void Algo_finalpos::initialize_process(sqlite3* DB) throw(DBError) {
- // printf("init Algo_finalpos\n");
- db = DB;
- char sql[100];
- sprintf(sql, "create table algo_finalpos_%d ( id integer primary key, data blob );", boardsize);
- int rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) {
- //throw DBError();
- }
- // printf("init Algo_finalpos\n");
- }
- void Algo_finalpos::newgame_process(int game_id) {
- gid = game_id;
- fp = new char[100];
- for(int i=0; i<100; i++) fp[i] = 255;
- }
- void Algo_finalpos::AB_process(int x, int y) {
- fp[y/2 + 10*(x/2)] &= ~(1 << (2*(x%2 + 2*(y%2))));
- }
- void Algo_finalpos::AW_process(int x, int y) {
- fp[y/2 + 10*(x/2)] &= ~(1 << (2*(x%2 + 2*(y%2))+1));
- }
- void Algo_finalpos::AE_process(int x, int y, char removed) {
- }
- void Algo_finalpos::endOfNode_process() {
- }
- void Algo_finalpos::move_process(Move m) {
- if (m.color == 'B')
- fp[m.y/2 + 10*(m.x/2)] &= ~(1 << (2*(m.x%2 + 2*(m.y%2))));
- else if (m.color == 'W')
- fp[m.y/2 + 10*(m.x/2)] &= ~(1 << (2*(m.x%2 + 2*(m.y%2))+1));
- }
- void Algo_finalpos::pass_process() {
- }
- void Algo_finalpos::branchpoint_process() {
- }
- void Algo_finalpos::endOfVariation_process() {
- }
- void Algo_finalpos::endgame_process(bool commit) throw(DBError) {
- if (commit) {
- char sql[100];
- sprintf(sql, "insert into algo_finalpos_%d (id, data) values (?,?);", boardsize);
- if (dbinsert1blob(db, sql, gid, fp, 100)) throw DBError();
- }
- delete [] fp;
- }
- void Algo_finalpos::finalize_process() {
- }
- int Algo_finalpos::readDB(sqlite3* DB) {
- db = DB;
- if (data) {
- for(map<int, char* >::iterator it = data->begin(); it != data->end(); it++) delete [] it->second;
- delete data;
- }
- data = new map<int, char* >;
- int rc = sqlite3_exec(db, "begin transaction;", 0, 0, 0);
- if (rc) throw DBError();
- sqlite3_stmt *ppStmt=0;
- char sql[100];
- sprintf(sql, "select id, data from algo_finalpos_%d order by id", boardsize);
- rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return rc; // FIXME: catch certain errors, (and/or throw DBError?)
- while (sqlite3_step(ppStmt) == SQLITE_ROW) {
- // printf("step0\n");
- int index = sqlite3_column_int(ppStmt, 0);
- char* d = (char*)sqlite3_column_blob(ppStmt, 1);
- // printf("step1\n");
- char* d1 = new char[100];
- // printf("step2\n");
- for(int i=0; i<100; i++) d1[i] = d[i];
- // printf("step3\n");
- // printf("insert %d %p\n", index, d1);
- data->insert(make_pair(index, d1));
- }
- // printf("done\n");
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_exec(db, "commit;", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- return 0;
- }
- int Algo_finalpos::search(PatternList& patternList, GameList& gl, SearchOptions& options) { // progress bar?!
- // Put the pattern into bitmap format, which is the format the final
- // positions are stored in in the database. This makes the comparisons
- // faster.
- int plS = patternList.size();
- char_p** allbits = new char_p*[plS];
- int** allbitlengths = new int*[plS];
- for(int N=0; N<plS; N++) {
- Pattern* pattern = &patternList.data[N];
- allbits[N] = new char_p[4];
- allbitlengths[N] = new int[4];
- for(int i=0; i<2; i++) {
- for(int j=0; j<2; j++) {
- int xBlocks = (pattern->sizeY+i+1)/2;
- int yBlocks = (pattern->sizeX+j+1)/2;
- char* nextBlock = new char[400];
- int nextBlockIndex = 0;
- nextBlock[nextBlockIndex++] = yBlocks;
- for(int k1=0; k1 < yBlocks; k1++) {
- char nlist[400];
- int nlistIndex = 0;
- for(int k2=0; k2 < xBlocks; k2++) {
- int n = 0;
- for(int x=0; x<2; x++) {
- for(int y=0; y<2; y++) {
- int indexX = k1 * 2 + y - j;
- int indexY = k2 * 2 + x - i;
- if (0 <= indexX && indexX < pattern->sizeX && 0 <= indexY && indexY < pattern->sizeY) {
- if (pattern->getFinal(indexX,indexY)=='X')
- n |= 1 << (2*(2*x+y));
- else if (pattern->getFinal(indexX,indexY)=='O')
- n |= 1 << (2*(2*x+y)+1);
- }
- }
- }
- nlist[nlistIndex++] = n;
- }
- int start = 0;
- int end = nlistIndex;
- while (start < end && !nlist[start]) start++;
- while (end > start && !nlist[end-1]) end--;
- nextBlock[nextBlockIndex++] = start;
- nextBlock[nextBlockIndex++] = end-start;
- for(int current=start; current < end; current++)
- nextBlock[nextBlockIndex++] = nlist[current];
- }
- char* nB = new char[nextBlockIndex];
- for(int ii=0; ii<nextBlockIndex; ii++) nB[ii] = nextBlock[ii];
- allbitlengths[N][2*i + j] = nextBlockIndex;
- allbits[N][2*i + j] = nB;
- delete [] nextBlock;
- }
- }
- }
- int index = gl.start();
- // int counter = 0; // to keep track of progress bar
- // printf("%d patterns\n", plS);
- char start;
- char length;
- char x;
- char y;
- while (index != -1) {
- // if (!(counter++ % 1000)) printf("counter: %d, index: %d\n", counter, index);
- // if (progBar && !(counter % 100))
- // progBar.redraw((progEnd-progStart)*counter/len(gl.current) + progStart);
- map<int, char* >::iterator it = data->find(index);
- if (it == data->end()) {
- // printf("skip\n");
- index = gl.next();
- continue;
- }
- char* finalpos = it->second;
- // printf("index %d, %p\n", index, finalpos);
- vector<Candidate* > *matchList = new vector<Candidate* >;;
- for(int N=0; N<plS; N++) {
- Pattern* pattern = &patternList.data[N];
- for(int a0=pattern->left; a0 <= pattern->right; a0++) {
- for(int a1 = pattern->top; a1 <= pattern->bottom; a1++) {
- int matches = 1;
- int pIndex = 2*(a1%2) + (a0%2);
- char* pbits = allbits[N][pIndex];
- int pbIndex = 0;
- int fpIndex = a1/2 + (a0/2)*10;
- for(x=0; x < pbits[0]; x++) {
- start = pbits[++pbIndex];
- length = pbits[++pbIndex];
- fpIndex += start;
- for(y=0; y<length; y++) {
- pbIndex++;
- if (pbits[pbIndex] & finalpos[fpIndex]) {
- matches = 0;
- break;
- }
- fpIndex++;
- }
- if (!matches) break;
- fpIndex += 10 - start - length;
- }
- if (matches) matchList->push_back(new Candidate(a0,a1,N));
- }
- }
- }
- if (matchList->size()) gl.makeCurrentCandidate(matchList);
- else delete matchList;
- index = gl.next();
- }
- {
- for(int N=0; N<plS; N++) {
- delete [] allbitlengths[N];
- for(int i=0; i<4; i++)
- if (allbits[N][i]) delete [] allbits[N][i];
- delete [] allbits[N];
- }
- }
- delete [] allbitlengths;
- delete [] allbits;
- return 0;
- }
- bool Algo_finalpos::equal(unsigned int i1, unsigned int i2) {
- // not to be used during processing
- // i1, i2 correspond to game id's
- sqlite3_stmt *ppStmt=0;
- char sql[100];
- sprintf(sql, "select data from algo_finalpos_%d where id = %d or id = %d", boardsize, i1, i2);
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return false; // FIXME: catch certain errors, (and/or throw DBError?)
- if (sqlite3_step(ppStmt) == SQLITE_ROW) {
- char* dd1 = (char*)sqlite3_column_blob(ppStmt, 0);
- char* d1 = new char[100];
- for(int i=0; i<100; i++) d1[i] = dd1[i]; // FIXME: is this necessary?
- if (sqlite3_step(ppStmt) == SQLITE_ROW) {
- char* d2 = (char*)sqlite3_column_blob(ppStmt, 0);
- for(int i=0; i<100; i++)
- if (d1[i] != d2[i]) {
- delete [] d1;
- sqlite3_finalize(ppStmt);
- return false;
- }
- delete [] d1;
- sqlite3_finalize(ppStmt);
- return true;
- }
- delete [] d1;
- }
- sqlite3_finalize(ppStmt);
- return false;
- }
- bool Algo_finalpos::equals_current(unsigned int id1) {
- // to be used only during processing
- // id1 here corresponds to a game id
- bool result = true;
- sqlite3_stmt *ppStmt=0;
- char sql[100];
- sprintf(sql, "select data from algo_finalpos_%d where id = %d", boardsize, id1);
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return false; // FIXME: catch certain errors, (and/or throw DBError?)
- if (sqlite3_step(ppStmt) == SQLITE_ROW) {
- char* d = (char*)sqlite3_column_blob(ppStmt, 0);
- for(int i=0; i<100; i++)
- if (d[i] != fp[i]) {
- result = false;
- break;
- }
- } else result = false;
- sqlite3_finalize(ppStmt);
- return result;
- }
- Algo_movelist::Algo_movelist(int bsize) : Algorithm(bsize) {
- data1 = 0;
- data2 = 0;
- data1l = 0;
- }
- Algo_movelist::~Algo_movelist() {
- if (data1) {
- for(map<int, char* >::iterator it = data1->begin(); it != data1->end(); it++) {
- delete [] it->second;
- }
- delete data1;
- }
- if (data2) {
- for(map<int, char* >::iterator it = data2->begin(); it != data2->end(); it++) {
- delete [] it->second;
- }
- delete data2;
- }
- if (data1l) delete data1l;
- }
- void Algo_movelist::initialize_process(sqlite3* DB) throw(DBError) {
- // printf("init Algo_movelist\n");
- db = DB;
- char sql[100];
- sprintf(sql, "create table algo_movelist_%d ( id integer primary key, movelist blob, fpC blob );", boardsize);
- int rc = sqlite3_exec(db, sql, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- // printf("init Algo_movelist\n");
- }
- void Algo_movelist::newgame_process(int game_id) {
- gid = game_id;
- movelist = vector<char>();
- fpC = new char[50];
- for(int i=0; i<50; i++) fpC[i] = 0;
- }
- void Algo_movelist::AB_process(int x, int y) {
- movelist.push_back((char)x);
- movelist.push_back((char)(y | BLACK));
- }
-
- void Algo_movelist::AW_process(int x, int y) {
- movelist.push_back((char)x);
- movelist.push_back((char)(y | WHITE));
- }
- void Algo_movelist::AE_process(int x, int y, char removed) {
- movelist.push_back((char)x);
- if (removed == 'B') movelist.push_back((char)(y | REMOVE | BLACK));
- else if (removed == 'W') movelist.push_back((char)(y | REMOVE | WHITE));
- }
- void Algo_movelist::endOfNode_process() {
- if (movelist.size()>1) {
- if (movelist[movelist.size()-2] & (ENDOFNODE | BRANCHPOINT | ENDOFVARIATION)) {
- movelist.push_back(ENDOFNODE);
- movelist.push_back(0);
- } else {
- movelist[movelist.size()-2] |= ENDOFNODE;
- }
- } else {
- movelist.push_back(ENDOFNODE);
- movelist.push_back(0);
- }
- }
- void Algo_movelist::move_process(Move m) {
- if (!movelist.size()) {
- movelist.push_back(ENDOFNODE);
- movelist.push_back(0);
- }
- movelist.push_back(m.x);
- if (m.color=='B') movelist.push_back(m.y | BLACK);
- else movelist.push_back(m.y | WHITE);
- if (m.captures) {
- vector<p_cc>::iterator it;
- for(it = m.captures->begin(); it != m.captures->end(); it++) {
- int xx = it->first;
- int yy = it->second;
- movelist.push_back(xx);
- if (m.color=='B') movelist.push_back(yy | REMOVE | WHITE);
- else movelist.push_back(yy | REMOVE | BLACK);
- fpC[yy/4 + 5*(xx/2)] |= 1 << (xx%2 + 2*(yy%4));
- }
- }
- }
- void Algo_movelist::pass_process() {
- movelist.push_back(19);
- movelist.push_back(19);
- }
- void Algo_movelist::branchpoint_process() {
- movelist.push_back(BRANCHPOINT);
- movelist.push_back(0);
- }
- void Algo_movelist::endOfVariation_process() {
- movelist.push_back(ENDOFVARIATION);
- movelist.push_back(0);
- }
- void Algo_movelist::endgame_process(bool commit) throw(DBError) {
- if (commit) {
- char* ml = new char[movelist.size()];
- int mlIndex = 0;
- for(vector<char>::iterator it = movelist.begin(); it != movelist.end(); it++) {
- ml[mlIndex++] = *it;
- }
- char sql[100];
- sprintf(sql, "insert into algo_movelist_%d (id, movelist, fpC) values (?, ?, ?);", boardsize);
- if (dbinsert2blobs(db, sql, gid, ml, mlIndex, fpC, 50)) throw DBError();
- delete [] ml;
- }
- delete [] fpC;
- }
- void Algo_movelist::finalize_process() {
- }
- int Algo_movelist::readDB(sqlite3* DB) {
- if (data1) {
- for(map<int, char* >::iterator it = data1->begin(); it != data1->end(); it++) delete [] it->second;
- delete data1;
- }
- data1 = new map<int, char* >;
- if (data1l) delete data1l;
- data1l = new map<int, int >;
- if (data2) {
- for(map<int, char* >::iterator it = data2->begin(); it != data2->end(); it++) delete [] it->second;
- delete data2;
- }
- data2 = new map<int, char* >;
- db = DB;
- int rc = sqlite3_exec(db, "begin transaction;", 0, 0, 0);
- if (rc) throw DBError();
- sqlite3_stmt *ppStmt=0;
- char sql[100];
- sprintf(sql, "select movelist,fpC,id from algo_movelist_%d order by id", boardsize);
- rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return rc; // FIXME: catch certain errors, (and/or throw DBError?)
- while (sqlite3_step(ppStmt) == SQLITE_ROW) {
- int l = sqlite3_column_bytes(ppStmt,0);
- // printf("len movelist: %d\n", l);
- char* d = (char*)sqlite3_column_blob(ppStmt, 0);
- char* d1 = new char[l];
- for(int i=0; i<l; i++) {
- d1[i] = d[i];
- // printf("%c", (d[i] & 31)+97);
- }
- int index = sqlite3_column_int(ppStmt, 2);
- // printf("\n");
- data1->insert(make_pair(index, d1));
- data1l->insert(make_pair(index, l));
- d = (char*)sqlite3_column_blob(ppStmt, 1);
- d1 = new char[50];
- {
- for(int i=0; i<50; i++) d1[i] = d[i];
- }
- data2->insert(make_pair(index, d1));
- }
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_exec(db, "commit;", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- // printf("data sizes %d, %d, %d\n", data1->size(), data1l->size(), data2->size());
- return 0;
- }
- MovelistCand::MovelistCand(Pattern* P, int ORIENTATION, char* DICTS, int NO, char X, char Y) {
- orientation = ORIENTATION;
- p = P;
- mx = X;
- my = Y;
- Xinterv = make_pair(mx, mx+p->sizeX);
- Yinterv = make_pair(my, my+p->sizeY);
- dicts = DICTS;
- dictsNO = NO;
- contListIndex = 0;
- dictsFound = false;
- dictsFoundInitial = false;
- dictsDR = false;
- contList = p->contList; // FIXME
- }
- MovelistCand::~MovelistCand() {
- delete [] dicts;
- }
- char MovelistCand::dictsget(char x, char y) {
- return dicts[x-mx + p->sizeX*(y-my)];
- }
- void MovelistCand::dictsset(char x, char y, char d) {
- dicts[x-mx + p->sizeX*(y-my)] = d;
- }
- bool MovelistCand::in_relevant_region(char x, char y) {
- return (mx <= x && x < mx + p->sizeX && my <= y && y < my + p->sizeY);
- }
- VecMC::VecMC() : vector<MovelistCand* >() {
- candssize = 0;
- }
- VecMC::~VecMC() {
- for(VecMC::iterator it = begin(); it != end(); it++) {
- if (*it) delete *it;
- }
- }
- VecMC* VecMC::deepcopy(ExtendedMoveNumber& COUNTER, int CANDSSIZE) {
- VecMC* result = new VecMC;
- result->candssize = CANDSSIZE;
- result->counter = COUNTER;
- for(VecMC::iterator it = begin(); it != end(); it++) {
- MovelistCand* mlc = 0;
- if (*it) {
- char* DICTS = new char[(*it)->p->sizeX * (*it)->p->sizeY];
- for (int i=0; i < (*it)->p->sizeX * (*it)->p->sizeY; i++) DICTS[i] = (*it)->dicts[i];
- mlc = new MovelistCand((*it)->p, (*it)->orientation, DICTS, (*it)->dictsNO, (*it)->mx, (*it)->my);
- mlc->contListIndex = (*it)->contListIndex;
- mlc->dictsFound = (*it)->dictsFound;
- mlc->dictsF = (*it)->dictsF;
- mlc->dictsFoundInitial = (*it)->dictsFoundInitial;
- mlc->dictsFI = (*it)->dictsFI;
- mlc->dictsDR = (*it)->dictsDR;
- mlc->contList = mlc->p->contList; // FIXME
- }
- result->push_back(mlc);
- }
- return result;
- }
- int Algo_movelist::search(PatternList& patternList, GameList& gl, SearchOptions& options) {
- // FIXME progbar
- // printf("Enter Algo_movelist::search\n");
- int numOfHits = 0;
- int self_numOfSwitched = 0;
- int Bwins = 0;
- int Wwins = 0;
- int movelimit = options.moveLimit;
- int index = gl.start();
- // int gameCounter = 0;
- while (index != -1) {
- // gameCounter++;
- // if (progBar && !(gameCounter % 10))
- // progBar.redraw((progEnd-progStart)*gameCounter/len(db.current) + progStart);
-
- // printf("Process index %d\n", index);
- vector<Hit* > * result = new vector<Hit* >;
- int numOfSwitched = 0;
- stack<VecMC* > branchpoints;
- char* movel = (*data1)[index];
- int movelistIndex = 0;
- int endMovelist = (*data1l)[index];
- // printf("len movelist: %d\n", (*data1l)[index]);
- // int nodeCtr = 0;
- // for(int i=0; i<endMovelist/2; i++) {
- // printf(" - ");
- // if (movel[2*i] & BRANCHPOINT) printf("BP\n");
- // if (movel[2*i] & ENDOFVARIATION) printf("EV\n");
- // if (movel[2*i+1] & BLACK) printf("B");
- // if (movel[2*i+1] & WHITE) printf("W");
- // if (movel[2*i+1] & REMOVE) printf("C");
- // printf("%c", (movel[2*i] & 31)+97);
- // printf("%c", (movel[2*i+1] & 31)+97);
- // if (movel[2*i] & ENDOFNODE) printf("\n%d ", nodeCtr++);
- // }
- // printf("\n");
- char* fpC = (*data2)[index];
- vector<Candidate* > *currentMatchList = gl.getCurrentCandidateList();
- int candssize = currentMatchList->size();
- VecMC* cands = new VecMC;
- cands->reserve(currentMatchList->size());
- for(int mCounter=0; mCounter<(int)currentMatchList->size(); mCounter++) {
- Candidate* m = (*currentMatchList)[mCounter];
- int dNO = 0;
- Pattern* p = &patternList.data[m->orientation];
- char* d = new char[p->sizeX * p->sizeY];
- for(int i=0; i<p->sizeX; i++) {
- for(int j=0; j<p->sizeY; j++) {
- char p_ij = p->getInitial(i,j);
- if (p_ij != '.') d[i+p->sizeX*j] = p_ij;
- else d[i+p->sizeX*j] = 0;
- if (p_ij == 'X' || p_ij == 'O') dNO++;
- }
- }
- cands->push_back(new MovelistCand(p, m->orientation, d, dNO, m->x, m->y));
- }
- // printf("candssize %d\n", cands->size());
- ExtendedMoveNumber counter(0);
- while (movelistIndex < endMovelist) {
- // printf("\nnextmove %d\n", counter.total_move_num());
- if (counter.total_move_num() == movelimit+1) {
- for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
- if (*it == 0) continue;
- if (!(*it)->dictsFound) {
- delete *it;
- *it = 0;
- candssize--;
- }
- }
- }
- if (options.searchInVariations && movel[movelistIndex] & BRANCHPOINT) {
- // printf("branchpoint\n");
- branchpoints.push(cands->deepcopy(counter, candssize));
- movelistIndex += 2;
- continue;
- }
- if (options.searchInVariations && movel[movelistIndex] & ENDOFVARIATION) {
- // printf("endofvariation\n");
- if (!patternList.nextMove) { // deal with hits w/o continuation
- for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
- if (*it == 0) continue;
- if ((*it)->dictsFound) {
- if ((*it)->p->colorSwitch) {
- numOfSwitched++;
- char* rstr = new char[3];
- rstr[0] = NO_CONT;
- rstr[1] = 0;
- rstr[2] = 1;
- result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr));
- } else {
- char* rstr = new char[3];
- rstr[0] = NO_CONT;
- rstr[1] = 0;
- rstr[2] = 0;
- result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr));
- }
- }
- }
- }
- delete cands;
- cands = branchpoints.top();
- counter = cands->counter;
- candssize = cands->candssize;
- counter.down();
- branchpoints.pop();
- movelistIndex += 2;
- continue;
- }
- char x = movel[movelistIndex] & 31;
- char y = movel[movelistIndex+1] & 31;
- char co = 'O';
- char invco = 'X';
- char lower_invco = 'x';
- if (!(movel[movelistIndex+1] & REMOVE) && (movel[movelistIndex+1] & (BLACK | WHITE))) {
- // printf("mv\n");
- if (movel[movelistIndex+1] & BLACK) {
- co = 'X';
- invco = 'O';
- lower_invco = 'o';
- }
- for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
- if (*it == 0) continue;
- if ((*it)->in_relevant_region(x,y)) {
- // printf("loop 1\n %c", (*it)->dictsget(x,y));
- if ((*it)->dictsFound) { // found, so now we have found the continuation
- // printf("found\n");
- char* label;
- label = patternList.updateContinuations(
- (*it)->orientation, // pattern in question
- x-(*it)->mx, y-(*it)->my, // pos of continuation
- co, // color of continuation
- (counter.total_move_num()-(*it)->dictsF.total_move_num())>2, // tenuki?
- gl.getCurrentWinner()
- );
- if (label) { // otherwise no hit because continuation has wrong color (i.e. nextMove set)
- numOfSwitched += label[2];
- result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), label));
- }
- delete *it;
- *it = 0;
- candssize--;
- continue;
- } else if ((*it)->dictsFoundInitial) { // foundInitial, so now look for contList
- if (MoveNC(x, y, co) == ((*it)->contList)[(*it)->contListIndex]) {
- (*it)->contListIndex++;
- if ((*it)->contListIndex == (int)(*it)->contList.size()) {
- (*it)->dictsF = counter;
- (*it)->dictsFound = true;
- }
- } else {
- if ((*it)->dictsDR) { // don't restore
- delete *it;
- *it = 0;
- candssize--;
- continue;
- } else {
- (*it)->contListIndex = 0;
- (*it)->dictsFoundInitial = false;
- }
- }
- }
- if (!(*it)->dictsget(x,y)) { // this move occupies a spot which should be empty
- if (!(fpC[y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) {
- if (!(*it)->contListIndex) {
- delete *it;
- *it = 0;
- candssize--;
- continue;
- } else (*it)->dictsDR = true;
- } else {
- (*it)->dictsset(x,y,'.');
- (*it)->dictsNO++; // printf("++ A\n");
- }
- } else if ((*it)->dictsget(x,y) == lower_invco) {
- // this move occupies a wildcard spot of the wrong color
- if (!(fpC[y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) {
- if (!(*it)->contListIndex) {
- delete *it;
- *it = 0;
- candssize--;
- continue;
- } else (*it)->dictsDR = true;
- } else (*it)->dictsNO++; // printf("++ B\n");
- } else if ((*it)->dictsget(x,y) == co) {
- // this move gives us the stone we are looking for
- (*it)->dictsset(x,y,0);
- (*it)->dictsNO--; // printf("-- A\n");
- }
- }
- }
- }
- else if (movel[movelistIndex+1] & REMOVE) {
- if (movel[movelistIndex+1] & BLACK) {
- co = 'X';
- invco = 'O';
- lower_invco = 'o';
- } else if (movel[movelistIndex+1] & WHITE) {
- co = 'O';
- invco = 'X';
- lower_invco = 'x';
- }
- for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
- // printf("loop 2\n");
- if (*it == 0) continue;
- if (!(*it)->dictsFound) { // not found yet
- if ((*it)->in_relevant_region(x,y)) {
- if ((*it)->dictsFoundInitial) { // foundInitial
- int ii = (*it)->contListIndex;
- while (ii < (int)(*it)->contList.size() && (*it)->contList[ii].color == '-' &&
- (x != (*it)->contList[ii].x || y != (*it)->contList[ii].y))
- ii++;
- if (ii < (int)(*it)->contList.size() && (*it)->contList[ii].color == '-') {
- MoveNC help = (*it)->contList[ii];
- (*it)->contList[ii] = (*it)->contList[(*it)->contListIndex];
- (*it)->contList[(*it)->contListIndex] = help;
- (*it)->contListIndex++;
- } else {
- if ((*it)->dictsDR) {
- delete *it;
- *it = 0;
- candssize--;
- continue;
- } else {
- (*it)->contListIndex = 0;
- (*it)->dictsFoundInitial = false;
- }
- }
- }
- if (!(*it)->dictsget(x,y)) {
- // the stone at this position was what we needed,
- // since it was captured, we are once again looking for it:
- (*it)->dictsset(x,y,co);
- (*it)->dictsNO++; // printf("++ C\n");
- }
- else if ((*it)->dictsget(x,y) == lower_invco) {
- (*it)->dictsNO--; // printf("-- B\n");
- }
- else if ((*it)->dictsget(x,y) == '.') {
- // we are looking for an empty spot here, so this capture is helpful:
- (*it)->dictsset(x,y,0);
- (*it)->dictsNO--; // printf("-- C\n");
- }
- }
- }
- }
- }
- if (movel[movelistIndex] & ENDOFNODE) {
- vector<MovelistCand* >::iterator candsend = cands->end();
- for(vector<MovelistCand* >::iterator it = cands->begin(); it != candsend; it++) {
- if (*it == 0) continue;
- if (!(*it)->dictsNO && !(*it)->dictsFound) {
- if (!(*it)->contList.size()) {
- (*it)->dictsF = counter;
- (*it)->dictsFound = true;
- } else if (!(*it)->dictsFoundInitial) {
- (*it)->dictsFI = counter;
- (*it)->dictsFoundInitial = true;
- } else if (!(*it)->dictsDR) { // found initial position again during processing of contList
- char* d = new char[(*it)->p->sizeX*(*it)->p->sizeY];
- for (int ct=0; ct < (*it)->p->sizeX*(*it)->p->sizeY; ct++) d[ct] = (*it)->dicts[ct];
- MovelistCand* mlc = new MovelistCand((*it)->p, (*it)->orientation, d, 0, (*it)->mx, (*it)->my);
- mlc->dictsFI = counter;
- cands->push_back(mlc);
- candssize++;
- }
- }
- }
- counter.next();
- }
- if (candssize==0 && branchpoints.size()==0) break;
- movelistIndex += 2;
- }
- // printf("assemble results\n");
- if (!patternList.nextMove) { // look at matches w/o continuation
- for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
- if (*it == 0) continue;
- if ((*it)->dictsFound) {
- if ((*it)->p->colorSwitch) {
- numOfSwitched++;
- char* rstr = new char[3];
- rstr[0] = NO_CONT;
- rstr[1] = 0;
- rstr[2] = 1;
- result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr)); // FIXME what w/ variations?
- } else {
- char* rstr = new char[3];
- rstr[0] = NO_CONT;
- rstr[1] = 0;
- rstr[2] = 0;
- result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr));
- }
- }
- }
- }
- if (result->size()) {
- numOfHits += result->size();
- self_numOfSwitched += numOfSwitched;
- if (gl.getCurrentWinner() == 'B') {
- Bwins += result->size() - numOfSwitched;
- Wwins += numOfSwitched;
- } else if (gl.getCurrentWinner() == 'W') {
- Bwins += numOfSwitched;
- Wwins += result->size() - numOfSwitched;
- }
- gl.makeCurrentHit(result);
- } else delete result;
- index = gl.next();
- delete cands;
- }
- gl.num_hits = numOfHits;
- gl.num_switched = self_numOfSwitched;
- gl.Bwins = Bwins;
- gl.Wwins = Wwins;
- return 0;
- }
- #if (defined(__BORLANDC__) || defined(_MSC_VER))
- const hashtype Algo_hash::hashCodes[] = {
- 1448047776469843i64 , 23745670021858756i64 , 2503503679898819i64 ,
- 20893061577159209i64 , 10807838381971450i64 , 2362252468869198i64 ,
- 24259008893265414i64 , 12770534669822463i64 , 6243872632612083i64 ,
- 9878602848666731i64 , 15403460661141300i64 , 23328125617276831i64 ,
- 24399618481479321i64 , 6553504962910284i64 , 1670313139184804i64 ,
- 12980312942597170i64 , 20479559860862969i64 , 9622188310955879i64 ,
- 240315181816498i64 , 15806748501866401i64 , 11025185739521454i64 ,
- 9892014082139049i64 , 24468178939325513i64 , 18336761931886570i64 ,
- 17607110247268341i64 , 1659968630984898i64 , 15644176636883129i64 ,
- 21288430710467667i64 , 21718647773405600i64 , 8449573198599383i64 ,
- 12949198458251018i64 , 13260609204816340i64 , 15942818511406502i64 ,
- 19422389391992560i64 , 2306873372585698i64 , 13245768415868578i64 ,
- 3527685889767840i64 , 16821792770065498i64 , 14659578113224043i64 ,
- 8882299950073676i64 , 7855747638699870i64 , 11443553816792995i64 ,
- 10278034782711378i64 , 9888977721917330i64 , 8622555585025384i64 ,
- 20622776792089008i64 , 6447699412562541i64 , 21593237574254863i64 ,
- 4100056509197325i64 , 8358405560798101i64 , 24120904895822569i64 ,
- 21004758159739407i64 , 4380824971205155i64 , 23810250238005035i64 ,
- 11573868012372637i64 , 21740007761325076i64 , 20569500166060069i64 ,
- 23367084743140030i64 , 832128940274250i64 , 3863567854976796i64 ,
- 8401188629788306i64 , 20293444021869434i64 , 12476938100997420i64 ,
- 5997141871489394i64 , 777596196611050i64 , 8407423122275781i64 ,
- 23742268390341663i64 , 6606677504119583i64 , 17099083579458611i64 ,
- 128040681345920i64 , 7441253945309846i64 , 17672412151152227i64 ,
- 14657002484427869i64 , 3764334613856311i64 , 7399928989161192i64 ,
- 24730167942169592i64 , 13814924480574978i64 , 5810810907567287i64 ,
- 7008927747711241i64 , 3714629224790215i64 , 9946435535599731i64 ,
- 20057491299504334i64 , 15866852457019228i64 , 123155262761331i64 ,
- 1315783062254243i64 , 24497766846727950i64 , 12902532251391440i64 ,
- 16788431106050494i64 , 15993209359043506i64 , 6163570598235227i64 ,
- 23479274902645580i64 , 12086295521073246i64 , 14074331278381816i64 ,
- 1049820141442769i64 , 5160957003350972i64 , 24302799572195320i64 ,
- 23881606652035662i64 , 23969818184919245i64 , 19374430422494128i64 ,
- 9346353622623467i64 , 13646698673919768i64 , 20787456987251805i64 ,
- 19834903548127921i64 , 8194151691638546i64 , 7687885124853709i64 ,
- 4843137186034754i64 , 23141719256229263i64 , 5528755394284040i64 ,
- 22362536622784133i64 , 7624654257445620i64 , 8792845080211956i64 ,
- 24991012676161170i64 , 5382030845010972i64 , 1942150054817210i64 ,
- 1024267612932772i64 , 14257279792025309i64 , 11127353401828247i64 ,
- 4123063511789286i64 , 363215666444395i64 , 15523634951795520i64 ,
- 21114031740764324i64 , 12549698630972549i64 , 7906682572409157i64 ,
- 9682658163949194i64 , 14445831019902887i64 , 19796086007848283i64 ,
- 25041651202294181i64 , 434144873391024i64 , 24468825775827696i64 ,
- 16436890395501393i64 , 16373785289815135i64 , 16626551488832360i64 ,
- 7748715007439309i64 , 22731617567631698i64 , 14232800365889972i64 ,
- 10951727445457549i64 , 8041373240290953i64 , 24930514145406896i64 ,
- 9591184974667554i64 , 24880672410562956i64 , 23221721160805093i64 ,
- 20593543181655919i64 , 23599230930155014i64 , 15520097083998302i64 ,
- 14424914931817466i64 , 7073972177203460i64 , 16674214483955582i64 ,
- 4557916889838393i64 , 14520120252661131i64 , 2948253205366287i64 ,
- 18549806070390636i64 , 10409566723123418i64 , 18398906015238963i64 ,
- 21169009649313417i64 , 18391044531337716i64 , 2911838512392375i64 ,
- 13771057876708721i64 , 11955633853535396i64 , 18911960208175147i64 ,
- 1483143365895487i64 , 5864164841327281i64 , 16798674080914657i64 ,
- 21169543712647072i64 , 2554895121282201i64 , 12465286616181485i64 ,
- 5756888636558955i64 , 2597276631190750i64 , 2560624395830604i64 ,
- 20296901708171088i64 , 14642976680682096i64 , 12194169777111940i64 ,
- 938262584370639i64 , 7206443811292574i64 , 501111636607822i64 ,
- 5705951146039127i64 , 19098237626875269i64 , 5726006303511723i64 ,
- 5717532750720198i64 , 4848344546021481i64 , 7407311808156422i64 ,
- 2061821731974308i64 , 8556380079387133i64 , 13575103943220600i64 ,
- 10594365938844562i64 , 19966653780019989i64 , 24412404083453688i64 ,
- 8019373982039936i64 , 7753495706295280i64 , 838015840877266i64 ,
- 5235642127051968i64 , 10225916255867901i64 , 14975561937408701i64 ,
- 4914762527221109i64 , 16273933213731410i64 , 25240707945233645i64 ,
- 6477894775523777i64 , 16128190602024745i64 , 12452291569329611i64 ,
- 51030855211419i64 , 1848783942303739i64 , 2537297571305471i64 ,
- 24811709277564335i64 , 23354767332363093i64 , 11338712562024830i64 ,
- 10845782284945582i64 , 20710115514013598i64 , 19611282767915684i64 ,
- 11160258605900113i64 , 17875966449141620i64 , 8400967803093668i64 ,
- 6871997953834029i64 , 13914235659320051i64 , 8949576634650339i64 ,
- 2143755776666584i64 , 13309009078638265i64 , 17871461210902733i64 ,
- 11987276750060947i64 , 19212042799964345i64 , 9684310155516547i64 ,
- 1307858104678668i64 , 8369225045337652i64 , 11470364009363081i64 ,
- 10726698770860164i64 , 22857364846703600i64 , 25284735055035435i64 ,
- 19224377054148393i64 , 16403807100295998i64 , 4653376186522389i64 ,
- 15242640882406966i64 , 15315275662931969i64 , 11642086728644568i64 ,
- 12158439227609947i64 , 5366950703441186i64 , 21989897136444615i64 ,
- 21241101455718813i64 , 1591417368086590i64 , 14579493634035095i64 ,
- 23329624772309429i64 , 4022767503269837i64 , 12858990365780377i64 ,
- 1546772101519453i64 , 23839228242060485i64 , 3152020333001361i64 ,
- 7700997223270546i64 , 7886359803633970i64 , 18794372628879385i64 ,
- 22159114735365084i64 , 7999390508114986i64 , 17413096555746886i64 ,
- 9385231705999634i64 , 15875377080359488i64 , 4319895571584052i64 ,
- 15831501864738265i64 , 23927036136254152i64 , 9023165779396619i64 ,
- 6131245054225200i64 , 20314359892927215i64 , 1896686091879468i64 ,
- 14130616725563771i64 , 22653904323575475i64 , 9831497463521490i64 ,
- 13110057076369419i64 , 5902087517632052i64 , 23714067728868348i64 ,
- 10422641883492326i64 , 10327276345146850i64 , 795518417987648i64 ,
- 25452954487907785i64 , 3500196309207718i64 , 14513995844064906i64 ,
- 7844549909962914i64 , 9407804562184273i64 , 15229768031797498i64 ,
- 14111656085687927i64 , 16834184600349678i64 , 7291182384885469i64 ,
- 17771577974633552i64 , 21586473553657942i64 , 18166326806718423i64 ,
- 10928317030329388i64 , 13135712137024532i64 , 12947681282864548i64 ,
- 21220312239923983i64 , 9606249244876101i64 , 4653965165819933i64 ,
- 5039148287631156i64 , 3987726544496362i64 , 11235885894214833i64 ,
- 3549024987193191i64 , 6369560450327424i64 , 5296536600431238i64 ,
- 10833371878822587i64 , 5746338282416722i64 , 20335144029844343i64 ,
- 14857534135172842i64 , 13933887642921338i64 , 3610489245941154i64 ,
- 7780064458218242i64 , 18217608762631328i64 , 4861734558486078i64 ,
- 19138089389909524i64 , 162404484845663i64 , 6326150309736266i64 ,
- 5691634479075905i64 , 14377989390160001i64 , 7788436404648140i64 ,
- 20312143630017606i64 , 6781467023516504i64 , 7265384191721189i64 ,
- 13990392558924592i64 , 4811546322556989i64 , 3891404257596968i64 ,
- 19222546653408634i64 , 9733466771346453i64 , 20011679489309705i64 ,
- 11556921572925005i64 , 13429005557512149i64 , 16680841455593148i64 ,
- 394589115298971i64 , 22224576785554448i64 , 18262625753524808i64 ,
- 20893780129453860i64 , 25064972830160559i64 , 241970110039610i64 ,
- 7452533933839720i64 , 10726026396546933i64 , 17312051917081899i64 ,
- 17281553837379637i64 , 24008819488103387i64 , 5193878516496164i64 ,
- 21529615734706496i64 , 22844915602846365i64 , 17118246686087168i64 ,
- 6560869056902581i64 , 10553021967047717i64 , 3729950813036887i64 ,
- 14459986099519295i64 , 15808907290234758i64 , 6234512969275540i64 ,
- 18690008075805909i64 , 492531108753402i64 , 7721002928884704i64 ,
- 4886156035126456i64 , 21716374046066558i64 , 11035311630511661i64 ,
- 16837692753538891i64 , 20172053977953882i64 , 15488511700491202i64 ,
- 17477921115358343i64 , 24726937211646877i64 , 22480504880004621i64 ,
- 18521326635500559i64 , 8076560603417178i64 , 22382516625473209i64 ,
- 21696842111535623i64 , 12559160944089288i64 , 1661142873895453i64 ,
- 18379772814447567i64 , 10295321430586466i64 , 12378145201769592i64 ,
- 11815752235866582i64 };
- #else
- const hashtype Algo_hash::hashCodes[] = {
- 1448047776469843LL , 23745670021858756LL , 2503503679898819LL ,
- 20893061577159209LL , 10807838381971450LL , 2362252468869198LL ,
- 24259008893265414LL , 12770534669822463LL , 6243872632612083LL ,
- 9878602848666731LL , 15403460661141300LL , 23328125617276831LL ,
- 24399618481479321LL , 6553504962910284LL , 1670313139184804LL ,
- 12980312942597170LL , 20479559860862969LL , 9622188310955879LL ,
- 240315181816498LL , 15806748501866401LL , 11025185739521454LL ,
- 9892014082139049LL , 24468178939325513LL , 18336761931886570LL ,
- 17607110247268341LL , 1659968630984898LL , 15644176636883129LL ,
- 21288430710467667LL , 21718647773405600LL , 8449573198599383LL ,
- 12949198458251018LL , 13260609204816340LL , 15942818511406502LL ,
- 19422389391992560LL , 2306873372585698LL , 13245768415868578LL ,
- 3527685889767840LL , 16821792770065498LL , 14659578113224043LL ,
- 8882299950073676LL , 7855747638699870LL , 11443553816792995LL ,
- 10278034782711378LL , 9888977721917330LL , 8622555585025384LL ,
- 20622776792089008LL , 6447699412562541LL , 21593237574254863LL ,
- 4100056509197325LL , 8358405560798101LL , 24120904895822569LL ,
- 21004758159739407LL , 4380824971205155LL , 23810250238005035LL ,
- 11573868012372637LL , 21740007761325076LL , 20569500166060069LL ,
- 23367084743140030LL , 832128940274250LL , 3863567854976796LL ,
- 8401188629788306LL , 20293444021869434LL , 12476938100997420LL ,
- 5997141871489394LL , 777596196611050LL , 8407423122275781LL ,
- 23742268390341663LL , 6606677504119583LL , 17099083579458611LL ,
- 128040681345920LL , 7441253945309846LL , 17672412151152227LL ,
- 14657002484427869LL , 3764334613856311LL , 7399928989161192LL ,
- 24730167942169592LL , 13814924480574978LL , 5810810907567287LL ,
- 7008927747711241LL , 3714629224790215LL , 9946435535599731LL ,
- 20057491299504334LL , 15866852457019228LL , 123155262761331LL ,
- 1315783062254243LL , 24497766846727950LL , 12902532251391440LL ,
- 16788431106050494LL , 15993209359043506LL , 6163570598235227LL ,
- 23479274902645580LL , 12086295521073246LL , 14074331278381816LL ,
- 1049820141442769LL , 5160957003350972LL , 24302799572195320LL ,
- 23881606652035662LL , 23969818184919245LL , 19374430422494128LL ,
- 9346353622623467LL , 13646698673919768LL , 20787456987251805LL ,
- 19834903548127921LL , 8194151691638546LL , 7687885124853709LL ,
- 4843137186034754LL , 23141719256229263LL , 5528755394284040LL ,
- 22362536622784133LL , 7624654257445620LL , 8792845080211956LL ,
- 24991012676161170LL , 5382030845010972LL , 1942150054817210LL ,
- 1024267612932772LL , 14257279792025309LL , 11127353401828247LL ,
- 4123063511789286LL , 363215666444395LL , 15523634951795520LL ,
- 21114031740764324LL , 12549698630972549LL , 7906682572409157LL ,
- 9682658163949194LL , 14445831019902887LL , 19796086007848283LL ,
- 25041651202294181LL , 434144873391024LL , 24468825775827696LL ,
- 16436890395501393LL , 16373785289815135LL , 16626551488832360LL ,
- 7748715007439309LL , 22731617567631698LL , 14232800365889972LL ,
- 10951727445457549LL , 8041373240290953LL , 24930514145406896LL ,
- 9591184974667554LL , 24880672410562956LL , 23221721160805093LL ,
- 20593543181655919LL , 23599230930155014LL , 15520097083998302LL ,
- 14424914931817466LL , 7073972177203460LL , 16674214483955582LL ,
- 4557916889838393LL , 14520120252661131LL , 2948253205366287LL ,
- 18549806070390636LL , 10409566723123418LL , 18398906015238963LL ,
- 21169009649313417LL , 18391044531337716LL , 2911838512392375LL ,
- 13771057876708721LL , 11955633853535396LL , 18911960208175147LL ,
- 1483143365895487LL , 5864164841327281LL , 16798674080914657LL ,
- 21169543712647072LL , 2554895121282201LL , 12465286616181485LL ,
- 5756888636558955LL , 2597276631190750LL , 2560624395830604LL ,
- 20296901708171088LL , 14642976680682096LL , 12194169777111940LL ,
- 938262584370639LL , 7206443811292574LL , 501111636607822LL ,
- 5705951146039127LL , 19098237626875269LL , 5726006303511723LL ,
- 5717532750720198LL , 4848344546021481LL , 7407311808156422LL ,
- 2061821731974308LL , 8556380079387133LL , 13575103943220600LL ,
- 10594365938844562LL , 19966653780019989LL , 24412404083453688LL ,
- 8019373982039936LL , 7753495706295280LL , 838015840877266LL ,
- 5235642127051968LL , 10225916255867901LL , 14975561937408701LL ,
- 4914762527221109LL , 16273933213731410LL , 25240707945233645LL ,
- 6477894775523777LL , 16128190602024745LL , 12452291569329611LL ,
- 51030855211419LL , 1848783942303739LL , 2537297571305471LL ,
- 24811709277564335LL , 23354767332363093LL , 11338712562024830LL ,
- 10845782284945582LL , 20710115514013598LL , 19611282767915684LL ,
- 11160258605900113LL , 17875966449141620LL , 8400967803093668LL ,
- 6871997953834029LL , 13914235659320051LL , 8949576634650339LL ,
- 2143755776666584LL , 13309009078638265LL , 17871461210902733LL ,
- 11987276750060947LL , 19212042799964345LL , 9684310155516547LL ,
- 1307858104678668LL , 8369225045337652LL , 11470364009363081LL ,
- 10726698770860164LL , 22857364846703600LL , 25284735055035435LL ,
- 19224377054148393LL , 16403807100295998LL , 4653376186522389LL ,
- 15242640882406966LL , 15315275662931969LL , 11642086728644568LL ,
- 12158439227609947LL , 5366950703441186LL , 21989897136444615LL ,
- 21241101455718813LL , 1591417368086590LL , 14579493634035095LL ,
- 23329624772309429LL , 4022767503269837LL , 12858990365780377LL ,
- 1546772101519453LL , 23839228242060485LL , 3152020333001361LL ,
- 7700997223270546LL , 7886359803633970LL , 18794372628879385LL ,
- 22159114735365084LL , 7999390508114986LL , 17413096555746886LL ,
- 9385231705999634LL , 15875377080359488LL , 4319895571584052LL ,
- 15831501864738265LL , 23927036136254152LL , 9023165779396619LL ,
- 6131245054225200LL , 20314359892927215LL , 1896686091879468LL ,
- 14130616725563771LL , 22653904323575475LL , 9831497463521490LL ,
- 13110057076369419LL , 5902087517632052LL , 23714067728868348LL ,
- 10422641883492326LL , 10327276345146850LL , 795518417987648LL ,
- 25452954487907785LL , 3500196309207718LL , 14513995844064906LL ,
- 7844549909962914LL , 9407804562184273LL , 15229768031797498LL ,
- 14111656085687927LL , 16834184600349678LL , 7291182384885469LL ,
- 17771577974633552LL , 21586473553657942LL , 18166326806718423LL ,
- 10928317030329388LL , 13135712137024532LL , 12947681282864548LL ,
- 21220312239923983LL , 9606249244876101LL , 4653965165819933LL ,
- 5039148287631156LL , 3987726544496362LL , 11235885894214833LL ,
- 3549024987193191LL , 6369560450327424LL , 5296536600431238LL ,
- 10833371878822587LL , 5746338282416722LL , 20335144029844343LL ,
- 14857534135172842LL , 13933887642921338LL , 3610489245941154LL ,
- 7780064458218242LL , 18217608762631328LL , 4861734558486078LL ,
- 19138089389909524LL , 162404484845663LL , 6326150309736266LL ,
- 5691634479075905LL , 14377989390160001LL , 7788436404648140LL ,
- 20312143630017606LL , 6781467023516504LL , 7265384191721189LL ,
- 13990392558924592LL , 4811546322556989LL , 3891404257596968LL ,
- 19222546653408634LL , 9733466771346453LL , 20011679489309705LL ,
- 11556921572925005LL , 13429005557512149LL , 16680841455593148LL ,
- 394589115298971LL , 22224576785554448LL , 18262625753524808LL ,
- 20893780129453860LL , 25064972830160559LL , 241970110039610LL ,
- 7452533933839720LL , 10726026396546933LL , 17312051917081899LL ,
- 17281553837379637LL , 24008819488103387LL , 5193878516496164LL ,
- 21529615734706496LL , 22844915602846365LL , 17118246686087168LL ,
- 6560869056902581LL , 10553021967047717LL , 3729950813036887LL ,
- 14459986099519295LL , 15808907290234758LL , 6234512969275540LL ,
- 18690008075805909LL , 492531108753402LL , 7721002928884704LL ,
- 4886156035126456LL , 21716374046066558LL , 11035311630511661LL ,
- 16837692753538891LL , 20172053977953882LL , 15488511700491202LL ,
- 17477921115358343LL , 24726937211646877LL , 22480504880004621LL ,
- 18521326635500559LL , 8076560603417178LL , 22382516625473209LL ,
- 21696842111535623LL , 12559160944089288LL , 1661142873895453LL ,
- 18379772814447567LL , 10295321430586466LL , 12378145201769592LL ,
- 11815752235866582LL };
- #endif
- HashFEntry::HashFEntry(hashtype HASHCODE, char* BUF, int LENGTH) {
- hashCode = HASHCODE;
- buf = BUF;
- length = LENGTH;
- }
- HashFEntry::HashFEntry(const HashFEntry& hfe) {
- hashCode = hfe.hashCode;
- length = hfe.length;
- buf = new char[length];
- for(int i=0; i<length; i++) buf[i] = hfe.buf[i];
- }
- HashFEntry::~HashFEntry() {
- if (buf) {
- delete [] buf;
- buf = 0;
- }
- }
- HashhitF::HashhitF(int GAMEID, char ORIENTATION, char* blob) {
- gameid = GAMEID;
- orientation = ORIENTATION;
- cont = new MoveNC(blob[0], blob[1], blob[2]);
- emn = new ExtendedMoveNumber;
- emn->length = blob[3] * 256 + blob[4];
- emn->data = new int[emn->length];
- for(int i=0; i<emn->length; i++) {
- emn->data[i] = blob[5+2*i]*256 + blob[6+2*i];
- }
- }
- HashhitF::HashhitF() {
- cont = 0;
- emn = 0;
- }
- HashhitF::~HashhitF() {
- if (cont) delete cont;
- if (emn) delete emn;
- }
- bool cmp_HashhitF(const HashhitF* a, const HashhitF* b) {
- return a->gameid < b->gameid;
- }
- HashhitCS::HashhitCS(int GAMEID, int POSITION, bool CS) {
- gameid = GAMEID;
- position = POSITION;
- cs = CS;
- }
- bool cmp_HashhitCS(const HashhitCS* a, const HashhitCS* b) {
- return a->gameid < b->gameid;
- }
- typedef vector<HashhitF* >* vpsip;
- HashVarInfo::HashVarInfo(hashtype CHC, vector<pair<hashtype, ExtendedMoveNumber>* > * LFC,
- ExtendedMoveNumber* MOVENUMBER, int NUMSTONES) {
- chc = CHC;
- numStones = NUMSTONES;
- moveNumber = new ExtendedMoveNumber(*MOVENUMBER);
- lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
- for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = LFC->begin(); it != LFC->end(); it++) {
- lfc->push_back(new pair<hashtype, ExtendedMoveNumber>((*it)->first, (*it)->second));
- }
- }
- Algo_hash_full::Algo_hash_full(int bsize, int MAXNUMSTONES) : Algorithm(bsize) {
- branchpoints = 0;
- maxNumStones = MAXNUMSTONES;
- }
- Algo_hash_full::~Algo_hash_full() {
- }
- int Algo_hash_full::insert_hash(hashtype hashCode, ExtendedMoveNumber& mn, Move* continuation) {
- // printf("insert %lld\n", hashCode);
- char* buf = new char[30 + mn.length*2];
- if (continuation) {
- buf[0] = continuation->x;
- buf[1] = continuation->y;
- buf[2] = continuation->color;
- } else {
- buf[0] = NO_CONT;
- buf[1] = 0;
- buf[2] = 0;
- }
- buf[3] = mn.length/256;
- buf[4] = mn.length%256;
- for (int i=0; i<mn.length; i++) {
- buf[5+2*i] = mn.data[i]/265;
- buf[6+2*i] = mn.data[i]%256;
- }
- hash_vector.push_back(HashFEntry(hashCode, buf, 5+2*mn.length));
- return 0;
- }
- int Algo_hash_full::insert_all_hashes() {
- char sql[100];
- sprintf(sql, "insert into algo_hash_full_%d (hash, gameid, hit) values (?,?,?);", boardsize);
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return rc;
- for(vector<HashFEntry>::iterator it = hash_vector.begin(); it != hash_vector.end(); it++) {
- rc = sqlite3_bind_int64(ppStmt, 1, it->hashCode);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_bind_int(ppStmt, 2, gid);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_bind_blob(ppStmt, 3, it->buf, it->length, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE) return rc;
- rc = sqlite3_reset(ppStmt);
- if (rc != SQLITE_OK) return rc;
- }
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) return rc;
- hash_vector.clear();
- return 0; // success
- }
- void Algo_hash_full::initialize_process(sqlite3* DB) throw(DBError) {
- // printf("enter algo_hash_full::initialize_processing\n");
- db = DB;
- char sql[200];
- sprintf(sql, "create table algo_hash_full_%d ( id integer primary key, hash integer, gameid integer, hit text );", boardsize);
- int rc = sqlite3_exec(db, sql, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- sprintf(sql, "create index hash_idx on algo_hash_full_%d(hash);", boardsize);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- // printf("leave algo_hash_full::initialize_processing\n");
- }
- void Algo_hash_full::newgame_process(int game_id) {
- numStones = 0;
- gid = game_id;
- moveNumber = new ExtendedMoveNumber(0);
- currentHashCode = 0; // start with empty board
- lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
- branchpoints = new stack<HashVarInfo>;
- }
- void Algo_hash_full::AB_process(int x, int y) {
- for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
- Move* continuation = new Move(x,y,'B');
- if (insert_hash((*it)->first, (*it)->second, continuation) != 0) throw DBError();
- delete continuation;
- delete *it;
- }
- delete lfc;
- lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
- currentHashCode += Algo_hash::hashCodes[x + boardsize*y];
- numStones++;
- }
- void Algo_hash_full::AW_process(int x, int y) {
- for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
- Move* continuation = new Move(x,y,'W');
- if (insert_hash((*it)->first, (*it)->second, continuation) != 0) throw DBError();
- delete continuation;
- delete *it;
- }
- delete lfc;
- lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
- currentHashCode -= Algo_hash::hashCodes[x + boardsize*y];
- numStones++;
- }
- void Algo_hash_full::AE_process(int x, int y, char removed) {
- if (removed == 'B') currentHashCode -= Algo_hash::hashCodes[x + boardsize*y];
- else currentHashCode += Algo_hash::hashCodes[x + boardsize*y];
- numStones--;
- }
- void Algo_hash_full::endOfNode_process() {
- if (numStones <= maxNumStones) lfc->push_back(new pair<hashtype, ExtendedMoveNumber>(currentHashCode, *moveNumber));
- moveNumber->next();
- }
- void Algo_hash_full::pass_process() {
- // (we do not count pass as continuation)
- }
- void Algo_hash_full::move_process(Move m) throw(DBError) {
- for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
- Move* continuation = new Move(m);
- int rc = insert_hash((*it)->first, (*it)->second, continuation);
- if (rc != 0) throw DBError();
- delete continuation;
- delete *it;
- }
- delete lfc;
- lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
- int epsilon = (m.color == 'B' || m.color == 'X' ? 1 : -1);
- currentHashCode += epsilon * Algo_hash::hashCodes[m.x + boardsize*m.y];
- numStones++;
- if (m.captures) {
- vector<p_cc>::iterator it;
- for(it = m.captures->begin(); it != m.captures->end(); it++) {
- int xx = it->first;
- int yy = it->second;
- currentHashCode += epsilon * Algo_hash::hashCodes[xx + boardsize*yy];
- numStones--;
- }
- }
- }
- void Algo_hash_full::branchpoint_process() {
- branchpoints->push(HashVarInfo(currentHashCode, lfc, moveNumber, numStones));
- // printf("push %lld\n", currentHashCode);
- }
- void Algo_hash_full::endOfVariation_process() throw(DBError) {
- for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
- int rc = insert_hash((*it)->first, (*it)->second, 0);
- if (rc != 0) throw DBError();
- delete *it;
- }
- delete lfc;
- delete moveNumber;
- currentHashCode = branchpoints->top().chc;
- lfc = branchpoints->top().lfc;
- moveNumber = branchpoints->top().moveNumber;
- numStones = branchpoints->top().numStones;
- // printf("pop %lld\n", currentHashCode);
- branchpoints->pop();
- }
- void Algo_hash_full::endgame_process(bool commit) throw(DBError) {
- for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
- Move* continuation = 0;
- int rc = insert_hash((*it)->first, (*it)->second, continuation);
- if (rc != 0) throw DBError();
- delete *it;
- }
- if (commit) {
- int rc = insert_all_hashes();
- if (rc) printf("ouch %d\n",rc);
- } else hash_vector.clear();
- delete lfc;
- delete moveNumber;
- delete branchpoints;
- }
-
- void Algo_hash_full::finalize_process() {
- }
- hashtype Algo_hash_full::compute_hashkey(Pattern& pattern) {
- if (pattern.sizeX != boardsize || pattern.sizeY != boardsize)
- return NOT_HASHABLE;
- hashtype hashkey = 0;
- int ns = 0;
- for(int i=0; i<boardsize; i++) {
- for(int j=0; j<boardsize; j++) {
- char p = pattern.finalPos[i + boardsize*j];
- if (p == 'x' || p == 'o' || p == '*') return NOT_HASHABLE;
- else if (p == 'X') {
- hashkey += Algo_hash::hashCodes[i + boardsize*j];
- ns++;
- } else if (p == 'O') {
- hashkey -= Algo_hash::hashCodes[i + boardsize*j];
- ns++;
- }
- }
- }
- if (ns > maxNumStones) return NOT_HASHABLE;
- return hashkey;
- }
- int insert_result_hf(void *results, int argc, char **argv, char **azColName) throw (DBError) {
- vpsip res = ((pair<vpsip, int>*)results)->first;
- int orientation = ((pair<vpsip, int>*)results)->second;
- if (argc==2 && argv[0]) {
- res->push_back(new HashhitF(atoi(argv[0]), orientation, argv[1]));
- } else throw DBError();
- return 0;
- }
- int Algo_hash_full::search(PatternList& patternList, GameList& gl, SearchOptions& options, sqlite3* db) {
- // printf("enter algo_hash_full::search\n");
- int numOfHits = 0;
- int self_numOfSwitched = 0;
- int Bwins = 0;
- int Wwins = 0;
- int hash_result = -1; // -1 = failure; 0 = ok, but have to check w/ Algo_movelist, 1 = ok, produced final result
- int plS = patternList.size();
- vpsip results = new vector<HashhitF* >;
- for(int N=0; N<plS; N++) {
- hashtype hashCode = compute_hashkey(patternList.data[N]);
- if (hashCode == NOT_HASHABLE) return -1; // failure
- char sql[100];
- #if (defined(__BORLANDC__) || defined(_MSC_VER))
- sprintf(sql, "select gameid,hit from algo_hash_full_%d where hash = %I64d", boardsize, hashCode);
- #else
- sprintf(sql, "select gameid,hit from algo_hash_full_%d where hash = %lld", boardsize, hashCode);
- #endif
- // printf("hc %lld, %s\n", hashCode, sql);
- pair<vpsip, int> rN(results, N);
- sqlite3_exec(db, sql, insert_result_hf, &rN, 0);
- }
- if (options.trustHashFull && patternList.pattern.contList.size()==0) hash_result = 1;
- else hash_result = 0;
- if (gl.start_sorted() == 0) {
- sort(results->begin(), results->end(), cmp_HashhitF);
- // printf("res-size %d\n", results->size());
- vector<HashhitF* >::iterator resultIT = results->begin();
- while (resultIT != results->end()) {
- int index = (*resultIT)->gameid;
- if (hash_result) {
- gl.setCurrentFromIndex(index);
- int numOfSwitched = 0;
- vector<Hit* >* hits = new vector<Hit* >;
- while ((*resultIT)->gameid == index) {
- if ((*resultIT)->emn->total_move_num() > options.moveLimit) {
- resultIT++;
- continue;
- }
- char *label;
- if ((*resultIT)->cont->x != NO_CONT) { // continuation
- label = patternList.updateContinuations((*resultIT)->orientation,
- (*resultIT)->cont->x, (*resultIT)->cont->y, (*resultIT)->cont->color,
- false, // tenuki impossible with full board pattern
- gl.getCurrentWinner());
- if (label) {
- hits->push_back(new Hit((*resultIT)->emn, label));
- (*resultIT)->emn = 0;
- numOfSwitched += label[2];
- }
- } else {
- label = new char[3];
- label[0] = NO_CONT;
- label[1] = 0;
- label[2] = patternList.data[(*resultIT)->orientation].colorSwitch;
- numOfSwitched += label[2];
- hits->push_back(new Hit((*resultIT)->emn, label));
- (*resultIT)->emn = 0;
- }
- resultIT++;
- if (resultIT == results->end()) break;
- }
- if (hits->size()) {
- numOfHits += hits->size();
- self_numOfSwitched += numOfSwitched;
- if (gl.getCurrentWinner() == 'B') {
- Bwins += hits->size() - numOfSwitched;
- Wwins += numOfSwitched;
- } else if (gl.getCurrentWinner() == 'W') {
- Bwins += numOfSwitched;
- Wwins += hits->size() - numOfSwitched;
- }
- gl.makeCurrentHit(hits);
- } else delete hits;
- } else { // produce Candidate list, check using another algorithm
- vector<Candidate* >* candidates = new vector<Candidate* >;
- while ((*resultIT)->gameid == index) {
- if ((*resultIT)->emn->total_move_num() > options.moveLimit) continue;
- candidates->push_back(new Candidate(0,0,(*resultIT)->orientation));
- resultIT++;
- if (resultIT == results->end()) break;
- }
- gl.makeIndexCandidate(index, candidates);
- }
- }
- for(vector<HashhitF* >::iterator it = results->begin(); it != results->end(); it++) delete *it;
- delete results;
- gl.end_sorted();
- }
- gl.num_hits = numOfHits;
- gl.num_switched = self_numOfSwitched;
- gl.Bwins = Bwins;
- gl.Wwins = Wwins;
- return hash_result;
- }
- // -----------------------------------------------------------------------------------
- Algo_hash::Algo_hash(int bsize, const string& DBNAMEEXT, int MAXNUMSTONES) : Algorithm(bsize) {
- dbnameext = DBNAMEEXT;
- hi = 0;
- maxNumStones = MAXNUMSTONES;
- }
- Algo_hash::~Algo_hash() {
- if (hi) delete hi;
- }
- int Algo_hash::insert_hash(hashtype hashCode, int pos) {
- hash_vector.push_back(make_pair(hashCode, pos));
- return 0;
- }
- int Algo_hash::insert_all_hashes() {
- // printf("insert all hashes %d\n", hash_vector.size());
- char sql[200];
- sprintf(sql, "insert into algo_hash_%d_%s (hash, gameid, position) values (?,?,?);", boardsize, dbnameext.c_str());
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) return rc;
- rc = sqlite3_bind_int(ppStmt, 2, gid);
- if (rc != SQLITE_OK) return rc;
- for(vector<pair<hashtype, int> >::iterator it = hash_vector.begin(); it != hash_vector.end(); it++) {
- // printf("insert %d %d\n", it->first, it->second);
- rc = sqlite3_bind_int64(ppStmt, 1, it->first);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_bind_int(ppStmt, 3, it->second);
- if (rc != SQLITE_OK) return rc;
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE) return rc;
- rc = sqlite3_reset(ppStmt);
- if (rc != SQLITE_OK) return rc;
- }
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) return rc;
- return 0; // success
- }
- void Algo_hash::initialize_process(sqlite3* DB) throw(DBError) {
- // printf("enter algo_hash::initialize_processing\n");
- db = DB;
- char buf[200];
- sprintf(buf, "create table algo_hash_%d_%s ( hash integer, gameid integer, position integer );", boardsize, dbnameext.c_str());
- int rc = sqlite3_exec(db, buf, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- sprintf(buf, "create index hash_idx_%d_%s on algo_hash_%d_%s(hash);", boardsize, dbnameext.c_str(), boardsize, dbnameext.c_str());
- rc = sqlite3_exec(db, buf, 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- // printf("leave algo_hash::initialize_processing\n");
- }
-
- void Algo_hash::newgame_process(int game_id) {
- gid = game_id;
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->initialize();
- }
- void Algo_hash::AB_process(int x, int y) {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->addB(x,y);
- }
- void Algo_hash::AW_process(int x, int y) {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->addW(x,y);
- }
- void Algo_hash::AE_process(int x, int y, char removed) {
- if (removed == 'B') {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++) it->removeB(x,y);
- } else {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++) it->removeW(x,y);
- }
- }
- void Algo_hash::endOfNode_process() {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++) {
- if (it->numStones <= maxNumStones && it->changed) {
- it->changed = false;
- pair<hashtype,int> phi = it->cHC();
- insert_hash(phi.first, phi.second);
- // printf("insert hash CORNER %d %d\n", phi.first, phi.second);
- }
- }
- }
- void Algo_hash::pass_process() {
- // (we do not count pass as continuation)
- }
- void Algo_hash::move_process(Move m) throw(DBError) {
- if (m.color == 'B') {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->addB(m.x, m.y);
- if (m.captures) {
- for(vector<p_cc>::iterator cap_it = m.captures->begin(); cap_it != m.captures->end(); cap_it++) {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->removeW(cap_it->first, cap_it->second);
- }
- }
- } else {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->addW(m.x, m.y);
- if (m.captures) {
- for(vector<p_cc>::iterator cap_it = m.captures->begin(); cap_it != m.captures->end(); cap_it++) {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->removeB(cap_it->first, cap_it->second);
- }
- }
- }
- }
- void Algo_hash::branchpoint_process() {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->bppush();
- }
- void Algo_hash::endOfVariation_process() {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->bppop();
- }
- void Algo_hash::endgame_process(bool commit) {
- for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
- it->finalize();
- if (commit) {
- int rc = insert_all_hashes();
- if (rc) printf("ouch %d\n",rc);
- hash_vector.clear();
- } else hash_vector.clear();
- }
-
- void Algo_hash::finalize_process() {
- }
- pair<hashtype,int> Algo_hash::compute_hashkey(PatternList& pl, int CS) {
- return make_pair(NOT_HASHABLE,0);
- }
- int insert_result(void *rN, int argc, char **argv, char **azColName) throw (DBError) {
- vector<HashhitCS* >* results = ((pair<vector<HashhitCS* >*, hashtype>*)rN)->first;
- hashtype hashCode = ((pair<vector<HashhitCS* >*, hashtype>*)rN)->second;
- if (argc==3 && argv[0] && argv[1] && argv[2]) {
- // printf("found %s, %lld", argv[2], atoi(argv[2]));
- #if (defined(__BORLANDC__) || defined(_MSC_VER))
- ((vector<HashhitCS* >*)results)->push_back(new HashhitCS(atoi(argv[0]), atoi(argv[1]), _atoi64(argv[2])!=hashCode));
- #else
- ((vector<HashhitCS* >*)results)->push_back(new HashhitCS(atoi(argv[0]), atoi(argv[1]), atoll(argv[2])!=hashCode));
- #endif
- } else throw DBError();
- return 0;
- }
- int Algo_hash::search(PatternList& patternList, GameList& gl, SearchOptions& options, sqlite3* db) {
- // return value: -1 = failure; 0 = ok, but have to check w/ Algo_movelist
- vector<HashhitCS* >* results = new vector<HashhitCS* >;
- pair<hashtype, int> hco = compute_hashkey(patternList, 0);
- hashtype hashCode = hco.first;
- // printf("HC %lld\n", hashCode);
- hashtype hashCode2 = hashCode;
- if (hashCode == NOT_HASHABLE) {
- delete results;
- return -1; // failure
- }
- int fl = patternList.data[hco.second].flip;
- int fl2 = fl;
- char buf[100];
- #if (defined(__BORLANDC__) || defined(_MSC_VER))
- sprintf(buf, "select gameid,position,hash from algo_hash_%d_%s where hash = %I64d",
- boardsize, dbnameext.c_str(), hashCode);
- #else
- sprintf(buf, "select gameid,position,hash from algo_hash_%d_%s where hash = %lld",
- boardsize, dbnameext.c_str(), hashCode);
- #endif
- string sql = buf;
- bool cs = patternList.data[patternList.size()-1].colorSwitch;
- if (cs) {
- pair<hashtype, int> hco = compute_hashkey(patternList, 1);
- hashCode2 = hco.first;
- // printf("HC2 %lld\n", hashCode2);
- if (hashCode == NOT_HASHABLE) {
- delete results;
- return -1; // failure
- }
- fl2 = patternList.data[hco.second].flip;
- if (hashCode != hashCode2) {
- #if (defined(__BORLANDC__) || defined(_MSC_VER))
- sprintf(buf, " or hash = %I64d", hashCode2);
- #else
- sprintf(buf, " or hash = %lld", hashCode2);
- #endif
- sql += buf;
- }
- }
- sql += " order by gameid";
- if (gl.start_sorted() == 0) {
- // query database
- // printf("%s\n", sql);
- pair<vector<HashhitCS* >*, hashtype> rN(results, hashCode);
- sqlite3_exec(db, sql.c_str(), insert_result, &rN, 0);
- // printf("results->size() %d\n", results->size());
- // communicate results of query to database
-
- vector<HashhitCS* >::iterator resultIT = results->begin();
- while (resultIT != results->end()) {
- // printf("gid %d\n", (*resultIT)->gameid);
- int index = (*resultIT)->gameid;
- vector<Candidate* >* candidates = new vector<Candidate* >;
- while ((*resultIT)->gameid == index) {
- // int pos = (*resultIT)->position % (1<<16);
- int ori = (*resultIT)->position / (1<<16);
- // printf("%d %d\n", pos, ori);
- if (cs && hashCode == hashCode2) { // this is a somewhat pathological case ...
- int ind = patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)];
- candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
- ind = patternList.flipTable[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl2)];
- candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
- } else {
- if ((*resultIT)->cs) {
- // FIXME works only for corner patterns right now!
- int ind = patternList.flipTable[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl2)];
- // printf("cand cs %d %d %d\n", patternList.flipTable[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl2)], patternList.data[ind].left, patternList.data[ind].top);
- candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
- } else {
- int ind = patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)];
- // printf("cand %d %d %d\n", patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)], patternList.data[ind].left, patternList.data[ind].top);
- candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
- }
- }
- resultIT++;
- if (resultIT == results->end()) break;
- }
- gl.makeIndexCandidate(index, candidates);
- }
- for(vector<HashhitCS* >::iterator it = results->begin(); it != results->end(); it++) delete *it;
- delete results;
- gl.end_sorted();
- } else return -1;
- return 0;
- }
- Algo_hash_corner::Algo_hash_corner(int bsize, int SIZE, int MAXNUMSTONES) : Algo_hash(bsize, "CORNER", MAXNUMSTONES) {
- size = SIZE;
- char buf[5];
- sprintf(buf, "%d", size);
- dbnameext += buf;
- hi = new vector<HashInstance>;
- hi->push_back(HashInstance(0,0,size,size,boardsize));
- hi->push_back(HashInstance(0,bsize-size,size,size,boardsize));
- hi->push_back(HashInstance(bsize-size,0,size,size,boardsize));
- hi->push_back(HashInstance(bsize-size, bsize-size, size, size,boardsize));
- }
- pair<hashtype,int> Algo_hash_corner::compute_hashkey(PatternList& pl, int CS) {
- if (pl.data[0].sizeX < size || pl.data[0].sizeY < size || pl.data[0].left != pl.data[0].right || pl.data[0].top != pl.data[0].bottom || (pl.data[0].left != 0 && pl.data[0].left != boardsize-size) || (pl.data[0].top != 0 && pl.data[0].top != boardsize-size)) return make_pair(NOT_HASHABLE,0);
- hashtype hk = NOT_HASHABLE;
- int f = 0;
- vector<hashtype> hCodes;
- for(int pCtr=0; pCtr<pl.size(); pCtr++) {
- if (CS == pl.data[pCtr].colorSwitch) {
- hashtype hashkey = 0;
- int ns = 0;
- Pattern *pattern = & pl.data[pCtr];
- int offsetX = 0;
- int offsetY = 0;
- if (pattern->left > 0) offsetX = boardsize-size-pattern->left; // pattern located on east side of board
- if (pattern->top > 0) offsetY = boardsize-size-pattern->top; // ... south ...
- for(int i=0; i<size; i++) {
- for(int j=0; j<size; j++) {
- char p = pattern->finalPos[i+offsetX + pattern->sizeX*(j+offsetY)];
- if (p == 'x' || p == 'o' || p == '*') return make_pair(NOT_HASHABLE,0);
- else if (p == 'X') {
- hashkey += hashCodes[i+offsetX+pattern->left + boardsize*(j+offsetY+pattern->top)];
- ns++;
- } else if (p == 'O') {
- hashkey -= hashCodes[i+offsetX+pattern->left + boardsize*(j+offsetY+pattern->top)];
- ns++;
- }
- }
- }
- if (ns < 3 || ns > maxNumStones) return make_pair(NOT_HASHABLE,0);
- // make sure all hash keys are unique
- for(vector<hashtype>::iterator it = hCodes.begin(); it != hCodes.end(); it++)
- if (*it == hashkey) return make_pair(NOT_HASHABLE, 0);
- hCodes.push_back(hashkey);
- if (hk==NOT_HASHABLE || hashkey<hk) {
- hk = hashkey;
- f = pCtr;
- }
- }
- }
- return make_pair(hk, f);
- }
- // Algo_hash_side::Algo_hash_side(int bsize, int SIZEX, int SIZEY) : Algo_hash(bsize, "SIDE") {
- // sizeX = SIZEX;
- // sizeY = SIZEY;
- // char buf[10];
- // sprintf(buf, "%d_%d", sizeX, sizeY);
- // dbnameext += buf;
- //
- // hi = new vector<HashInstance>;
- // for(int i=1; i<bsize-1-sizeX; i++)
- // hi->push_back(HashInstance(i,0,sizeX, sizeY,boardsize));
- // for(int i=1; i<bsize-1-sizeX; i++)
- // hi->push_back(HashInstance(i,bsize-sizeY,sizeX, sizeY,boardsize));
- // for(int i=1; i<bsize-1-sizeX; i++)
- // hi->push_back(HashInstance(0, i, sizeY, sizeX,boardsize));
- // for(int i=1; i<bsize-1-sizeX; i++)
- // hi->push_back(HashInstance(bsize-sizeY, i, sizeY, sizeX,boardsize));
- // }
- HashInstance::HashInstance(char X, char Y, char SIZEX, char SIZEY, int BOARDSIZE) {
- boardsize = BOARDSIZE;
- xx = X;
- yy = Y;
- pos = xx + boardsize*yy;
- sizeX = SIZEX;
- sizeY = SIZEY;
- branchpoints = 0;
- currentHashCode = 0;
- numStones = 0;
- changed = true;
- }
- HashInstance::~HashInstance() {
- finalize();
- }
- void HashInstance::finalize() {
- if (branchpoints) {
- while (branchpoints->size()) {
- delete [] branchpoints->top().first;
- branchpoints->pop();
- }
- delete branchpoints;
- branchpoints = 0;
- }
- if (currentHashCode) {
- delete [] currentHashCode;
- currentHashCode = 0;
- }
- }
- bool HashInstance::inRelevantRegion(char X, char Y) {
- if (xx <= X && X < xx+sizeX && yy <= Y && Y < yy+sizeY) return true;
- return false;
- }
- void HashInstance::initialize() {
- currentHashCode = new hashtype[8];
- for(int i=0; i<8; i++) currentHashCode[i] = 0; // start with empty board
- numStones = 0;
- branchpoints = new stack<pair<hashtype*,int> >;
- changed = true; // do record empty pattern ...
- }
- void HashInstance::addB(char x, char y) {
- if (inRelevantRegion(x,y)) {
- changed = true;
- for(int i=0; i<8; i++) {
- currentHashCode[i] += Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
- }
- numStones++;
- }
- }
- void HashInstance::addW(char x, char y) {
- if (inRelevantRegion(x,y)) {
- changed = true;
- for(int i=0; i<8; i++) {
- currentHashCode[i] -= Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
- }
- numStones++;
- }
- }
- void HashInstance::removeB(char x, char y) {
- if (inRelevantRegion(x,y)) {
- changed = true;
- for(int i=0; i<8; i++) {
- currentHashCode[i] -= Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
- }
- numStones++;
- }
- }
- void HashInstance::removeW(char x, char y) {
- if (inRelevantRegion(x,y)) {
- changed = true;
- for(int i=0; i<8; i++) {
- currentHashCode[i] += Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
- }
- numStones++;
- }
- }
- pair<hashtype,int> HashInstance::cHC() {
- int flip = 0;
- hashtype minCHC = currentHashCode[0];
- for(int i=1; i<8; i++) {
- if (currentHashCode[i] < minCHC) {
- minCHC = currentHashCode[i];
- flip = i;
- }
- }
- return make_pair(minCHC, flip*(1<<16) + pos);
- }
- void HashInstance::bppush() {
- hashtype* chc = new hashtype[8];
- for(int i=0; i<8; i++) chc[i] = currentHashCode[i];
- branchpoints->push(make_pair(chc, numStones));
- }
- void HashInstance::bppop() {
- delete [] currentHashCode;
- currentHashCode = branchpoints->top().first;
- numStones = branchpoints->top().second;
- branchpoints->pop();
- }
- // UIntervals::UIntervals(intervs = []) {
- // data = intervs;
- // }
- //
- //
- // void UIntervals::first() {
- // if (data->size()) return data[0].first;
- // else return -1; // FIXME ?!
- // }
- //
- // void UIntervals::append(int interv_start, int interv_end) {
- // data.push_back(pair<int,int>(interv_start, interv_end));
- // }
- //
- //
- // void UIntervals::inters(UIntervals& uinterv) {
- // int current2low = 0;
- // int current2high = 0;
- //
- // vector<pair<int,int>> newUInt();
- //
- // for(int current1=0; current1 < data.size(); current1++) {
- // while (current2low < uinterv.data.size && !(uinterv.data[current2low].second > data[current1].first))
- // current2low++;
- // current2high = current2low;
- // while (current2high < uinterv.data.size() && uinterv.data[current2high].first < data[current1].second)
- // current2high++;
- // current2high--;
- //
- // if (current2low == uinterv.data.size()) break;
- // if (current2high < current2low) continue;
- //
- // newUInt.append(max(self.data[current1][0], uinterv.data[current2low][0]),
- // min(self.data[current1][1], uinterv.data[current2low][1]));
- //
- // for(int c=current2low+1; c < current2high; c++)
- // newUInt.append(uinterv.data[c].first, uninterv.data[c].second);
- //
- // if (current2high > current2low)
- // newUInt.append(uinterv.data[current2high].first, min(uinterv.data[current2high].second, data[current1].second));
- //
- // current2low = current2high;
- // }
- // data = newUInt;
- // }
- //
- // void UIntervals::isEmpty() {
- // int isEmpty = 1;
- // for(int i=0; i<data.size(); i++)
- // if (data[i].first < data[i].second) isEmpty = 0;
- // return isEmpty;
- // }
- //
- //
- //
- // Algo_intervals::Algo_intervals(int bsize) {
- // boardsize = bsize;
- // }
- //
- //
- // void Algo_intervals::initialize_process(int l) {
- //
- // movesArr = vector<long>();
- // moveIntsArr = vector<long>();
- // }
- //
- // void Algo_intervals::newgame_process() {
- // counter = 0;
- // moves = [];
- // for(int i=0; i<boardsize*boardsize; i++) moves.append([]);
- // ignore = 0;
- // }
- //
- // void Algo_intervals::AB_process(int x, int y) {
- // if (ignore) return;
- // moves[boardsize*x+y]->push_back(counter | FLAG_BLACK);
- // }
- //
- //
- // void Algo_intervals::AW_process(int x, int y) {
- // if (ignore) return;
- // moves[boardsize*x+y]->push_back(counter | FLAG_WHITE);
- // }
- //
- // void Algo_intervals::AE_process(int x, int y, char removed) {
- // if (ignore) return;
- // self.moves[self.boardsize*x+y]->push_back(counter | FLAG_REMOVE);
- // }
- //
- // void Algo_intervals::endOfNode_process() {
- // if (ignore) return;
- // counter++;
- // }
- //
- // void Algo_intervals::B_process(int x, int y, cap) {
- // if (ignore) return;
- // moves[self.boardsize*x+y]->push_back(counter | FLAG_BLACK);
- // for(c in cap)
- // moves[self.boardsize*c[0] + c[1]]->push_back(counter | FLAG_REMOVE);
- // }
- //
- // void Algo_intervals::W_process(int x, int y, cap) {
- // if (ignore) return;
- // moves[self.boardsize*x+y]->push_back(counter | FLAG_WHITE);
- // for(c in cap)
- // moves[self.boardsize*c[0] + c[1]]->push_back(counter | FLAG_REMOVE);
- // }
- //
- // void Algo_intervals::branchpoint_process() {
- // }
- //
- //
- // void Algo_intervals::endOfVariation_process() {
- // ignore = 1;
- // }
- //
- //
- // void Algo_intervals::endgame_process() {
- // for(int x=0; x < boardsize; x++) {
- // for(int y=0; y < boardsize; y++) {
- // if (!moves[self.boardsize*x+y]->size())
- // movesArr.push_back(0);
- // else if (moves[self.boardsize*x+y]->size() == 1) {
- // long d = (*moves[self.boardsize*x+y])[0];
- // self.movesArr.append(d);
- // }
- // else {
- // vector<int>* mvs = moves[self.boardsize*x+y];
- // long d = moveIntsArr.size() | FLAG_POINTER;
- //
- // vector<long> Blist;
- // vector<long> Wlist;
- // vector<long> Elist;
- //
- // Elist.push_back(0);
- //
- // int moveIndex = 0;
- // while (moveIndex < mvs.size()) {
- // if (mvs[moveIndex] & FLAG_BLACK) {
- // d = d | FLAG_BLACK;
- // Blist.push_back(mvs[moveIndex] & ~FLAG_BLACK);
- // Elist.push_back(mvs[moveIndex] & ~FLAG_BLACK);
- // if (moveIndex + 1 < mvs->size()) {
- // Blist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
- // Elist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
- // }
- // else Blist.push_back(MAXNOMOVES);
- // }
- // if (mvs[moveIndex] & FLAG_WHITE) {
- // d = d | FLAG_WHITE;
- // Wlist.push_back(mvs[moveIndex] & ~FLAG_WHITE);
- // Elist.push_back(mvs[moveIndex] & ~FLAG_WHITE);
- // if (moveIndex + 1 < mvs->size()) {
- // Wlist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
- // Elist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
- // }
- // else Wlist.append(MAXNOMOVES);
- // }
- // moveIndex += 2;
- // }
- //
- // if ((!Blist.size() || Blist[Blist.size()-1] != MAXNOMOVES) &&
- // (!Wlist.size() || Wlist[Wlist.size()-1] != MAXNOMOVES))
- // Elist.push_back(MAXNOMOVES);
- //
- // moveIntsArr.push_back(Blist.size());
- // moveIntsArr.push_back(Wlist.size());
- // moveIntsArr.push_back(Elist.size());
- // moveIntsArr.extend(Blist);
- // moveIntsArr.extend(Wlist);
- // moveIntsArr.extend(Elist);
- //
- // movesArr.push_back(d);
- // }
- // }
- // }
- // }
- //
- // void Algo_intervals::finalize_process(datap) {
- // // FIXME
- // extract datap0, datap1 from datap
- //
- // String fn = datap0 + "/movesarr" + datap1 + ".db"; // FIXME: linux specific!?
- // ofstream file(fn, ios::out|ios::trunc|ios::binary) // FIXME: careful with ios::trunc
- // file.write(movesArr, movesArrSize);
- // file.close();
- //
- // fn = datap0 + "/moveints" + datap1 + ".db"; // FIXME: linux specific!?
- // file(fn, ios::out|ios::trunc|ios::binary) // FIXME: careful with ios::trunc
- // file.write(moveIntsArr, moveIntsArrSize);
- // file.close();
- //
- // }
- //
- //
- // int Algo_intervals::retrieve_db(datap) {
- // String fn = ... "/movesarr" ...; // FIXME
- // ifstream file (fn, ios::in|ios::binary|ios::ate);
- // if (file.is_open()) {
- // ifstream::pos_type size = file.tellg();
- // delete [] movesArr;
- // movesArr = new char[size]; // FIXME: not a char array?
- // file.seekg (0, ios::beg);
- // file.read (memblock, size);
- // file.close();
- // }
- // else {
- // return 0;
- // }
- // String fn = ... "/moveints" ...; // FIXME
- // ifstream file (fn, ios::in|ios::binary|ios::ate);
- // if (file.is_open()) {
- // ifstream::pos_type size = file.tellg();
- // delete [] moveIntsArr;
- // moveIntsArr = new char[size]; // FIXME: not a char array?
- // file.seekg (0, ios::beg);
- // file.read (memblock, size);
- // file.close();
- // }
- // else {
- // return 0;
- // }
- // return 0;
- // }
- //
- // void Algo_intervals::getUInterv(mves, vector<long> mves1, int gameno, int x, int y, char color) {
- //
- // UIntervals UInterv();
- // int typeInterv = 0;
- // long d = mves[gameno*boardsize*boardsize + boardsize*x + y];
- //
- // if (d & FLAG_POINTER) {
- //
- // if (color == 'X' && !(d & FLAG_BLACK)) return 0, UIntervals();
- // if (color == 'O' && !(d & FLAG_WHITE)) return 0, UIntervals();
- //
- // long p = d & MAXNOMOVES;
- // long lenB = moves1[p];
- // long lenW = moves1[p+1];
- // long lenE = moves1[p+2];
- // long start;
- // long length;
- //
- // if (color == 'X') {
- // start = p + 3;
- // length = lenB;
- // }
- // else if (color == 'O') {
- // start = p + 3 + lenB;
- // length = lenW;
- // }
- // else if (color == '.') {
- // start = p + 3 + lenB + lenW;
- // length = lenE;
- // }
- //
- // l = [];
- // for(int i=0; i<length/2; i++)
- // l.append((moves1[start+2*i], moves1[start+2*i+1]));
- //
- // if (l[-1][1] == MAXNOMOVES) typeInterv = length-1;
- // else typeInterv = length;
- // return typeInterv, UIntervals(l);
- // }
- // else {
- // if (color == 'X' && (d & FLAG_BLACK))
- // return 1, UIntervals([( d & MAXNOMOVES , MAXNOMOVES)]);
- // else if (color == 'O' && (d & FLAG_WHITE))
- // return 1, UIntervals([( d & MAXNOMOVES , MAXNOMOVES)]);
- // else if (color == '.') {
- // if (!d) return -1, UIntervals([(0, MAXNOMOVES)]);
- // else return 1, UIntervals([(0, d & MAXNOMOVES)]);
- // }
- // }
- // return 0, UIntervals();
- // }
- //
- //
- // void Algo_intervals::search(patternList, options, db,
- // continuations, contLabelsIndex, contLabels,
- // progBar, progStart, progEnd) {
- // int ctr = 0;
- // int numOfHits = 0;
- // int overallSwitched = 0;
- // int Bwins = 0;
- // int Wwins = 0;
- // int index = db.start();
- //
- // if (!self.retrieve_db(db.datapath)) {
- // printf("Error!\n"); // FIXME
- // return;
- // }
- //
- // int movelimit = MAXNOMOVES;
- // if (options.has_key('movelimit')) movelimit = options['movelimit'];
- //
- // // moves, moves1 = self.movesArr, self.moveIntsArr;
- //
- // while (index != -1) {
- // ctr++;
- //
- // matchList = db.getCurrentMatchlist();
- // result = [];
- // int numOfSwitched = 0;
- //
- // if (progBar && !(ctr % 10))
- // progBar.redraw((progEnd-progStart)*ctr/len(db.current) + progStart);
- //
- // for(m in matchList) {
- // Pattern p = patternList.get(m[0]);
- // a0, a1 = m[1];
- //
- // UIntervals currentUInterv([(0, self.movelimit)]);
- //
- // toDo = {};
- // cont = [(MAXNOMOVES, -1,-1)];
- // int i = 0;
- // int j = 0;
- //
- // while (i < p.sizeX && !currentUInterv.isEmpty()) {
- //
- // if (p.data[i][j] == '*') {
- // Bint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
- // if (Bint.data) cont.extend([(x,i,j) for x in [z[0] for z in Bint.data]]);
- // Wint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
- // if (Wint.data) cont.extend([(x,i,j) for x in [z[0] for z in Wint.data]]);
- // }
- // else if p.data[i][j] == 'x': printf("oops\n"); // FIXME
- // else if p.data[i][j] == 'o': printf("oops\n"); // FIXME
- //
- // else {
- // typeInt, nextInt = self.getUInterv(moves, moves1, index, i+a0, j+a1, p.data[i][j]);
- //
- // if (typeInt == -1) ;
- // else if (typeInt == 0) currentUInterv = UIntervals();
- // else if (typeInt == 1) {
- // if (p.data[i][j] == '.' && cont[0][0] > nextInt.data[0][1]) {
- // Bi = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
- // Wi = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
- // counter = nextInt.data[0][1];
- // cont[0] = (nextInt.data[0][1], i, j);
- // }
- // currentUInterv.inters(nextInt);
- // }
- // else {
- // if (toDo.has_key(typeInt)) toDo[typeInt].append((i,j,nextInt));
- // else toDo[typeInt] = [(i, j, nextInt)];
- // }
- // }
- // j++;
- // if (j == p.sizeY) {
- // j = 0;
- // i++;
- // }
- // }
- //
- // toDoList = [];
- // for(ii in toDo.keys()) toDoList.extend(toDo[ii]);
- //
- // while (toDoList && !currentUInterv.isEmpty()) {
- // i, j, nextInt = toDoList[0];
- // del toDoList[0];
- //
- // currentUInterv.inters(nextInt);
- // if (currentUInterv.isEmpty()) break;
- //
- // if (p.data[i][j] == 'X') Bint = nextInt;
- // else Bint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
- // if (Bint.data) cont.extend([(x,i,j) for x in [z[0] for z in Bint.data]]);
- // if (p.data[i][j] == 'O') Wint = nextInt;
- // else Wint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
- // if (Wint.data) cont.extend([(x,i,j) for x in [z[0] for z in Wint.data]]);
- // }
- //
- // if (!currentUInterv.isEmpty()) {
- //
- // cont.sort();
- // for(counter, x, y in cont)
- // if (counter > currentUInterv.first()) break;
- //
- // if (counter == MAXNOMOVES || counter <= currentUInterv.first()) {
- // hit = 1;
- // label = '';
- // switched = p.colorSwitch;
- // }
- // else {
- // Xint = (m[1][0], m[1][0] + patternList.get(m[0]).sizeX);
- // Yint = (m[1][1], m[1][1] + patternList.get(m[0]).sizeY);
- //
- // Bint = self.getUInterv(moves, moves1, index, x+a0, y+a1, 'X')[1];
- // Wint = self.getUInterv(moves, moves1, index, x+a0, y+a1, 'O')[1];
- // if (counter in [z[0] for z in Bint.data]) co = 'W'; // !!! FIXME (cf. Algo_movelist.search)
- // else if (counter in [z[0] for z in Wint.data]) co = 'B'; // !!!
- // else raise Exception; // FIXME
- //
- // hit, label, contLabelsIndex, switched =
- // patternList.updateContinuations(m[0], x+a0, y+a1, co, Xint, Yint,
- // currentUInterv.first(), counter-1,
- // continuations, contLabels, contLabelsIndex,
- // gl.getCurrentWinner());
- // }
- //
- // if (hit) {
- // numOfSwitched += switched;
- // if (switched) result.append(str(currentUInterv.first())+label+'-');
- // else result.append(str(currentUInterv.first())+label);
- // }
- // }
- // }
- //
- // if (result) {
- // result.sort();
- // db.makeCurrentHit(join(result, ', '));
- // numOfHits = numOfHits + len(result);
- // overallSwitched += numOfSwitched;
- //
- // if (gl.getCurrentWinner() == 'B') {
- // Bwins = Bwins + len(result) - numOfSwitched;
- // Wwins = Wwins + numOfSwitched;
- // }
- // else if (gl.getCurrentWinner() == 'W') {
- // Bwins = Bwins + numOfSwitched;
- // Wwins = Wwins + len(result) - numOfSwitched;
- // }
- // }
- // else db.discardCurrent();
- //
- // index = db.next();
- // }
- // return numOfHits, Bwins, Wwins, overallSwitched;
- // }
- // ----------------------------------------------------------------------------------------------
- // GameList and related stuff
- Candidate::Candidate(char X, char Y, char ORIENTATION) {
- x = X;
- y = Y;
- orientation = ORIENTATION;
- }
- Hit::Hit(ExtendedMoveNumber* POS, char* LABEL) { // LABEL is a char[3]
- pos = POS; // note that we do not copy these!
- label = LABEL;
- }
- Hit::~Hit() {
- delete pos;
- delete [] label;
- }
- Hit::Hit(SnapshotVector& snv) {
- int length = snv.retrieve_int();
- int* data = snv.retrieve_intp();
- pos = new ExtendedMoveNumber(length, data);
- delete [] data;
- label = snv.retrieve_charp();
- }
- void Hit::to_snv(SnapshotVector& snv) {
- snv.pb_int(pos->length);
- snv.pb_intp(pos->data, pos->length);
- snv.pb_charp(label, 3);
- }
- bool Hit::cmp_pts(Hit* a, Hit* b) {
- if (a->pos->length != b->pos->length) return a->pos->length < b->pos->length;
- for(int i=0; i < a->pos->length; i++)
- if (a->pos->data[i] != b->pos->data[i]) return a->pos->data[i] < b->pos->data[i];
- return false;
- }
- SearchOptions::SearchOptions() {
- fixedColor = 0;
- moveLimit = 10000;
- nextMove = 0;
- trustHashFull = false;
- searchInVariations = true;
- algos = (1<<30) - 1; // use all available algorithms
- }
- SearchOptions::SearchOptions(int FIXEDCOLOR, int NEXTMOVE, int MOVELIMIT) {
- fixedColor = FIXEDCOLOR;
- moveLimit = MOVELIMIT;
- nextMove = NEXTMOVE;
- trustHashFull = false;
- searchInVariations = true;
- algos = (1<<30) - 1; // use all available algorithms
- }
- SearchOptions::SearchOptions(SnapshotVector& snv) {
- fixedColor = snv.retrieve_int();
- moveLimit = snv.retrieve_int();
- nextMove = snv.retrieve_int();
- trustHashFull = snv.retrieve_int();
- searchInVariations= snv.retrieve_int();
- algos = snv.retrieve_int();
- }
- void SearchOptions::to_snv(SnapshotVector& snv) {
- snv.pb_int(fixedColor);
- snv.pb_int(moveLimit);
- snv.pb_int(nextMove);
- snv.pb_int(trustHashFull);
- snv.pb_int(searchInVariations);
- snv.pb_int(algos);
- }
- ProcessOptions::ProcessOptions() {
- processVariations = true;
- sgfInDB = true;
- rootNodeTags = "BR,CA,DT,EV,HA,KM,PB,PC,PW,RE,RO,RU,SZ,US,WR";
- algos = ALGO_FINALPOS | ALGO_MOVELIST | ALGO_HASH_FULL | ALGO_HASH_CORNER;
- algo_hash_full_maxNumStones = 50;
- algo_hash_corner_maxNumStones = 20;
- }
- ProcessOptions::ProcessOptions(string s) {
- int p = 0;
- if (s[p++] == 't') processVariations = true;
- else processVariations = false;
- if (s[p++] == 't') sgfInDB = true;
- else sgfInDB = false;
- p++;
- int pn = s.find('|', p) + 1;
- algos = atoi(s.substr(p, pn-p-1).c_str());
-
- p = pn;
- pn = s.find('|', p) + 1;
- algo_hash_full_maxNumStones = atoi(s.substr(p, pn-p-1).c_str());
-
- p = pn;
- pn = s.find('|', p) + 1;
- algo_hash_corner_maxNumStones = atoi(s.substr(p, pn-p-1).c_str());
-
- rootNodeTags = s.substr(pn);
- }
- string ProcessOptions::asString() {
- string result;
- if (processVariations) result += "t";
- else result += "f";
- if (sgfInDB) result += "t";
- else result += "f";
- char buf[200];
- sprintf(buf, "|%d|%d|%d|%s", algos, algo_hash_full_maxNumStones, algo_hash_corner_maxNumStones, rootNodeTags.c_str());
- result += buf;
- return result;
- }
- void ProcessOptions::validate() {
- string::iterator it = rootNodeTags.begin();
- while (it != rootNodeTags.end()) {
- if (*it == ' ') it = rootNodeTags.erase(it);
- else it++;
- }
- if (rootNodeTags.find("PB") == string::npos) rootNodeTags += ",PB";
- if (rootNodeTags.find("PW") == string::npos) rootNodeTags += ",PW";
- if (rootNodeTags.find("RE") == string::npos) rootNodeTags += ",RE";
- if (rootNodeTags.find("DT") == string::npos) rootNodeTags += ",DT";
- algos |= ALGO_FINALPOS | ALGO_MOVELIST; // these are mandatory at the moment
- }
- vector<string>* ProcessOptions::SGFTagsAsStrings() {
- vector<string>* SGFtags = new vector<string>;
- int ctr = 0;
- unsigned int p = 0;
- unsigned int pn = rootNodeTags.find(',', p);
- while (pn != string::npos) {
- SGFtags->push_back(rootNodeTags.substr(p,pn-p));
- ctr++;
- p = pn+1;
- pn = rootNodeTags.find(',', p);
- }
- SGFtags->push_back(rootNodeTags.substr(p));
- return SGFtags;
- }
- GameListEntry::GameListEntry(int ID, char WINNER, string GAMEINFOSTR) {
- // printf("GLE %d %c %s\n", ID, WINNER, GAMEINFOSTR);
- id = ID;
- if (WINNER == 'B' || WINNER == 'b') winner = 'B';
- else if (WINNER == 'W' || WINNER == 'w') winner = 'W';
- else if (WINNER == 'J' || WINNER == 'j') winner = 'J';
- else winner = '-';
- gameInfoStr = GAMEINFOSTR;
- hits = 0;
- candidates = 0;
- }
- GameListEntry::~GameListEntry() {
- if (hits) {
- for(vector<Hit* >::iterator it = hits->begin(); it != hits->end(); it++) delete *it;
- delete hits;
- hits = 0;
- }
- if (candidates) {
- for(vector<Candidate* >::iterator it = candidates->begin(); it != candidates->end(); it++) delete *it;
- delete candidates;
- candidates = 0;
- }
- }
- void GameListEntry::hits_from_snv(SnapshotVector& snv) {
- int h_size = snv.retrieve_int();
- hits = new vector<Hit* >;
- for(int j=0; j<h_size; j++) {
- hits->push_back(new Hit(snv));
- }
- }
- int insertEntry(void *gl, int argc, char **argv, char **azColName) {
- char winner = '-';
- if (argv[1] && (argv[1][0] == 'B' || argv[1][0] == 'W' || argv[1][0] == 'J')) winner = argv[1][0];
- string gameInfoStr = ((GameList*)gl)->format2;
- for(int i=0; i<((GameList*)gl)->numColumns; i++) {
- char strpip1[20];
- sprintf(strpip1, "[[%d[[F", i);
- unsigned int p = gameInfoStr.find(strpip1);
- if (p != string::npos) {
- if (argv[i]) {
- string fn = argv[i];
- if (fn.substr(fn.size()-4) == ".sgf" || fn.substr(fn.size()-4) == ".mgt")
- gameInfoStr.replace(p, strlen(strpip1), fn.substr(0,fn.size()-4));
- else gameInfoStr.replace(p, strlen(strpip1), fn);
- } else gameInfoStr.erase(gameInfoStr.find(strpip1), strlen(strpip1));
- continue;
- }
- sprintf(strpip1, "[[%d", i);
- p = gameInfoStr.find(strpip1);
- if (p != string::npos) {
- if (argv[i]) gameInfoStr.replace(p, strlen(strpip1), argv[i]);
- else gameInfoStr.erase(gameInfoStr.find(strpip1), strlen(strpip1));
- }
- }
- unsigned int p = gameInfoStr.find("[[W");
- if (p != string::npos) gameInfoStr.replace(p, 3, 1, winner);
- // printf("id %s\n", argv[0]);
- ((GameList*)gl)->all->push_back(new GameListEntry(atoi(argv[0]), winner, gameInfoStr));
- return 0;
- }
- int dbinfo_callback(void *s, int argc, char **argv, char **asColName) {
- char** cpp = (char**)s;
- if (argc && argv[0]) {
- // printf("dbi_cb %s\n", argv[0]);
- *cpp = new char[strlen(argv[0])+1];
- strcpy(*cpp, argv[0]);
- }
- return 0;
- }
- GameList::GameList(char* DBNAME, string ORDERBY, string FORMAT, ProcessOptions* p_options, int cache) throw(DBError) {
- duplicates = 0;
- labels = 0;
- continuations = 0;
- mrs_pattern = 0;
- searchOptions = 0;
- dbname = new char[strlen(DBNAME)+2];
- strcpy(dbname, DBNAME);
- db = algo_db1 = algo_db2 = 0;
- dbname[strlen(DBNAME)] = '1';
- dbname[strlen(DBNAME)+1] = 0;
- int rc = sqlite3_open(dbname, &algo_db1);
- if (rc) {
- sqlite3_close(algo_db1);
- algo_db1 = 0;
- throw DBError();
- }
- rc = sqlite3_busy_timeout(algo_db1, 200);
- if (rc) throw DBError();
- rc = sqlite3_exec(algo_db1, "pragma synchronous = off;", 0, 0, 0);
- if (rc) throw DBError();
- char cache_str[100];
- sprintf(cache_str, "pragma cache_size = %d", cache*1000);
- rc = sqlite3_exec(algo_db1, cache_str, 0, 0, 0);
- if (rc) throw DBError();
- dbname[strlen(DBNAME)] = '2';
- dbname[strlen(DBNAME)+1] = 0;
- rc = sqlite3_open(dbname, &algo_db2);
- if (rc) {
- sqlite3_close(algo_db2);
- algo_db2 = 0;
- throw DBError();
- }
- rc = sqlite3_busy_timeout(algo_db2, 200);
- if (rc) throw DBError();
- rc = sqlite3_exec(algo_db2, "pragma synchronous = off;", 0, 0, 0);
- if (rc) throw DBError();
- sprintf(cache_str, "pragma cache_size = %d", cache*7000);
- rc = sqlite3_exec(algo_db2, cache_str, 0, 0, 0);
- if (rc) throw DBError();
- // try to retrieve basic options from database
- dbname[strlen(DBNAME)] = 0;
- rc = sqlite3_open(dbname, &db);
- if (rc) {
- sqlite3_close(db);
- db = 0;
- throw DBError();
- }
- rc = sqlite3_busy_timeout(db, 200);
- if (rc) throw DBError();
- rc = sqlite3_exec(db, "pragma synchronous = off;", 0, 0, 0);
- if (rc) throw DBError();
- sprintf(cache_str, "pragma cache_size = %d", cache*1000);
- rc = sqlite3_exec(db, cache_str, 0, 0, 0);
- if (rc) throw DBError();
- rc = sqlite3_exec(db, "create table db_info ( info text );", 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- char* dbinfo = 0;
- rc = sqlite3_exec(db, "select * from db_info where rowid = 1;", dbinfo_callback, &dbinfo, 0);
- if (rc != SQLITE_OK) throw DBError();
- if (dbinfo) {
- // printf("dbinfo: %s\n", dbinfo);
- p_op = new ProcessOptions(dbinfo);
- delete [] dbinfo;
- char* bsizes = 0;
- rc = sqlite3_exec(db, "select * from db_info where rowid = 2;", dbinfo_callback, &bsizes, 0);
- if (rc != SQLITE_OK) throw DBError();
- if (bsizes) {
- // printf("board sizes %s\n", bsizes); // should be a comma-sep. list of integers *ending w/ a comma*
- string bsizes_str(bsizes);
- delete [] bsizes;
- unsigned int p = 0;
- unsigned int pn = bsizes_str.find(",",p);
- while (pn > p && pn != string::npos) {
- boardsizes.push_back(atoi(bsizes_str.substr(p, pn-p).c_str()));
- p = pn+1;
- pn = bsizes_str.find(",",p);
- }
- }
- } else { // if this does not work: create database and read p_options (or use defaults)
- // printf("retrieving dbinfo failed\n");
- if (p_options == 0) p_op = new ProcessOptions(); // use default values
- else {
- // printf("use p_options\n");
- p_op = new ProcessOptions(*p_options);
- p_op->validate(); // make sure the most important information is contained in rootNodeTags list
- }
- string sql = "insert into db_info (rowid,info) values (1,'";
- sql += p_op->asString();
- sql += "');";
- rc = sqlite3_exec(db, sql.c_str(), 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_exec(db, "insert into db_info (rowid, info) values (2, ',');", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- // set up snapshot db
- rc = sqlite3_exec(db, "create table snapshots ( data text );", 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- // printf("set up Algorithm instances\n");
- for(vector<int>::iterator it = boardsizes.begin(); it != boardsizes.end(); it++)
- addAlgos(*it);
- all = 0;
- currentList = oldList = 0;
- readDBs = 0;
- resetFormat(ORDERBY, FORMAT);
- }
- void GameList::resetFormat(string ORDERBY, string FORMAT) {
- // printf("enter resetFormat\n");
- if (FORMAT == "") { // use default format string
- numColumns = 5;
- format1 = "id,re,pw,pb,dt";
- format2 = "[[2 - [[3 ([[W), [[4, ";
- } else {
- char buf[10];
- numColumns = 2;
- format1 = "id,re";
- format2 = FORMAT;
- unsigned int p = 0;
- unsigned int q = 0;
- while (p != string::npos) {
- p = format2.find("[[",p);
- q = format2.find("]]",p);
- if (p+2 < format2.size() && q != string::npos) {
- string col = format2.substr(p+2, q-p-2);
- // check availability
- if (col == "id" || col == "filename" || col == "pos" || col == "duplicate" || col == "date" || p_op->rootNodeTags.find(col) != string::npos) {
- sprintf(buf, "[[%d", numColumns++);
- format2.replace(p,q+2-p, buf);
- format1 += ",";
- format1 += col;
- } else if (col == "winner") format2.replace(p,q+2-p, "[[W");
- else if (col == "filename.") {
- sprintf(buf, "[[%d[[F", numColumns++);
- format2.replace(p, q+2-p, buf);
- format1 += ",filename";
- }
- p++;
- } else break;
- }
- }
- if (ORDERBY == "" || ORDERBY == "id" || ORDERBY == "ID" || ORDERBY == "Id" || ORDERBY == "iD") orderby = "id";
- else orderby = ORDERBY + ",id";
- // printf("finished parsing\n");
- readDB();
- }
- void GameList::addAlgos(int bs) {
- int ctr = algo_ps.size()/20;
- // printf("add algos %d %d %d\n", bs, ctr, p_op->algos);
- for(int i=0; i<20; i++) {
- algo_ps.push_back(0);
- algo_dbs.push_back(0);
- }
- algo_ps[20*ctr] = new Algo_signature(bs);
- algo_dbs[20*ctr] = db;
- if (p_op->algos & ALGO_FINALPOS) {
- algo_ps[algo_finalpos+20*ctr] = new Algo_finalpos(bs);
- algo_dbs[algo_finalpos+20*ctr] = algo_db1;
- }
- if (p_op->algos & ALGO_MOVELIST) {
- algo_ps[algo_movelist+20*ctr] = new Algo_movelist(bs);
- algo_dbs[algo_movelist+20*ctr] = algo_db1;
- }
- if (p_op->algos & ALGO_HASH_FULL) {
- algo_ps[algo_hash_full+20*ctr] = new Algo_hash_full(bs, p_op->algo_hash_corner_maxNumStones);
- algo_dbs[algo_hash_full+20*ctr] = algo_db2;
- }
- if (p_op->algos & ALGO_HASH_CORNER) {
- algo_ps[algo_hash_corner+20*ctr] = new Algo_hash_corner(bs, 7, p_op->algo_hash_corner_maxNumStones);
- algo_dbs[algo_hash_corner+20*ctr] = algo_db2;
- }
- // for(int a=20*ctr; a<20*(ctr+1); a++) printf("aa %d %p\n", a, algo_ps[a]);
- // if (algos & ALGO_HASH_SIDE)
- // algo_ps[algo_hash_side] = new Algo_hash_side(boardsize, 6, 4, p_op->algo_hash_side_maxNumStones);
- }
- void GameList::readDB() throw(DBError) {
- // printf("read dbs\n");
- if (oldList) delete oldList;
- if (currentList) delete currentList;
- if (all) {
- for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++)
- delete *it;
- delete all;
- }
- current = -1;
- all = new vector<GameListEntry* >;
- currentList = 0;
- oldList = 0;
- int rc;
- rc = sqlite3_exec(db, "begin transaction;", 0, 0, 0);
- if (rc) throw DBError();
- string sql = "select ";
- sql += format1;
- sql += " from games order by ";
- sql += orderby;
- // printf("sql: %s\n", sql.c_str());
- rc = sqlite3_exec(db, sql.c_str(), insertEntry, this, 0);
- if (rc != SQLITE_OK && rc != SQLITE_ERROR) {
- throw DBError();
- }
- // printf("read.\n");
- // SQLITE_ERROR may occur since table might not yet exist
- readPlayersList();
- rc = sqlite3_exec(db, "commit;", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- if (rc == SQLITE_OK && !readDBs) {
- for(unsigned int a=0; a < 20*boardsizes.size(); a++) {
- if (algo_ps[a]) algo_ps[a]->readDB(algo_dbs[a]);
- }
- readDBs = 1;
- }
- // printf("read.\n");
- reset();
- // printf("leave readDB\n");
- }
- GameList::~GameList() {
- // printf("enter ~GameList\n");
- if (mrs_pattern) delete mrs_pattern;
- if (searchOptions) delete searchOptions;
- if (p_op) delete p_op;
- if (labels) delete [] labels;
- if (continuations) delete [] continuations; // FIXME CHECK whether the Continuation destructor is invoked!
- if (duplicates) delete duplicates;
- delete [] dbname;
- if (all) {
- for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++)
- delete *it;
- delete all;
- }
- if (currentList) delete currentList;
- if (oldList) delete oldList;
- for(unsigned int i=0; i<20*boardsizes.size(); i++)
- if (algo_ps[i]) delete algo_ps[i];
- if (db) sqlite3_close(db);
- db = 0;
- if (algo_db1) sqlite3_close(algo_db1);
- algo_db1 = 0;
- if (algo_db2) sqlite3_close(algo_db2);
- algo_db2 = 0;
- // printf("leave ~GameList\n");
- }
- int GameList::start() {
- current = 0;
- if (oldList) delete oldList;
- oldList = currentList;
- currentList = new vector<pair<int,int> >;
- if (oldList && oldList->size()) return (*oldList)[0].first;
- else {
- if (oldList) delete oldList;
- oldList = 0;
- return -1;
- }
- }
- int GameList::next() {
- current++;
- if (current < (int)oldList->size()) return (*oldList)[current].first;
- else {
- if (oldList) delete oldList;
- oldList = 0;
- return -1;
- }
- }
- bool sndcomp(const pair<int,int>& a, const pair<int,int>& b) {
- return a.second < b.second;
- }
- int GameList::start_sorted() {
- current = 0;
- if (oldList) delete oldList;
- oldList = currentList;
- currentList = new vector<pair<int,int> >;
- if (!oldList || !oldList->size()) {
- if (oldList) delete oldList;
- oldList = 0;
- return -1;
- }
- sort(oldList->begin(), oldList->end());
- return 0;
- }
- int GameList::end_sorted() {
- // printf("end sorted\n");
- sort(currentList->begin(), currentList->end(), sndcomp);
- delete oldList;
- oldList = 0;
- return 0;
- }
- char GameList::getCurrentWinner() {
- return (*all)[(*oldList)[current].second]->winner;
- }
- vector<Candidate* > * GameList::getCurrentCandidateList() {
- return (*all)[(*oldList)[current].second]->candidates;
- }
- void GameList::makeCurrentCandidate(vector<Candidate* > * candidates) {
- GameListEntry* gle = (*all)[(*oldList)[current].second];
- if (gle->candidates) delete gle->candidates;
- gle->candidates = candidates;
- currentList->push_back((*oldList)[current]);
- }
- void GameList::makeCurrentHit(vector<Hit* > * hits) {
- GameListEntry* gle = (*all)[(*oldList)[current].second];
- if (gle->hits) delete gle->hits;
- gle->hits = hits;
- sort(gle->hits->begin(), gle->hits->end(), Hit::cmp_pts);
- currentList->push_back((*oldList)[current]);
- }
- void GameList::setCurrentFromIndex(int index) {
- int start = current;
- int end = oldList->size();
- int m = start;
- while (start < end) {
- m = (end+start)/2;
- if (index == (*oldList)[m].first) {
- break;
- } else {
- if (index < (*oldList)[m].first) end = m;
- else start = m+1;
- }
- }
- current = m;
- }
- void GameList::makeIndexHit(int index, vector<Hit* > * hits) {
- int m = get_current_index(index, ¤t);
- if (m != -1) {
- currentList->push_back((*oldList)[m]);
- if (hits) {
- if ((*all)[(*oldList)[m].second]->hits) delete (*all)[(*oldList)[m].second]->hits;
- (*all)[(*oldList)[m].second]->hits = hits;
- }
- }
- }
- void GameList::makeIndexCandidate(int index, vector<Candidate* > * candidates) {
- int m = get_current_index(index, ¤t);
- if (m != -1) {
- currentList->push_back((*oldList)[m]);
- if (candidates) {
- if ((*all)[(*oldList)[m].second]->candidates) delete (*all)[(*oldList)[m].second]->candidates;
- (*all)[(*oldList)[m].second]->candidates = candidates;
- }
- }
- }
- void GameList::reset() {
- if (oldList) delete oldList;
- oldList = 0;
- if (currentList) delete currentList;
- currentList = new vector<pair<int,int> >;
- int counter = 0;
- for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++) {
- if ((*it)->hits) {
- for(vector<Hit* >::iterator ith = (*it)->hits->begin(); ith != (*it)->hits->end(); ith++)
- delete *ith;
- delete (*it)->hits;
- (*it)->hits = 0;
- }
- if ((*it)->candidates) {
- for(vector<Candidate* >::iterator itc = (*it)->candidates->begin(); itc != (*it)->candidates->end(); itc++)
- delete *itc;
- delete (*it)->candidates;
- (*it)->candidates = 0;
- }
- currentList->push_back(make_pair((*it)->id, counter++));
- }
- num_hits = 0;
- num_switched = 0;
- Bwins = 0;
- Wwins = 0;
- }
- void GameList::tagsearch(int tag) throw(DBError) {
- char sql[200];
- if (!tag) return;
- if (tag > 0) {
- sprintf(sql, "select games.id from games join game_tags on games.id = game_tags.game_id where game_tags.tag_id = %d order by games.id", tag);
- } else {
- sprintf(sql, "select games.id from games except select games.id from games join game_tags on games.id = game_tags.game_id where game_tags.tag_id = %d order by games.id;", -tag);
- }
- gisearch(sql, 1);
- }
- void GameList::setTag(int tag, int start, int end) throw(DBError) {
- if (end==0) end = currentList->size();
- if (start>end || end > (int)currentList->size()) return;
- int rc = sqlite3_exec(db, "begin transaction", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- for(int i = start; i < end; i++) {
- if (getTags(i, tag).size()) continue;
- char sql[200];
- sprintf(sql, "insert into game_tags (game_id, tag_id) values (%d, %d)", (*all)[(*currentList)[i].second]->id, tag);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- rc = sqlite3_exec(db, "commit", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- void GameList::deleteTag(int tag, int i) throw(DBError) {
- char sql[200];
- if (i == -1) sprintf(sql, "delete from game_tags where tag_id=%d", tag);
- else sprintf(sql, "delete from game_tags where game_id=%d and tag_id=%d", (*all)[(*currentList)[i].second]->id, tag);
- int rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- int gettags_callback(void *res, int argc, char **argv, char **azColName) {
- if (!argc) return 1;
- ((vector<int>*)res)->push_back(atoi(argv[0]));
- return 0;
- }
- vector<int> GameList::getTags(int i, int tag) throw(DBError) {
- vector<int> result;
- char sql[200];
- if (tag==0) sprintf(sql, "select tag_id from game_tags where game_id=%d", (*all)[(*currentList)[i].second]->id);
- else sprintf(sql, "select tag_id from game_tags where game_id=%d and tag_id=%d", (*all)[(*currentList)[i].second]->id, tag);
- int rc = sqlite3_exec(db, sql, gettags_callback, &result, 0);
- if (rc != SQLITE_OK) throw DBError();
- return result;
- }
- void GameList::insert_duplicate(int i1, int i2, vector<vector<int> >* dupl) {
- int ii1 = get_current_index_CL(i1);
- int ii2 = get_current_index_CL(i2);
- // printf("insert_duplicate %d, %d\n", ii1, ii2);
- if (ii1 == -1 || ii2 == -1) return;
- bool inserted = false;
- for(vector<vector<int> >::iterator it = dupl->begin(); it != dupl->end(); it++) {
- vector<int>::iterator i = it->begin();
- while(i != it->end() && *i != ii1 && *i != ii2) i++;
- if (i == it->end()) continue;
- int insert = ii1;
- if (*i == ii1) insert = ii2;
- while (i != it->end() && *i != insert) i++;
- if (i == it->end()) it->push_back(insert);
- sort(it->begin(), it->end());
- inserted = true;
- break;
- }
- if (!inserted) {
- vector<int> new_list;
- if (ii1 < ii2) {
- new_list.push_back(ii1);
- new_list.push_back(ii2);
- } else {
- new_list.push_back(ii2);
- new_list.push_back(ii1);
- }
- dupl->push_back(new_list);
- }
- }
- int GameList::find_duplicates(int bs, bool strict) throw(DBError) {
- if (!currentList->size()) return 0; // this also deals with the case of an empty db
- int bs_index = 0;
- if (duplicates) delete duplicates;
- duplicates = new vector<vector<int> >;
- if (strict) {
- vector<int>::iterator it = boardsizes.begin();
- while (it != boardsizes.end() && *it != bs) {
- bs_index++;
- it++;
- }
- if (it == boardsizes.end()) {
- return 0;
- }
- }
- sort(currentList->begin(), currentList->end());
- sqlite3_stmt *ppStmt=0;
- char sql[200];
- sprintf(sql, "select as1.id,as2.id from algo_signature_%d as1 join algo_signature_%d as2 on as1.signature = as2.signature where as1.id < as2.id;", bs, bs);
- int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) throw DBError();
- do {
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE && rc != SQLITE_ROW) throw DBError();
- if (rc == SQLITE_ROW) {
- if (!strict || ((Algo_finalpos*)algo_ps[20*bs_index+algo_finalpos])->equal(sqlite3_column_int(ppStmt, 0), sqlite3_column_int(ppStmt, 1)))
- insert_duplicate(sqlite3_column_int(ppStmt, 0), sqlite3_column_int(ppStmt, 1), duplicates);
- }
- } while (rc == SQLITE_ROW);
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) throw DBError();
- sort(currentList->begin(), currentList->end(), sndcomp);
- return duplicates->size();
- }
- vector<int> GameList::retrieve_duplicates_VI(unsigned int i) {
- if (i>=duplicates->size()) return vector<int>();
- return (*duplicates)[i];
- }
- int* GameList::retrieve_duplicates_PI(unsigned int i) {
- if (i>=duplicates->size()) return 0;
- int* result = new int[(*duplicates)[i].size()+1];
- int j = 0;
- for(vector<int>::iterator it = (*duplicates)[i].begin(); it != (*duplicates)[i].end(); it++)
- result[j++] = *it;
- result[(*duplicates)[i].size()] = -1;
- return result;
- }
- int GameList::get_current_index(int id, int* start) {
- // use this in between start_sorted() and end_sorted() only!
- int end = oldList->size();
- int m = *start;
- while (*start < end) {
- m = (end+*start)/2;
- if (id == (*oldList)[m].first) {
- *start = m;
- return m;
- } else {
- if (id < (*oldList)[m].first) end = m;
- else *start = m+1;
- }
- }
- return -1;
- }
- int GameList::get_current_index_CL(int id, int start) {
- // use this in between start_sorted() and end_sorted() only!
- int end = currentList->size();
- int m = start;
- while (start < end) {
- m = (end+start)/2;
- if (id == (*currentList)[m].first) return m;
- else {
- if (id < (*currentList)[m].first) end = m;
- else start = m+1;
- }
- }
- return -1;
- }
- void GameList::sigsearch(char* sig, int boardsize) throw(DBError) {
- if (start_sorted() == 0) {
- char* symmetrized_sig = 0;
- if (boardsize) symmetrized_sig = symmetrize(sig, boardsize);
- // char ssig[13];
- // for(int i=0; i<12; i++) ssig[i] = symmetrized_sig[i];
- // ssig[12] = 0;
- // printf("ssig: %s\n", ssig);
- string query = "select id from algo_signature_19 where signature like ? order by id";
- // int rc = sqlite3_exec(db, query.c_str(), sigs_callback, this, 0);
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, query.c_str(), -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) throw DBError();
- if (boardsize) rc = sqlite3_bind_blob(ppStmt, 1, symmetrized_sig, 12, SQLITE_TRANSIENT);
- else rc = sqlite3_bind_blob(ppStmt, 1, sig, 12, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK || ppStmt==0) throw DBError();
- do {
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE && rc != SQLITE_ROW) throw DBError();
- if (rc == SQLITE_ROW) {
- makeIndexHit(sqlite3_column_int(ppStmt, 0), 0);
- }
- } while (rc == SQLITE_ROW);
- rc = sqlite3_finalize(ppStmt);
- if (symmetrized_sig) delete [] symmetrized_sig;
- if (rc != SQLITE_OK) throw DBError();
- end_sorted();
- }
- }
- int gis_callback(void *gl, int argc, char **argv, char **azColName) {
- if (!argc) return 1;
- ((GameList*)gl)->makeIndexHit(atoi(argv[0]), 0);
- return 0;
- }
- void GameList::gisearch(char* sql, int complete) throw(DBError) {
- if (start_sorted() == 0) {
- string query;
- if (!complete) query = "select id from games where ";
- query += sql;
- if (!complete) query += " order by id";
- // printf("%s\n", query.c_str());
- int rc = sqlite3_exec(db, query.c_str(), gis_callback, this, 0);
- if( rc!=SQLITE_OK ) throw DBError();
- end_sorted();
- }
- }
- int GameList::numHits() {
- return num_hits;
- }
- int GameList::size() {
- return currentList->size();
- }
- string GameList::resultsStr(GameListEntry* gle) {
- string result;
- if (!gle->hits) return result;
- char buf[20];
- result.reserve(gle->hits->size()*8);
- for(vector<Hit* >::iterator it = gle->hits->begin(); it != gle->hits->end(); it++) {
- sprintf(buf, "%d", (*it)->pos->data[0]);
- result += buf;
- for(int i=1; i<(*it)->pos->length; i++) {
- sprintf(buf, "-%d", (*it)->pos->data[i]);
- result += buf;
- }
- if ((*it)->label[0] != NO_CONT) result += lookupLabel((*it)->label[0], (*it)->label[1]); // coordinates of Hit
- if ((*it)->label[2]) result += "-, ";
- else result += ", ";
- }
- return result;
- }
- char GameList::lookupLabel(char x, char y) {
- if (!labels || !mrs_pattern || x < 0 || x >= mrs_pattern->sizeX || y < 0 || y >= mrs_pattern->sizeY) return '?';
- return labels[x+y*mrs_pattern->sizeX];
- }
- Continuation GameList::lookupContinuation(char x, char y) {
- if (!continuations || !mrs_pattern || x < 0 || x >= mrs_pattern->sizeX || y < 0 || y >= mrs_pattern->sizeY) return Continuation();
- return continuations[x+y*mrs_pattern->sizeX];
- }
- vector<string> GameList::currentEntriesAsStrings(int start, int end) {
- if (end==0) end = currentList->size();
- vector<string> result;
- if (start>end || end > (int)currentList->size()) return result;
- for(int i=start; i<end; i++) {
- result.push_back((*all)[(*currentList)[i].second]->gameInfoStr + resultsStr((*all)[(*currentList)[i].second]));
- }
- return result;
- }
- string GameList::currentEntryAsString(int i) {
- if (i < 0 || i >= (int)currentList->size()) {
- return "";
- } else return (*all)[(*currentList)[i].second]->gameInfoStr + resultsStr((*all)[(*currentList)[i].second]);
- }
- int getpropcallback(void *s, int argc, char **argv, char **azColName) {
- char** prop = (char**)s;
- if (argc && argv[0]) {
- *prop = new char[strlen(argv[0])+1];
- strcpy(*prop, argv[0]);
- }
- return 0;
- }
- string GameList::getSignature(int i) throw(DBError) {
- if (i < 0 || i >= (int)currentList->size()) {
- // printf("index out of range\n");
- return "";
- }
- int index = (*all)[(*currentList)[i].second]->id;
- char* prop = 0;
- char sql[200];
- sprintf(sql, "select signature from algo_signature_19 where id = %d;", index);
- // printf("%s\n", sql);
- int rc = sqlite3_exec(db, sql, getpropcallback, &prop, 0);
- if (rc != SQLITE_OK) throw DBError();
- if (!prop) return "";
- string prop_str(prop);
- delete [] prop;
- return prop_str;
- }
- string GameList::getSGF(int i) throw(DBError) {
- if (!p_op->sgfInDB) return "";
- return getCurrentProperty(i, "sgf");
- }
- string GameList::getCurrentProperty(int i, string tag) throw(DBError) {
- if (i < 0 || i >= (int)currentList->size()) {
- // printf("index out of range\n");
- return "";
- }
- int index = (*all)[(*currentList)[i].second]->id;
- char* prop = 0;
- char sql[200];
- sprintf(sql, "select %s from games where id = %d;", tag.c_str(), index);
- // printf("%s\n", sql);
- int rc = sqlite3_exec(db, sql, getpropcallback, &prop, 0);
- if (rc != SQLITE_OK) throw DBError();
- if (!prop) return "";
- string prop_str(prop);
- delete [] prop;
- return prop_str;
- }
- void GameList::search(Pattern& pattern, SearchOptions* so) throw(DBError) {
- if (mrs_pattern) delete mrs_pattern;
- mrs_pattern = new Pattern(pattern);
- if (searchOptions) delete searchOptions;
- if (so) searchOptions = new SearchOptions(*so);
- else searchOptions = new SearchOptions();
- PatternList pl(pattern, searchOptions->fixedColor, searchOptions->nextMove);
- vector<int>::iterator it = boardsizes.begin();
- int bs_index = 0;
- while (it != boardsizes.end() && *it != pattern.boardsize) {
- bs_index++;
- it++;
- }
- if (it == boardsizes.end()) {
- delete searchOptions;
- searchOptions = 0;
- if (oldList) delete oldList;
- oldList = 0;
- if (currentList) delete currentList;
- currentList = new vector<pair<int,int> >;
- return;
- }
- if (boardsizes.size() != 1) {
- char buf[20];
- sprintf(buf, "sz = %d", pattern.boardsize);
- gisearch(buf);
- }
- if (!readDBs) {
- for(unsigned int a=0; a < 20*boardsizes.size(); a++) if (algo_ps[a]) algo_ps[a]->readDB(algo_dbs[a]);
- readDBs = 1;
- }
- int hash_result = -1;
- // FULL BOARD PATTERN?
- if ((searchOptions->algos & ALGO_HASH_FULL) && pattern.sizeX == pattern.boardsize && pattern.sizeY == pattern.boardsize && algo_ps[algo_hash_full+20*bs_index]) {
- hash_result = ((Algo_hash_full*)algo_ps[algo_hash_full+20*bs_index])->search(pl, *this, *searchOptions, algo_dbs[algo_hash_full+20*bs_index]);
- if (hash_result == 1) {
- } else if (hash_result == 0) {
- if (searchOptions->algos & ALGO_MOVELIST && algo_ps[algo_movelist+20*bs_index])
- algo_ps[algo_movelist+20*bs_index]->search(pl, *this, *searchOptions);
- }
- }
- if (hash_result == -1) { // not a full board pattern (or not hashable)
- // CORNER PATTERN?
- if ((searchOptions->algos & ALGO_HASH_CORNER) && pattern.sizeX >= 7 && pattern.sizeY >= 7 && algo_ps[algo_hash_corner+20*bs_index]) {
- hash_result = ((Algo_hash_corner*)algo_ps[algo_hash_corner+20*bs_index])->search(pl, *this, *searchOptions, algo_dbs[algo_hash_corner+20*bs_index]);
- if (hash_result == 0) {
- if (searchOptions->algos & ALGO_MOVELIST && algo_ps[algo_movelist+20*bs_index])
- algo_ps[algo_movelist+20*bs_index]->search(pl, *this, *searchOptions);
- }
- }
- if (hash_result == -1) {
- if (searchOptions->algos & ALGO_FINALPOS && algo_ps[algo_finalpos+20*bs_index])
- algo_ps[algo_finalpos+20*bs_index]->search(pl, *this, *searchOptions);
- if (searchOptions->algos & ALGO_MOVELIST && algo_ps[algo_movelist+20*bs_index])
- algo_ps[algo_movelist+20*bs_index]->search(pl, *this, *searchOptions);
- }
- }
- if (labels) delete [] labels;
- labels = pl.sortContinuations();
- if (continuations) delete [] continuations;
- continuations = pl.continuations;
- pl.continuations = new Continuation[pattern.sizeX*pattern.sizeY];
- // FIXME: delete all candidate lists!
- }
- int GameList::plSize() {
- return pl.size();
- }
- string GameList::plEntry(int i) {
- if (i < 0 || i >= (int)pl.size()) return "";
- else return pl[i];
- }
- int rpl_callback(void *pl, int argc, char **argv, char **azColName) {
- if (!argc) return 1;
- ((vector<string>*)pl)->push_back(string(argv[0]));
- return 0;
- }
- void GameList::readPlayersList() throw(DBError) {
- if (pl.size()) pl = vector<string>();
- sqlite3_exec(db, "select p from (select pw p from games union select pb p from games) order by lower(p)", rpl_callback, &pl, 0);
- // we ignore possible errors, since the table might not yet exist
- }
- void GameList::createGamesDB() throw(DBError) {
- SGFtags = p_op->SGFTagsAsStrings();
- string sql1 = "create table GAMES ( ";
- sql1 += "id integer primary key, ";
- sql1 += "path text, ";
- sql1 += "filename text, ";
- sql1 += "pos integer default 0, ";
- sql1 += "duplicate integer, ";
- sql1 += "dbtree text, ";
- sql1 += "date date";
- sql_ins_rnp = "insert into games (path, filename, pos, dbtree, date";
- string question_marks = "?,?,?,?,?";
- if (p_op->sgfInDB) {
- sql1 += ", sgf text";
- sql_ins_rnp += ", sgf";
- question_marks += ",?";
- }
- SGFtagsSize = SGFtags->size();
- int ctr = 0;
- posDT = posSZ = posWR = posBR = posHA = -1;
- for(vector<string>::iterator it = SGFtags->begin(); it != SGFtags->end(); it++) {
- sql1 += ", " + *it + " text";
- sql_ins_rnp += ", " + *it;
- question_marks += ",?";
- if (*it == "DT") posDT = ctr;
- if (*it == "SZ") posSZ = ctr;
- if (*it == "WR") posWR = ctr;
- if (*it == "BR") posBR = ctr;
- if (*it == "HA") posHA = ctr;
- ctr++;
- }
- if (posDT == -1) throw DBError();
- if (posSZ == -1) {
- posSZ = SGFtags->size();
- SGFtags->push_back("SZ");
- }
- if (posWR == -1) {
- posWR = SGFtags->size();
- SGFtags->push_back("WR");
- }
- if (posBR == -1) {
- posBR = SGFtags->size();
- SGFtags->push_back("BR");
- }
- if (posHA == -1) {
- posHA = SGFtags->size();
- SGFtags->push_back("HA");
- }
- sql1 += ");";
- sql_ins_rnp += ") values (" + question_marks + ");";
- int rc = sqlite3_exec(db, sql1.c_str(), 0, 0, 0);
- //if(rc != SQLITE_OK) throw DBError();
- sql1 = "create table TAGS ( id integer primary key, name text, visible integer default 1 );";
- rc = sqlite3_exec(db, sql1.c_str(), 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- char sql[100];
- sprintf(sql, "insert into TAGS (id, name) values (%d, '%d');", HANDI_TAG, HANDI_TAG);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- // if (rc != SQLITE_OK) throw DBError();
- sprintf(sql, "insert into TAGS (id, name) values (%d, '%d');", PROFESSIONAL_TAG, PROFESSIONAL_TAG);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- // if (rc != SQLITE_OK) throw DBError();
- sql1 = "create table GAME_TAGS ( id integer primary key, game_id integer, tag_id integer );";
- rc = sqlite3_exec(db, sql1.c_str(), 0, 0, 0);
- //if (rc != SQLITE_OK) throw DBError();
- }
- void GameList::start_processing(int PROCESSVARIATIONS) throw(DBError) {
- // printf("enter start_processing %p\n", p_op);
- delete_all_snapshots();
- if (PROCESSVARIATIONS != -1) processVariations = PROCESSVARIATIONS;
- else processVariations = p_op->processVariations;
- readDBs = 0;
- // printf("dt %d sz %d\n", posDT, posSZ);
- int rc;
- createGamesDB();
- char* sql = "begin transaction;";
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc) { throw DBError(); }
- rc = sqlite3_exec(algo_db1, sql, 0, 0, 0);
- if (rc) { throw DBError(); }
- rc = sqlite3_exec(algo_db2, sql, 0, 0, 0);
- if (rc) { throw DBError(); }
- current = 0;
- for(unsigned int a=0; a < 20*boardsizes.size(); a++) {
- if (algo_ps[a]) algo_ps[a]->initialize_process(algo_dbs[a]);
- }
- }
- void GameList::finalize_processing() throw(DBError) {
- for(unsigned int a=0; a<20*boardsizes.size(); a++)
- if (algo_ps[a]) algo_ps[a]->finalize_process();
- int rc = sqlite3_exec(db, "commit;", 0, 0, 0);
- if (rc != SQLITE_OK) {
- sqlite3_close(db);
- db = 0;
- throw DBError();
- }
- rc = sqlite3_exec(algo_db1, "commit;", 0, 0, 0);
- if (rc != SQLITE_OK) {
- sqlite3_close(algo_db1);
- algo_db1 = 0;
- throw DBError();
- }
- rc = sqlite3_exec(algo_db2, "commit;", 0, 0, 0);
- if (rc != SQLITE_OK) {
- sqlite3_close(algo_db2);
- algo_db2 = 0;
- throw DBError();
- }
- string sql = "update db_info set info = '";
- for(vector<int>::iterator it = boardsizes.begin(); it != boardsizes.end(); it++) {
- char buf[20];
- sprintf(buf, "%d,", *it);
- sql += buf;
- }
- sql += "' WHERE rowid = 2;";
- rc = sqlite3_exec(db, sql.c_str(), 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- // sqlite3_close(db);
- // db = 0;
- readDBs = 0;
- readDB();
- delete SGFtags;
- }
- int GameList::process(const char* sgf, const char* path, const char* fn,
- const char* DBTREE, int flags) throw(SGFError,DBError) {
- process_results_vector.clear();
- const char* dbtree = "";
- if (DBTREE) dbtree = DBTREE;
- Cursor* c = 0;
- try {
- c = new Cursor(sgf, 1); // parse sgf sloppily
- } catch (SGFError) {
- return 0;
- }
- Node* root = c->root->next;
- int pos = 0;
- while (root) {
- current++;
- int return_val = 0;
- // if (!(current%1000)) {
- // char* sql = "end transaction;";
- // int rc = sqlite3_exec(db, sql, 0, 0, 0);
- // if (rc) {
- // sqlite3_close(db);
- // db = 0;
- // throw DBError();
- // }
- // sql = "begin transaction;";
- // rc = sqlite3_exec(db, sql, 0, 0, 0);
- // if (rc) {
- // sqlite3_close(db);
- // db = 0;
- // throw DBError();
- // }
- // }
- vector<string>* rootNodeProperties = parseRootNode(root, SGFtags);
- // for(vector<string>::iterator rnp = rootNodeProperties->begin(); rnp != rootNodeProperties->end(); rnp++)
- // printf("rnp %s\n", rnp->c_str());
- // check board size
- string sz = (*rootNodeProperties)[posSZ];
- // printf("sz %s\n", sz.c_str());
- if (sz=="") sz = "19";
- int bs = atoi(sz.c_str());
- if (bs < 1) {
- return_val |= UNACCEPTABLE_BOARDSIZE;
- process_results_vector.push_back(return_val);
- delete rootNodeProperties;
- root = root->down;
- pos++;
- continue;
- }
- int algo_offset = -1;
- int bs_ctr = 0;
- for(vector<int>::iterator it = boardsizes.begin(); it != boardsizes.end(); it++) {
- if (*it == bs) {
- algo_offset = bs_ctr;
- break;
- }
- bs_ctr++;
- }
- if (algo_offset == -1) { // not found
- boardsizes.push_back(bs);
- addAlgos(bs);
- algo_offset = algo_ps.size()/20 - 1;
- // printf("algo_offset %d %d \n", algo_offset, algo_ps.size());
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++) {
- // printf("a %d\n", a);
- // printf("%p\n", algo_ps[a]);
- if (algo_ps[a]) algo_ps[a]->initialize_process(algo_dbs[a]);
- }
- }
- // parse DT tag
- string dt = (*rootNodeProperties)[posDT];
- // printf("dt %s\n", dt.c_str());
- string date;
- bool year_found = false;
- int p = 0;
- while (!year_found && p < (int)dt.size()) {
- p = dt.find_first_of("0123456789", p);
- if (p == (int)string::npos || p+4 > (int)dt.size() ) break;
- else {
- year_found = (('0' <= dt[p] && dt[p] <= '9') && ('0' <= dt[p+1] && dt[p+1] <= '9') && ('0' <= dt[p+2] && dt[p+2] <= '9') && ('0' <= dt[p+3] && dt[p+3] <= '9'));
- if (year_found && (int)dt.find_first_of("0123456789", p+4) != p+4) { // success: found 4 digits in a row
- date += dt.substr(p,4);
- date += '-';
- dt.erase(p,4);
- } else {
- while ('0' <= dt[p] && dt[p] <= '9') p++;
- year_found = false;
- continue;
- }
- }
- }
- if (!year_found) date = "0000-00-00";
- else {
- bool month_found = false;
- p = 0;
- while (!month_found && p < (int)dt.size()) {
- p = dt.find_first_of("0123456789", p);
- if (p == (int)string::npos || p+2 > (int)dt.size() ) break;
- else {
- month_found = ('0' <= dt[p] && dt[p] <= '9' && '0' <= dt[p+1] && dt[p+1] <= '9');
- if (month_found && (int)dt.find_first_of("0123456789", p+2) != p+2) {
- date += dt.substr(p,2);
- date += '-';
- dt.erase(p,2);
- } else {
- while ('0' <= dt[p] && dt[p] <= '9') p++;
- month_found = false;
- continue;
- }
- }
- }
- if (!month_found) date += "00-00";
- else {
- bool day_found = false;
- p = 0;
- while (!day_found && p < (int)dt.size()) {
- p = dt.find_first_of("0123456789", p);
- if (p == (int)string::npos || p+2 > (int)dt.size() ) break;
- else {
- day_found = ('0' <= dt[p] && dt[p] <= '9' && '0' <= dt[p+1] && dt[p+1] <= '9');
- if (day_found && (int)dt.find_first_of("0123456789", p+2) != p+2) {
- date += dt.substr(p,2);
- } else {
- while ('0' <= dt[p] && dt[p] <= '9') p++;
- day_found = false;
- continue;
- }
- }
- }
- if (!day_found) date += "00";
- }
- }
- // printf("sql %s\n", sql_ins_rnp.c_str());
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, sql_ins_rnp.c_str(), -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) {
- throw DBError(); // FIXME: catch busy error, (and/or throw DBError?)
- }
- int stmt_ctr = 1;
- rc = sqlite3_bind_text(ppStmt, stmt_ctr++, path, -1, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_bind_text(ppStmt, stmt_ctr++, fn, -1, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_bind_int(ppStmt, stmt_ctr++, pos);
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_bind_text(ppStmt, stmt_ctr++, dbtree, -1, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_bind_text(ppStmt, stmt_ctr++, date.c_str(), -1, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) throw DBError();
- if (p_op->sgfInDB) {
- if (c->root->numChildren == 1) rc = sqlite3_bind_text(ppStmt, stmt_ctr++, sgf, -1, SQLITE_TRANSIENT);
- else {
- string s= "(";
- s += c->outputVar(root);
- s+= ")";
- rc = sqlite3_bind_text(ppStmt, stmt_ctr++, s.c_str(), -1, SQLITE_TRANSIENT);
- }
- if (rc != SQLITE_OK) throw DBError();
- }
- for(int i=0; i < SGFtagsSize; i++) {
- rc = sqlite3_bind_text(ppStmt, stmt_ctr++, (*rootNodeProperties)[i].c_str(), -1, SQLITE_TRANSIENT);
- if (rc != SQLITE_OK) throw DBError();
- }
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE) throw DBError();
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) throw DBError();
- int game_id = sqlite3_last_insert_rowid(db);
- // printf("play through the game\n");
- bool commit = true;
- Node* currentN = root;
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->newgame_process(game_id);
- abstractBoard b = abstractBoard(bs);
- int whichVar = 0;
- stack<VarInfo> branchpoints;
- while (currentN) {
- // printf("nn\n");
- bool caughtSGFError = false;
- char* propValue = 0;
- try {
- // parse current node, watch out for B, W, AB, AW, AE properties
- const char* s = currentN->SGFstring.c_str();
- int lSGFstring = strlen(s);
- int i = 0;
- while (i < lSGFstring && s[i] != ';' && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
- i++;
- if (i>=lSGFstring || s[i] != ';') throw SGFError();
- i++;
- while (i < lSGFstring) { // while parsing
- while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
- i++;
- if (i >= lSGFstring) break;
- char ID[30];
- int IDindex = 0;
- while (i < lSGFstring && s[i] != '[' && IDindex < 30) {
- if (65 <= s[i] && s[i] <= 90)
- ID[IDindex++] = s[i];
- else if (!(97 <= s[i] && s[i] <= 122) && !(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) {
- throw SGFError();
- }
- i++;
- }
- i++;
- if (i >= lSGFstring || IDindex >= 30 || !IDindex) {
- throw SGFError();
- }
- ID[IDindex] = 0; // found next property ID
- bool IDrelevant= (!strcmp(ID,"B") || !strcmp(ID,"W") || !strcmp(ID,"AB") || !strcmp(ID,"AW") || !strcmp(ID,"AE"));
- propValue = new char[100000];
- int propValueIndex = 0;
- int oldPropValueIndex = 0;
- while (i < lSGFstring) { // while looking for property values of the current property
- while (s[i] != ']' && i < lSGFstring) {
- if (s[i] == '\\') i++;
- if (!IDrelevant || s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n') {
- i++;
- continue;
- }
- if (97 <= s[i] && s[i] <= 96+bs) { // valid board coordinate?
- propValue[propValueIndex++] = s[i];
- if (propValueIndex > 99990) throw SGFError();
- } else if (s[i] == 't') { ; // allow passes, but do not record them (we handle them a little sloppily here)
- } else if (s[i] == ':') {
- if (propValueIndex - oldPropValueIndex != 2)
- throw SGFError();
- char rect1 = 'a';
- char rect2 = 'a';
- i++;
- while (i<lSGFstring && (s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n')) i++;
- if (i >= lSGFstring) throw SGFError();
- if (97 <= s[i] && s[i] <= 96+bs) // valid board coordinate?
- rect1 = s[i];
- else throw SGFError();
- i++;
- while (i<lSGFstring && (s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n')) i++;
- if (i >= lSGFstring) throw SGFError();
- if (97 <= s[i] && s[i] <= 96+bs) // valid board coordinate?
- rect2 = s[i];
- else throw SGFError();
- i++;
- while (i<lSGFstring && (s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n')) i++;
- if (i >= lSGFstring) throw SGFError();
- if (s[i] == ']') {
- char st1 = propValue[propValueIndex-2];
- char st2 = propValue[propValueIndex-1];
- propValueIndex -= 2; // do not want to have the first entry twice!
- for(char x1 = st1; x1 <= rect1; x1++) {
- for(char x2 = st2; x2 <= rect2; x2++) {
- propValue[propValueIndex++] = x1;
- propValue[propValueIndex++] = x2;
- if (propValueIndex > 99990) throw SGFError();
- }
- }
- oldPropValueIndex = propValueIndex;
- break;
- } else throw SGFError();
- } else {
- throw SGFError();
- }
- i++;
- }
- if (i >= lSGFstring) throw SGFError();
- if (propValueIndex - oldPropValueIndex != 0 && propValueIndex - oldPropValueIndex != 2) {
- throw SGFError();
- }
- oldPropValueIndex = propValueIndex;
- i++;
- while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) i++;
- if (i >= lSGFstring || s[i] != '[') break; // end of node, or found next property
- else i++; // s[i] == '[', so another property value follows.
- }
- int p_len = propValueIndex/2;
- if (!propValueIndex) { // in particular, this happens if !IDrelevant
- if (!strcmp(ID, "B") || !strcmp(ID, "W")) {
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->pass_process();
- }
- delete [] propValue;
- propValue = 0;
- continue;
- }
- if (!strcmp(ID, "B") || !strcmp(ID, "W")) {
- char x = propValue[0]-97; // 97 == ord('a'), (0,0) <= (x,y) <= (bs-1, bs-1)
- char y = propValue[1]-97;
- if (!b.play(x, y, ID)) throw SGFError();
- Move m = b.undostack.top();
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->move_process(m);
- } else
- if (!strcmp(ID, "AB")) {
- for(int pp=0; pp < p_len; pp++) {
- char x = propValue[2*pp]-97;
- char y = propValue[2*pp+1]-97;
- if (!b.play(x, y, "B")) throw SGFError();
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->AB_process(x, y);
- }
- } else
- if (!strcmp(ID, "AW")) {
- for(int pp=0; pp < p_len; pp++) {
- char x = propValue[2*pp]-97;
- char y = propValue[2*pp+1]-97;
- if (!b.play(x, y, "W")) throw SGFError();
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->AW_process(x, y);
- }
- } else {
- if (!strcmp(ID, "AE")) {
- for(int pp=0; pp < p_len; pp++) {
- char x = propValue[2*pp]-97;
- char y = propValue[2*pp+1]-97;
- char removed = b.getStatus(x,y);
- if (removed==' ') throw SGFError();
- b.remove(x, y);
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->AE_process(x, y, removed);
- }
- }
- }
- delete [] propValue;
- propValue = 0;
- }
- } catch (SGFError) {
- if (propValue) {
- delete [] propValue;
- propValue = 0;
- }
- return_val |= SGF_ERROR;
- caughtSGFError = true;
- if (flags & OMIT_GAMES_WITH_SGF_ERRORS) {
- commit = false;
- // (FIXME should exit from the loop here)
- }
- }
- {
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->endOfNode_process();
- }
- if (processVariations && currentN->numChildren > 1) { // several variations start from this node;
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->branchpoint_process();
- branchpoints.push(VarInfo(currentN, new abstractBoard(b), 0));
- }
- if (caughtSGFError) currentN = 0; // stop here with this branch
- else currentN = currentN->next;
- if (!currentN && branchpoints.size()) {
- currentN = branchpoints.top().n;
- b = abstractBoard(*branchpoints.top().b);
- whichVar = branchpoints.top().i;
- branchpoints.pop();
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->endOfVariation_process();
- if (whichVar+2 < currentN->numChildren) {
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
- if (algo_ps[a]) algo_ps[a]->branchpoint_process();
- branchpoints.push(VarInfo(currentN, new abstractBoard(b), whichVar+1));
- }
- currentN = currentN->next;
- for(int vi=0; vi < whichVar+1; vi++) currentN = currentN->down;
- }
- } // while
- {
- // check for duplicates (if desired)
- bool is_duplicate = false;
- if (flags & (CHECK_FOR_DUPLICATES|CHECK_FOR_DUPLICATES_STRICT)) {
- char* sig = ((Algo_signature*)algo_ps[20*algo_offset])->get_current_signature();
- vector<int> all_duplicates = ((Algo_signature*)algo_ps[20*algo_offset])->search_signature(sig);
- if (all_duplicates.size()) {
- // printf("dupl %d\n", all_duplicates.size());
- is_duplicate = true;
- if ((flags & CHECK_FOR_DUPLICATES_STRICT) && (p_op->algos & ALGO_FINALPOS)) {
- vector<int>::iterator d_it = all_duplicates.begin();
- while (d_it != all_duplicates.end() && !((Algo_finalpos*)algo_ps[20*algo_offset + algo_finalpos])->equals_current(*d_it))
- d_it++;
- if (d_it == all_duplicates.end()) is_duplicate = false;
- }
- if (is_duplicate) {
- return_val |= IS_DUPLICATE;
- if (flags & OMIT_DUPLICATES) commit = false;
- }
- }
- delete [] sig;
- }
- if (commit) {
- // evaluate tags
- if ((*rootNodeProperties)[posHA] != "") { // handicap game
- char sql[100];
- sprintf(sql, "insert into GAME_TAGS (game_id, tag_id) values (%d, %d);", game_id, HANDI_TAG);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- if ((*rootNodeProperties)[posWR].find('p') != string::npos ||
- (*rootNodeProperties)[posBR].find('p') != string::npos) {
- // at least one of the players is professional
- char sql[100];
- sprintf(sql, "insert into GAME_TAGS (game_id, tag_id) values (%d, %d);", game_id, PROFESSIONAL_TAG);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- } else {
- return_val |= NOT_INSERTED_INTO_DB;
- char sql[200];
- sprintf(sql, "delete from GAMES where id=%d", game_id);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc) printf("ouch %d\n", rc);
- }
- for(int a=20*algo_offset; a < 20*(algo_offset+1); a++) {
- // printf("endgame %d\n", a);
- if (algo_ps[a]) algo_ps[a]->endgame_process(commit);
- }
- }
- delete rootNodeProperties;
- process_results_vector.push_back(return_val);
- root = root->down;
- pos++;
- }
- delete c;
- return process_results_vector.size();
- }
- int GameList::process_results(unsigned int i) {
- if (i<0 || i>=process_results_vector.size()) return INDEX_OUT_OF_RANGE;
- return process_results_vector[i];
- }
- int GameList::snapshot() throw(DBError) {
- // return a handle to a snapshot stored in the main GameList db
- // the snapshot contains copies of
- // - orderby, format1, format2
- // - currentList
- // - all hits in the GameListEntry's of currentList
- // - pattern, labels, continuations, num_hits, num_switched, Bwins, Wwins
- SnapshotVector snapshot;
- snapshot.pb_string(orderby);
- snapshot.pb_string(format1);
- snapshot.pb_string(format2);
- snapshot.pb_int(currentList->size());
- for(vector<pair<int,int> >::iterator it = currentList->begin(); it != currentList->end(); it++) {
- snapshot.pb_int(it->first);
- snapshot.pb_int(it->second);
- vector<Hit* >* hits = (*all)[it->second]->hits;
- snapshot.pb_int(hits->size());
- for (vector<Hit* >::iterator it_h = hits->begin(); it_h != hits->end(); it_h++) {
- (*it_h)->to_snv(snapshot);
- }
- }
- if (mrs_pattern) {
- snapshot.pb_char(1);
- mrs_pattern->to_snv(snapshot);
- } else snapshot.pb_char(0);
- if (searchOptions) {
- snapshot.pb_char(1);
- searchOptions->to_snv(snapshot);
- } else snapshot.pb_char(0);
- if (mrs_pattern && labels && continuations) {
- snapshot.pb_char(1);
- snapshot.pb_charp(labels, mrs_pattern->sizeX * mrs_pattern->sizeY);
- for(int i=0; i<mrs_pattern->sizeX * mrs_pattern->sizeY; i++) continuations[i].to_snv(snapshot);
- } else snapshot.pb_char(0);
- snapshot.pb_int(num_hits);
- snapshot.pb_int(num_switched);
- snapshot.pb_int(Bwins);
- snapshot.pb_int(Wwins);
- // insert snapshot into database
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, "insert into snapshots (data) values (?)", -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) throw DBError();
- char* snchp = snapshot.to_charp();
- rc = sqlite3_bind_blob(ppStmt, 1, snchp, snapshot.size(), SQLITE_TRANSIENT);
- delete [] snchp;
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_step(ppStmt);
- if (rc != SQLITE_DONE) throw DBError();
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) throw DBError();
- return sqlite3_last_insert_rowid(db);
- }
- void GameList::restore(int handle, bool del) throw(DBError) {
- // restore the state of the GameList associated with handle
- // retrieve info associated with handle from db
- char* sn = 0;
- int sn_size = 0;
- sqlite3_stmt *ppStmt=0;
- int rc = sqlite3_prepare(db, "select data from snapshots where rowid = ?", -1, &ppStmt, 0);
- if (rc != SQLITE_OK || ppStmt==0) {
- throw DBError();
- }
- rc = sqlite3_bind_int(ppStmt, 1, handle);
- if (rc != SQLITE_OK) throw DBError();
- rc = sqlite3_step(ppStmt);
- if (rc == SQLITE_ROW) {
- sn = (char*)sqlite3_column_blob(ppStmt, 0);
- sn_size = sqlite3_column_bytes(ppStmt, 0);
- } else throw DBError();
- SnapshotVector snapshot(sn, sn_size);
- // parse info
- string ob = snapshot.retrieve_string();
- string f1 = snapshot.retrieve_string();
- string f2 = snapshot.retrieve_string();
- if (ob != orderby || f1 != format1 || f2 != format2) resetFormat();
- if (oldList) delete oldList;
- oldList = 0;
- if (currentList) delete currentList;
- currentList = new vector<pair<int,int> >;
- for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++) {
- if ((*it)->hits) {
- for(vector<Hit* >::iterator ith = (*it)->hits->begin(); ith != (*it)->hits->end(); ith++)
- delete *ith;
- delete (*it)->hits;
- (*it)->hits = 0;
- }
- if ((*it)->candidates) {
- for(vector<Candidate* >::iterator itc = (*it)->candidates->begin(); itc != (*it)->candidates->end(); itc++)
- delete *itc;
- delete (*it)->candidates;
- (*it)->candidates = 0;
- }
- }
- int cl_size = snapshot.retrieve_int();
- for(int i=0; i<cl_size; i++) {
- int i1 = snapshot.retrieve_int();
- int i2 = snapshot.retrieve_int();
- currentList->push_back(make_pair(i1, i2));
- // if ((*currentList)[currentList->size()-1].second >= all->size()) printf("ouch %d\n", (*currentList)[currentList->size()-1].second);
- (*all)[(*currentList)[currentList->size()-1].second]->hits_from_snv(snapshot);
- }
- if (mrs_pattern) delete mrs_pattern;
- if (snapshot.retrieve_char()) mrs_pattern = new Pattern(snapshot);
- else mrs_pattern = 0;
- if (searchOptions) delete searchOptions;
- if (snapshot.retrieve_char()) searchOptions = new SearchOptions(snapshot);
- else searchOptions = 0;
- if (labels) delete [] labels;
- if (continuations) delete [] continuations; // FIXME check (cf. ~GameList)
- if (snapshot.retrieve_char()) {
- labels = snapshot.retrieve_charp();
- continuations = new Continuation[mrs_pattern->sizeX * mrs_pattern->sizeY];
- for(int i=0; i<mrs_pattern->sizeX * mrs_pattern->sizeY; i++)
- continuations[i].from_snv(snapshot);
- } else {
- labels = 0;
- continuations = 0;
- }
- num_hits = snapshot.retrieve_int();
- num_switched = snapshot.retrieve_int();
- Bwins = snapshot.retrieve_int();
- Wwins = snapshot.retrieve_int();
- rc = sqlite3_finalize(ppStmt);
- if (rc != SQLITE_OK) throw DBError();
- if (del) { // delete snapshot from db
- char sql[100];
- sprintf(sql, "delete from snapshots where rowid = %d", handle);
- rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- }
- void GameList::delete_snapshot(int handle) throw(DBError) {
- char sql[100];
- sprintf(sql, "delete from snapshots where rowid = %d", handle);
- int rc = sqlite3_exec(db, sql, 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- void GameList::delete_all_snapshots() throw(DBError) {
- int rc = sqlite3_exec(db, "delete from snapshots", 0, 0, 0);
- if (rc != SQLITE_OK) throw DBError();
- }
- VarInfo::VarInfo(Node* N, abstractBoard* B, int I) {
- n = N;
- b = B;
- i = I;
- }
- VarInfo::VarInfo(const VarInfo& v) {
- n = v.n;
- b = new abstractBoard(*v.b);
- i = v.i;
- }
- VarInfo::~VarInfo() {
- delete b;
- }