PageRenderTime 87ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/kombilo/search.cpp

http://eidogo.googlecode.com/
C++ | 5380 lines | 4166 code | 524 blank | 690 comment | 1777 complexity | 0e1bbdbcb1b0e8ea2618a8bcc476aa52 MD5 | raw file
  1. // File: search.cpp
  2. // part of libkombilo, http://www.u-go.net/kombilo/
  3. // Copyright (c) 2006-7 Ulrich Goertz <u@g0ertz.de>
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. // this software and associated documentation files (the "Software"), to deal in
  6. // the Software without restriction, including without limitation the rights to
  7. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  8. // of the Software, and to permit persons to whom the Software is furnished to do
  9. // so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in all
  12. // copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. // SOFTWARE.
  21. #include "sgfparser.h"
  22. #include "abstractboard.h"
  23. #include "search.h"
  24. #include <stdio.h>
  25. #include <string>
  26. #include <cstring>
  27. using std::min;
  28. using std::max;
  29. using std::string;
  30. using std::vector;
  31. using std::map;
  32. using std::pair;
  33. using std::make_pair;
  34. using std::stack;
  35. #if defined(_MSC_VER)
  36. #include <algorithm>
  37. #else
  38. using std::sort;
  39. #endif
  40. SnapshotVector::SnapshotVector() : vector<unsigned char>() {
  41. current = begin();
  42. }
  43. SnapshotVector::SnapshotVector(char* c, int size) : vector<unsigned char>() {
  44. for(int i=0; i<size; i++) push_back(c[i]);
  45. current = begin();
  46. }
  47. void SnapshotVector::pb_int(int d) {
  48. for(int i = 0; i < 4; i++) {
  49. push_back((unsigned char)(d % 256));
  50. d = d >> 8;
  51. }
  52. }
  53. void SnapshotVector::pb_charp(char* c, int size) {
  54. pb_int(size);
  55. for(int i=0; i<size; i++) push_back(c[i]);
  56. }
  57. void SnapshotVector::pb_intp(int* p, int size) {
  58. pb_int(size);
  59. for(int i=0; i<size; i++) pb_int(p[i]);
  60. }
  61. void SnapshotVector::pb_string(string s) {
  62. pb_int(s.size()+1);
  63. for(unsigned int i=0; i<s.size(); i++) push_back(s[i]);
  64. push_back(0);
  65. }
  66. void SnapshotVector::pb_char(char c) {
  67. push_back(c);
  68. }
  69. int SnapshotVector::retrieve_int() {
  70. int result = 0;
  71. for(int i=0; i<4; i++) {
  72. result += *current << (i*8);
  73. current++;
  74. }
  75. return result;
  76. }
  77. int* SnapshotVector::retrieve_intp() {
  78. int sz = retrieve_int();
  79. int* result = new int[sz];
  80. for(int i=0; i<sz; i++)
  81. result[i] = retrieve_int();
  82. return result;
  83. }
  84. char SnapshotVector::retrieve_char() {
  85. char c = *current;
  86. current++;
  87. return c;
  88. }
  89. char* SnapshotVector::retrieve_charp() {
  90. int sz = retrieve_int();
  91. char* result = new char[sz];
  92. for(int i=0; i<sz; i++) {
  93. result[i] = *current;
  94. current++;
  95. }
  96. return result;
  97. }
  98. string SnapshotVector::retrieve_string() {
  99. char* cp = retrieve_charp();
  100. string s(cp);
  101. delete [] cp;
  102. return s;
  103. }
  104. char* SnapshotVector::to_charp() {
  105. char* result = new char[size()];
  106. int counter = 0;
  107. for(SnapshotVector::iterator it = begin(); it != end(); it++) result[counter++] = *it;
  108. return result;
  109. }
  110. PatternError::PatternError() {}
  111. Continuation::Continuation() {
  112. B = 0;
  113. W = 0;
  114. tB = 0;
  115. tW = 0;
  116. wB = 0;
  117. lB = 0;
  118. wW = 0;
  119. lW = 0;
  120. }
  121. void Continuation::from_snv(SnapshotVector& snv) {
  122. B = snv.retrieve_int();
  123. W = snv.retrieve_int();
  124. tB = snv.retrieve_int();
  125. tW = snv.retrieve_int();
  126. wB = snv.retrieve_int();
  127. lB = snv.retrieve_int();
  128. wW = snv.retrieve_int();
  129. lW = snv.retrieve_int();
  130. }
  131. void Continuation::to_snv(SnapshotVector& snv) {
  132. snv.pb_int(B);
  133. snv.pb_int(W);
  134. snv.pb_int(tB);
  135. snv.pb_int(tW);
  136. snv.pb_int(wB);
  137. snv.pb_int(lB);
  138. snv.pb_int(wW);
  139. snv.pb_int(lW);
  140. }
  141. Symmetries::Symmetries(char sX, char sY) {
  142. sizeX = sX;
  143. sizeY = sY;
  144. dataX = new char[sizeX*sizeY];
  145. dataY = new char[sizeX*sizeY];
  146. dataCS = new char[sizeX*sizeY];
  147. for(int i=0; i<sizeX*sizeY; i++) {
  148. dataX[i] = -1;
  149. dataY[i] = -1;
  150. dataCS[i] = -1;
  151. }
  152. }
  153. Symmetries::~Symmetries() {
  154. delete [] dataX;
  155. delete [] dataY;
  156. delete [] dataCS;
  157. }
  158. Symmetries::Symmetries(const Symmetries& s) {
  159. sizeX = s.sizeX;
  160. sizeY = s.sizeY;
  161. dataX = new char[sizeX*sizeY];
  162. dataY = new char[sizeX*sizeY];
  163. dataCS = new char[sizeX*sizeY];
  164. for(int i=0; i<sizeX*sizeY; i++) {
  165. dataX[i] = s.dataX[i];
  166. dataY[i] = s.dataY[i];
  167. dataCS[i] = s.dataCS[i];
  168. }
  169. }
  170. Symmetries& Symmetries::operator=(const Symmetries& s) {
  171. if (&s != this) {
  172. sizeX = s.sizeX;
  173. sizeY = s.sizeY;
  174. delete [] dataX;
  175. delete [] dataY;
  176. delete [] dataCS;
  177. dataX = new char[sizeX*sizeY];
  178. dataY = new char[sizeX*sizeY];
  179. dataCS = new char[sizeX*sizeY];
  180. for(int i=0; i<sizeX*sizeY; i++) {
  181. dataX[i] = s.dataX[i];
  182. dataY[i] = s.dataY[i];
  183. dataCS[i] = s.dataCS[i];
  184. }
  185. }
  186. return *this;
  187. }
  188. void Symmetries::set(char i, char j, char k, char l, char cs) throw(PatternError) {
  189. if (0 <= i && i < sizeX && 0 <= j && j < sizeY) {
  190. dataX[i + j*sizeX] = k;
  191. dataY[i + j*sizeX] = l;
  192. dataCS[i + j*sizeX] = cs;
  193. }
  194. else throw PatternError();
  195. }
  196. char Symmetries::getX(char i, char j) throw(PatternError) {
  197. if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataX[i + j*sizeX];
  198. else throw PatternError();
  199. return -1;
  200. }
  201. char Symmetries::getY(char i, char j) throw(PatternError) {
  202. if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataY[i + j*sizeX];
  203. else throw PatternError();
  204. return -1;
  205. }
  206. char Symmetries::getCS(char i, char j) throw(PatternError) {
  207. if (0 <= i && i < sizeX && 0 <= j && j < sizeY) return dataCS[i + j*sizeX];
  208. else throw PatternError();
  209. return -1;
  210. }
  211. char Symmetries::has_key(char i, char j) throw(PatternError) {
  212. if (0 <= i && i < sizeX && 0 <= j && j < sizeY) {
  213. if (dataX[i + j*sizeX] == -1) return 0;
  214. else return 1;
  215. }
  216. else throw PatternError();
  217. return 0;
  218. }
  219. // ----------- class Pattern -----------------------------------------------
  220. int Pattern::operator==(const Pattern& p) {
  221. if (boardsize != p.boardsize) return 0;
  222. if (sizeX != p.sizeX || sizeY != p.sizeY) return 0;
  223. if (left != p.left || right != p.right || top != p.top || bottom != p.bottom) return 0;
  224. for(int i=0; i < sizeX*sizeY; i++)
  225. if (initialPos[i] != p.initialPos[i]) return 0;
  226. if (contList != p.contList) return 0;
  227. return 1;
  228. }
  229. char Pattern::BW2XO(char c) {
  230. if (c == 'B') return 'X';
  231. if (c == 'W') return 'O';
  232. return c;
  233. }
  234. char Pattern::getInitial(int i, int j) {
  235. return initialPos[i + sizeX*j];
  236. }
  237. char Pattern::getFinal(int i, int j) {
  238. return finalPos[i + sizeX*j];
  239. }
  240. Pattern::Pattern() {
  241. initialPos = 0;
  242. finalPos = 0;
  243. flip = 0;
  244. colorSwitch = 0;
  245. sizeX = 0;
  246. sizeY = 0;
  247. boardsize = 0;
  248. contLabels = 0;
  249. }
  250. Pattern::Pattern(int type, int BOARDSIZE, int sX, int sY, char* iPos, char* CONTLABELS) {
  251. flip = 0;
  252. colorSwitch = 0;
  253. sizeX = sX;
  254. sizeY = sY;
  255. boardsize = BOARDSIZE;
  256. if (CONTLABELS) {
  257. contLabels = new char[sizeX * sizeY];
  258. for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
  259. } else contLabels = 0;
  260. if (type == CORNER_NW_PATTERN || type == FULLBOARD_PATTERN) {
  261. left = right = top = bottom = 0;
  262. } else if (type == CORNER_NE_PATTERN) {
  263. top = bottom = 0;
  264. left = right = boardsize - sizeX;
  265. } else if (type == CORNER_SE_PATTERN) {
  266. top = bottom = boardsize - sizeY;
  267. left = right = boardsize - sizeX;
  268. } else if (type == CORNER_SW_PATTERN) {
  269. top = bottom = boardsize - sizeY;
  270. left = right = 0;
  271. } else if (type == SIDE_N_PATTERN) {
  272. top = bottom = 0;
  273. left = 1;
  274. right = boardsize -1 - sizeX;
  275. } else if (type == SIDE_E_PATTERN) {
  276. left = right = boardsize - sizeX;
  277. top = 1;
  278. bottom = boardsize -1 - sizeY;
  279. } else if (type == SIDE_W_PATTERN) {
  280. left = right = 0;
  281. top = 1;
  282. bottom = boardsize -1 - sizeY;
  283. } else if (type == SIDE_S_PATTERN) {
  284. top = bottom = boardsize - sizeY;
  285. left = 1;
  286. right = boardsize -1 - sizeX;
  287. } else if (type == CENTER_PATTERN) {
  288. left = top = 1;
  289. right = boardsize -1 - sizeX;
  290. bottom = boardsize -1 - sizeY;
  291. }
  292. initialPos = new char[sizeX * sizeY];
  293. finalPos = new char[sizeX*sizeY];
  294. for(int i=0; i<sizeX*sizeY; i++) {
  295. initialPos[i] = iPos[i];
  296. finalPos[i] = iPos[i];
  297. }
  298. }
  299. Pattern::Pattern(int type, int BOARDSIZE, int sX, int sY,
  300. char* iPos, vector<MoveNC> CONTLIST, char* CONTLABELS) {
  301. flip = 0;
  302. colorSwitch = 0;
  303. sizeX = sX;
  304. sizeY = sY;
  305. boardsize = BOARDSIZE;
  306. if (CONTLABELS) {
  307. contLabels = new char[sizeX * sizeY];
  308. for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
  309. } else contLabels = 0;
  310. if (type == CORNER_NW_PATTERN || type == FULLBOARD_PATTERN) {
  311. left = right = top = bottom = 0;
  312. } else if (type == CORNER_NE_PATTERN) {
  313. top = bottom = 0;
  314. left = right = boardsize - sizeX;
  315. } else if (type == CORNER_SE_PATTERN) {
  316. top = bottom = boardsize - sizeY;
  317. left = right = boardsize - sizeX;
  318. } else if (type == CORNER_SW_PATTERN) {
  319. top = bottom = boardsize - sizeY;
  320. left = right = 0;
  321. } else if (type == SIDE_N_PATTERN) {
  322. top = bottom = 0;
  323. left = 1;
  324. right = boardsize -1 - sizeX;
  325. } else if (type == SIDE_E_PATTERN) {
  326. left = right = boardsize - sizeX;
  327. top = 1;
  328. bottom = boardsize -1 - sizeY;
  329. } else if (type == SIDE_W_PATTERN) {
  330. left = right = 0;
  331. top = 1;
  332. bottom = boardsize -1 - sizeY;
  333. } else if (type == SIDE_S_PATTERN) {
  334. top = bottom = boardsize - sizeY;
  335. left = 1;
  336. right = boardsize -1 - sizeX;
  337. } else if (type == CENTER_PATTERN) {
  338. left = top = 1;
  339. right = boardsize -1 - sizeX;
  340. bottom = boardsize -1 - sizeY;
  341. }
  342. initialPos = new char[sizeX * sizeY];
  343. finalPos = new char[sizeX*sizeY];
  344. for(int i=0; i<sizeX*sizeY; i++) {
  345. initialPos[i] = iPos[i];
  346. finalPos[i] = iPos[i];
  347. }
  348. contList = CONTLIST;
  349. }
  350. Pattern::Pattern(int le, int ri, int to, int bo, int BOARDSIZE, int sX, int sY,
  351. char* iPos, const vector<MoveNC>& CONTLIST, char* CONTLABELS) throw(PatternError) {
  352. // check whether anchor rectangle is valid
  353. if (le < 0 || ri+sX > BOARDSIZE || to < 0 || bo+sY > BOARDSIZE || ri < le || bo < to) throw PatternError();
  354. flip = 0;
  355. colorSwitch = 0;
  356. left = le;
  357. right = ri;
  358. top = to;
  359. bottom = bo;
  360. boardsize = BOARDSIZE;
  361. sizeX = sX;
  362. sizeY = sY;
  363. if (CONTLABELS) {
  364. contLabels = new char[sizeX * sizeY];
  365. for(int i=0; i<sizeX*sizeY; i++) contLabels[i] = CONTLABELS[i];
  366. } else contLabels = 0;
  367. initialPos = new char[sizeX * sizeY];
  368. finalPos = new char[sizeX*sizeY];
  369. for(int i=0; i<sizeX*sizeY; i++) {
  370. initialPos[i] = iPos[i];
  371. finalPos[i] = iPos[i];
  372. }
  373. contList = CONTLIST;
  374. }
  375. Pattern::Pattern(SnapshotVector& snv) {
  376. flip = snv.retrieve_int();
  377. colorSwitch = snv.retrieve_int();
  378. left = snv.retrieve_int();
  379. right = snv.retrieve_int();
  380. top = snv.retrieve_int();
  381. bottom = snv.retrieve_int();
  382. boardsize = snv.retrieve_int();
  383. sizeX = snv.retrieve_int();
  384. sizeY = snv.retrieve_int();
  385. if (snv.retrieve_char()) { // contLabels?
  386. contLabels = snv.retrieve_charp();
  387. } else contLabels = 0;
  388. initialPos = snv.retrieve_charp();
  389. finalPos = snv.retrieve_charp();
  390. int size = snv.retrieve_int();
  391. for(int i=0; i<size; i++)
  392. contList.push_back(MoveNC(snv.retrieve_char(), snv.retrieve_char(), snv.retrieve_char())); // x, y, color
  393. }
  394. void Pattern::to_snv(SnapshotVector& snv) {
  395. snv.pb_int(flip);
  396. snv.pb_int(colorSwitch);
  397. snv.pb_int(left);
  398. snv.pb_int(right);
  399. snv.pb_int(top);
  400. snv.pb_int(bottom);
  401. snv.pb_int(boardsize);
  402. snv.pb_int(sizeX);
  403. snv.pb_int(sizeY);
  404. if (contLabels) {
  405. snv.pb_char(1);
  406. snv.pb_charp(contLabels, sizeX*sizeY);
  407. } else snv.pb_char(0);
  408. snv.pb_charp(initialPos, sizeX*sizeY);
  409. snv.pb_charp(finalPos, sizeX*sizeY);
  410. snv.pb_int(contList.size());
  411. for(vector<MoveNC>::iterator it = contList.begin(); it != contList.end(); it++) {
  412. snv.pb_char(it->x);
  413. snv.pb_char(it->y);
  414. snv.pb_char(it->color);
  415. }
  416. }
  417. Pattern::~Pattern() {
  418. if (initialPos) delete [] initialPos;
  419. if (finalPos) delete [] finalPos;
  420. if (contLabels) delete [] contLabels;
  421. }
  422. Pattern::Pattern(const Pattern& p) {
  423. left = p.left;
  424. right = p.right;
  425. top = p.top;
  426. bottom = p.bottom;
  427. boardsize = p.boardsize;
  428. sizeX = p.sizeX;
  429. sizeY = p.sizeY;
  430. flip = p.flip;
  431. colorSwitch = p.colorSwitch;
  432. initialPos = new char[sizeX*sizeY];
  433. finalPos = new char[sizeX*sizeY];
  434. if (p.contLabels) contLabels = new char[sizeX*sizeY];
  435. else contLabels = 0;
  436. for(int i=0; i<sizeX*sizeY; i++) {
  437. initialPos[i] = p.initialPos[i];
  438. finalPos[i] = p.finalPos[i];
  439. if (p.contLabels) contLabels[i] = p.contLabels[i];
  440. }
  441. contList = p.contList;
  442. }
  443. Pattern& Pattern::operator=(const Pattern& p) {
  444. if (&p != this) {
  445. left = p.left;
  446. right = p.right;
  447. top = p.top;
  448. bottom = p.bottom;
  449. boardsize = p.boardsize;
  450. sizeX = p.sizeX;
  451. sizeY = p.sizeY;
  452. flip = p.flip;
  453. colorSwitch = p.colorSwitch;
  454. if (initialPos) delete [] initialPos;
  455. if (finalPos) delete [] finalPos;
  456. if (contLabels) delete [] contLabels;
  457. initialPos = new char[sizeX*sizeY];
  458. finalPos = new char[sizeX*sizeY];
  459. if (p.contLabels) contLabels = new char[sizeX*sizeY];
  460. else contLabels = 0;
  461. for(int i=0; i<sizeX*sizeY; i++) {
  462. initialPos[i] = p.initialPos[i];
  463. finalPos[i] = p.finalPos[i];
  464. if (p.contLabels) contLabels[i] = p.contLabels[i];
  465. }
  466. contList = p.contList;
  467. }
  468. return *this;
  469. }
  470. Pattern& Pattern::copy(const Pattern& p) {
  471. if (&p != this) {
  472. left = p.left;
  473. right = p.right;
  474. top = p.top;
  475. bottom = p.bottom;
  476. boardsize = p.boardsize;
  477. sizeX = p.sizeX;
  478. sizeY = p.sizeY;
  479. flip = p.flip;
  480. colorSwitch = p.colorSwitch;
  481. if (initialPos) delete [] initialPos;
  482. if (finalPos) delete [] finalPos;
  483. initialPos = new char[sizeX*sizeY];
  484. finalPos = new char[sizeX*sizeY];
  485. if (p.contLabels) contLabels = new char[sizeX*sizeY];
  486. else contLabels = 0;
  487. for(int i=0; i<sizeX*sizeY; i++) {
  488. initialPos[i] = p.initialPos[i];
  489. finalPos[i] = p.finalPos[i];
  490. if (p.contLabels) contLabels[i] = p.contLabels[i];
  491. }
  492. contList = p.contList;
  493. }
  494. return *this;
  495. }
  496. string Pattern::printPattern() {
  497. string result;
  498. char buf[100];
  499. sprintf(buf, "boardsize: %d, area: %d, %d, %d, %d\nsize: %d, %d\n", boardsize, left, right, top, bottom, sizeX, sizeY);
  500. result += buf;
  501. for(int i=0; i<sizeY; i++) {
  502. for(int j=0; j<sizeX; j++) {
  503. 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];
  504. else result += '.';
  505. }
  506. result += "\n";
  507. }
  508. result += "\n";
  509. return result;
  510. }
  511. int Pattern::flipsX(int i, int x, int y, int XX, int YY) {
  512. if (i==0) return x;
  513. if (i==1) return XX-x;
  514. if (i==2) return x;
  515. if (i==3) return XX-x;
  516. if (i==4) return y;
  517. if (i==5) return YY-y;
  518. if (i==6) return y;
  519. if (i==7) return YY-y;
  520. return -1;
  521. }
  522. int Pattern::flipsY(int i, int x, int y, int XX, int YY) {
  523. if (i==0) return y;
  524. if (i==1) return y;
  525. if (i==2) return YY-y;
  526. if (i==3) return YY-y;
  527. if (i==4) return x;
  528. if (i==5) return x;
  529. if (i==6) return XX-x;
  530. if (i==7) return XX-x;
  531. return -1;
  532. }
  533. int Pattern::PatternInvFlip(int i) {
  534. if (i == 5) return 6;
  535. if (i == 6) return 5;
  536. return i;
  537. }
  538. const int composition_table[] = {
  539. 0, 1, 2, 3, 4, 5, 6, 7,
  540. 1, 0, 3, 2, 5, 4, 7, 6,
  541. 2, 3, 0, 1, 6, 7, 4, 5,
  542. 3, 2, 1, 0, 7, 6, 5, 4,
  543. 4, 6, 5, 7, 0, 2, 1, 3,
  544. 5, 7, 4, 6, 1, 3, 0, 2,
  545. 6, 4, 7, 5, 2, 0, 3, 1,
  546. 7, 5, 6, 4, 3, 1, 2, 0 };
  547. int Pattern::compose_flips(int i, int j) {
  548. return composition_table[j+8*i];
  549. }
  550. PatternList::PatternList(Pattern& p, int fColor, int nMove) throw(PatternError) {
  551. pattern.copy(p);
  552. fixedColor = fColor;
  553. nextMove = nMove;
  554. special = -1;
  555. flipTable = new int[16];
  556. for(int i=0; i<16; i++) flipTable[i] = -1; // (patternList() relies on this)
  557. patternList();
  558. continuations = new Continuation[pattern.sizeX * pattern.sizeY];
  559. }
  560. PatternList::~PatternList() {
  561. delete [] continuations;
  562. delete [] flipTable;
  563. }
  564. char PatternList::invertColor(char co) {
  565. if (co == 'X') return 'O';
  566. if (co == 'x') return 'o';
  567. if (co == 'O') return 'X';
  568. if (co == 'o') return 'x';
  569. return co;
  570. }
  571. void PatternList::patternList() {
  572. vector<Pattern> lCS;
  573. vector<pair<int,int> > sy;
  574. int boardsize = pattern.boardsize;
  575. for(int f = 0; f < 8; f++) {
  576. int newSizeX = max(Pattern::flipsX(f,0,0,pattern.sizeX,pattern.sizeY),
  577. Pattern::flipsX(f,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
  578. int newSizeY = max(Pattern::flipsY(f,0,0,pattern.sizeX,pattern.sizeY),
  579. Pattern::flipsY(f,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
  580. int newLeft = min(Pattern::flipsX(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
  581. Pattern::flipsX(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
  582. boardsize-1,boardsize-1));
  583. int newRight = max(Pattern::flipsX(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
  584. Pattern::flipsX(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
  585. boardsize-1,boardsize-1)) - (newSizeX-1);
  586. int newTop = min(Pattern::flipsY(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
  587. Pattern::flipsY(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
  588. boardsize-1,boardsize-1));
  589. int newBottom = max(Pattern::flipsY(f,pattern.left,pattern.top,boardsize-1,boardsize-1),
  590. Pattern::flipsY(f,pattern.right+pattern.sizeX-1,pattern.bottom+pattern.sizeY-1,
  591. boardsize-1,boardsize-1)) - (newSizeY - 1);
  592. // printf("%d, %d, %d, %d, %d, %d, %d\n", f, newSizeX, newSizeY, newLeft, newRight, newTop, newBottom);
  593. char* newInitialPos = new char[pattern.sizeX*pattern.sizeY];
  594. int i=0;
  595. for(i=0; i<pattern.sizeX; i++) {
  596. for(int j=0; j<pattern.sizeY; j++) {
  597. newInitialPos[Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1) + \
  598. newSizeX*Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1)] = pattern.getInitial(i, j);
  599. }
  600. }
  601. vector<MoveNC> newContList;
  602. for(i=0; (unsigned int)i<pattern.contList.size(); i++) {
  603. newContList.push_back(MoveNC(Pattern::flipsX(f, pattern.contList[i].x, pattern.contList[i].y,
  604. pattern.sizeX-1,pattern.sizeY-1),
  605. Pattern::flipsY(f, pattern.contList[i].x, pattern.contList[i].y,
  606. pattern.sizeX-1,pattern.sizeY-1),
  607. pattern.contList[i].color));
  608. }
  609. Pattern pNew(newLeft, newRight, newTop, newBottom, pattern.boardsize, newSizeX, newSizeY,
  610. newInitialPos, newContList);
  611. pNew.flip = f;
  612. // printf("new size %d %d\n", pNew.sizeX, pNew.sizeY);
  613. delete [] newInitialPos;
  614. vector<Pattern>::iterator it;
  615. bool foundNewPattern = true;
  616. for(it = data.begin(); it != data.end(); it++) {
  617. if (pNew == *it) {
  618. foundNewPattern = false;
  619. flipTable[f] = flipTable[it->flip];
  620. break;
  621. }
  622. }
  623. if (foundNewPattern) {
  624. flipTable[f] = data.size();
  625. data.push_back(pNew);
  626. }
  627. if (pNew == pattern) sy.push_back(pair<int,int>(f,0));
  628. if (nextMove || !fixedColor) {
  629. char* newInitialPos = new char[pattern.sizeX*pattern.sizeY];
  630. for(int i=0; i<pattern.sizeX; i++) {
  631. for(int j=0; j<pattern.sizeY; j++) {
  632. newInitialPos[Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1) + newSizeX*Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1)] =
  633. invertColor(pattern.getInitial(i, j));
  634. }
  635. }
  636. vector<MoveNC> newContList;
  637. {
  638. for(unsigned int i=0; i<pattern.contList.size(); i++) {
  639. newContList.push_back(MoveNC(Pattern::flipsX(f, pattern.contList[i].x, pattern.contList[i].y,
  640. pattern.sizeX-1,pattern.sizeY-1),
  641. Pattern::flipsY(f, pattern.contList[i].x, pattern.contList[i].y,
  642. pattern.sizeX-1,pattern.sizeY-1),
  643. invertColor(pattern.contList[i].color)));
  644. }
  645. }
  646. // printf("new size %d %d", newSizeX, newSizeY);
  647. Pattern pNew1(newLeft, newRight, newTop, newBottom, pattern.boardsize, newSizeX, newSizeY,
  648. newInitialPos, newContList);
  649. pNew1.flip = f;
  650. pNew1.colorSwitch = 1;
  651. delete [] newInitialPos;
  652. if (!fixedColor) {
  653. bool foundNewPattern = true;
  654. int lCS_ctr = 0;
  655. for(vector<Pattern>::iterator it = lCS.begin(); it != lCS.end(); it++) {
  656. if (pNew1 == *it) {
  657. foundNewPattern = false;
  658. flipTable[f+8] = lCS_ctr;
  659. break;
  660. }
  661. lCS_ctr++;
  662. }
  663. if (foundNewPattern) {
  664. lCS.push_back(pNew1);
  665. }
  666. }
  667. if (pNew1 == pattern) {
  668. if (!fixedColor) sy.push_back(pair<int,int>(f,1));
  669. if (nextMove) special = Pattern::PatternInvFlip(f);
  670. }
  671. }
  672. }
  673. int lCS_ctr = 0;
  674. for(vector<Pattern>::iterator it = lCS.begin(); it != lCS.end(); it++) {
  675. bool contained_in_l = false;
  676. for(vector<Pattern>::iterator it_l = data.begin(); it_l != data.end(); it_l++)
  677. if (*it == *it_l) {
  678. contained_in_l = true;
  679. flipTable[8+it->flip] = flipTable[it_l->flip];
  680. break;
  681. }
  682. if (!contained_in_l) {
  683. flipTable[8+it->flip] = data.size();
  684. data.push_back(*it);
  685. }
  686. for(int ii=it->flip+1; ii<8; ii++)
  687. if (flipTable[8+ii] == lCS_ctr) flipTable[8+ii] = flipTable[8+it->flip];
  688. lCS_ctr++;
  689. }
  690. Symmetries symm(pattern.sizeX, pattern.sizeY);
  691. for(int i=0; i<symm.sizeX; i++)
  692. for(int j=0; j<symm.sizeY; j++)
  693. symm.set(i,j, i,j,0);
  694. for(vector<pair<int,int> >::iterator it_s=sy.begin(); it_s!=sy.end(); it_s++) {
  695. int s = it_s->first;
  696. int newSizeX = max(Pattern::flipsX(s,0,0,pattern.sizeX,pattern.sizeY),
  697. Pattern::flipsX(s,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
  698. int newSizeY = max(Pattern::flipsY(s,0,0,pattern.sizeX,pattern.sizeY),
  699. Pattern::flipsY(s,pattern.sizeX,pattern.sizeY,pattern.sizeX,pattern.sizeY));
  700. int c = it_s->second;
  701. Symmetries symm1(newSizeX, newSizeY);
  702. for(int i=0; i < pattern.sizeX; i++) {
  703. for(int j=0; j < pattern.sizeY; j++) {
  704. int fX = Pattern::flipsX(s, i, j, pattern.sizeX-1, pattern.sizeY-1);
  705. int fY = Pattern::flipsY(s, i, j, pattern.sizeX-1, pattern.sizeY-1);
  706. if ((i != fX || j != fY) && !symm1.has_key(fX, fY))
  707. symm1.set(i,j, fX, fY, c);
  708. }
  709. }
  710. {
  711. int cs;
  712. for(int i=0; i<symm.sizeX; i++)
  713. for(int j=0; j<symm.sizeY; j++)
  714. if (symm1.has_key(symm.getX(i,j), symm.getY(i,j))) {
  715. if ((symm1.getCS(symm.getX(i,j),symm.getY(i,j)) || symm.getCS(i,j)) &&
  716. !(symm1.getCS(symm.getX(i,j),symm.getY(i,j)) && symm.getCS(i,j)))
  717. cs = 1;
  718. else cs = 0;
  719. symm.set(i,j,symm1.getX(symm.getX(i,j),symm.getY(i,j)),
  720. symm1.getY(symm.getX(i,j),symm.getY(i,j)), cs);
  721. }
  722. }
  723. }
  724. symmetries.push_back(symm);
  725. {
  726. vector<Pattern>::iterator it = data.begin();
  727. it++;
  728. for(; it != data.end(); it++) {
  729. // printf("ne %d, %d\n", it->sizeX, it->sizeY);
  730. int f = it->flip;
  731. Symmetries s(it->sizeX, it->sizeY);
  732. for(int i=0; i<pattern.sizeX; i++) {
  733. for(int j=0; j<pattern.sizeY; j++) {
  734. if (!it->colorSwitch) {
  735. s.set(Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
  736. Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
  737. symm.getX(i,j), symm.getY(i,j), symm.getCS(i,j));
  738. } else {
  739. s.set(Pattern::flipsX(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
  740. Pattern::flipsY(f,i,j,pattern.sizeX-1,pattern.sizeY-1),
  741. symm.getX(i,j), symm.getY(i,j), 1-symm.getCS(i,j));
  742. }
  743. }
  744. }
  745. symmetries.push_back(s);
  746. }
  747. }
  748. }
  749. Pattern PatternList::get(int i) {
  750. return data[i];
  751. }
  752. int PatternList::size() {
  753. return data.size();
  754. }
  755. char* PatternList::updateContinuations(int index, int x, int y, char co, bool tenuki, char winner) {
  756. char xx;
  757. char yy;
  758. char cSymm;
  759. char cc;
  760. xx = symmetries[index].getX(x,y);
  761. yy = symmetries[index].getY(x,y);
  762. cSymm = symmetries[index].getCS(x,y);
  763. if (co == 'X' || co == 'B') {
  764. if (cSymm) cc = 'W'; else cc = 'B';
  765. } else {
  766. if (cSymm) cc = 'B'; else cc = 'W';
  767. }
  768. if ((nextMove == 1 && cc == 'W') || (nextMove == 2 && cc == 'B')) {
  769. if (special != -1) {
  770. char xx1 = xx;
  771. // printf("s1 xx %d, yy %d sp %d\n", xx, yy, special);
  772. xx = Pattern::flipsX(special, xx, yy, pattern.sizeX-1, pattern.sizeY-1);
  773. yy = Pattern::flipsY(special, xx1, yy, pattern.sizeX-1, pattern.sizeY-1);
  774. // printf("s2 xx %d, yy %d\n", xx, yy);
  775. if (cc == 'B') cc = 'W';
  776. else cc = 'B';
  777. cSymm = 1-cSymm;
  778. } else {
  779. return 0;
  780. }
  781. }
  782. if (cc == 'B') {
  783. continuations[xx + pattern.sizeX*yy].B++;
  784. if (tenuki) continuations[xx + pattern.sizeX*yy].tB++;
  785. if ((winner == 'B' && !cSymm) || (winner == 'W' && cSymm)) continuations[xx + pattern.sizeX*yy].wB++;
  786. else if ((winner == 'W' && !cSymm) || (winner == 'B' && cSymm)) continuations[xx + pattern.sizeX*yy].lB++;
  787. } else {
  788. // printf("xx %d, yy %d\n", xx, yy);
  789. continuations[xx + pattern.sizeX*yy].W++;
  790. if (tenuki) continuations[xx + pattern.sizeX*yy].tW++;
  791. if ((winner == 'B' && !cSymm) || (winner == 'W' && cSymm)) continuations[xx + pattern.sizeX*yy].wW++;
  792. else if ((winner == 'W' && !cSymm) || (winner ='B' && cSymm)) continuations[xx + pattern.sizeX*yy].lW++;
  793. }
  794. char* result = new char[3];
  795. result[0] = xx;
  796. result[1] = yy;
  797. result[2] = cSymm;
  798. return result;
  799. }
  800. char* PatternList::sortContinuations() {
  801. char* labels = new char[pattern.sizeX*pattern.sizeY+1];
  802. labels[pattern.sizeX * pattern.sizeY] = 0; // so we can just printf the labels as a string
  803. for(int i=0; i<pattern.sizeX*pattern.sizeY; i++) {
  804. if (continuations[i].B || continuations[i].W) labels[i] = '?'; // need to assign label
  805. else labels[i] = '.';
  806. }
  807. string labelList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  808. unsigned int labelIndex = 0;
  809. // assign labels which are in the contLabels array passed to the original pattern
  810. // (these will usually be labels "already present in the SGF file")
  811. if (pattern.contLabels) {
  812. for(int i=0; i<pattern.sizeX*pattern.sizeY; i++) {
  813. if (pattern.contLabels[i] != '.') {
  814. labels[i] = pattern.contLabels[i];
  815. unsigned int j = labelList.find(pattern.contLabels[i]);
  816. if (j != string::npos) labelList.erase(j,1);
  817. }
  818. }
  819. }
  820. // now give labels to the remaining points, starting with the one with
  821. // most hits
  822. int max_hits = 0;
  823. int max_hits_index = 0;
  824. while (max_hits != -1 && labelIndex < labelList.size()) {
  825. for(int i=0; i<pattern.sizeX*pattern.sizeY; i++) {
  826. if (labels[i] == '?' && continuations[i].B + continuations[i].W > max_hits) {
  827. max_hits = continuations[i].B + continuations[i].W;
  828. max_hits_index = i;
  829. }
  830. }
  831. if (max_hits != 0) { // found another point needing a label
  832. labels[max_hits_index] = labelList[labelIndex++];
  833. max_hits = 0;
  834. } else max_hits = -1; // done
  835. }
  836. return labels;
  837. }
  838. DBError::DBError() {
  839. }
  840. int dbinsert1blob(sqlite3* db, char* sql, int id, char* blob, int size) {
  841. sqlite3_stmt *ppStmt=0;
  842. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  843. if (rc != SQLITE_OK || ppStmt==0) return rc;
  844. rc = sqlite3_bind_int(ppStmt, 1, id);
  845. if (rc != SQLITE_OK) return rc;
  846. rc = sqlite3_bind_blob(ppStmt, 2, blob, size, SQLITE_TRANSIENT);
  847. if (rc != SQLITE_OK) return rc;
  848. rc = sqlite3_step(ppStmt);
  849. if (rc != SQLITE_DONE) return rc;
  850. rc = sqlite3_finalize(ppStmt);
  851. if (rc != SQLITE_OK) return rc;
  852. return 0; // Success
  853. }
  854. int dbinsert2blobs(sqlite3* db, char* sql, int id, char* blob1, int size1, char* blob2, int size2) {
  855. sqlite3_stmt *ppStmt=0;
  856. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  857. if (rc != SQLITE_OK || ppStmt==0) return rc;
  858. rc = sqlite3_bind_int(ppStmt, 1, id);
  859. if (rc != SQLITE_OK) return rc;
  860. rc = sqlite3_bind_blob(ppStmt, 2, blob1, size1, SQLITE_TRANSIENT);
  861. if (rc != SQLITE_OK) return rc;
  862. rc = sqlite3_bind_blob(ppStmt, 3, blob2, size2, SQLITE_TRANSIENT);
  863. if (rc != SQLITE_OK) return rc;
  864. rc = sqlite3_step(ppStmt);
  865. if (rc != SQLITE_DONE) return rc;
  866. rc = sqlite3_finalize(ppStmt);
  867. if (rc != SQLITE_OK) return rc;
  868. return 0; // Success
  869. }
  870. Algorithm::Algorithm(int bsize) {
  871. boardsize = bsize;
  872. db = 0;
  873. }
  874. Algorithm::~Algorithm() {}
  875. void Algorithm::initialize_process(sqlite3* DB) {}
  876. void Algorithm::newgame_process(int game_id) {}
  877. void Algorithm::AB_process(int x, int y) {}
  878. void Algorithm::AW_process(int x, int y) {}
  879. void Algorithm::AE_process(int x, int y, char removed) {}
  880. void Algorithm::endOfNode_process() {}
  881. void Algorithm::move_process(Move m) {}
  882. void Algorithm::pass_process() {}
  883. void Algorithm::branchpoint_process() {}
  884. void Algorithm::endOfVariation_process() {}
  885. void Algorithm::endgame_process(bool commit) {}
  886. void Algorithm::finalize_process() {}
  887. int Algorithm::readDB(sqlite3* DB) { return 0; }
  888. int Algorithm::search(PatternList& patternList, GameList& gl, SearchOptions& options) {
  889. return -1;
  890. }
  891. Algo_signature::Algo_signature(int bsize) : Algorithm(bsize) {
  892. main_variation = true;
  893. }
  894. Algo_signature::~Algo_signature() {
  895. }
  896. void Algo_signature::initialize_process(sqlite3* DB) throw(DBError) {
  897. db = DB;
  898. char sql[100];
  899. sprintf(sql, "create table algo_signature_%d ( id integer primary key, signature varchar(12) );", boardsize);
  900. int rc = sqlite3_exec(db, sql, 0, 0, 0);
  901. //if (rc != SQLITE_OK) throw DBError();
  902. sprintf(sql, "create index sig_idx on algo_signature_%d(signature);", boardsize);
  903. rc = sqlite3_exec(db, sql, 0, 0, 0);
  904. //if (rc != SQLITE_OK) throw DBError();
  905. }
  906. void Algo_signature::newgame_process(int game_id) {
  907. main_variation = true;
  908. counter = 0;
  909. gid = game_id;
  910. signature = new char[12];
  911. for(int i=0; i<12; i++) signature[i] = '?';
  912. }
  913. void Algo_signature::AB_process(int x, int y) {
  914. }
  915. void Algo_signature::AW_process(int x, int y) {
  916. }
  917. void Algo_signature::AE_process(int x, int y, char removed) {
  918. }
  919. void Algo_signature::endOfNode_process() {
  920. }
  921. void Algo_signature::move_process(Move m) {
  922. if (!main_variation) return;
  923. counter++;
  924. if (counter==20) {
  925. signature[0] = m.x + 97;
  926. signature[1] = m.y + 97;
  927. }
  928. if (counter==40) {
  929. signature[2] = m.x + 97;
  930. signature[3] = m.y + 97;
  931. }
  932. if (counter==60) {
  933. signature[4] = m.x + 97;
  934. signature[5] = m.y + 97;
  935. }
  936. if (counter==31) {
  937. signature[6] = m.x + 97;
  938. signature[7] = m.y + 97;
  939. }
  940. if (counter==51) {
  941. signature[8] = m.x + 97;
  942. signature[9] = m.y + 97;
  943. }
  944. if (counter==71) {
  945. signature[10] = m.x + 97;
  946. signature[11] = m.y + 97;
  947. }
  948. }
  949. void Algo_signature::pass_process() {
  950. if (main_variation) move_process(Move(19,19,'p'));
  951. }
  952. void Algo_signature::branchpoint_process() {
  953. }
  954. void Algo_signature::endOfVariation_process() {
  955. main_variation = false;
  956. }
  957. char* symmetrize(char* signature, int boardsize) {
  958. // symmetrize signature
  959. char* min_signature = new char[12];
  960. for(int i=0; i<12; i++) min_signature[i] = signature[i];
  961. for (int f=0; f<8; f++) { // for all flips
  962. // compute flipped signature
  963. char* next = new char[12];
  964. for(int i=0; i<6; i++) {
  965. if ('a' <= signature[2*i] && signature[2*i] <= 's')
  966. next[2*i] = Pattern::flipsX(f, signature[2*i]-'a', signature[2*i+1]-'a', boardsize-1, boardsize-1)+'a';
  967. else next[2*i] = signature[2*i];
  968. if ('a' <= signature[2*i+1] && signature[2*i+1] <= 's')
  969. next[2*i+1] = Pattern::flipsY(f, signature[2*i]-'a', signature[2*i+1]-'a', boardsize-1, boardsize-1)+'a';
  970. else next[2*i+1] = signature[2*i+1];
  971. }
  972. // if next < min_signature, then swap
  973. for(int j=0; j<12; j++) {
  974. if (next[j] > min_signature[j]) break;
  975. if (next[j] < min_signature[j]) {
  976. char* help = next;
  977. next = min_signature;
  978. min_signature = help;
  979. break;
  980. }
  981. }
  982. delete [] next;
  983. }
  984. return min_signature;
  985. }
  986. void Algo_signature::endgame_process(bool commit) throw(DBError) {
  987. if (commit) {
  988. char* min_signature = symmetrize(signature, boardsize);
  989. char sql[100];
  990. sprintf(sql, "insert into algo_signature_%d (id, signature) values (?,?);", boardsize);
  991. if (dbinsert1blob(db, sql, gid, min_signature, 12)) throw DBError();
  992. // for(int i=0; i<12; i++) printf("%c", min_signature[i]); printf("\n");
  993. delete [] min_signature;
  994. }
  995. delete [] signature;
  996. }
  997. void Algo_signature::finalize_process() {
  998. }
  999. char* Algo_signature::get_current_signature() {
  1000. return symmetrize(signature, boardsize);
  1001. }
  1002. vector<int> Algo_signature::search_signature(char* sig) {
  1003. // to be used during processing! (because we need the db)
  1004. char sql[100];
  1005. sprintf(sql, "select id from algo_signature_%d where signature=? order by id", boardsize);
  1006. sqlite3_stmt *ppStmt=0;
  1007. vector<int> result;
  1008. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  1009. if (rc != SQLITE_OK || ppStmt==0) throw DBError();
  1010. rc = sqlite3_bind_blob(ppStmt, 1, sig, 12, SQLITE_TRANSIENT);
  1011. if (rc != SQLITE_OK || ppStmt==0) throw DBError();
  1012. do {
  1013. rc = sqlite3_step(ppStmt);
  1014. if (rc != SQLITE_DONE && rc != SQLITE_ROW) throw DBError();
  1015. if (rc == SQLITE_ROW) {
  1016. result.push_back(sqlite3_column_int(ppStmt, 0));
  1017. }
  1018. } while (rc == SQLITE_ROW);
  1019. rc = sqlite3_finalize(ppStmt);
  1020. if (rc != SQLITE_OK) throw DBError();
  1021. return result;
  1022. }
  1023. Algo_finalpos::Algo_finalpos(int bsize) : Algorithm(bsize) {
  1024. fp = 0;
  1025. fpIndex = -1;
  1026. data = 0;
  1027. }
  1028. Algo_finalpos::~Algo_finalpos() {
  1029. if (data) {
  1030. for(map<int, char* >::iterator it = data->begin(); it != data->end(); it++) delete [] it->second;
  1031. delete data;
  1032. }
  1033. }
  1034. void Algo_finalpos::initialize_process(sqlite3* DB) throw(DBError) {
  1035. // printf("init Algo_finalpos\n");
  1036. db = DB;
  1037. char sql[100];
  1038. sprintf(sql, "create table algo_finalpos_%d ( id integer primary key, data blob );", boardsize);
  1039. int rc = sqlite3_exec(db, sql, 0, 0, 0);
  1040. if (rc != SQLITE_OK) {
  1041. //throw DBError();
  1042. }
  1043. // printf("init Algo_finalpos\n");
  1044. }
  1045. void Algo_finalpos::newgame_process(int game_id) {
  1046. gid = game_id;
  1047. fp = new char[100];
  1048. for(int i=0; i<100; i++) fp[i] = 255;
  1049. }
  1050. void Algo_finalpos::AB_process(int x, int y) {
  1051. fp[y/2 + 10*(x/2)] &= ~(1 << (2*(x%2 + 2*(y%2))));
  1052. }
  1053. void Algo_finalpos::AW_process(int x, int y) {
  1054. fp[y/2 + 10*(x/2)] &= ~(1 << (2*(x%2 + 2*(y%2))+1));
  1055. }
  1056. void Algo_finalpos::AE_process(int x, int y, char removed) {
  1057. }
  1058. void Algo_finalpos::endOfNode_process() {
  1059. }
  1060. void Algo_finalpos::move_process(Move m) {
  1061. if (m.color == 'B')
  1062. fp[m.y/2 + 10*(m.x/2)] &= ~(1 << (2*(m.x%2 + 2*(m.y%2))));
  1063. else if (m.color == 'W')
  1064. fp[m.y/2 + 10*(m.x/2)] &= ~(1 << (2*(m.x%2 + 2*(m.y%2))+1));
  1065. }
  1066. void Algo_finalpos::pass_process() {
  1067. }
  1068. void Algo_finalpos::branchpoint_process() {
  1069. }
  1070. void Algo_finalpos::endOfVariation_process() {
  1071. }
  1072. void Algo_finalpos::endgame_process(bool commit) throw(DBError) {
  1073. if (commit) {
  1074. char sql[100];
  1075. sprintf(sql, "insert into algo_finalpos_%d (id, data) values (?,?);", boardsize);
  1076. if (dbinsert1blob(db, sql, gid, fp, 100)) throw DBError();
  1077. }
  1078. delete [] fp;
  1079. }
  1080. void Algo_finalpos::finalize_process() {
  1081. }
  1082. int Algo_finalpos::readDB(sqlite3* DB) {
  1083. db = DB;
  1084. if (data) {
  1085. for(map<int, char* >::iterator it = data->begin(); it != data->end(); it++) delete [] it->second;
  1086. delete data;
  1087. }
  1088. data = new map<int, char* >;
  1089. int rc = sqlite3_exec(db, "begin transaction;", 0, 0, 0);
  1090. if (rc) throw DBError();
  1091. sqlite3_stmt *ppStmt=0;
  1092. char sql[100];
  1093. sprintf(sql, "select id, data from algo_finalpos_%d order by id", boardsize);
  1094. rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  1095. if (rc != SQLITE_OK || ppStmt==0) return rc; // FIXME: catch certain errors, (and/or throw DBError?)
  1096. while (sqlite3_step(ppStmt) == SQLITE_ROW) {
  1097. // printf("step0\n");
  1098. int index = sqlite3_column_int(ppStmt, 0);
  1099. char* d = (char*)sqlite3_column_blob(ppStmt, 1);
  1100. // printf("step1\n");
  1101. char* d1 = new char[100];
  1102. // printf("step2\n");
  1103. for(int i=0; i<100; i++) d1[i] = d[i];
  1104. // printf("step3\n");
  1105. // printf("insert %d %p\n", index, d1);
  1106. data->insert(make_pair(index, d1));
  1107. }
  1108. // printf("done\n");
  1109. rc = sqlite3_finalize(ppStmt);
  1110. if (rc != SQLITE_OK) return rc;
  1111. rc = sqlite3_exec(db, "commit;", 0, 0, 0);
  1112. if (rc != SQLITE_OK) throw DBError();
  1113. return 0;
  1114. }
  1115. int Algo_finalpos::search(PatternList& patternList, GameList& gl, SearchOptions& options) { // progress bar?!
  1116. // Put the pattern into bitmap format, which is the format the final
  1117. // positions are stored in in the database. This makes the comparisons
  1118. // faster.
  1119. int plS = patternList.size();
  1120. char_p** allbits = new char_p*[plS];
  1121. int** allbitlengths = new int*[plS];
  1122. for(int N=0; N<plS; N++) {
  1123. Pattern* pattern = &patternList.data[N];
  1124. allbits[N] = new char_p[4];
  1125. allbitlengths[N] = new int[4];
  1126. for(int i=0; i<2; i++) {
  1127. for(int j=0; j<2; j++) {
  1128. int xBlocks = (pattern->sizeY+i+1)/2;
  1129. int yBlocks = (pattern->sizeX+j+1)/2;
  1130. char* nextBlock = new char[400];
  1131. int nextBlockIndex = 0;
  1132. nextBlock[nextBlockIndex++] = yBlocks;
  1133. for(int k1=0; k1 < yBlocks; k1++) {
  1134. char nlist[400];
  1135. int nlistIndex = 0;
  1136. for(int k2=0; k2 < xBlocks; k2++) {
  1137. int n = 0;
  1138. for(int x=0; x<2; x++) {
  1139. for(int y=0; y<2; y++) {
  1140. int indexX = k1 * 2 + y - j;
  1141. int indexY = k2 * 2 + x - i;
  1142. if (0 <= indexX && indexX < pattern->sizeX && 0 <= indexY && indexY < pattern->sizeY) {
  1143. if (pattern->getFinal(indexX,indexY)=='X')
  1144. n |= 1 << (2*(2*x+y));
  1145. else if (pattern->getFinal(indexX,indexY)=='O')
  1146. n |= 1 << (2*(2*x+y)+1);
  1147. }
  1148. }
  1149. }
  1150. nlist[nlistIndex++] = n;
  1151. }
  1152. int start = 0;
  1153. int end = nlistIndex;
  1154. while (start < end && !nlist[start]) start++;
  1155. while (end > start && !nlist[end-1]) end--;
  1156. nextBlock[nextBlockIndex++] = start;
  1157. nextBlock[nextBlockIndex++] = end-start;
  1158. for(int current=start; current < end; current++)
  1159. nextBlock[nextBlockIndex++] = nlist[current];
  1160. }
  1161. char* nB = new char[nextBlockIndex];
  1162. for(int ii=0; ii<nextBlockIndex; ii++) nB[ii] = nextBlock[ii];
  1163. allbitlengths[N][2*i + j] = nextBlockIndex;
  1164. allbits[N][2*i + j] = nB;
  1165. delete [] nextBlock;
  1166. }
  1167. }
  1168. }
  1169. int index = gl.start();
  1170. // int counter = 0; // to keep track of progress bar
  1171. // printf("%d patterns\n", plS);
  1172. char start;
  1173. char length;
  1174. char x;
  1175. char y;
  1176. while (index != -1) {
  1177. // if (!(counter++ % 1000)) printf("counter: %d, index: %d\n", counter, index);
  1178. // if (progBar && !(counter % 100))
  1179. // progBar.redraw((progEnd-progStart)*counter/len(gl.current) + progStart);
  1180. map<int, char* >::iterator it = data->find(index);
  1181. if (it == data->end()) {
  1182. // printf("skip\n");
  1183. index = gl.next();
  1184. continue;
  1185. }
  1186. char* finalpos = it->second;
  1187. // printf("index %d, %p\n", index, finalpos);
  1188. vector<Candidate* > *matchList = new vector<Candidate* >;;
  1189. for(int N=0; N<plS; N++) {
  1190. Pattern* pattern = &patternList.data[N];
  1191. for(int a0=pattern->left; a0 <= pattern->right; a0++) {
  1192. for(int a1 = pattern->top; a1 <= pattern->bottom; a1++) {
  1193. int matches = 1;
  1194. int pIndex = 2*(a1%2) + (a0%2);
  1195. char* pbits = allbits[N][pIndex];
  1196. int pbIndex = 0;
  1197. int fpIndex = a1/2 + (a0/2)*10;
  1198. for(x=0; x < pbits[0]; x++) {
  1199. start = pbits[++pbIndex];
  1200. length = pbits[++pbIndex];
  1201. fpIndex += start;
  1202. for(y=0; y<length; y++) {
  1203. pbIndex++;
  1204. if (pbits[pbIndex] & finalpos[fpIndex]) {
  1205. matches = 0;
  1206. break;
  1207. }
  1208. fpIndex++;
  1209. }
  1210. if (!matches) break;
  1211. fpIndex += 10 - start - length;
  1212. }
  1213. if (matches) matchList->push_back(new Candidate(a0,a1,N));
  1214. }
  1215. }
  1216. }
  1217. if (matchList->size()) gl.makeCurrentCandidate(matchList);
  1218. else delete matchList;
  1219. index = gl.next();
  1220. }
  1221. {
  1222. for(int N=0; N<plS; N++) {
  1223. delete [] allbitlengths[N];
  1224. for(int i=0; i<4; i++)
  1225. if (allbits[N][i]) delete [] allbits[N][i];
  1226. delete [] allbits[N];
  1227. }
  1228. }
  1229. delete [] allbitlengths;
  1230. delete [] allbits;
  1231. return 0;
  1232. }
  1233. bool Algo_finalpos::equal(unsigned int i1, unsigned int i2) {
  1234. // not to be used during processing
  1235. // i1, i2 correspond to game id's
  1236. sqlite3_stmt *ppStmt=0;
  1237. char sql[100];
  1238. sprintf(sql, "select data from algo_finalpos_%d where id = %d or id = %d", boardsize, i1, i2);
  1239. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  1240. if (rc != SQLITE_OK || ppStmt==0) return false; // FIXME: catch certain errors, (and/or throw DBError?)
  1241. if (sqlite3_step(ppStmt) == SQLITE_ROW) {
  1242. char* dd1 = (char*)sqlite3_column_blob(ppStmt, 0);
  1243. char* d1 = new char[100];
  1244. for(int i=0; i<100; i++) d1[i] = dd1[i]; // FIXME: is this necessary?
  1245. if (sqlite3_step(ppStmt) == SQLITE_ROW) {
  1246. char* d2 = (char*)sqlite3_column_blob(ppStmt, 0);
  1247. for(int i=0; i<100; i++)
  1248. if (d1[i] != d2[i]) {
  1249. delete [] d1;
  1250. sqlite3_finalize(ppStmt);
  1251. return false;
  1252. }
  1253. delete [] d1;
  1254. sqlite3_finalize(ppStmt);
  1255. return true;
  1256. }
  1257. delete [] d1;
  1258. }
  1259. sqlite3_finalize(ppStmt);
  1260. return false;
  1261. }
  1262. bool Algo_finalpos::equals_current(unsigned int id1) {
  1263. // to be used only during processing
  1264. // id1 here corresponds to a game id
  1265. bool result = true;
  1266. sqlite3_stmt *ppStmt=0;
  1267. char sql[100];
  1268. sprintf(sql, "select data from algo_finalpos_%d where id = %d", boardsize, id1);
  1269. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  1270. if (rc != SQLITE_OK || ppStmt==0) return false; // FIXME: catch certain errors, (and/or throw DBError?)
  1271. if (sqlite3_step(ppStmt) == SQLITE_ROW) {
  1272. char* d = (char*)sqlite3_column_blob(ppStmt, 0);
  1273. for(int i=0; i<100; i++)
  1274. if (d[i] != fp[i]) {
  1275. result = false;
  1276. break;
  1277. }
  1278. } else result = false;
  1279. sqlite3_finalize(ppStmt);
  1280. return result;
  1281. }
  1282. Algo_movelist::Algo_movelist(int bsize) : Algorithm(bsize) {
  1283. data1 = 0;
  1284. data2 = 0;
  1285. data1l = 0;
  1286. }
  1287. Algo_movelist::~Algo_movelist() {
  1288. if (data1) {
  1289. for(map<int, char* >::iterator it = data1->begin(); it != data1->end(); it++) {
  1290. delete [] it->second;
  1291. }
  1292. delete data1;
  1293. }
  1294. if (data2) {
  1295. for(map<int, char* >::iterator it = data2->begin(); it != data2->end(); it++) {
  1296. delete [] it->second;
  1297. }
  1298. delete data2;
  1299. }
  1300. if (data1l) delete data1l;
  1301. }
  1302. void Algo_movelist::initialize_process(sqlite3* DB) throw(DBError) {
  1303. // printf("init Algo_movelist\n");
  1304. db = DB;
  1305. char sql[100];
  1306. sprintf(sql, "create table algo_movelist_%d ( id integer primary key, movelist blob, fpC blob );", boardsize);
  1307. int rc = sqlite3_exec(db, sql, 0, 0, 0);
  1308. //if (rc != SQLITE_OK) throw DBError();
  1309. // printf("init Algo_movelist\n");
  1310. }
  1311. void Algo_movelist::newgame_process(int game_id) {
  1312. gid = game_id;
  1313. movelist = vector<char>();
  1314. fpC = new char[50];
  1315. for(int i=0; i<50; i++) fpC[i] = 0;
  1316. }
  1317. void Algo_movelist::AB_process(int x, int y) {
  1318. movelist.push_back((char)x);
  1319. movelist.push_back((char)(y | BLACK));
  1320. }
  1321. void Algo_movelist::AW_process(int x, int y) {
  1322. movelist.push_back((char)x);
  1323. movelist.push_back((char)(y | WHITE));
  1324. }
  1325. void Algo_movelist::AE_process(int x, int y, char removed) {
  1326. movelist.push_back((char)x);
  1327. if (removed == 'B') movelist.push_back((char)(y | REMOVE | BLACK));
  1328. else if (removed == 'W') movelist.push_back((char)(y | REMOVE | WHITE));
  1329. }
  1330. void Algo_movelist::endOfNode_process() {
  1331. if (movelist.size()>1) {
  1332. if (movelist[movelist.size()-2] & (ENDOFNODE | BRANCHPOINT | ENDOFVARIATION)) {
  1333. movelist.push_back(ENDOFNODE);
  1334. movelist.push_back(0);
  1335. } else {
  1336. movelist[movelist.size()-2] |= ENDOFNODE;
  1337. }
  1338. } else {
  1339. movelist.push_back(ENDOFNODE);
  1340. movelist.push_back(0);
  1341. }
  1342. }
  1343. void Algo_movelist::move_process(Move m) {
  1344. if (!movelist.size()) {
  1345. movelist.push_back(ENDOFNODE);
  1346. movelist.push_back(0);
  1347. }
  1348. movelist.push_back(m.x);
  1349. if (m.color=='B') movelist.push_back(m.y | BLACK);
  1350. else movelist.push_back(m.y | WHITE);
  1351. if (m.captures) {
  1352. vector<p_cc>::iterator it;
  1353. for(it = m.captures->begin(); it != m.captures->end(); it++) {
  1354. int xx = it->first;
  1355. int yy = it->second;
  1356. movelist.push_back(xx);
  1357. if (m.color=='B') movelist.push_back(yy | REMOVE | WHITE);
  1358. else movelist.push_back(yy | REMOVE | BLACK);
  1359. fpC[yy/4 + 5*(xx/2)] |= 1 << (xx%2 + 2*(yy%4));
  1360. }
  1361. }
  1362. }
  1363. void Algo_movelist::pass_process() {
  1364. movelist.push_back(19);
  1365. movelist.push_back(19);
  1366. }
  1367. void Algo_movelist::branchpoint_process() {
  1368. movelist.push_back(BRANCHPOINT);
  1369. movelist.push_back(0);
  1370. }
  1371. void Algo_movelist::endOfVariation_process() {
  1372. movelist.push_back(ENDOFVARIATION);
  1373. movelist.push_back(0);
  1374. }
  1375. void Algo_movelist::endgame_process(bool commit) throw(DBError) {
  1376. if (commit) {
  1377. char* ml = new char[movelist.size()];
  1378. int mlIndex = 0;
  1379. for(vector<char>::iterator it = movelist.begin(); it != movelist.end(); it++) {
  1380. ml[mlIndex++] = *it;
  1381. }
  1382. char sql[100];
  1383. sprintf(sql, "insert into algo_movelist_%d (id, movelist, fpC) values (?, ?, ?);", boardsize);
  1384. if (dbinsert2blobs(db, sql, gid, ml, mlIndex, fpC, 50)) throw DBError();
  1385. delete [] ml;
  1386. }
  1387. delete [] fpC;
  1388. }
  1389. void Algo_movelist::finalize_process() {
  1390. }
  1391. int Algo_movelist::readDB(sqlite3* DB) {
  1392. if (data1) {
  1393. for(map<int, char* >::iterator it = data1->begin(); it != data1->end(); it++) delete [] it->second;
  1394. delete data1;
  1395. }
  1396. data1 = new map<int, char* >;
  1397. if (data1l) delete data1l;
  1398. data1l = new map<int, int >;
  1399. if (data2) {
  1400. for(map<int, char* >::iterator it = data2->begin(); it != data2->end(); it++) delete [] it->second;
  1401. delete data2;
  1402. }
  1403. data2 = new map<int, char* >;
  1404. db = DB;
  1405. int rc = sqlite3_exec(db, "begin transaction;", 0, 0, 0);
  1406. if (rc) throw DBError();
  1407. sqlite3_stmt *ppStmt=0;
  1408. char sql[100];
  1409. sprintf(sql, "select movelist,fpC,id from algo_movelist_%d order by id", boardsize);
  1410. rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  1411. if (rc != SQLITE_OK || ppStmt==0) return rc; // FIXME: catch certain errors, (and/or throw DBError?)
  1412. while (sqlite3_step(ppStmt) == SQLITE_ROW) {
  1413. int l = sqlite3_column_bytes(ppStmt,0);
  1414. // printf("len movelist: %d\n", l);
  1415. char* d = (char*)sqlite3_column_blob(ppStmt, 0);
  1416. char* d1 = new char[l];
  1417. for(int i=0; i<l; i++) {
  1418. d1[i] = d[i];
  1419. // printf("%c", (d[i] & 31)+97);
  1420. }
  1421. int index = sqlite3_column_int(ppStmt, 2);
  1422. // printf("\n");
  1423. data1->insert(make_pair(index, d1));
  1424. data1l->insert(make_pair(index, l));
  1425. d = (char*)sqlite3_column_blob(ppStmt, 1);
  1426. d1 = new char[50];
  1427. {
  1428. for(int i=0; i<50; i++) d1[i] = d[i];
  1429. }
  1430. data2->insert(make_pair(index, d1));
  1431. }
  1432. rc = sqlite3_finalize(ppStmt);
  1433. if (rc != SQLITE_OK) return rc;
  1434. rc = sqlite3_exec(db, "commit;", 0, 0, 0);
  1435. if (rc != SQLITE_OK) throw DBError();
  1436. // printf("data sizes %d, %d, %d\n", data1->size(), data1l->size(), data2->size());
  1437. return 0;
  1438. }
  1439. MovelistCand::MovelistCand(Pattern* P, int ORIENTATION, char* DICTS, int NO, char X, char Y) {
  1440. orientation = ORIENTATION;
  1441. p = P;
  1442. mx = X;
  1443. my = Y;
  1444. Xinterv = make_pair(mx, mx+p->sizeX);
  1445. Yinterv = make_pair(my, my+p->sizeY);
  1446. dicts = DICTS;
  1447. dictsNO = NO;
  1448. contListIndex = 0;
  1449. dictsFound = false;
  1450. dictsFoundInitial = false;
  1451. dictsDR = false;
  1452. contList = p->contList; // FIXME
  1453. }
  1454. MovelistCand::~MovelistCand() {
  1455. delete [] dicts;
  1456. }
  1457. char MovelistCand::dictsget(char x, char y) {
  1458. return dicts[x-mx + p->sizeX*(y-my)];
  1459. }
  1460. void MovelistCand::dictsset(char x, char y, char d) {
  1461. dicts[x-mx + p->sizeX*(y-my)] = d;
  1462. }
  1463. bool MovelistCand::in_relevant_region(char x, char y) {
  1464. return (mx <= x && x < mx + p->sizeX && my <= y && y < my + p->sizeY);
  1465. }
  1466. VecMC::VecMC() : vector<MovelistCand* >() {
  1467. candssize = 0;
  1468. }
  1469. VecMC::~VecMC() {
  1470. for(VecMC::iterator it = begin(); it != end(); it++) {
  1471. if (*it) delete *it;
  1472. }
  1473. }
  1474. VecMC* VecMC::deepcopy(ExtendedMoveNumber& COUNTER, int CANDSSIZE) {
  1475. VecMC* result = new VecMC;
  1476. result->candssize = CANDSSIZE;
  1477. result->counter = COUNTER;
  1478. for(VecMC::iterator it = begin(); it != end(); it++) {
  1479. MovelistCand* mlc = 0;
  1480. if (*it) {
  1481. char* DICTS = new char[(*it)->p->sizeX * (*it)->p->sizeY];
  1482. for (int i=0; i < (*it)->p->sizeX * (*it)->p->sizeY; i++) DICTS[i] = (*it)->dicts[i];
  1483. mlc = new MovelistCand((*it)->p, (*it)->orientation, DICTS, (*it)->dictsNO, (*it)->mx, (*it)->my);
  1484. mlc->contListIndex = (*it)->contListIndex;
  1485. mlc->dictsFound = (*it)->dictsFound;
  1486. mlc->dictsF = (*it)->dictsF;
  1487. mlc->dictsFoundInitial = (*it)->dictsFoundInitial;
  1488. mlc->dictsFI = (*it)->dictsFI;
  1489. mlc->dictsDR = (*it)->dictsDR;
  1490. mlc->contList = mlc->p->contList; // FIXME
  1491. }
  1492. result->push_back(mlc);
  1493. }
  1494. return result;
  1495. }
  1496. int Algo_movelist::search(PatternList& patternList, GameList& gl, SearchOptions& options) {
  1497. // FIXME progbar
  1498. // printf("Enter Algo_movelist::search\n");
  1499. int numOfHits = 0;
  1500. int self_numOfSwitched = 0;
  1501. int Bwins = 0;
  1502. int Wwins = 0;
  1503. int movelimit = options.moveLimit;
  1504. int index = gl.start();
  1505. // int gameCounter = 0;
  1506. while (index != -1) {
  1507. // gameCounter++;
  1508. // if (progBar && !(gameCounter % 10))
  1509. // progBar.redraw((progEnd-progStart)*gameCounter/len(db.current) + progStart);
  1510. // printf("Process index %d\n", index);
  1511. vector<Hit* > * result = new vector<Hit* >;
  1512. int numOfSwitched = 0;
  1513. stack<VecMC* > branchpoints;
  1514. char* movel = (*data1)[index];
  1515. int movelistIndex = 0;
  1516. int endMovelist = (*data1l)[index];
  1517. // printf("len movelist: %d\n", (*data1l)[index]);
  1518. // int nodeCtr = 0;
  1519. // for(int i=0; i<endMovelist/2; i++) {
  1520. // printf(" - ");
  1521. // if (movel[2*i] & BRANCHPOINT) printf("BP\n");
  1522. // if (movel[2*i] & ENDOFVARIATION) printf("EV\n");
  1523. // if (movel[2*i+1] & BLACK) printf("B");
  1524. // if (movel[2*i+1] & WHITE) printf("W");
  1525. // if (movel[2*i+1] & REMOVE) printf("C");
  1526. // printf("%c", (movel[2*i] & 31)+97);
  1527. // printf("%c", (movel[2*i+1] & 31)+97);
  1528. // if (movel[2*i] & ENDOFNODE) printf("\n%d ", nodeCtr++);
  1529. // }
  1530. // printf("\n");
  1531. char* fpC = (*data2)[index];
  1532. vector<Candidate* > *currentMatchList = gl.getCurrentCandidateList();
  1533. int candssize = currentMatchList->size();
  1534. VecMC* cands = new VecMC;
  1535. cands->reserve(currentMatchList->size());
  1536. for(int mCounter=0; mCounter<(int)currentMatchList->size(); mCounter++) {
  1537. Candidate* m = (*currentMatchList)[mCounter];
  1538. int dNO = 0;
  1539. Pattern* p = &patternList.data[m->orientation];
  1540. char* d = new char[p->sizeX * p->sizeY];
  1541. for(int i=0; i<p->sizeX; i++) {
  1542. for(int j=0; j<p->sizeY; j++) {
  1543. char p_ij = p->getInitial(i,j);
  1544. if (p_ij != '.') d[i+p->sizeX*j] = p_ij;
  1545. else d[i+p->sizeX*j] = 0;
  1546. if (p_ij == 'X' || p_ij == 'O') dNO++;
  1547. }
  1548. }
  1549. cands->push_back(new MovelistCand(p, m->orientation, d, dNO, m->x, m->y));
  1550. }
  1551. // printf("candssize %d\n", cands->size());
  1552. ExtendedMoveNumber counter(0);
  1553. while (movelistIndex < endMovelist) {
  1554. // printf("\nnextmove %d\n", counter.total_move_num());
  1555. if (counter.total_move_num() == movelimit+1) {
  1556. for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
  1557. if (*it == 0) continue;
  1558. if (!(*it)->dictsFound) {
  1559. delete *it;
  1560. *it = 0;
  1561. candssize--;
  1562. }
  1563. }
  1564. }
  1565. if (options.searchInVariations && movel[movelistIndex] & BRANCHPOINT) {
  1566. // printf("branchpoint\n");
  1567. branchpoints.push(cands->deepcopy(counter, candssize));
  1568. movelistIndex += 2;
  1569. continue;
  1570. }
  1571. if (options.searchInVariations && movel[movelistIndex] & ENDOFVARIATION) {
  1572. // printf("endofvariation\n");
  1573. if (!patternList.nextMove) { // deal with hits w/o continuation
  1574. for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
  1575. if (*it == 0) continue;
  1576. if ((*it)->dictsFound) {
  1577. if ((*it)->p->colorSwitch) {
  1578. numOfSwitched++;
  1579. char* rstr = new char[3];
  1580. rstr[0] = NO_CONT;
  1581. rstr[1] = 0;
  1582. rstr[2] = 1;
  1583. result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr));
  1584. } else {
  1585. char* rstr = new char[3];
  1586. rstr[0] = NO_CONT;
  1587. rstr[1] = 0;
  1588. rstr[2] = 0;
  1589. result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr));
  1590. }
  1591. }
  1592. }
  1593. }
  1594. delete cands;
  1595. cands = branchpoints.top();
  1596. counter = cands->counter;
  1597. candssize = cands->candssize;
  1598. counter.down();
  1599. branchpoints.pop();
  1600. movelistIndex += 2;
  1601. continue;
  1602. }
  1603. char x = movel[movelistIndex] & 31;
  1604. char y = movel[movelistIndex+1] & 31;
  1605. char co = 'O';
  1606. char invco = 'X';
  1607. char lower_invco = 'x';
  1608. if (!(movel[movelistIndex+1] & REMOVE) && (movel[movelistIndex+1] & (BLACK | WHITE))) {
  1609. // printf("mv\n");
  1610. if (movel[movelistIndex+1] & BLACK) {
  1611. co = 'X';
  1612. invco = 'O';
  1613. lower_invco = 'o';
  1614. }
  1615. for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
  1616. if (*it == 0) continue;
  1617. if ((*it)->in_relevant_region(x,y)) {
  1618. // printf("loop 1\n %c", (*it)->dictsget(x,y));
  1619. if ((*it)->dictsFound) { // found, so now we have found the continuation
  1620. // printf("found\n");
  1621. char* label;
  1622. label = patternList.updateContinuations(
  1623. (*it)->orientation, // pattern in question
  1624. x-(*it)->mx, y-(*it)->my, // pos of continuation
  1625. co, // color of continuation
  1626. (counter.total_move_num()-(*it)->dictsF.total_move_num())>2, // tenuki?
  1627. gl.getCurrentWinner()
  1628. );
  1629. if (label) { // otherwise no hit because continuation has wrong color (i.e. nextMove set)
  1630. numOfSwitched += label[2];
  1631. result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), label));
  1632. }
  1633. delete *it;
  1634. *it = 0;
  1635. candssize--;
  1636. continue;
  1637. } else if ((*it)->dictsFoundInitial) { // foundInitial, so now look for contList
  1638. if (MoveNC(x, y, co) == ((*it)->contList)[(*it)->contListIndex]) {
  1639. (*it)->contListIndex++;
  1640. if ((*it)->contListIndex == (int)(*it)->contList.size()) {
  1641. (*it)->dictsF = counter;
  1642. (*it)->dictsFound = true;
  1643. }
  1644. } else {
  1645. if ((*it)->dictsDR) { // don't restore
  1646. delete *it;
  1647. *it = 0;
  1648. candssize--;
  1649. continue;
  1650. } else {
  1651. (*it)->contListIndex = 0;
  1652. (*it)->dictsFoundInitial = false;
  1653. }
  1654. }
  1655. }
  1656. if (!(*it)->dictsget(x,y)) { // this move occupies a spot which should be empty
  1657. if (!(fpC[y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) {
  1658. if (!(*it)->contListIndex) {
  1659. delete *it;
  1660. *it = 0;
  1661. candssize--;
  1662. continue;
  1663. } else (*it)->dictsDR = true;
  1664. } else {
  1665. (*it)->dictsset(x,y,'.');
  1666. (*it)->dictsNO++; // printf("++ A\n");
  1667. }
  1668. } else if ((*it)->dictsget(x,y) == lower_invco) {
  1669. // this move occupies a wildcard spot of the wrong color
  1670. if (!(fpC[y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) {
  1671. if (!(*it)->contListIndex) {
  1672. delete *it;
  1673. *it = 0;
  1674. candssize--;
  1675. continue;
  1676. } else (*it)->dictsDR = true;
  1677. } else (*it)->dictsNO++; // printf("++ B\n");
  1678. } else if ((*it)->dictsget(x,y) == co) {
  1679. // this move gives us the stone we are looking for
  1680. (*it)->dictsset(x,y,0);
  1681. (*it)->dictsNO--; // printf("-- A\n");
  1682. }
  1683. }
  1684. }
  1685. }
  1686. else if (movel[movelistIndex+1] & REMOVE) {
  1687. if (movel[movelistIndex+1] & BLACK) {
  1688. co = 'X';
  1689. invco = 'O';
  1690. lower_invco = 'o';
  1691. } else if (movel[movelistIndex+1] & WHITE) {
  1692. co = 'O';
  1693. invco = 'X';
  1694. lower_invco = 'x';
  1695. }
  1696. for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
  1697. // printf("loop 2\n");
  1698. if (*it == 0) continue;
  1699. if (!(*it)->dictsFound) { // not found yet
  1700. if ((*it)->in_relevant_region(x,y)) {
  1701. if ((*it)->dictsFoundInitial) { // foundInitial
  1702. int ii = (*it)->contListIndex;
  1703. while (ii < (int)(*it)->contList.size() && (*it)->contList[ii].color == '-' &&
  1704. (x != (*it)->contList[ii].x || y != (*it)->contList[ii].y))
  1705. ii++;
  1706. if (ii < (int)(*it)->contList.size() && (*it)->contList[ii].color == '-') {
  1707. MoveNC help = (*it)->contList[ii];
  1708. (*it)->contList[ii] = (*it)->contList[(*it)->contListIndex];
  1709. (*it)->contList[(*it)->contListIndex] = help;
  1710. (*it)->contListIndex++;
  1711. } else {
  1712. if ((*it)->dictsDR) {
  1713. delete *it;
  1714. *it = 0;
  1715. candssize--;
  1716. continue;
  1717. } else {
  1718. (*it)->contListIndex = 0;
  1719. (*it)->dictsFoundInitial = false;
  1720. }
  1721. }
  1722. }
  1723. if (!(*it)->dictsget(x,y)) {
  1724. // the stone at this position was what we needed,
  1725. // since it was captured, we are once again looking for it:
  1726. (*it)->dictsset(x,y,co);
  1727. (*it)->dictsNO++; // printf("++ C\n");
  1728. }
  1729. else if ((*it)->dictsget(x,y) == lower_invco) {
  1730. (*it)->dictsNO--; // printf("-- B\n");
  1731. }
  1732. else if ((*it)->dictsget(x,y) == '.') {
  1733. // we are looking for an empty spot here, so this capture is helpful:
  1734. (*it)->dictsset(x,y,0);
  1735. (*it)->dictsNO--; // printf("-- C\n");
  1736. }
  1737. }
  1738. }
  1739. }
  1740. }
  1741. if (movel[movelistIndex] & ENDOFNODE) {
  1742. vector<MovelistCand* >::iterator candsend = cands->end();
  1743. for(vector<MovelistCand* >::iterator it = cands->begin(); it != candsend; it++) {
  1744. if (*it == 0) continue;
  1745. if (!(*it)->dictsNO && !(*it)->dictsFound) {
  1746. if (!(*it)->contList.size()) {
  1747. (*it)->dictsF = counter;
  1748. (*it)->dictsFound = true;
  1749. } else if (!(*it)->dictsFoundInitial) {
  1750. (*it)->dictsFI = counter;
  1751. (*it)->dictsFoundInitial = true;
  1752. } else if (!(*it)->dictsDR) { // found initial position again during processing of contList
  1753. char* d = new char[(*it)->p->sizeX*(*it)->p->sizeY];
  1754. for (int ct=0; ct < (*it)->p->sizeX*(*it)->p->sizeY; ct++) d[ct] = (*it)->dicts[ct];
  1755. MovelistCand* mlc = new MovelistCand((*it)->p, (*it)->orientation, d, 0, (*it)->mx, (*it)->my);
  1756. mlc->dictsFI = counter;
  1757. cands->push_back(mlc);
  1758. candssize++;
  1759. }
  1760. }
  1761. }
  1762. counter.next();
  1763. }
  1764. if (candssize==0 && branchpoints.size()==0) break;
  1765. movelistIndex += 2;
  1766. }
  1767. // printf("assemble results\n");
  1768. if (!patternList.nextMove) { // look at matches w/o continuation
  1769. for(vector<MovelistCand* >::iterator it = cands->begin(); it != cands->end(); it++) {
  1770. if (*it == 0) continue;
  1771. if ((*it)->dictsFound) {
  1772. if ((*it)->p->colorSwitch) {
  1773. numOfSwitched++;
  1774. char* rstr = new char[3];
  1775. rstr[0] = NO_CONT;
  1776. rstr[1] = 0;
  1777. rstr[2] = 1;
  1778. result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr)); // FIXME what w/ variations?
  1779. } else {
  1780. char* rstr = new char[3];
  1781. rstr[0] = NO_CONT;
  1782. rstr[1] = 0;
  1783. rstr[2] = 0;
  1784. result->push_back(new Hit(new ExtendedMoveNumber((*it)->dictsF), rstr));
  1785. }
  1786. }
  1787. }
  1788. }
  1789. if (result->size()) {
  1790. numOfHits += result->size();
  1791. self_numOfSwitched += numOfSwitched;
  1792. if (gl.getCurrentWinner() == 'B') {
  1793. Bwins += result->size() - numOfSwitched;
  1794. Wwins += numOfSwitched;
  1795. } else if (gl.getCurrentWinner() == 'W') {
  1796. Bwins += numOfSwitched;
  1797. Wwins += result->size() - numOfSwitched;
  1798. }
  1799. gl.makeCurrentHit(result);
  1800. } else delete result;
  1801. index = gl.next();
  1802. delete cands;
  1803. }
  1804. gl.num_hits = numOfHits;
  1805. gl.num_switched = self_numOfSwitched;
  1806. gl.Bwins = Bwins;
  1807. gl.Wwins = Wwins;
  1808. return 0;
  1809. }
  1810. #if (defined(__BORLANDC__) || defined(_MSC_VER))
  1811. const hashtype Algo_hash::hashCodes[] = {
  1812. 1448047776469843i64 , 23745670021858756i64 , 2503503679898819i64 ,
  1813. 20893061577159209i64 , 10807838381971450i64 , 2362252468869198i64 ,
  1814. 24259008893265414i64 , 12770534669822463i64 , 6243872632612083i64 ,
  1815. 9878602848666731i64 , 15403460661141300i64 , 23328125617276831i64 ,
  1816. 24399618481479321i64 , 6553504962910284i64 , 1670313139184804i64 ,
  1817. 12980312942597170i64 , 20479559860862969i64 , 9622188310955879i64 ,
  1818. 240315181816498i64 , 15806748501866401i64 , 11025185739521454i64 ,
  1819. 9892014082139049i64 , 24468178939325513i64 , 18336761931886570i64 ,
  1820. 17607110247268341i64 , 1659968630984898i64 , 15644176636883129i64 ,
  1821. 21288430710467667i64 , 21718647773405600i64 , 8449573198599383i64 ,
  1822. 12949198458251018i64 , 13260609204816340i64 , 15942818511406502i64 ,
  1823. 19422389391992560i64 , 2306873372585698i64 , 13245768415868578i64 ,
  1824. 3527685889767840i64 , 16821792770065498i64 , 14659578113224043i64 ,
  1825. 8882299950073676i64 , 7855747638699870i64 , 11443553816792995i64 ,
  1826. 10278034782711378i64 , 9888977721917330i64 , 8622555585025384i64 ,
  1827. 20622776792089008i64 , 6447699412562541i64 , 21593237574254863i64 ,
  1828. 4100056509197325i64 , 8358405560798101i64 , 24120904895822569i64 ,
  1829. 21004758159739407i64 , 4380824971205155i64 , 23810250238005035i64 ,
  1830. 11573868012372637i64 , 21740007761325076i64 , 20569500166060069i64 ,
  1831. 23367084743140030i64 , 832128940274250i64 , 3863567854976796i64 ,
  1832. 8401188629788306i64 , 20293444021869434i64 , 12476938100997420i64 ,
  1833. 5997141871489394i64 , 777596196611050i64 , 8407423122275781i64 ,
  1834. 23742268390341663i64 , 6606677504119583i64 , 17099083579458611i64 ,
  1835. 128040681345920i64 , 7441253945309846i64 , 17672412151152227i64 ,
  1836. 14657002484427869i64 , 3764334613856311i64 , 7399928989161192i64 ,
  1837. 24730167942169592i64 , 13814924480574978i64 , 5810810907567287i64 ,
  1838. 7008927747711241i64 , 3714629224790215i64 , 9946435535599731i64 ,
  1839. 20057491299504334i64 , 15866852457019228i64 , 123155262761331i64 ,
  1840. 1315783062254243i64 , 24497766846727950i64 , 12902532251391440i64 ,
  1841. 16788431106050494i64 , 15993209359043506i64 , 6163570598235227i64 ,
  1842. 23479274902645580i64 , 12086295521073246i64 , 14074331278381816i64 ,
  1843. 1049820141442769i64 , 5160957003350972i64 , 24302799572195320i64 ,
  1844. 23881606652035662i64 , 23969818184919245i64 , 19374430422494128i64 ,
  1845. 9346353622623467i64 , 13646698673919768i64 , 20787456987251805i64 ,
  1846. 19834903548127921i64 , 8194151691638546i64 , 7687885124853709i64 ,
  1847. 4843137186034754i64 , 23141719256229263i64 , 5528755394284040i64 ,
  1848. 22362536622784133i64 , 7624654257445620i64 , 8792845080211956i64 ,
  1849. 24991012676161170i64 , 5382030845010972i64 , 1942150054817210i64 ,
  1850. 1024267612932772i64 , 14257279792025309i64 , 11127353401828247i64 ,
  1851. 4123063511789286i64 , 363215666444395i64 , 15523634951795520i64 ,
  1852. 21114031740764324i64 , 12549698630972549i64 , 7906682572409157i64 ,
  1853. 9682658163949194i64 , 14445831019902887i64 , 19796086007848283i64 ,
  1854. 25041651202294181i64 , 434144873391024i64 , 24468825775827696i64 ,
  1855. 16436890395501393i64 , 16373785289815135i64 , 16626551488832360i64 ,
  1856. 7748715007439309i64 , 22731617567631698i64 , 14232800365889972i64 ,
  1857. 10951727445457549i64 , 8041373240290953i64 , 24930514145406896i64 ,
  1858. 9591184974667554i64 , 24880672410562956i64 , 23221721160805093i64 ,
  1859. 20593543181655919i64 , 23599230930155014i64 , 15520097083998302i64 ,
  1860. 14424914931817466i64 , 7073972177203460i64 , 16674214483955582i64 ,
  1861. 4557916889838393i64 , 14520120252661131i64 , 2948253205366287i64 ,
  1862. 18549806070390636i64 , 10409566723123418i64 , 18398906015238963i64 ,
  1863. 21169009649313417i64 , 18391044531337716i64 , 2911838512392375i64 ,
  1864. 13771057876708721i64 , 11955633853535396i64 , 18911960208175147i64 ,
  1865. 1483143365895487i64 , 5864164841327281i64 , 16798674080914657i64 ,
  1866. 21169543712647072i64 , 2554895121282201i64 , 12465286616181485i64 ,
  1867. 5756888636558955i64 , 2597276631190750i64 , 2560624395830604i64 ,
  1868. 20296901708171088i64 , 14642976680682096i64 , 12194169777111940i64 ,
  1869. 938262584370639i64 , 7206443811292574i64 , 501111636607822i64 ,
  1870. 5705951146039127i64 , 19098237626875269i64 , 5726006303511723i64 ,
  1871. 5717532750720198i64 , 4848344546021481i64 , 7407311808156422i64 ,
  1872. 2061821731974308i64 , 8556380079387133i64 , 13575103943220600i64 ,
  1873. 10594365938844562i64 , 19966653780019989i64 , 24412404083453688i64 ,
  1874. 8019373982039936i64 , 7753495706295280i64 , 838015840877266i64 ,
  1875. 5235642127051968i64 , 10225916255867901i64 , 14975561937408701i64 ,
  1876. 4914762527221109i64 , 16273933213731410i64 , 25240707945233645i64 ,
  1877. 6477894775523777i64 , 16128190602024745i64 , 12452291569329611i64 ,
  1878. 51030855211419i64 , 1848783942303739i64 , 2537297571305471i64 ,
  1879. 24811709277564335i64 , 23354767332363093i64 , 11338712562024830i64 ,
  1880. 10845782284945582i64 , 20710115514013598i64 , 19611282767915684i64 ,
  1881. 11160258605900113i64 , 17875966449141620i64 , 8400967803093668i64 ,
  1882. 6871997953834029i64 , 13914235659320051i64 , 8949576634650339i64 ,
  1883. 2143755776666584i64 , 13309009078638265i64 , 17871461210902733i64 ,
  1884. 11987276750060947i64 , 19212042799964345i64 , 9684310155516547i64 ,
  1885. 1307858104678668i64 , 8369225045337652i64 , 11470364009363081i64 ,
  1886. 10726698770860164i64 , 22857364846703600i64 , 25284735055035435i64 ,
  1887. 19224377054148393i64 , 16403807100295998i64 , 4653376186522389i64 ,
  1888. 15242640882406966i64 , 15315275662931969i64 , 11642086728644568i64 ,
  1889. 12158439227609947i64 , 5366950703441186i64 , 21989897136444615i64 ,
  1890. 21241101455718813i64 , 1591417368086590i64 , 14579493634035095i64 ,
  1891. 23329624772309429i64 , 4022767503269837i64 , 12858990365780377i64 ,
  1892. 1546772101519453i64 , 23839228242060485i64 , 3152020333001361i64 ,
  1893. 7700997223270546i64 , 7886359803633970i64 , 18794372628879385i64 ,
  1894. 22159114735365084i64 , 7999390508114986i64 , 17413096555746886i64 ,
  1895. 9385231705999634i64 , 15875377080359488i64 , 4319895571584052i64 ,
  1896. 15831501864738265i64 , 23927036136254152i64 , 9023165779396619i64 ,
  1897. 6131245054225200i64 , 20314359892927215i64 , 1896686091879468i64 ,
  1898. 14130616725563771i64 , 22653904323575475i64 , 9831497463521490i64 ,
  1899. 13110057076369419i64 , 5902087517632052i64 , 23714067728868348i64 ,
  1900. 10422641883492326i64 , 10327276345146850i64 , 795518417987648i64 ,
  1901. 25452954487907785i64 , 3500196309207718i64 , 14513995844064906i64 ,
  1902. 7844549909962914i64 , 9407804562184273i64 , 15229768031797498i64 ,
  1903. 14111656085687927i64 , 16834184600349678i64 , 7291182384885469i64 ,
  1904. 17771577974633552i64 , 21586473553657942i64 , 18166326806718423i64 ,
  1905. 10928317030329388i64 , 13135712137024532i64 , 12947681282864548i64 ,
  1906. 21220312239923983i64 , 9606249244876101i64 , 4653965165819933i64 ,
  1907. 5039148287631156i64 , 3987726544496362i64 , 11235885894214833i64 ,
  1908. 3549024987193191i64 , 6369560450327424i64 , 5296536600431238i64 ,
  1909. 10833371878822587i64 , 5746338282416722i64 , 20335144029844343i64 ,
  1910. 14857534135172842i64 , 13933887642921338i64 , 3610489245941154i64 ,
  1911. 7780064458218242i64 , 18217608762631328i64 , 4861734558486078i64 ,
  1912. 19138089389909524i64 , 162404484845663i64 , 6326150309736266i64 ,
  1913. 5691634479075905i64 , 14377989390160001i64 , 7788436404648140i64 ,
  1914. 20312143630017606i64 , 6781467023516504i64 , 7265384191721189i64 ,
  1915. 13990392558924592i64 , 4811546322556989i64 , 3891404257596968i64 ,
  1916. 19222546653408634i64 , 9733466771346453i64 , 20011679489309705i64 ,
  1917. 11556921572925005i64 , 13429005557512149i64 , 16680841455593148i64 ,
  1918. 394589115298971i64 , 22224576785554448i64 , 18262625753524808i64 ,
  1919. 20893780129453860i64 , 25064972830160559i64 , 241970110039610i64 ,
  1920. 7452533933839720i64 , 10726026396546933i64 , 17312051917081899i64 ,
  1921. 17281553837379637i64 , 24008819488103387i64 , 5193878516496164i64 ,
  1922. 21529615734706496i64 , 22844915602846365i64 , 17118246686087168i64 ,
  1923. 6560869056902581i64 , 10553021967047717i64 , 3729950813036887i64 ,
  1924. 14459986099519295i64 , 15808907290234758i64 , 6234512969275540i64 ,
  1925. 18690008075805909i64 , 492531108753402i64 , 7721002928884704i64 ,
  1926. 4886156035126456i64 , 21716374046066558i64 , 11035311630511661i64 ,
  1927. 16837692753538891i64 , 20172053977953882i64 , 15488511700491202i64 ,
  1928. 17477921115358343i64 , 24726937211646877i64 , 22480504880004621i64 ,
  1929. 18521326635500559i64 , 8076560603417178i64 , 22382516625473209i64 ,
  1930. 21696842111535623i64 , 12559160944089288i64 , 1661142873895453i64 ,
  1931. 18379772814447567i64 , 10295321430586466i64 , 12378145201769592i64 ,
  1932. 11815752235866582i64 };
  1933. #else
  1934. const hashtype Algo_hash::hashCodes[] = {
  1935. 1448047776469843LL , 23745670021858756LL , 2503503679898819LL ,
  1936. 20893061577159209LL , 10807838381971450LL , 2362252468869198LL ,
  1937. 24259008893265414LL , 12770534669822463LL , 6243872632612083LL ,
  1938. 9878602848666731LL , 15403460661141300LL , 23328125617276831LL ,
  1939. 24399618481479321LL , 6553504962910284LL , 1670313139184804LL ,
  1940. 12980312942597170LL , 20479559860862969LL , 9622188310955879LL ,
  1941. 240315181816498LL , 15806748501866401LL , 11025185739521454LL ,
  1942. 9892014082139049LL , 24468178939325513LL , 18336761931886570LL ,
  1943. 17607110247268341LL , 1659968630984898LL , 15644176636883129LL ,
  1944. 21288430710467667LL , 21718647773405600LL , 8449573198599383LL ,
  1945. 12949198458251018LL , 13260609204816340LL , 15942818511406502LL ,
  1946. 19422389391992560LL , 2306873372585698LL , 13245768415868578LL ,
  1947. 3527685889767840LL , 16821792770065498LL , 14659578113224043LL ,
  1948. 8882299950073676LL , 7855747638699870LL , 11443553816792995LL ,
  1949. 10278034782711378LL , 9888977721917330LL , 8622555585025384LL ,
  1950. 20622776792089008LL , 6447699412562541LL , 21593237574254863LL ,
  1951. 4100056509197325LL , 8358405560798101LL , 24120904895822569LL ,
  1952. 21004758159739407LL , 4380824971205155LL , 23810250238005035LL ,
  1953. 11573868012372637LL , 21740007761325076LL , 20569500166060069LL ,
  1954. 23367084743140030LL , 832128940274250LL , 3863567854976796LL ,
  1955. 8401188629788306LL , 20293444021869434LL , 12476938100997420LL ,
  1956. 5997141871489394LL , 777596196611050LL , 8407423122275781LL ,
  1957. 23742268390341663LL , 6606677504119583LL , 17099083579458611LL ,
  1958. 128040681345920LL , 7441253945309846LL , 17672412151152227LL ,
  1959. 14657002484427869LL , 3764334613856311LL , 7399928989161192LL ,
  1960. 24730167942169592LL , 13814924480574978LL , 5810810907567287LL ,
  1961. 7008927747711241LL , 3714629224790215LL , 9946435535599731LL ,
  1962. 20057491299504334LL , 15866852457019228LL , 123155262761331LL ,
  1963. 1315783062254243LL , 24497766846727950LL , 12902532251391440LL ,
  1964. 16788431106050494LL , 15993209359043506LL , 6163570598235227LL ,
  1965. 23479274902645580LL , 12086295521073246LL , 14074331278381816LL ,
  1966. 1049820141442769LL , 5160957003350972LL , 24302799572195320LL ,
  1967. 23881606652035662LL , 23969818184919245LL , 19374430422494128LL ,
  1968. 9346353622623467LL , 13646698673919768LL , 20787456987251805LL ,
  1969. 19834903548127921LL , 8194151691638546LL , 7687885124853709LL ,
  1970. 4843137186034754LL , 23141719256229263LL , 5528755394284040LL ,
  1971. 22362536622784133LL , 7624654257445620LL , 8792845080211956LL ,
  1972. 24991012676161170LL , 5382030845010972LL , 1942150054817210LL ,
  1973. 1024267612932772LL , 14257279792025309LL , 11127353401828247LL ,
  1974. 4123063511789286LL , 363215666444395LL , 15523634951795520LL ,
  1975. 21114031740764324LL , 12549698630972549LL , 7906682572409157LL ,
  1976. 9682658163949194LL , 14445831019902887LL , 19796086007848283LL ,
  1977. 25041651202294181LL , 434144873391024LL , 24468825775827696LL ,
  1978. 16436890395501393LL , 16373785289815135LL , 16626551488832360LL ,
  1979. 7748715007439309LL , 22731617567631698LL , 14232800365889972LL ,
  1980. 10951727445457549LL , 8041373240290953LL , 24930514145406896LL ,
  1981. 9591184974667554LL , 24880672410562956LL , 23221721160805093LL ,
  1982. 20593543181655919LL , 23599230930155014LL , 15520097083998302LL ,
  1983. 14424914931817466LL , 7073972177203460LL , 16674214483955582LL ,
  1984. 4557916889838393LL , 14520120252661131LL , 2948253205366287LL ,
  1985. 18549806070390636LL , 10409566723123418LL , 18398906015238963LL ,
  1986. 21169009649313417LL , 18391044531337716LL , 2911838512392375LL ,
  1987. 13771057876708721LL , 11955633853535396LL , 18911960208175147LL ,
  1988. 1483143365895487LL , 5864164841327281LL , 16798674080914657LL ,
  1989. 21169543712647072LL , 2554895121282201LL , 12465286616181485LL ,
  1990. 5756888636558955LL , 2597276631190750LL , 2560624395830604LL ,
  1991. 20296901708171088LL , 14642976680682096LL , 12194169777111940LL ,
  1992. 938262584370639LL , 7206443811292574LL , 501111636607822LL ,
  1993. 5705951146039127LL , 19098237626875269LL , 5726006303511723LL ,
  1994. 5717532750720198LL , 4848344546021481LL , 7407311808156422LL ,
  1995. 2061821731974308LL , 8556380079387133LL , 13575103943220600LL ,
  1996. 10594365938844562LL , 19966653780019989LL , 24412404083453688LL ,
  1997. 8019373982039936LL , 7753495706295280LL , 838015840877266LL ,
  1998. 5235642127051968LL , 10225916255867901LL , 14975561937408701LL ,
  1999. 4914762527221109LL , 16273933213731410LL , 25240707945233645LL ,
  2000. 6477894775523777LL , 16128190602024745LL , 12452291569329611LL ,
  2001. 51030855211419LL , 1848783942303739LL , 2537297571305471LL ,
  2002. 24811709277564335LL , 23354767332363093LL , 11338712562024830LL ,
  2003. 10845782284945582LL , 20710115514013598LL , 19611282767915684LL ,
  2004. 11160258605900113LL , 17875966449141620LL , 8400967803093668LL ,
  2005. 6871997953834029LL , 13914235659320051LL , 8949576634650339LL ,
  2006. 2143755776666584LL , 13309009078638265LL , 17871461210902733LL ,
  2007. 11987276750060947LL , 19212042799964345LL , 9684310155516547LL ,
  2008. 1307858104678668LL , 8369225045337652LL , 11470364009363081LL ,
  2009. 10726698770860164LL , 22857364846703600LL , 25284735055035435LL ,
  2010. 19224377054148393LL , 16403807100295998LL , 4653376186522389LL ,
  2011. 15242640882406966LL , 15315275662931969LL , 11642086728644568LL ,
  2012. 12158439227609947LL , 5366950703441186LL , 21989897136444615LL ,
  2013. 21241101455718813LL , 1591417368086590LL , 14579493634035095LL ,
  2014. 23329624772309429LL , 4022767503269837LL , 12858990365780377LL ,
  2015. 1546772101519453LL , 23839228242060485LL , 3152020333001361LL ,
  2016. 7700997223270546LL , 7886359803633970LL , 18794372628879385LL ,
  2017. 22159114735365084LL , 7999390508114986LL , 17413096555746886LL ,
  2018. 9385231705999634LL , 15875377080359488LL , 4319895571584052LL ,
  2019. 15831501864738265LL , 23927036136254152LL , 9023165779396619LL ,
  2020. 6131245054225200LL , 20314359892927215LL , 1896686091879468LL ,
  2021. 14130616725563771LL , 22653904323575475LL , 9831497463521490LL ,
  2022. 13110057076369419LL , 5902087517632052LL , 23714067728868348LL ,
  2023. 10422641883492326LL , 10327276345146850LL , 795518417987648LL ,
  2024. 25452954487907785LL , 3500196309207718LL , 14513995844064906LL ,
  2025. 7844549909962914LL , 9407804562184273LL , 15229768031797498LL ,
  2026. 14111656085687927LL , 16834184600349678LL , 7291182384885469LL ,
  2027. 17771577974633552LL , 21586473553657942LL , 18166326806718423LL ,
  2028. 10928317030329388LL , 13135712137024532LL , 12947681282864548LL ,
  2029. 21220312239923983LL , 9606249244876101LL , 4653965165819933LL ,
  2030. 5039148287631156LL , 3987726544496362LL , 11235885894214833LL ,
  2031. 3549024987193191LL , 6369560450327424LL , 5296536600431238LL ,
  2032. 10833371878822587LL , 5746338282416722LL , 20335144029844343LL ,
  2033. 14857534135172842LL , 13933887642921338LL , 3610489245941154LL ,
  2034. 7780064458218242LL , 18217608762631328LL , 4861734558486078LL ,
  2035. 19138089389909524LL , 162404484845663LL , 6326150309736266LL ,
  2036. 5691634479075905LL , 14377989390160001LL , 7788436404648140LL ,
  2037. 20312143630017606LL , 6781467023516504LL , 7265384191721189LL ,
  2038. 13990392558924592LL , 4811546322556989LL , 3891404257596968LL ,
  2039. 19222546653408634LL , 9733466771346453LL , 20011679489309705LL ,
  2040. 11556921572925005LL , 13429005557512149LL , 16680841455593148LL ,
  2041. 394589115298971LL , 22224576785554448LL , 18262625753524808LL ,
  2042. 20893780129453860LL , 25064972830160559LL , 241970110039610LL ,
  2043. 7452533933839720LL , 10726026396546933LL , 17312051917081899LL ,
  2044. 17281553837379637LL , 24008819488103387LL , 5193878516496164LL ,
  2045. 21529615734706496LL , 22844915602846365LL , 17118246686087168LL ,
  2046. 6560869056902581LL , 10553021967047717LL , 3729950813036887LL ,
  2047. 14459986099519295LL , 15808907290234758LL , 6234512969275540LL ,
  2048. 18690008075805909LL , 492531108753402LL , 7721002928884704LL ,
  2049. 4886156035126456LL , 21716374046066558LL , 11035311630511661LL ,
  2050. 16837692753538891LL , 20172053977953882LL , 15488511700491202LL ,
  2051. 17477921115358343LL , 24726937211646877LL , 22480504880004621LL ,
  2052. 18521326635500559LL , 8076560603417178LL , 22382516625473209LL ,
  2053. 21696842111535623LL , 12559160944089288LL , 1661142873895453LL ,
  2054. 18379772814447567LL , 10295321430586466LL , 12378145201769592LL ,
  2055. 11815752235866582LL };
  2056. #endif
  2057. HashFEntry::HashFEntry(hashtype HASHCODE, char* BUF, int LENGTH) {
  2058. hashCode = HASHCODE;
  2059. buf = BUF;
  2060. length = LENGTH;
  2061. }
  2062. HashFEntry::HashFEntry(const HashFEntry& hfe) {
  2063. hashCode = hfe.hashCode;
  2064. length = hfe.length;
  2065. buf = new char[length];
  2066. for(int i=0; i<length; i++) buf[i] = hfe.buf[i];
  2067. }
  2068. HashFEntry::~HashFEntry() {
  2069. if (buf) {
  2070. delete [] buf;
  2071. buf = 0;
  2072. }
  2073. }
  2074. HashhitF::HashhitF(int GAMEID, char ORIENTATION, char* blob) {
  2075. gameid = GAMEID;
  2076. orientation = ORIENTATION;
  2077. cont = new MoveNC(blob[0], blob[1], blob[2]);
  2078. emn = new ExtendedMoveNumber;
  2079. emn->length = blob[3] * 256 + blob[4];
  2080. emn->data = new int[emn->length];
  2081. for(int i=0; i<emn->length; i++) {
  2082. emn->data[i] = blob[5+2*i]*256 + blob[6+2*i];
  2083. }
  2084. }
  2085. HashhitF::HashhitF() {
  2086. cont = 0;
  2087. emn = 0;
  2088. }
  2089. HashhitF::~HashhitF() {
  2090. if (cont) delete cont;
  2091. if (emn) delete emn;
  2092. }
  2093. bool cmp_HashhitF(const HashhitF* a, const HashhitF* b) {
  2094. return a->gameid < b->gameid;
  2095. }
  2096. HashhitCS::HashhitCS(int GAMEID, int POSITION, bool CS) {
  2097. gameid = GAMEID;
  2098. position = POSITION;
  2099. cs = CS;
  2100. }
  2101. bool cmp_HashhitCS(const HashhitCS* a, const HashhitCS* b) {
  2102. return a->gameid < b->gameid;
  2103. }
  2104. typedef vector<HashhitF* >* vpsip;
  2105. HashVarInfo::HashVarInfo(hashtype CHC, vector<pair<hashtype, ExtendedMoveNumber>* > * LFC,
  2106. ExtendedMoveNumber* MOVENUMBER, int NUMSTONES) {
  2107. chc = CHC;
  2108. numStones = NUMSTONES;
  2109. moveNumber = new ExtendedMoveNumber(*MOVENUMBER);
  2110. lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
  2111. for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = LFC->begin(); it != LFC->end(); it++) {
  2112. lfc->push_back(new pair<hashtype, ExtendedMoveNumber>((*it)->first, (*it)->second));
  2113. }
  2114. }
  2115. Algo_hash_full::Algo_hash_full(int bsize, int MAXNUMSTONES) : Algorithm(bsize) {
  2116. branchpoints = 0;
  2117. maxNumStones = MAXNUMSTONES;
  2118. }
  2119. Algo_hash_full::~Algo_hash_full() {
  2120. }
  2121. int Algo_hash_full::insert_hash(hashtype hashCode, ExtendedMoveNumber& mn, Move* continuation) {
  2122. // printf("insert %lld\n", hashCode);
  2123. char* buf = new char[30 + mn.length*2];
  2124. if (continuation) {
  2125. buf[0] = continuation->x;
  2126. buf[1] = continuation->y;
  2127. buf[2] = continuation->color;
  2128. } else {
  2129. buf[0] = NO_CONT;
  2130. buf[1] = 0;
  2131. buf[2] = 0;
  2132. }
  2133. buf[3] = mn.length/256;
  2134. buf[4] = mn.length%256;
  2135. for (int i=0; i<mn.length; i++) {
  2136. buf[5+2*i] = mn.data[i]/265;
  2137. buf[6+2*i] = mn.data[i]%256;
  2138. }
  2139. hash_vector.push_back(HashFEntry(hashCode, buf, 5+2*mn.length));
  2140. return 0;
  2141. }
  2142. int Algo_hash_full::insert_all_hashes() {
  2143. char sql[100];
  2144. sprintf(sql, "insert into algo_hash_full_%d (hash, gameid, hit) values (?,?,?);", boardsize);
  2145. sqlite3_stmt *ppStmt=0;
  2146. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  2147. if (rc != SQLITE_OK || ppStmt==0) return rc;
  2148. for(vector<HashFEntry>::iterator it = hash_vector.begin(); it != hash_vector.end(); it++) {
  2149. rc = sqlite3_bind_int64(ppStmt, 1, it->hashCode);
  2150. if (rc != SQLITE_OK) return rc;
  2151. rc = sqlite3_bind_int(ppStmt, 2, gid);
  2152. if (rc != SQLITE_OK) return rc;
  2153. rc = sqlite3_bind_blob(ppStmt, 3, it->buf, it->length, SQLITE_TRANSIENT);
  2154. if (rc != SQLITE_OK) return rc;
  2155. rc = sqlite3_step(ppStmt);
  2156. if (rc != SQLITE_DONE) return rc;
  2157. rc = sqlite3_reset(ppStmt);
  2158. if (rc != SQLITE_OK) return rc;
  2159. }
  2160. rc = sqlite3_finalize(ppStmt);
  2161. if (rc != SQLITE_OK) return rc;
  2162. hash_vector.clear();
  2163. return 0; // success
  2164. }
  2165. void Algo_hash_full::initialize_process(sqlite3* DB) throw(DBError) {
  2166. // printf("enter algo_hash_full::initialize_processing\n");
  2167. db = DB;
  2168. char sql[200];
  2169. sprintf(sql, "create table algo_hash_full_%d ( id integer primary key, hash integer, gameid integer, hit text );", boardsize);
  2170. int rc = sqlite3_exec(db, sql, 0, 0, 0);
  2171. //if (rc != SQLITE_OK) throw DBError();
  2172. sprintf(sql, "create index hash_idx on algo_hash_full_%d(hash);", boardsize);
  2173. rc = sqlite3_exec(db, sql, 0, 0, 0);
  2174. //if (rc != SQLITE_OK) throw DBError();
  2175. // printf("leave algo_hash_full::initialize_processing\n");
  2176. }
  2177. void Algo_hash_full::newgame_process(int game_id) {
  2178. numStones = 0;
  2179. gid = game_id;
  2180. moveNumber = new ExtendedMoveNumber(0);
  2181. currentHashCode = 0; // start with empty board
  2182. lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
  2183. branchpoints = new stack<HashVarInfo>;
  2184. }
  2185. void Algo_hash_full::AB_process(int x, int y) {
  2186. for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
  2187. Move* continuation = new Move(x,y,'B');
  2188. if (insert_hash((*it)->first, (*it)->second, continuation) != 0) throw DBError();
  2189. delete continuation;
  2190. delete *it;
  2191. }
  2192. delete lfc;
  2193. lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
  2194. currentHashCode += Algo_hash::hashCodes[x + boardsize*y];
  2195. numStones++;
  2196. }
  2197. void Algo_hash_full::AW_process(int x, int y) {
  2198. for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
  2199. Move* continuation = new Move(x,y,'W');
  2200. if (insert_hash((*it)->first, (*it)->second, continuation) != 0) throw DBError();
  2201. delete continuation;
  2202. delete *it;
  2203. }
  2204. delete lfc;
  2205. lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
  2206. currentHashCode -= Algo_hash::hashCodes[x + boardsize*y];
  2207. numStones++;
  2208. }
  2209. void Algo_hash_full::AE_process(int x, int y, char removed) {
  2210. if (removed == 'B') currentHashCode -= Algo_hash::hashCodes[x + boardsize*y];
  2211. else currentHashCode += Algo_hash::hashCodes[x + boardsize*y];
  2212. numStones--;
  2213. }
  2214. void Algo_hash_full::endOfNode_process() {
  2215. if (numStones <= maxNumStones) lfc->push_back(new pair<hashtype, ExtendedMoveNumber>(currentHashCode, *moveNumber));
  2216. moveNumber->next();
  2217. }
  2218. void Algo_hash_full::pass_process() {
  2219. // (we do not count pass as continuation)
  2220. }
  2221. void Algo_hash_full::move_process(Move m) throw(DBError) {
  2222. for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
  2223. Move* continuation = new Move(m);
  2224. int rc = insert_hash((*it)->first, (*it)->second, continuation);
  2225. if (rc != 0) throw DBError();
  2226. delete continuation;
  2227. delete *it;
  2228. }
  2229. delete lfc;
  2230. lfc = new vector<pair<hashtype, ExtendedMoveNumber>* >;
  2231. int epsilon = (m.color == 'B' || m.color == 'X' ? 1 : -1);
  2232. currentHashCode += epsilon * Algo_hash::hashCodes[m.x + boardsize*m.y];
  2233. numStones++;
  2234. if (m.captures) {
  2235. vector<p_cc>::iterator it;
  2236. for(it = m.captures->begin(); it != m.captures->end(); it++) {
  2237. int xx = it->first;
  2238. int yy = it->second;
  2239. currentHashCode += epsilon * Algo_hash::hashCodes[xx + boardsize*yy];
  2240. numStones--;
  2241. }
  2242. }
  2243. }
  2244. void Algo_hash_full::branchpoint_process() {
  2245. branchpoints->push(HashVarInfo(currentHashCode, lfc, moveNumber, numStones));
  2246. // printf("push %lld\n", currentHashCode);
  2247. }
  2248. void Algo_hash_full::endOfVariation_process() throw(DBError) {
  2249. for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
  2250. int rc = insert_hash((*it)->first, (*it)->second, 0);
  2251. if (rc != 0) throw DBError();
  2252. delete *it;
  2253. }
  2254. delete lfc;
  2255. delete moveNumber;
  2256. currentHashCode = branchpoints->top().chc;
  2257. lfc = branchpoints->top().lfc;
  2258. moveNumber = branchpoints->top().moveNumber;
  2259. numStones = branchpoints->top().numStones;
  2260. // printf("pop %lld\n", currentHashCode);
  2261. branchpoints->pop();
  2262. }
  2263. void Algo_hash_full::endgame_process(bool commit) throw(DBError) {
  2264. for(vector<pair<hashtype, ExtendedMoveNumber>* >::iterator it = lfc->begin(); it != lfc->end(); it++) {
  2265. Move* continuation = 0;
  2266. int rc = insert_hash((*it)->first, (*it)->second, continuation);
  2267. if (rc != 0) throw DBError();
  2268. delete *it;
  2269. }
  2270. if (commit) {
  2271. int rc = insert_all_hashes();
  2272. if (rc) printf("ouch %d\n",rc);
  2273. } else hash_vector.clear();
  2274. delete lfc;
  2275. delete moveNumber;
  2276. delete branchpoints;
  2277. }
  2278. void Algo_hash_full::finalize_process() {
  2279. }
  2280. hashtype Algo_hash_full::compute_hashkey(Pattern& pattern) {
  2281. if (pattern.sizeX != boardsize || pattern.sizeY != boardsize)
  2282. return NOT_HASHABLE;
  2283. hashtype hashkey = 0;
  2284. int ns = 0;
  2285. for(int i=0; i<boardsize; i++) {
  2286. for(int j=0; j<boardsize; j++) {
  2287. char p = pattern.finalPos[i + boardsize*j];
  2288. if (p == 'x' || p == 'o' || p == '*') return NOT_HASHABLE;
  2289. else if (p == 'X') {
  2290. hashkey += Algo_hash::hashCodes[i + boardsize*j];
  2291. ns++;
  2292. } else if (p == 'O') {
  2293. hashkey -= Algo_hash::hashCodes[i + boardsize*j];
  2294. ns++;
  2295. }
  2296. }
  2297. }
  2298. if (ns > maxNumStones) return NOT_HASHABLE;
  2299. return hashkey;
  2300. }
  2301. int insert_result_hf(void *results, int argc, char **argv, char **azColName) throw (DBError) {
  2302. vpsip res = ((pair<vpsip, int>*)results)->first;
  2303. int orientation = ((pair<vpsip, int>*)results)->second;
  2304. if (argc==2 && argv[0]) {
  2305. res->push_back(new HashhitF(atoi(argv[0]), orientation, argv[1]));
  2306. } else throw DBError();
  2307. return 0;
  2308. }
  2309. int Algo_hash_full::search(PatternList& patternList, GameList& gl, SearchOptions& options, sqlite3* db) {
  2310. // printf("enter algo_hash_full::search\n");
  2311. int numOfHits = 0;
  2312. int self_numOfSwitched = 0;
  2313. int Bwins = 0;
  2314. int Wwins = 0;
  2315. int hash_result = -1; // -1 = failure; 0 = ok, but have to check w/ Algo_movelist, 1 = ok, produced final result
  2316. int plS = patternList.size();
  2317. vpsip results = new vector<HashhitF* >;
  2318. for(int N=0; N<plS; N++) {
  2319. hashtype hashCode = compute_hashkey(patternList.data[N]);
  2320. if (hashCode == NOT_HASHABLE) return -1; // failure
  2321. char sql[100];
  2322. #if (defined(__BORLANDC__) || defined(_MSC_VER))
  2323. sprintf(sql, "select gameid,hit from algo_hash_full_%d where hash = %I64d", boardsize, hashCode);
  2324. #else
  2325. sprintf(sql, "select gameid,hit from algo_hash_full_%d where hash = %lld", boardsize, hashCode);
  2326. #endif
  2327. // printf("hc %lld, %s\n", hashCode, sql);
  2328. pair<vpsip, int> rN(results, N);
  2329. sqlite3_exec(db, sql, insert_result_hf, &rN, 0);
  2330. }
  2331. if (options.trustHashFull && patternList.pattern.contList.size()==0) hash_result = 1;
  2332. else hash_result = 0;
  2333. if (gl.start_sorted() == 0) {
  2334. sort(results->begin(), results->end(), cmp_HashhitF);
  2335. // printf("res-size %d\n", results->size());
  2336. vector<HashhitF* >::iterator resultIT = results->begin();
  2337. while (resultIT != results->end()) {
  2338. int index = (*resultIT)->gameid;
  2339. if (hash_result) {
  2340. gl.setCurrentFromIndex(index);
  2341. int numOfSwitched = 0;
  2342. vector<Hit* >* hits = new vector<Hit* >;
  2343. while ((*resultIT)->gameid == index) {
  2344. if ((*resultIT)->emn->total_move_num() > options.moveLimit) {
  2345. resultIT++;
  2346. continue;
  2347. }
  2348. char *label;
  2349. if ((*resultIT)->cont->x != NO_CONT) { // continuation
  2350. label = patternList.updateContinuations((*resultIT)->orientation,
  2351. (*resultIT)->cont->x, (*resultIT)->cont->y, (*resultIT)->cont->color,
  2352. false, // tenuki impossible with full board pattern
  2353. gl.getCurrentWinner());
  2354. if (label) {
  2355. hits->push_back(new Hit((*resultIT)->emn, label));
  2356. (*resultIT)->emn = 0;
  2357. numOfSwitched += label[2];
  2358. }
  2359. } else {
  2360. label = new char[3];
  2361. label[0] = NO_CONT;
  2362. label[1] = 0;
  2363. label[2] = patternList.data[(*resultIT)->orientation].colorSwitch;
  2364. numOfSwitched += label[2];
  2365. hits->push_back(new Hit((*resultIT)->emn, label));
  2366. (*resultIT)->emn = 0;
  2367. }
  2368. resultIT++;
  2369. if (resultIT == results->end()) break;
  2370. }
  2371. if (hits->size()) {
  2372. numOfHits += hits->size();
  2373. self_numOfSwitched += numOfSwitched;
  2374. if (gl.getCurrentWinner() == 'B') {
  2375. Bwins += hits->size() - numOfSwitched;
  2376. Wwins += numOfSwitched;
  2377. } else if (gl.getCurrentWinner() == 'W') {
  2378. Bwins += numOfSwitched;
  2379. Wwins += hits->size() - numOfSwitched;
  2380. }
  2381. gl.makeCurrentHit(hits);
  2382. } else delete hits;
  2383. } else { // produce Candidate list, check using another algorithm
  2384. vector<Candidate* >* candidates = new vector<Candidate* >;
  2385. while ((*resultIT)->gameid == index) {
  2386. if ((*resultIT)->emn->total_move_num() > options.moveLimit) continue;
  2387. candidates->push_back(new Candidate(0,0,(*resultIT)->orientation));
  2388. resultIT++;
  2389. if (resultIT == results->end()) break;
  2390. }
  2391. gl.makeIndexCandidate(index, candidates);
  2392. }
  2393. }
  2394. for(vector<HashhitF* >::iterator it = results->begin(); it != results->end(); it++) delete *it;
  2395. delete results;
  2396. gl.end_sorted();
  2397. }
  2398. gl.num_hits = numOfHits;
  2399. gl.num_switched = self_numOfSwitched;
  2400. gl.Bwins = Bwins;
  2401. gl.Wwins = Wwins;
  2402. return hash_result;
  2403. }
  2404. // -----------------------------------------------------------------------------------
  2405. Algo_hash::Algo_hash(int bsize, const string& DBNAMEEXT, int MAXNUMSTONES) : Algorithm(bsize) {
  2406. dbnameext = DBNAMEEXT;
  2407. hi = 0;
  2408. maxNumStones = MAXNUMSTONES;
  2409. }
  2410. Algo_hash::~Algo_hash() {
  2411. if (hi) delete hi;
  2412. }
  2413. int Algo_hash::insert_hash(hashtype hashCode, int pos) {
  2414. hash_vector.push_back(make_pair(hashCode, pos));
  2415. return 0;
  2416. }
  2417. int Algo_hash::insert_all_hashes() {
  2418. // printf("insert all hashes %d\n", hash_vector.size());
  2419. char sql[200];
  2420. sprintf(sql, "insert into algo_hash_%d_%s (hash, gameid, position) values (?,?,?);", boardsize, dbnameext.c_str());
  2421. sqlite3_stmt *ppStmt=0;
  2422. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  2423. if (rc != SQLITE_OK || ppStmt==0) return rc;
  2424. rc = sqlite3_bind_int(ppStmt, 2, gid);
  2425. if (rc != SQLITE_OK) return rc;
  2426. for(vector<pair<hashtype, int> >::iterator it = hash_vector.begin(); it != hash_vector.end(); it++) {
  2427. // printf("insert %d %d\n", it->first, it->second);
  2428. rc = sqlite3_bind_int64(ppStmt, 1, it->first);
  2429. if (rc != SQLITE_OK) return rc;
  2430. rc = sqlite3_bind_int(ppStmt, 3, it->second);
  2431. if (rc != SQLITE_OK) return rc;
  2432. rc = sqlite3_step(ppStmt);
  2433. if (rc != SQLITE_DONE) return rc;
  2434. rc = sqlite3_reset(ppStmt);
  2435. if (rc != SQLITE_OK) return rc;
  2436. }
  2437. rc = sqlite3_finalize(ppStmt);
  2438. if (rc != SQLITE_OK) return rc;
  2439. return 0; // success
  2440. }
  2441. void Algo_hash::initialize_process(sqlite3* DB) throw(DBError) {
  2442. // printf("enter algo_hash::initialize_processing\n");
  2443. db = DB;
  2444. char buf[200];
  2445. sprintf(buf, "create table algo_hash_%d_%s ( hash integer, gameid integer, position integer );", boardsize, dbnameext.c_str());
  2446. int rc = sqlite3_exec(db, buf, 0, 0, 0);
  2447. //if (rc != SQLITE_OK) throw DBError();
  2448. sprintf(buf, "create index hash_idx_%d_%s on algo_hash_%d_%s(hash);", boardsize, dbnameext.c_str(), boardsize, dbnameext.c_str());
  2449. rc = sqlite3_exec(db, buf, 0, 0, 0);
  2450. //if (rc != SQLITE_OK) throw DBError();
  2451. // printf("leave algo_hash::initialize_processing\n");
  2452. }
  2453. void Algo_hash::newgame_process(int game_id) {
  2454. gid = game_id;
  2455. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2456. it->initialize();
  2457. }
  2458. void Algo_hash::AB_process(int x, int y) {
  2459. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2460. it->addB(x,y);
  2461. }
  2462. void Algo_hash::AW_process(int x, int y) {
  2463. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2464. it->addW(x,y);
  2465. }
  2466. void Algo_hash::AE_process(int x, int y, char removed) {
  2467. if (removed == 'B') {
  2468. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++) it->removeB(x,y);
  2469. } else {
  2470. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++) it->removeW(x,y);
  2471. }
  2472. }
  2473. void Algo_hash::endOfNode_process() {
  2474. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++) {
  2475. if (it->numStones <= maxNumStones && it->changed) {
  2476. it->changed = false;
  2477. pair<hashtype,int> phi = it->cHC();
  2478. insert_hash(phi.first, phi.second);
  2479. // printf("insert hash CORNER %d %d\n", phi.first, phi.second);
  2480. }
  2481. }
  2482. }
  2483. void Algo_hash::pass_process() {
  2484. // (we do not count pass as continuation)
  2485. }
  2486. void Algo_hash::move_process(Move m) throw(DBError) {
  2487. if (m.color == 'B') {
  2488. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2489. it->addB(m.x, m.y);
  2490. if (m.captures) {
  2491. for(vector<p_cc>::iterator cap_it = m.captures->begin(); cap_it != m.captures->end(); cap_it++) {
  2492. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2493. it->removeW(cap_it->first, cap_it->second);
  2494. }
  2495. }
  2496. } else {
  2497. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2498. it->addW(m.x, m.y);
  2499. if (m.captures) {
  2500. for(vector<p_cc>::iterator cap_it = m.captures->begin(); cap_it != m.captures->end(); cap_it++) {
  2501. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2502. it->removeB(cap_it->first, cap_it->second);
  2503. }
  2504. }
  2505. }
  2506. }
  2507. void Algo_hash::branchpoint_process() {
  2508. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2509. it->bppush();
  2510. }
  2511. void Algo_hash::endOfVariation_process() {
  2512. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2513. it->bppop();
  2514. }
  2515. void Algo_hash::endgame_process(bool commit) {
  2516. for(vector<HashInstance>::iterator it = hi->begin(); it != hi->end(); it++)
  2517. it->finalize();
  2518. if (commit) {
  2519. int rc = insert_all_hashes();
  2520. if (rc) printf("ouch %d\n",rc);
  2521. hash_vector.clear();
  2522. } else hash_vector.clear();
  2523. }
  2524. void Algo_hash::finalize_process() {
  2525. }
  2526. pair<hashtype,int> Algo_hash::compute_hashkey(PatternList& pl, int CS) {
  2527. return make_pair(NOT_HASHABLE,0);
  2528. }
  2529. int insert_result(void *rN, int argc, char **argv, char **azColName) throw (DBError) {
  2530. vector<HashhitCS* >* results = ((pair<vector<HashhitCS* >*, hashtype>*)rN)->first;
  2531. hashtype hashCode = ((pair<vector<HashhitCS* >*, hashtype>*)rN)->second;
  2532. if (argc==3 && argv[0] && argv[1] && argv[2]) {
  2533. // printf("found %s, %lld", argv[2], atoi(argv[2]));
  2534. #if (defined(__BORLANDC__) || defined(_MSC_VER))
  2535. ((vector<HashhitCS* >*)results)->push_back(new HashhitCS(atoi(argv[0]), atoi(argv[1]), _atoi64(argv[2])!=hashCode));
  2536. #else
  2537. ((vector<HashhitCS* >*)results)->push_back(new HashhitCS(atoi(argv[0]), atoi(argv[1]), atoll(argv[2])!=hashCode));
  2538. #endif
  2539. } else throw DBError();
  2540. return 0;
  2541. }
  2542. int Algo_hash::search(PatternList& patternList, GameList& gl, SearchOptions& options, sqlite3* db) {
  2543. // return value: -1 = failure; 0 = ok, but have to check w/ Algo_movelist
  2544. vector<HashhitCS* >* results = new vector<HashhitCS* >;
  2545. pair<hashtype, int> hco = compute_hashkey(patternList, 0);
  2546. hashtype hashCode = hco.first;
  2547. // printf("HC %lld\n", hashCode);
  2548. hashtype hashCode2 = hashCode;
  2549. if (hashCode == NOT_HASHABLE) {
  2550. delete results;
  2551. return -1; // failure
  2552. }
  2553. int fl = patternList.data[hco.second].flip;
  2554. int fl2 = fl;
  2555. char buf[100];
  2556. #if (defined(__BORLANDC__) || defined(_MSC_VER))
  2557. sprintf(buf, "select gameid,position,hash from algo_hash_%d_%s where hash = %I64d",
  2558. boardsize, dbnameext.c_str(), hashCode);
  2559. #else
  2560. sprintf(buf, "select gameid,position,hash from algo_hash_%d_%s where hash = %lld",
  2561. boardsize, dbnameext.c_str(), hashCode);
  2562. #endif
  2563. string sql = buf;
  2564. bool cs = patternList.data[patternList.size()-1].colorSwitch;
  2565. if (cs) {
  2566. pair<hashtype, int> hco = compute_hashkey(patternList, 1);
  2567. hashCode2 = hco.first;
  2568. // printf("HC2 %lld\n", hashCode2);
  2569. if (hashCode == NOT_HASHABLE) {
  2570. delete results;
  2571. return -1; // failure
  2572. }
  2573. fl2 = patternList.data[hco.second].flip;
  2574. if (hashCode != hashCode2) {
  2575. #if (defined(__BORLANDC__) || defined(_MSC_VER))
  2576. sprintf(buf, " or hash = %I64d", hashCode2);
  2577. #else
  2578. sprintf(buf, " or hash = %lld", hashCode2);
  2579. #endif
  2580. sql += buf;
  2581. }
  2582. }
  2583. sql += " order by gameid";
  2584. if (gl.start_sorted() == 0) {
  2585. // query database
  2586. // printf("%s\n", sql);
  2587. pair<vector<HashhitCS* >*, hashtype> rN(results, hashCode);
  2588. sqlite3_exec(db, sql.c_str(), insert_result, &rN, 0);
  2589. // printf("results->size() %d\n", results->size());
  2590. // communicate results of query to database
  2591. vector<HashhitCS* >::iterator resultIT = results->begin();
  2592. while (resultIT != results->end()) {
  2593. // printf("gid %d\n", (*resultIT)->gameid);
  2594. int index = (*resultIT)->gameid;
  2595. vector<Candidate* >* candidates = new vector<Candidate* >;
  2596. while ((*resultIT)->gameid == index) {
  2597. // int pos = (*resultIT)->position % (1<<16);
  2598. int ori = (*resultIT)->position / (1<<16);
  2599. // printf("%d %d\n", pos, ori);
  2600. if (cs && hashCode == hashCode2) { // this is a somewhat pathological case ...
  2601. int ind = patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)];
  2602. candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
  2603. ind = patternList.flipTable[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl2)];
  2604. candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
  2605. } else {
  2606. if ((*resultIT)->cs) {
  2607. // FIXME works only for corner patterns right now!
  2608. int ind = patternList.flipTable[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl2)];
  2609. // 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);
  2610. candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
  2611. } else {
  2612. int ind = patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)];
  2613. // printf("cand %d %d %d\n", patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)], patternList.data[ind].left, patternList.data[ind].top);
  2614. candidates->push_back(new Candidate(patternList.data[ind].left, patternList.data[ind].top, ind));
  2615. }
  2616. }
  2617. resultIT++;
  2618. if (resultIT == results->end()) break;
  2619. }
  2620. gl.makeIndexCandidate(index, candidates);
  2621. }
  2622. for(vector<HashhitCS* >::iterator it = results->begin(); it != results->end(); it++) delete *it;
  2623. delete results;
  2624. gl.end_sorted();
  2625. } else return -1;
  2626. return 0;
  2627. }
  2628. Algo_hash_corner::Algo_hash_corner(int bsize, int SIZE, int MAXNUMSTONES) : Algo_hash(bsize, "CORNER", MAXNUMSTONES) {
  2629. size = SIZE;
  2630. char buf[5];
  2631. sprintf(buf, "%d", size);
  2632. dbnameext += buf;
  2633. hi = new vector<HashInstance>;
  2634. hi->push_back(HashInstance(0,0,size,size,boardsize));
  2635. hi->push_back(HashInstance(0,bsize-size,size,size,boardsize));
  2636. hi->push_back(HashInstance(bsize-size,0,size,size,boardsize));
  2637. hi->push_back(HashInstance(bsize-size, bsize-size, size, size,boardsize));
  2638. }
  2639. pair<hashtype,int> Algo_hash_corner::compute_hashkey(PatternList& pl, int CS) {
  2640. 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);
  2641. hashtype hk = NOT_HASHABLE;
  2642. int f = 0;
  2643. vector<hashtype> hCodes;
  2644. for(int pCtr=0; pCtr<pl.size(); pCtr++) {
  2645. if (CS == pl.data[pCtr].colorSwitch) {
  2646. hashtype hashkey = 0;
  2647. int ns = 0;
  2648. Pattern *pattern = & pl.data[pCtr];
  2649. int offsetX = 0;
  2650. int offsetY = 0;
  2651. if (pattern->left > 0) offsetX = boardsize-size-pattern->left; // pattern located on east side of board
  2652. if (pattern->top > 0) offsetY = boardsize-size-pattern->top; // ... south ...
  2653. for(int i=0; i<size; i++) {
  2654. for(int j=0; j<size; j++) {
  2655. char p = pattern->finalPos[i+offsetX + pattern->sizeX*(j+offsetY)];
  2656. if (p == 'x' || p == 'o' || p == '*') return make_pair(NOT_HASHABLE,0);
  2657. else if (p == 'X') {
  2658. hashkey += hashCodes[i+offsetX+pattern->left + boardsize*(j+offsetY+pattern->top)];
  2659. ns++;
  2660. } else if (p == 'O') {
  2661. hashkey -= hashCodes[i+offsetX+pattern->left + boardsize*(j+offsetY+pattern->top)];
  2662. ns++;
  2663. }
  2664. }
  2665. }
  2666. if (ns < 3 || ns > maxNumStones) return make_pair(NOT_HASHABLE,0);
  2667. // make sure all hash keys are unique
  2668. for(vector<hashtype>::iterator it = hCodes.begin(); it != hCodes.end(); it++)
  2669. if (*it == hashkey) return make_pair(NOT_HASHABLE, 0);
  2670. hCodes.push_back(hashkey);
  2671. if (hk==NOT_HASHABLE || hashkey<hk) {
  2672. hk = hashkey;
  2673. f = pCtr;
  2674. }
  2675. }
  2676. }
  2677. return make_pair(hk, f);
  2678. }
  2679. // Algo_hash_side::Algo_hash_side(int bsize, int SIZEX, int SIZEY) : Algo_hash(bsize, "SIDE") {
  2680. // sizeX = SIZEX;
  2681. // sizeY = SIZEY;
  2682. // char buf[10];
  2683. // sprintf(buf, "%d_%d", sizeX, sizeY);
  2684. // dbnameext += buf;
  2685. //
  2686. // hi = new vector<HashInstance>;
  2687. // for(int i=1; i<bsize-1-sizeX; i++)
  2688. // hi->push_back(HashInstance(i,0,sizeX, sizeY,boardsize));
  2689. // for(int i=1; i<bsize-1-sizeX; i++)
  2690. // hi->push_back(HashInstance(i,bsize-sizeY,sizeX, sizeY,boardsize));
  2691. // for(int i=1; i<bsize-1-sizeX; i++)
  2692. // hi->push_back(HashInstance(0, i, sizeY, sizeX,boardsize));
  2693. // for(int i=1; i<bsize-1-sizeX; i++)
  2694. // hi->push_back(HashInstance(bsize-sizeY, i, sizeY, sizeX,boardsize));
  2695. // }
  2696. HashInstance::HashInstance(char X, char Y, char SIZEX, char SIZEY, int BOARDSIZE) {
  2697. boardsize = BOARDSIZE;
  2698. xx = X;
  2699. yy = Y;
  2700. pos = xx + boardsize*yy;
  2701. sizeX = SIZEX;
  2702. sizeY = SIZEY;
  2703. branchpoints = 0;
  2704. currentHashCode = 0;
  2705. numStones = 0;
  2706. changed = true;
  2707. }
  2708. HashInstance::~HashInstance() {
  2709. finalize();
  2710. }
  2711. void HashInstance::finalize() {
  2712. if (branchpoints) {
  2713. while (branchpoints->size()) {
  2714. delete [] branchpoints->top().first;
  2715. branchpoints->pop();
  2716. }
  2717. delete branchpoints;
  2718. branchpoints = 0;
  2719. }
  2720. if (currentHashCode) {
  2721. delete [] currentHashCode;
  2722. currentHashCode = 0;
  2723. }
  2724. }
  2725. bool HashInstance::inRelevantRegion(char X, char Y) {
  2726. if (xx <= X && X < xx+sizeX && yy <= Y && Y < yy+sizeY) return true;
  2727. return false;
  2728. }
  2729. void HashInstance::initialize() {
  2730. currentHashCode = new hashtype[8];
  2731. for(int i=0; i<8; i++) currentHashCode[i] = 0; // start with empty board
  2732. numStones = 0;
  2733. branchpoints = new stack<pair<hashtype*,int> >;
  2734. changed = true; // do record empty pattern ...
  2735. }
  2736. void HashInstance::addB(char x, char y) {
  2737. if (inRelevantRegion(x,y)) {
  2738. changed = true;
  2739. for(int i=0; i<8; i++) {
  2740. currentHashCode[i] += Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
  2741. }
  2742. numStones++;
  2743. }
  2744. }
  2745. void HashInstance::addW(char x, char y) {
  2746. if (inRelevantRegion(x,y)) {
  2747. changed = true;
  2748. for(int i=0; i<8; i++) {
  2749. currentHashCode[i] -= Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
  2750. }
  2751. numStones++;
  2752. }
  2753. }
  2754. void HashInstance::removeB(char x, char y) {
  2755. if (inRelevantRegion(x,y)) {
  2756. changed = true;
  2757. for(int i=0; i<8; i++) {
  2758. currentHashCode[i] -= Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
  2759. }
  2760. numStones++;
  2761. }
  2762. }
  2763. void HashInstance::removeW(char x, char y) {
  2764. if (inRelevantRegion(x,y)) {
  2765. changed = true;
  2766. for(int i=0; i<8; i++) {
  2767. currentHashCode[i] += Algo_hash::hashCodes[Pattern::flipsX(i,x,y,boardsize-1, boardsize-1) + boardsize*Pattern::flipsY(i,x,y,boardsize-1, boardsize-1)];
  2768. }
  2769. numStones++;
  2770. }
  2771. }
  2772. pair<hashtype,int> HashInstance::cHC() {
  2773. int flip = 0;
  2774. hashtype minCHC = currentHashCode[0];
  2775. for(int i=1; i<8; i++) {
  2776. if (currentHashCode[i] < minCHC) {
  2777. minCHC = currentHashCode[i];
  2778. flip = i;
  2779. }
  2780. }
  2781. return make_pair(minCHC, flip*(1<<16) + pos);
  2782. }
  2783. void HashInstance::bppush() {
  2784. hashtype* chc = new hashtype[8];
  2785. for(int i=0; i<8; i++) chc[i] = currentHashCode[i];
  2786. branchpoints->push(make_pair(chc, numStones));
  2787. }
  2788. void HashInstance::bppop() {
  2789. delete [] currentHashCode;
  2790. currentHashCode = branchpoints->top().first;
  2791. numStones = branchpoints->top().second;
  2792. branchpoints->pop();
  2793. }
  2794. // UIntervals::UIntervals(intervs = []) {
  2795. // data = intervs;
  2796. // }
  2797. //
  2798. //
  2799. // void UIntervals::first() {
  2800. // if (data->size()) return data[0].first;
  2801. // else return -1; // FIXME ?!
  2802. // }
  2803. //
  2804. // void UIntervals::append(int interv_start, int interv_end) {
  2805. // data.push_back(pair<int,int>(interv_start, interv_end));
  2806. // }
  2807. //
  2808. //
  2809. // void UIntervals::inters(UIntervals& uinterv) {
  2810. // int current2low = 0;
  2811. // int current2high = 0;
  2812. //
  2813. // vector<pair<int,int>> newUInt();
  2814. //
  2815. // for(int current1=0; current1 < data.size(); current1++) {
  2816. // while (current2low < uinterv.data.size && !(uinterv.data[current2low].second > data[current1].first))
  2817. // current2low++;
  2818. // current2high = current2low;
  2819. // while (current2high < uinterv.data.size() && uinterv.data[current2high].first < data[current1].second)
  2820. // current2high++;
  2821. // current2high--;
  2822. //
  2823. // if (current2low == uinterv.data.size()) break;
  2824. // if (current2high < current2low) continue;
  2825. //
  2826. // newUInt.append(max(self.data[current1][0], uinterv.data[current2low][0]),
  2827. // min(self.data[current1][1], uinterv.data[current2low][1]));
  2828. //
  2829. // for(int c=current2low+1; c < current2high; c++)
  2830. // newUInt.append(uinterv.data[c].first, uninterv.data[c].second);
  2831. //
  2832. // if (current2high > current2low)
  2833. // newUInt.append(uinterv.data[current2high].first, min(uinterv.data[current2high].second, data[current1].second));
  2834. //
  2835. // current2low = current2high;
  2836. // }
  2837. // data = newUInt;
  2838. // }
  2839. //
  2840. // void UIntervals::isEmpty() {
  2841. // int isEmpty = 1;
  2842. // for(int i=0; i<data.size(); i++)
  2843. // if (data[i].first < data[i].second) isEmpty = 0;
  2844. // return isEmpty;
  2845. // }
  2846. //
  2847. //
  2848. //
  2849. // Algo_intervals::Algo_intervals(int bsize) {
  2850. // boardsize = bsize;
  2851. // }
  2852. //
  2853. //
  2854. // void Algo_intervals::initialize_process(int l) {
  2855. //
  2856. // movesArr = vector<long>();
  2857. // moveIntsArr = vector<long>();
  2858. // }
  2859. //
  2860. // void Algo_intervals::newgame_process() {
  2861. // counter = 0;
  2862. // moves = [];
  2863. // for(int i=0; i<boardsize*boardsize; i++) moves.append([]);
  2864. // ignore = 0;
  2865. // }
  2866. //
  2867. // void Algo_intervals::AB_process(int x, int y) {
  2868. // if (ignore) return;
  2869. // moves[boardsize*x+y]->push_back(counter | FLAG_BLACK);
  2870. // }
  2871. //
  2872. //
  2873. // void Algo_intervals::AW_process(int x, int y) {
  2874. // if (ignore) return;
  2875. // moves[boardsize*x+y]->push_back(counter | FLAG_WHITE);
  2876. // }
  2877. //
  2878. // void Algo_intervals::AE_process(int x, int y, char removed) {
  2879. // if (ignore) return;
  2880. // self.moves[self.boardsize*x+y]->push_back(counter | FLAG_REMOVE);
  2881. // }
  2882. //
  2883. // void Algo_intervals::endOfNode_process() {
  2884. // if (ignore) return;
  2885. // counter++;
  2886. // }
  2887. //
  2888. // void Algo_intervals::B_process(int x, int y, cap) {
  2889. // if (ignore) return;
  2890. // moves[self.boardsize*x+y]->push_back(counter | FLAG_BLACK);
  2891. // for(c in cap)
  2892. // moves[self.boardsize*c[0] + c[1]]->push_back(counter | FLAG_REMOVE);
  2893. // }
  2894. //
  2895. // void Algo_intervals::W_process(int x, int y, cap) {
  2896. // if (ignore) return;
  2897. // moves[self.boardsize*x+y]->push_back(counter | FLAG_WHITE);
  2898. // for(c in cap)
  2899. // moves[self.boardsize*c[0] + c[1]]->push_back(counter | FLAG_REMOVE);
  2900. // }
  2901. //
  2902. // void Algo_intervals::branchpoint_process() {
  2903. // }
  2904. //
  2905. //
  2906. // void Algo_intervals::endOfVariation_process() {
  2907. // ignore = 1;
  2908. // }
  2909. //
  2910. //
  2911. // void Algo_intervals::endgame_process() {
  2912. // for(int x=0; x < boardsize; x++) {
  2913. // for(int y=0; y < boardsize; y++) {
  2914. // if (!moves[self.boardsize*x+y]->size())
  2915. // movesArr.push_back(0);
  2916. // else if (moves[self.boardsize*x+y]->size() == 1) {
  2917. // long d = (*moves[self.boardsize*x+y])[0];
  2918. // self.movesArr.append(d);
  2919. // }
  2920. // else {
  2921. // vector<int>* mvs = moves[self.boardsize*x+y];
  2922. // long d = moveIntsArr.size() | FLAG_POINTER;
  2923. //
  2924. // vector<long> Blist;
  2925. // vector<long> Wlist;
  2926. // vector<long> Elist;
  2927. //
  2928. // Elist.push_back(0);
  2929. //
  2930. // int moveIndex = 0;
  2931. // while (moveIndex < mvs.size()) {
  2932. // if (mvs[moveIndex] & FLAG_BLACK) {
  2933. // d = d | FLAG_BLACK;
  2934. // Blist.push_back(mvs[moveIndex] & ~FLAG_BLACK);
  2935. // Elist.push_back(mvs[moveIndex] & ~FLAG_BLACK);
  2936. // if (moveIndex + 1 < mvs->size()) {
  2937. // Blist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
  2938. // Elist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
  2939. // }
  2940. // else Blist.push_back(MAXNOMOVES);
  2941. // }
  2942. // if (mvs[moveIndex] & FLAG_WHITE) {
  2943. // d = d | FLAG_WHITE;
  2944. // Wlist.push_back(mvs[moveIndex] & ~FLAG_WHITE);
  2945. // Elist.push_back(mvs[moveIndex] & ~FLAG_WHITE);
  2946. // if (moveIndex + 1 < mvs->size()) {
  2947. // Wlist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
  2948. // Elist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
  2949. // }
  2950. // else Wlist.append(MAXNOMOVES);
  2951. // }
  2952. // moveIndex += 2;
  2953. // }
  2954. //
  2955. // if ((!Blist.size() || Blist[Blist.size()-1] != MAXNOMOVES) &&
  2956. // (!Wlist.size() || Wlist[Wlist.size()-1] != MAXNOMOVES))
  2957. // Elist.push_back(MAXNOMOVES);
  2958. //
  2959. // moveIntsArr.push_back(Blist.size());
  2960. // moveIntsArr.push_back(Wlist.size());
  2961. // moveIntsArr.push_back(Elist.size());
  2962. // moveIntsArr.extend(Blist);
  2963. // moveIntsArr.extend(Wlist);
  2964. // moveIntsArr.extend(Elist);
  2965. //
  2966. // movesArr.push_back(d);
  2967. // }
  2968. // }
  2969. // }
  2970. // }
  2971. //
  2972. // void Algo_intervals::finalize_process(datap) {
  2973. // // FIXME
  2974. // extract datap0, datap1 from datap
  2975. //
  2976. // String fn = datap0 + "/movesarr" + datap1 + ".db"; // FIXME: linux specific!?
  2977. // ofstream file(fn, ios::out|ios::trunc|ios::binary) // FIXME: careful with ios::trunc
  2978. // file.write(movesArr, movesArrSize);
  2979. // file.close();
  2980. //
  2981. // fn = datap0 + "/moveints" + datap1 + ".db"; // FIXME: linux specific!?
  2982. // file(fn, ios::out|ios::trunc|ios::binary) // FIXME: careful with ios::trunc
  2983. // file.write(moveIntsArr, moveIntsArrSize);
  2984. // file.close();
  2985. //
  2986. // }
  2987. //
  2988. //
  2989. // int Algo_intervals::retrieve_db(datap) {
  2990. // String fn = ... "/movesarr" ...; // FIXME
  2991. // ifstream file (fn, ios::in|ios::binary|ios::ate);
  2992. // if (file.is_open()) {
  2993. // ifstream::pos_type size = file.tellg();
  2994. // delete [] movesArr;
  2995. // movesArr = new char[size]; // FIXME: not a char array?
  2996. // file.seekg (0, ios::beg);
  2997. // file.read (memblock, size);
  2998. // file.close();
  2999. // }
  3000. // else {
  3001. // return 0;
  3002. // }
  3003. // String fn = ... "/moveints" ...; // FIXME
  3004. // ifstream file (fn, ios::in|ios::binary|ios::ate);
  3005. // if (file.is_open()) {
  3006. // ifstream::pos_type size = file.tellg();
  3007. // delete [] moveIntsArr;
  3008. // moveIntsArr = new char[size]; // FIXME: not a char array?
  3009. // file.seekg (0, ios::beg);
  3010. // file.read (memblock, size);
  3011. // file.close();
  3012. // }
  3013. // else {
  3014. // return 0;
  3015. // }
  3016. // return 0;
  3017. // }
  3018. //
  3019. // void Algo_intervals::getUInterv(mves, vector<long> mves1, int gameno, int x, int y, char color) {
  3020. //
  3021. // UIntervals UInterv();
  3022. // int typeInterv = 0;
  3023. // long d = mves[gameno*boardsize*boardsize + boardsize*x + y];
  3024. //
  3025. // if (d & FLAG_POINTER) {
  3026. //
  3027. // if (color == 'X' && !(d & FLAG_BLACK)) return 0, UIntervals();
  3028. // if (color == 'O' && !(d & FLAG_WHITE)) return 0, UIntervals();
  3029. //
  3030. // long p = d & MAXNOMOVES;
  3031. // long lenB = moves1[p];
  3032. // long lenW = moves1[p+1];
  3033. // long lenE = moves1[p+2];
  3034. // long start;
  3035. // long length;
  3036. //
  3037. // if (color == 'X') {
  3038. // start = p + 3;
  3039. // length = lenB;
  3040. // }
  3041. // else if (color == 'O') {
  3042. // start = p + 3 + lenB;
  3043. // length = lenW;
  3044. // }
  3045. // else if (color == '.') {
  3046. // start = p + 3 + lenB + lenW;
  3047. // length = lenE;
  3048. // }
  3049. //
  3050. // l = [];
  3051. // for(int i=0; i<length/2; i++)
  3052. // l.append((moves1[start+2*i], moves1[start+2*i+1]));
  3053. //
  3054. // if (l[-1][1] == MAXNOMOVES) typeInterv = length-1;
  3055. // else typeInterv = length;
  3056. // return typeInterv, UIntervals(l);
  3057. // }
  3058. // else {
  3059. // if (color == 'X' && (d & FLAG_BLACK))
  3060. // return 1, UIntervals([( d & MAXNOMOVES , MAXNOMOVES)]);
  3061. // else if (color == 'O' && (d & FLAG_WHITE))
  3062. // return 1, UIntervals([( d & MAXNOMOVES , MAXNOMOVES)]);
  3063. // else if (color == '.') {
  3064. // if (!d) return -1, UIntervals([(0, MAXNOMOVES)]);
  3065. // else return 1, UIntervals([(0, d & MAXNOMOVES)]);
  3066. // }
  3067. // }
  3068. // return 0, UIntervals();
  3069. // }
  3070. //
  3071. //
  3072. // void Algo_intervals::search(patternList, options, db,
  3073. // continuations, contLabelsIndex, contLabels,
  3074. // progBar, progStart, progEnd) {
  3075. // int ctr = 0;
  3076. // int numOfHits = 0;
  3077. // int overallSwitched = 0;
  3078. // int Bwins = 0;
  3079. // int Wwins = 0;
  3080. // int index = db.start();
  3081. //
  3082. // if (!self.retrieve_db(db.datapath)) {
  3083. // printf("Error!\n"); // FIXME
  3084. // return;
  3085. // }
  3086. //
  3087. // int movelimit = MAXNOMOVES;
  3088. // if (options.has_key('movelimit')) movelimit = options['movelimit'];
  3089. //
  3090. // // moves, moves1 = self.movesArr, self.moveIntsArr;
  3091. //
  3092. // while (index != -1) {
  3093. // ctr++;
  3094. //
  3095. // matchList = db.getCurrentMatchlist();
  3096. // result = [];
  3097. // int numOfSwitched = 0;
  3098. //
  3099. // if (progBar && !(ctr % 10))
  3100. // progBar.redraw((progEnd-progStart)*ctr/len(db.current) + progStart);
  3101. //
  3102. // for(m in matchList) {
  3103. // Pattern p = patternList.get(m[0]);
  3104. // a0, a1 = m[1];
  3105. //
  3106. // UIntervals currentUInterv([(0, self.movelimit)]);
  3107. //
  3108. // toDo = {};
  3109. // cont = [(MAXNOMOVES, -1,-1)];
  3110. // int i = 0;
  3111. // int j = 0;
  3112. //
  3113. // while (i < p.sizeX && !currentUInterv.isEmpty()) {
  3114. //
  3115. // if (p.data[i][j] == '*') {
  3116. // Bint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
  3117. // if (Bint.data) cont.extend([(x,i,j) for x in [z[0] for z in Bint.data]]);
  3118. // Wint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
  3119. // if (Wint.data) cont.extend([(x,i,j) for x in [z[0] for z in Wint.data]]);
  3120. // }
  3121. // else if p.data[i][j] == 'x': printf("oops\n"); // FIXME
  3122. // else if p.data[i][j] == 'o': printf("oops\n"); // FIXME
  3123. //
  3124. // else {
  3125. // typeInt, nextInt = self.getUInterv(moves, moves1, index, i+a0, j+a1, p.data[i][j]);
  3126. //
  3127. // if (typeInt == -1) ;
  3128. // else if (typeInt == 0) currentUInterv = UIntervals();
  3129. // else if (typeInt == 1) {
  3130. // if (p.data[i][j] == '.' && cont[0][0] > nextInt.data[0][1]) {
  3131. // Bi = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
  3132. // Wi = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
  3133. // counter = nextInt.data[0][1];
  3134. // cont[0] = (nextInt.data[0][1], i, j);
  3135. // }
  3136. // currentUInterv.inters(nextInt);
  3137. // }
  3138. // else {
  3139. // if (toDo.has_key(typeInt)) toDo[typeInt].append((i,j,nextInt));
  3140. // else toDo[typeInt] = [(i, j, nextInt)];
  3141. // }
  3142. // }
  3143. // j++;
  3144. // if (j == p.sizeY) {
  3145. // j = 0;
  3146. // i++;
  3147. // }
  3148. // }
  3149. //
  3150. // toDoList = [];
  3151. // for(ii in toDo.keys()) toDoList.extend(toDo[ii]);
  3152. //
  3153. // while (toDoList && !currentUInterv.isEmpty()) {
  3154. // i, j, nextInt = toDoList[0];
  3155. // del toDoList[0];
  3156. //
  3157. // currentUInterv.inters(nextInt);
  3158. // if (currentUInterv.isEmpty()) break;
  3159. //
  3160. // if (p.data[i][j] == 'X') Bint = nextInt;
  3161. // else Bint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
  3162. // if (Bint.data) cont.extend([(x,i,j) for x in [z[0] for z in Bint.data]]);
  3163. // if (p.data[i][j] == 'O') Wint = nextInt;
  3164. // else Wint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
  3165. // if (Wint.data) cont.extend([(x,i,j) for x in [z[0] for z in Wint.data]]);
  3166. // }
  3167. //
  3168. // if (!currentUInterv.isEmpty()) {
  3169. //
  3170. // cont.sort();
  3171. // for(counter, x, y in cont)
  3172. // if (counter > currentUInterv.first()) break;
  3173. //
  3174. // if (counter == MAXNOMOVES || counter <= currentUInterv.first()) {
  3175. // hit = 1;
  3176. // label = '';
  3177. // switched = p.colorSwitch;
  3178. // }
  3179. // else {
  3180. // Xint = (m[1][0], m[1][0] + patternList.get(m[0]).sizeX);
  3181. // Yint = (m[1][1], m[1][1] + patternList.get(m[0]).sizeY);
  3182. //
  3183. // Bint = self.getUInterv(moves, moves1, index, x+a0, y+a1, 'X')[1];
  3184. // Wint = self.getUInterv(moves, moves1, index, x+a0, y+a1, 'O')[1];
  3185. // if (counter in [z[0] for z in Bint.data]) co = 'W'; // !!! FIXME (cf. Algo_movelist.search)
  3186. // else if (counter in [z[0] for z in Wint.data]) co = 'B'; // !!!
  3187. // else raise Exception; // FIXME
  3188. //
  3189. // hit, label, contLabelsIndex, switched =
  3190. // patternList.updateContinuations(m[0], x+a0, y+a1, co, Xint, Yint,
  3191. // currentUInterv.first(), counter-1,
  3192. // continuations, contLabels, contLabelsIndex,
  3193. // gl.getCurrentWinner());
  3194. // }
  3195. //
  3196. // if (hit) {
  3197. // numOfSwitched += switched;
  3198. // if (switched) result.append(str(currentUInterv.first())+label+'-');
  3199. // else result.append(str(currentUInterv.first())+label);
  3200. // }
  3201. // }
  3202. // }
  3203. //
  3204. // if (result) {
  3205. // result.sort();
  3206. // db.makeCurrentHit(join(result, ', '));
  3207. // numOfHits = numOfHits + len(result);
  3208. // overallSwitched += numOfSwitched;
  3209. //
  3210. // if (gl.getCurrentWinner() == 'B') {
  3211. // Bwins = Bwins + len(result) - numOfSwitched;
  3212. // Wwins = Wwins + numOfSwitched;
  3213. // }
  3214. // else if (gl.getCurrentWinner() == 'W') {
  3215. // Bwins = Bwins + numOfSwitched;
  3216. // Wwins = Wwins + len(result) - numOfSwitched;
  3217. // }
  3218. // }
  3219. // else db.discardCurrent();
  3220. //
  3221. // index = db.next();
  3222. // }
  3223. // return numOfHits, Bwins, Wwins, overallSwitched;
  3224. // }
  3225. // ----------------------------------------------------------------------------------------------
  3226. // GameList and related stuff
  3227. Candidate::Candidate(char X, char Y, char ORIENTATION) {
  3228. x = X;
  3229. y = Y;
  3230. orientation = ORIENTATION;
  3231. }
  3232. Hit::Hit(ExtendedMoveNumber* POS, char* LABEL) { // LABEL is a char[3]
  3233. pos = POS; // note that we do not copy these!
  3234. label = LABEL;
  3235. }
  3236. Hit::~Hit() {
  3237. delete pos;
  3238. delete [] label;
  3239. }
  3240. Hit::Hit(SnapshotVector& snv) {
  3241. int length = snv.retrieve_int();
  3242. int* data = snv.retrieve_intp();
  3243. pos = new ExtendedMoveNumber(length, data);
  3244. delete [] data;
  3245. label = snv.retrieve_charp();
  3246. }
  3247. void Hit::to_snv(SnapshotVector& snv) {
  3248. snv.pb_int(pos->length);
  3249. snv.pb_intp(pos->data, pos->length);
  3250. snv.pb_charp(label, 3);
  3251. }
  3252. bool Hit::cmp_pts(Hit* a, Hit* b) {
  3253. if (a->pos->length != b->pos->length) return a->pos->length < b->pos->length;
  3254. for(int i=0; i < a->pos->length; i++)
  3255. if (a->pos->data[i] != b->pos->data[i]) return a->pos->data[i] < b->pos->data[i];
  3256. return false;
  3257. }
  3258. SearchOptions::SearchOptions() {
  3259. fixedColor = 0;
  3260. moveLimit = 10000;
  3261. nextMove = 0;
  3262. trustHashFull = false;
  3263. searchInVariations = true;
  3264. algos = (1<<30) - 1; // use all available algorithms
  3265. }
  3266. SearchOptions::SearchOptions(int FIXEDCOLOR, int NEXTMOVE, int MOVELIMIT) {
  3267. fixedColor = FIXEDCOLOR;
  3268. moveLimit = MOVELIMIT;
  3269. nextMove = NEXTMOVE;
  3270. trustHashFull = false;
  3271. searchInVariations = true;
  3272. algos = (1<<30) - 1; // use all available algorithms
  3273. }
  3274. SearchOptions::SearchOptions(SnapshotVector& snv) {
  3275. fixedColor = snv.retrieve_int();
  3276. moveLimit = snv.retrieve_int();
  3277. nextMove = snv.retrieve_int();
  3278. trustHashFull = snv.retrieve_int();
  3279. searchInVariations= snv.retrieve_int();
  3280. algos = snv.retrieve_int();
  3281. }
  3282. void SearchOptions::to_snv(SnapshotVector& snv) {
  3283. snv.pb_int(fixedColor);
  3284. snv.pb_int(moveLimit);
  3285. snv.pb_int(nextMove);
  3286. snv.pb_int(trustHashFull);
  3287. snv.pb_int(searchInVariations);
  3288. snv.pb_int(algos);
  3289. }
  3290. ProcessOptions::ProcessOptions() {
  3291. processVariations = true;
  3292. sgfInDB = true;
  3293. rootNodeTags = "BR,CA,DT,EV,HA,KM,PB,PC,PW,RE,RO,RU,SZ,US,WR";
  3294. algos = ALGO_FINALPOS | ALGO_MOVELIST | ALGO_HASH_FULL | ALGO_HASH_CORNER;
  3295. algo_hash_full_maxNumStones = 50;
  3296. algo_hash_corner_maxNumStones = 20;
  3297. }
  3298. ProcessOptions::ProcessOptions(string s) {
  3299. int p = 0;
  3300. if (s[p++] == 't') processVariations = true;
  3301. else processVariations = false;
  3302. if (s[p++] == 't') sgfInDB = true;
  3303. else sgfInDB = false;
  3304. p++;
  3305. int pn = s.find('|', p) + 1;
  3306. algos = atoi(s.substr(p, pn-p-1).c_str());
  3307. p = pn;
  3308. pn = s.find('|', p) + 1;
  3309. algo_hash_full_maxNumStones = atoi(s.substr(p, pn-p-1).c_str());
  3310. p = pn;
  3311. pn = s.find('|', p) + 1;
  3312. algo_hash_corner_maxNumStones = atoi(s.substr(p, pn-p-1).c_str());
  3313. rootNodeTags = s.substr(pn);
  3314. }
  3315. string ProcessOptions::asString() {
  3316. string result;
  3317. if (processVariations) result += "t";
  3318. else result += "f";
  3319. if (sgfInDB) result += "t";
  3320. else result += "f";
  3321. char buf[200];
  3322. sprintf(buf, "|%d|%d|%d|%s", algos, algo_hash_full_maxNumStones, algo_hash_corner_maxNumStones, rootNodeTags.c_str());
  3323. result += buf;
  3324. return result;
  3325. }
  3326. void ProcessOptions::validate() {
  3327. string::iterator it = rootNodeTags.begin();
  3328. while (it != rootNodeTags.end()) {
  3329. if (*it == ' ') it = rootNodeTags.erase(it);
  3330. else it++;
  3331. }
  3332. if (rootNodeTags.find("PB") == string::npos) rootNodeTags += ",PB";
  3333. if (rootNodeTags.find("PW") == string::npos) rootNodeTags += ",PW";
  3334. if (rootNodeTags.find("RE") == string::npos) rootNodeTags += ",RE";
  3335. if (rootNodeTags.find("DT") == string::npos) rootNodeTags += ",DT";
  3336. algos |= ALGO_FINALPOS | ALGO_MOVELIST; // these are mandatory at the moment
  3337. }
  3338. vector<string>* ProcessOptions::SGFTagsAsStrings() {
  3339. vector<string>* SGFtags = new vector<string>;
  3340. int ctr = 0;
  3341. unsigned int p = 0;
  3342. unsigned int pn = rootNodeTags.find(',', p);
  3343. while (pn != string::npos) {
  3344. SGFtags->push_back(rootNodeTags.substr(p,pn-p));
  3345. ctr++;
  3346. p = pn+1;
  3347. pn = rootNodeTags.find(',', p);
  3348. }
  3349. SGFtags->push_back(rootNodeTags.substr(p));
  3350. return SGFtags;
  3351. }
  3352. GameListEntry::GameListEntry(int ID, char WINNER, string GAMEINFOSTR) {
  3353. // printf("GLE %d %c %s\n", ID, WINNER, GAMEINFOSTR);
  3354. id = ID;
  3355. if (WINNER == 'B' || WINNER == 'b') winner = 'B';
  3356. else if (WINNER == 'W' || WINNER == 'w') winner = 'W';
  3357. else if (WINNER == 'J' || WINNER == 'j') winner = 'J';
  3358. else winner = '-';
  3359. gameInfoStr = GAMEINFOSTR;
  3360. hits = 0;
  3361. candidates = 0;
  3362. }
  3363. GameListEntry::~GameListEntry() {
  3364. if (hits) {
  3365. for(vector<Hit* >::iterator it = hits->begin(); it != hits->end(); it++) delete *it;
  3366. delete hits;
  3367. hits = 0;
  3368. }
  3369. if (candidates) {
  3370. for(vector<Candidate* >::iterator it = candidates->begin(); it != candidates->end(); it++) delete *it;
  3371. delete candidates;
  3372. candidates = 0;
  3373. }
  3374. }
  3375. void GameListEntry::hits_from_snv(SnapshotVector& snv) {
  3376. int h_size = snv.retrieve_int();
  3377. hits = new vector<Hit* >;
  3378. for(int j=0; j<h_size; j++) {
  3379. hits->push_back(new Hit(snv));
  3380. }
  3381. }
  3382. int insertEntry(void *gl, int argc, char **argv, char **azColName) {
  3383. char winner = '-';
  3384. if (argv[1] && (argv[1][0] == 'B' || argv[1][0] == 'W' || argv[1][0] == 'J')) winner = argv[1][0];
  3385. string gameInfoStr = ((GameList*)gl)->format2;
  3386. for(int i=0; i<((GameList*)gl)->numColumns; i++) {
  3387. char strpip1[20];
  3388. sprintf(strpip1, "[[%d[[F", i);
  3389. unsigned int p = gameInfoStr.find(strpip1);
  3390. if (p != string::npos) {
  3391. if (argv[i]) {
  3392. string fn = argv[i];
  3393. if (fn.substr(fn.size()-4) == ".sgf" || fn.substr(fn.size()-4) == ".mgt")
  3394. gameInfoStr.replace(p, strlen(strpip1), fn.substr(0,fn.size()-4));
  3395. else gameInfoStr.replace(p, strlen(strpip1), fn);
  3396. } else gameInfoStr.erase(gameInfoStr.find(strpip1), strlen(strpip1));
  3397. continue;
  3398. }
  3399. sprintf(strpip1, "[[%d", i);
  3400. p = gameInfoStr.find(strpip1);
  3401. if (p != string::npos) {
  3402. if (argv[i]) gameInfoStr.replace(p, strlen(strpip1), argv[i]);
  3403. else gameInfoStr.erase(gameInfoStr.find(strpip1), strlen(strpip1));
  3404. }
  3405. }
  3406. unsigned int p = gameInfoStr.find("[[W");
  3407. if (p != string::npos) gameInfoStr.replace(p, 3, 1, winner);
  3408. // printf("id %s\n", argv[0]);
  3409. ((GameList*)gl)->all->push_back(new GameListEntry(atoi(argv[0]), winner, gameInfoStr));
  3410. return 0;
  3411. }
  3412. int dbinfo_callback(void *s, int argc, char **argv, char **asColName) {
  3413. char** cpp = (char**)s;
  3414. if (argc && argv[0]) {
  3415. // printf("dbi_cb %s\n", argv[0]);
  3416. *cpp = new char[strlen(argv[0])+1];
  3417. strcpy(*cpp, argv[0]);
  3418. }
  3419. return 0;
  3420. }
  3421. GameList::GameList(char* DBNAME, string ORDERBY, string FORMAT, ProcessOptions* p_options, int cache) throw(DBError) {
  3422. duplicates = 0;
  3423. labels = 0;
  3424. continuations = 0;
  3425. mrs_pattern = 0;
  3426. searchOptions = 0;
  3427. dbname = new char[strlen(DBNAME)+2];
  3428. strcpy(dbname, DBNAME);
  3429. db = algo_db1 = algo_db2 = 0;
  3430. dbname[strlen(DBNAME)] = '1';
  3431. dbname[strlen(DBNAME)+1] = 0;
  3432. int rc = sqlite3_open(dbname, &algo_db1);
  3433. if (rc) {
  3434. sqlite3_close(algo_db1);
  3435. algo_db1 = 0;
  3436. throw DBError();
  3437. }
  3438. rc = sqlite3_busy_timeout(algo_db1, 200);
  3439. if (rc) throw DBError();
  3440. rc = sqlite3_exec(algo_db1, "pragma synchronous = off;", 0, 0, 0);
  3441. if (rc) throw DBError();
  3442. char cache_str[100];
  3443. sprintf(cache_str, "pragma cache_size = %d", cache*1000);
  3444. rc = sqlite3_exec(algo_db1, cache_str, 0, 0, 0);
  3445. if (rc) throw DBError();
  3446. dbname[strlen(DBNAME)] = '2';
  3447. dbname[strlen(DBNAME)+1] = 0;
  3448. rc = sqlite3_open(dbname, &algo_db2);
  3449. if (rc) {
  3450. sqlite3_close(algo_db2);
  3451. algo_db2 = 0;
  3452. throw DBError();
  3453. }
  3454. rc = sqlite3_busy_timeout(algo_db2, 200);
  3455. if (rc) throw DBError();
  3456. rc = sqlite3_exec(algo_db2, "pragma synchronous = off;", 0, 0, 0);
  3457. if (rc) throw DBError();
  3458. sprintf(cache_str, "pragma cache_size = %d", cache*7000);
  3459. rc = sqlite3_exec(algo_db2, cache_str, 0, 0, 0);
  3460. if (rc) throw DBError();
  3461. // try to retrieve basic options from database
  3462. dbname[strlen(DBNAME)] = 0;
  3463. rc = sqlite3_open(dbname, &db);
  3464. if (rc) {
  3465. sqlite3_close(db);
  3466. db = 0;
  3467. throw DBError();
  3468. }
  3469. rc = sqlite3_busy_timeout(db, 200);
  3470. if (rc) throw DBError();
  3471. rc = sqlite3_exec(db, "pragma synchronous = off;", 0, 0, 0);
  3472. if (rc) throw DBError();
  3473. sprintf(cache_str, "pragma cache_size = %d", cache*1000);
  3474. rc = sqlite3_exec(db, cache_str, 0, 0, 0);
  3475. if (rc) throw DBError();
  3476. rc = sqlite3_exec(db, "create table db_info ( info text );", 0, 0, 0);
  3477. //if (rc != SQLITE_OK) throw DBError();
  3478. char* dbinfo = 0;
  3479. rc = sqlite3_exec(db, "select * from db_info where rowid = 1;", dbinfo_callback, &dbinfo, 0);
  3480. if (rc != SQLITE_OK) throw DBError();
  3481. if (dbinfo) {
  3482. // printf("dbinfo: %s\n", dbinfo);
  3483. p_op = new ProcessOptions(dbinfo);
  3484. delete [] dbinfo;
  3485. char* bsizes = 0;
  3486. rc = sqlite3_exec(db, "select * from db_info where rowid = 2;", dbinfo_callback, &bsizes, 0);
  3487. if (rc != SQLITE_OK) throw DBError();
  3488. if (bsizes) {
  3489. // printf("board sizes %s\n", bsizes); // should be a comma-sep. list of integers *ending w/ a comma*
  3490. string bsizes_str(bsizes);
  3491. delete [] bsizes;
  3492. unsigned int p = 0;
  3493. unsigned int pn = bsizes_str.find(",",p);
  3494. while (pn > p && pn != string::npos) {
  3495. boardsizes.push_back(atoi(bsizes_str.substr(p, pn-p).c_str()));
  3496. p = pn+1;
  3497. pn = bsizes_str.find(",",p);
  3498. }
  3499. }
  3500. } else { // if this does not work: create database and read p_options (or use defaults)
  3501. // printf("retrieving dbinfo failed\n");
  3502. if (p_options == 0) p_op = new ProcessOptions(); // use default values
  3503. else {
  3504. // printf("use p_options\n");
  3505. p_op = new ProcessOptions(*p_options);
  3506. p_op->validate(); // make sure the most important information is contained in rootNodeTags list
  3507. }
  3508. string sql = "insert into db_info (rowid,info) values (1,'";
  3509. sql += p_op->asString();
  3510. sql += "');";
  3511. rc = sqlite3_exec(db, sql.c_str(), 0, 0, 0);
  3512. if (rc != SQLITE_OK) throw DBError();
  3513. rc = sqlite3_exec(db, "insert into db_info (rowid, info) values (2, ',');", 0, 0, 0);
  3514. if (rc != SQLITE_OK) throw DBError();
  3515. }
  3516. // set up snapshot db
  3517. rc = sqlite3_exec(db, "create table snapshots ( data text );", 0, 0, 0);
  3518. //if (rc != SQLITE_OK) throw DBError();
  3519. // printf("set up Algorithm instances\n");
  3520. for(vector<int>::iterator it = boardsizes.begin(); it != boardsizes.end(); it++)
  3521. addAlgos(*it);
  3522. all = 0;
  3523. currentList = oldList = 0;
  3524. readDBs = 0;
  3525. resetFormat(ORDERBY, FORMAT);
  3526. }
  3527. void GameList::resetFormat(string ORDERBY, string FORMAT) {
  3528. // printf("enter resetFormat\n");
  3529. if (FORMAT == "") { // use default format string
  3530. numColumns = 5;
  3531. format1 = "id,re,pw,pb,dt";
  3532. format2 = "[[2 - [[3 ([[W), [[4, ";
  3533. } else {
  3534. char buf[10];
  3535. numColumns = 2;
  3536. format1 = "id,re";
  3537. format2 = FORMAT;
  3538. unsigned int p = 0;
  3539. unsigned int q = 0;
  3540. while (p != string::npos) {
  3541. p = format2.find("[[",p);
  3542. q = format2.find("]]",p);
  3543. if (p+2 < format2.size() && q != string::npos) {
  3544. string col = format2.substr(p+2, q-p-2);
  3545. // check availability
  3546. if (col == "id" || col == "filename" || col == "pos" || col == "duplicate" || col == "date" || p_op->rootNodeTags.find(col) != string::npos) {
  3547. sprintf(buf, "[[%d", numColumns++);
  3548. format2.replace(p,q+2-p, buf);
  3549. format1 += ",";
  3550. format1 += col;
  3551. } else if (col == "winner") format2.replace(p,q+2-p, "[[W");
  3552. else if (col == "filename.") {
  3553. sprintf(buf, "[[%d[[F", numColumns++);
  3554. format2.replace(p, q+2-p, buf);
  3555. format1 += ",filename";
  3556. }
  3557. p++;
  3558. } else break;
  3559. }
  3560. }
  3561. if (ORDERBY == "" || ORDERBY == "id" || ORDERBY == "ID" || ORDERBY == "Id" || ORDERBY == "iD") orderby = "id";
  3562. else orderby = ORDERBY + ",id";
  3563. // printf("finished parsing\n");
  3564. readDB();
  3565. }
  3566. void GameList::addAlgos(int bs) {
  3567. int ctr = algo_ps.size()/20;
  3568. // printf("add algos %d %d %d\n", bs, ctr, p_op->algos);
  3569. for(int i=0; i<20; i++) {
  3570. algo_ps.push_back(0);
  3571. algo_dbs.push_back(0);
  3572. }
  3573. algo_ps[20*ctr] = new Algo_signature(bs);
  3574. algo_dbs[20*ctr] = db;
  3575. if (p_op->algos & ALGO_FINALPOS) {
  3576. algo_ps[algo_finalpos+20*ctr] = new Algo_finalpos(bs);
  3577. algo_dbs[algo_finalpos+20*ctr] = algo_db1;
  3578. }
  3579. if (p_op->algos & ALGO_MOVELIST) {
  3580. algo_ps[algo_movelist+20*ctr] = new Algo_movelist(bs);
  3581. algo_dbs[algo_movelist+20*ctr] = algo_db1;
  3582. }
  3583. if (p_op->algos & ALGO_HASH_FULL) {
  3584. algo_ps[algo_hash_full+20*ctr] = new Algo_hash_full(bs, p_op->algo_hash_corner_maxNumStones);
  3585. algo_dbs[algo_hash_full+20*ctr] = algo_db2;
  3586. }
  3587. if (p_op->algos & ALGO_HASH_CORNER) {
  3588. algo_ps[algo_hash_corner+20*ctr] = new Algo_hash_corner(bs, 7, p_op->algo_hash_corner_maxNumStones);
  3589. algo_dbs[algo_hash_corner+20*ctr] = algo_db2;
  3590. }
  3591. // for(int a=20*ctr; a<20*(ctr+1); a++) printf("aa %d %p\n", a, algo_ps[a]);
  3592. // if (algos & ALGO_HASH_SIDE)
  3593. // algo_ps[algo_hash_side] = new Algo_hash_side(boardsize, 6, 4, p_op->algo_hash_side_maxNumStones);
  3594. }
  3595. void GameList::readDB() throw(DBError) {
  3596. // printf("read dbs\n");
  3597. if (oldList) delete oldList;
  3598. if (currentList) delete currentList;
  3599. if (all) {
  3600. for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++)
  3601. delete *it;
  3602. delete all;
  3603. }
  3604. current = -1;
  3605. all = new vector<GameListEntry* >;
  3606. currentList = 0;
  3607. oldList = 0;
  3608. int rc;
  3609. rc = sqlite3_exec(db, "begin transaction;", 0, 0, 0);
  3610. if (rc) throw DBError();
  3611. string sql = "select ";
  3612. sql += format1;
  3613. sql += " from games order by ";
  3614. sql += orderby;
  3615. // printf("sql: %s\n", sql.c_str());
  3616. rc = sqlite3_exec(db, sql.c_str(), insertEntry, this, 0);
  3617. if (rc != SQLITE_OK && rc != SQLITE_ERROR) {
  3618. throw DBError();
  3619. }
  3620. // printf("read.\n");
  3621. // SQLITE_ERROR may occur since table might not yet exist
  3622. readPlayersList();
  3623. rc = sqlite3_exec(db, "commit;", 0, 0, 0);
  3624. if (rc != SQLITE_OK) throw DBError();
  3625. if (rc == SQLITE_OK && !readDBs) {
  3626. for(unsigned int a=0; a < 20*boardsizes.size(); a++) {
  3627. if (algo_ps[a]) algo_ps[a]->readDB(algo_dbs[a]);
  3628. }
  3629. readDBs = 1;
  3630. }
  3631. // printf("read.\n");
  3632. reset();
  3633. // printf("leave readDB\n");
  3634. }
  3635. GameList::~GameList() {
  3636. // printf("enter ~GameList\n");
  3637. if (mrs_pattern) delete mrs_pattern;
  3638. if (searchOptions) delete searchOptions;
  3639. if (p_op) delete p_op;
  3640. if (labels) delete [] labels;
  3641. if (continuations) delete [] continuations; // FIXME CHECK whether the Continuation destructor is invoked!
  3642. if (duplicates) delete duplicates;
  3643. delete [] dbname;
  3644. if (all) {
  3645. for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++)
  3646. delete *it;
  3647. delete all;
  3648. }
  3649. if (currentList) delete currentList;
  3650. if (oldList) delete oldList;
  3651. for(unsigned int i=0; i<20*boardsizes.size(); i++)
  3652. if (algo_ps[i]) delete algo_ps[i];
  3653. if (db) sqlite3_close(db);
  3654. db = 0;
  3655. if (algo_db1) sqlite3_close(algo_db1);
  3656. algo_db1 = 0;
  3657. if (algo_db2) sqlite3_close(algo_db2);
  3658. algo_db2 = 0;
  3659. // printf("leave ~GameList\n");
  3660. }
  3661. int GameList::start() {
  3662. current = 0;
  3663. if (oldList) delete oldList;
  3664. oldList = currentList;
  3665. currentList = new vector<pair<int,int> >;
  3666. if (oldList && oldList->size()) return (*oldList)[0].first;
  3667. else {
  3668. if (oldList) delete oldList;
  3669. oldList = 0;
  3670. return -1;
  3671. }
  3672. }
  3673. int GameList::next() {
  3674. current++;
  3675. if (current < (int)oldList->size()) return (*oldList)[current].first;
  3676. else {
  3677. if (oldList) delete oldList;
  3678. oldList = 0;
  3679. return -1;
  3680. }
  3681. }
  3682. bool sndcomp(const pair<int,int>& a, const pair<int,int>& b) {
  3683. return a.second < b.second;
  3684. }
  3685. int GameList::start_sorted() {
  3686. current = 0;
  3687. if (oldList) delete oldList;
  3688. oldList = currentList;
  3689. currentList = new vector<pair<int,int> >;
  3690. if (!oldList || !oldList->size()) {
  3691. if (oldList) delete oldList;
  3692. oldList = 0;
  3693. return -1;
  3694. }
  3695. sort(oldList->begin(), oldList->end());
  3696. return 0;
  3697. }
  3698. int GameList::end_sorted() {
  3699. // printf("end sorted\n");
  3700. sort(currentList->begin(), currentList->end(), sndcomp);
  3701. delete oldList;
  3702. oldList = 0;
  3703. return 0;
  3704. }
  3705. char GameList::getCurrentWinner() {
  3706. return (*all)[(*oldList)[current].second]->winner;
  3707. }
  3708. vector<Candidate* > * GameList::getCurrentCandidateList() {
  3709. return (*all)[(*oldList)[current].second]->candidates;
  3710. }
  3711. void GameList::makeCurrentCandidate(vector<Candidate* > * candidates) {
  3712. GameListEntry* gle = (*all)[(*oldList)[current].second];
  3713. if (gle->candidates) delete gle->candidates;
  3714. gle->candidates = candidates;
  3715. currentList->push_back((*oldList)[current]);
  3716. }
  3717. void GameList::makeCurrentHit(vector<Hit* > * hits) {
  3718. GameListEntry* gle = (*all)[(*oldList)[current].second];
  3719. if (gle->hits) delete gle->hits;
  3720. gle->hits = hits;
  3721. sort(gle->hits->begin(), gle->hits->end(), Hit::cmp_pts);
  3722. currentList->push_back((*oldList)[current]);
  3723. }
  3724. void GameList::setCurrentFromIndex(int index) {
  3725. int start = current;
  3726. int end = oldList->size();
  3727. int m = start;
  3728. while (start < end) {
  3729. m = (end+start)/2;
  3730. if (index == (*oldList)[m].first) {
  3731. break;
  3732. } else {
  3733. if (index < (*oldList)[m].first) end = m;
  3734. else start = m+1;
  3735. }
  3736. }
  3737. current = m;
  3738. }
  3739. void GameList::makeIndexHit(int index, vector<Hit* > * hits) {
  3740. int m = get_current_index(index, &current);
  3741. if (m != -1) {
  3742. currentList->push_back((*oldList)[m]);
  3743. if (hits) {
  3744. if ((*all)[(*oldList)[m].second]->hits) delete (*all)[(*oldList)[m].second]->hits;
  3745. (*all)[(*oldList)[m].second]->hits = hits;
  3746. }
  3747. }
  3748. }
  3749. void GameList::makeIndexCandidate(int index, vector<Candidate* > * candidates) {
  3750. int m = get_current_index(index, &current);
  3751. if (m != -1) {
  3752. currentList->push_back((*oldList)[m]);
  3753. if (candidates) {
  3754. if ((*all)[(*oldList)[m].second]->candidates) delete (*all)[(*oldList)[m].second]->candidates;
  3755. (*all)[(*oldList)[m].second]->candidates = candidates;
  3756. }
  3757. }
  3758. }
  3759. void GameList::reset() {
  3760. if (oldList) delete oldList;
  3761. oldList = 0;
  3762. if (currentList) delete currentList;
  3763. currentList = new vector<pair<int,int> >;
  3764. int counter = 0;
  3765. for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++) {
  3766. if ((*it)->hits) {
  3767. for(vector<Hit* >::iterator ith = (*it)->hits->begin(); ith != (*it)->hits->end(); ith++)
  3768. delete *ith;
  3769. delete (*it)->hits;
  3770. (*it)->hits = 0;
  3771. }
  3772. if ((*it)->candidates) {
  3773. for(vector<Candidate* >::iterator itc = (*it)->candidates->begin(); itc != (*it)->candidates->end(); itc++)
  3774. delete *itc;
  3775. delete (*it)->candidates;
  3776. (*it)->candidates = 0;
  3777. }
  3778. currentList->push_back(make_pair((*it)->id, counter++));
  3779. }
  3780. num_hits = 0;
  3781. num_switched = 0;
  3782. Bwins = 0;
  3783. Wwins = 0;
  3784. }
  3785. void GameList::tagsearch(int tag) throw(DBError) {
  3786. char sql[200];
  3787. if (!tag) return;
  3788. if (tag > 0) {
  3789. 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);
  3790. } else {
  3791. 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);
  3792. }
  3793. gisearch(sql, 1);
  3794. }
  3795. void GameList::setTag(int tag, int start, int end) throw(DBError) {
  3796. if (end==0) end = currentList->size();
  3797. if (start>end || end > (int)currentList->size()) return;
  3798. int rc = sqlite3_exec(db, "begin transaction", 0, 0, 0);
  3799. if (rc != SQLITE_OK) throw DBError();
  3800. for(int i = start; i < end; i++) {
  3801. if (getTags(i, tag).size()) continue;
  3802. char sql[200];
  3803. sprintf(sql, "insert into game_tags (game_id, tag_id) values (%d, %d)", (*all)[(*currentList)[i].second]->id, tag);
  3804. rc = sqlite3_exec(db, sql, 0, 0, 0);
  3805. if (rc != SQLITE_OK) throw DBError();
  3806. }
  3807. rc = sqlite3_exec(db, "commit", 0, 0, 0);
  3808. if (rc != SQLITE_OK) throw DBError();
  3809. }
  3810. void GameList::deleteTag(int tag, int i) throw(DBError) {
  3811. char sql[200];
  3812. if (i == -1) sprintf(sql, "delete from game_tags where tag_id=%d", tag);
  3813. else sprintf(sql, "delete from game_tags where game_id=%d and tag_id=%d", (*all)[(*currentList)[i].second]->id, tag);
  3814. int rc = sqlite3_exec(db, sql, 0, 0, 0);
  3815. if (rc != SQLITE_OK) throw DBError();
  3816. }
  3817. int gettags_callback(void *res, int argc, char **argv, char **azColName) {
  3818. if (!argc) return 1;
  3819. ((vector<int>*)res)->push_back(atoi(argv[0]));
  3820. return 0;
  3821. }
  3822. vector<int> GameList::getTags(int i, int tag) throw(DBError) {
  3823. vector<int> result;
  3824. char sql[200];
  3825. if (tag==0) sprintf(sql, "select tag_id from game_tags where game_id=%d", (*all)[(*currentList)[i].second]->id);
  3826. else sprintf(sql, "select tag_id from game_tags where game_id=%d and tag_id=%d", (*all)[(*currentList)[i].second]->id, tag);
  3827. int rc = sqlite3_exec(db, sql, gettags_callback, &result, 0);
  3828. if (rc != SQLITE_OK) throw DBError();
  3829. return result;
  3830. }
  3831. void GameList::insert_duplicate(int i1, int i2, vector<vector<int> >* dupl) {
  3832. int ii1 = get_current_index_CL(i1);
  3833. int ii2 = get_current_index_CL(i2);
  3834. // printf("insert_duplicate %d, %d\n", ii1, ii2);
  3835. if (ii1 == -1 || ii2 == -1) return;
  3836. bool inserted = false;
  3837. for(vector<vector<int> >::iterator it = dupl->begin(); it != dupl->end(); it++) {
  3838. vector<int>::iterator i = it->begin();
  3839. while(i != it->end() && *i != ii1 && *i != ii2) i++;
  3840. if (i == it->end()) continue;
  3841. int insert = ii1;
  3842. if (*i == ii1) insert = ii2;
  3843. while (i != it->end() && *i != insert) i++;
  3844. if (i == it->end()) it->push_back(insert);
  3845. sort(it->begin(), it->end());
  3846. inserted = true;
  3847. break;
  3848. }
  3849. if (!inserted) {
  3850. vector<int> new_list;
  3851. if (ii1 < ii2) {
  3852. new_list.push_back(ii1);
  3853. new_list.push_back(ii2);
  3854. } else {
  3855. new_list.push_back(ii2);
  3856. new_list.push_back(ii1);
  3857. }
  3858. dupl->push_back(new_list);
  3859. }
  3860. }
  3861. int GameList::find_duplicates(int bs, bool strict) throw(DBError) {
  3862. if (!currentList->size()) return 0; // this also deals with the case of an empty db
  3863. int bs_index = 0;
  3864. if (duplicates) delete duplicates;
  3865. duplicates = new vector<vector<int> >;
  3866. if (strict) {
  3867. vector<int>::iterator it = boardsizes.begin();
  3868. while (it != boardsizes.end() && *it != bs) {
  3869. bs_index++;
  3870. it++;
  3871. }
  3872. if (it == boardsizes.end()) {
  3873. return 0;
  3874. }
  3875. }
  3876. sort(currentList->begin(), currentList->end());
  3877. sqlite3_stmt *ppStmt=0;
  3878. char sql[200];
  3879. 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);
  3880. int rc = sqlite3_prepare(db, sql, -1, &ppStmt, 0);
  3881. if (rc != SQLITE_OK || ppStmt==0) throw DBError();
  3882. do {
  3883. rc = sqlite3_step(ppStmt);
  3884. if (rc != SQLITE_DONE && rc != SQLITE_ROW) throw DBError();
  3885. if (rc == SQLITE_ROW) {
  3886. if (!strict || ((Algo_finalpos*)algo_ps[20*bs_index+algo_finalpos])->equal(sqlite3_column_int(ppStmt, 0), sqlite3_column_int(ppStmt, 1)))
  3887. insert_duplicate(sqlite3_column_int(ppStmt, 0), sqlite3_column_int(ppStmt, 1), duplicates);
  3888. }
  3889. } while (rc == SQLITE_ROW);
  3890. rc = sqlite3_finalize(ppStmt);
  3891. if (rc != SQLITE_OK) throw DBError();
  3892. sort(currentList->begin(), currentList->end(), sndcomp);
  3893. return duplicates->size();
  3894. }
  3895. vector<int> GameList::retrieve_duplicates_VI(unsigned int i) {
  3896. if (i>=duplicates->size()) return vector<int>();
  3897. return (*duplicates)[i];
  3898. }
  3899. int* GameList::retrieve_duplicates_PI(unsigned int i) {
  3900. if (i>=duplicates->size()) return 0;
  3901. int* result = new int[(*duplicates)[i].size()+1];
  3902. int j = 0;
  3903. for(vector<int>::iterator it = (*duplicates)[i].begin(); it != (*duplicates)[i].end(); it++)
  3904. result[j++] = *it;
  3905. result[(*duplicates)[i].size()] = -1;
  3906. return result;
  3907. }
  3908. int GameList::get_current_index(int id, int* start) {
  3909. // use this in between start_sorted() and end_sorted() only!
  3910. int end = oldList->size();
  3911. int m = *start;
  3912. while (*start < end) {
  3913. m = (end+*start)/2;
  3914. if (id == (*oldList)[m].first) {
  3915. *start = m;
  3916. return m;
  3917. } else {
  3918. if (id < (*oldList)[m].first) end = m;
  3919. else *start = m+1;
  3920. }
  3921. }
  3922. return -1;
  3923. }
  3924. int GameList::get_current_index_CL(int id, int start) {
  3925. // use this in between start_sorted() and end_sorted() only!
  3926. int end = currentList->size();
  3927. int m = start;
  3928. while (start < end) {
  3929. m = (end+start)/2;
  3930. if (id == (*currentList)[m].first) return m;
  3931. else {
  3932. if (id < (*currentList)[m].first) end = m;
  3933. else start = m+1;
  3934. }
  3935. }
  3936. return -1;
  3937. }
  3938. void GameList::sigsearch(char* sig, int boardsize) throw(DBError) {
  3939. if (start_sorted() == 0) {
  3940. char* symmetrized_sig = 0;
  3941. if (boardsize) symmetrized_sig = symmetrize(sig, boardsize);
  3942. // char ssig[13];
  3943. // for(int i=0; i<12; i++) ssig[i] = symmetrized_sig[i];
  3944. // ssig[12] = 0;
  3945. // printf("ssig: %s\n", ssig);
  3946. string query = "select id from algo_signature_19 where signature like ? order by id";
  3947. // int rc = sqlite3_exec(db, query.c_str(), sigs_callback, this, 0);
  3948. sqlite3_stmt *ppStmt=0;
  3949. int rc = sqlite3_prepare(db, query.c_str(), -1, &ppStmt, 0);
  3950. if (rc != SQLITE_OK || ppStmt==0) throw DBError();
  3951. if (boardsize) rc = sqlite3_bind_blob(ppStmt, 1, symmetrized_sig, 12, SQLITE_TRANSIENT);
  3952. else rc = sqlite3_bind_blob(ppStmt, 1, sig, 12, SQLITE_TRANSIENT);
  3953. if (rc != SQLITE_OK || ppStmt==0) throw DBError();
  3954. do {
  3955. rc = sqlite3_step(ppStmt);
  3956. if (rc != SQLITE_DONE && rc != SQLITE_ROW) throw DBError();
  3957. if (rc == SQLITE_ROW) {
  3958. makeIndexHit(sqlite3_column_int(ppStmt, 0), 0);
  3959. }
  3960. } while (rc == SQLITE_ROW);
  3961. rc = sqlite3_finalize(ppStmt);
  3962. if (symmetrized_sig) delete [] symmetrized_sig;
  3963. if (rc != SQLITE_OK) throw DBError();
  3964. end_sorted();
  3965. }
  3966. }
  3967. int gis_callback(void *gl, int argc, char **argv, char **azColName) {
  3968. if (!argc) return 1;
  3969. ((GameList*)gl)->makeIndexHit(atoi(argv[0]), 0);
  3970. return 0;
  3971. }
  3972. void GameList::gisearch(char* sql, int complete) throw(DBError) {
  3973. if (start_sorted() == 0) {
  3974. string query;
  3975. if (!complete) query = "select id from games where ";
  3976. query += sql;
  3977. if (!complete) query += " order by id";
  3978. // printf("%s\n", query.c_str());
  3979. int rc = sqlite3_exec(db, query.c_str(), gis_callback, this, 0);
  3980. if( rc!=SQLITE_OK ) throw DBError();
  3981. end_sorted();
  3982. }
  3983. }
  3984. int GameList::numHits() {
  3985. return num_hits;
  3986. }
  3987. int GameList::size() {
  3988. return currentList->size();
  3989. }
  3990. string GameList::resultsStr(GameListEntry* gle) {
  3991. string result;
  3992. if (!gle->hits) return result;
  3993. char buf[20];
  3994. result.reserve(gle->hits->size()*8);
  3995. for(vector<Hit* >::iterator it = gle->hits->begin(); it != gle->hits->end(); it++) {
  3996. sprintf(buf, "%d", (*it)->pos->data[0]);
  3997. result += buf;
  3998. for(int i=1; i<(*it)->pos->length; i++) {
  3999. sprintf(buf, "-%d", (*it)->pos->data[i]);
  4000. result += buf;
  4001. }
  4002. if ((*it)->label[0] != NO_CONT) result += lookupLabel((*it)->label[0], (*it)->label[1]); // coordinates of Hit
  4003. if ((*it)->label[2]) result += "-, ";
  4004. else result += ", ";
  4005. }
  4006. return result;
  4007. }
  4008. char GameList::lookupLabel(char x, char y) {
  4009. if (!labels || !mrs_pattern || x < 0 || x >= mrs_pattern->sizeX || y < 0 || y >= mrs_pattern->sizeY) return '?';
  4010. return labels[x+y*mrs_pattern->sizeX];
  4011. }
  4012. Continuation GameList::lookupContinuation(char x, char y) {
  4013. if (!continuations || !mrs_pattern || x < 0 || x >= mrs_pattern->sizeX || y < 0 || y >= mrs_pattern->sizeY) return Continuation();
  4014. return continuations[x+y*mrs_pattern->sizeX];
  4015. }
  4016. vector<string> GameList::currentEntriesAsStrings(int start, int end) {
  4017. if (end==0) end = currentList->size();
  4018. vector<string> result;
  4019. if (start>end || end > (int)currentList->size()) return result;
  4020. for(int i=start; i<end; i++) {
  4021. result.push_back((*all)[(*currentList)[i].second]->gameInfoStr + resultsStr((*all)[(*currentList)[i].second]));
  4022. }
  4023. return result;
  4024. }
  4025. string GameList::currentEntryAsString(int i) {
  4026. if (i < 0 || i >= (int)currentList->size()) {
  4027. return "";
  4028. } else return (*all)[(*currentList)[i].second]->gameInfoStr + resultsStr((*all)[(*currentList)[i].second]);
  4029. }
  4030. int getpropcallback(void *s, int argc, char **argv, char **azColName) {
  4031. char** prop = (char**)s;
  4032. if (argc && argv[0]) {
  4033. *prop = new char[strlen(argv[0])+1];
  4034. strcpy(*prop, argv[0]);
  4035. }
  4036. return 0;
  4037. }
  4038. string GameList::getSignature(int i) throw(DBError) {
  4039. if (i < 0 || i >= (int)currentList->size()) {
  4040. // printf("index out of range\n");
  4041. return "";
  4042. }
  4043. int index = (*all)[(*currentList)[i].second]->id;
  4044. char* prop = 0;
  4045. char sql[200];
  4046. sprintf(sql, "select signature from algo_signature_19 where id = %d;", index);
  4047. // printf("%s\n", sql);
  4048. int rc = sqlite3_exec(db, sql, getpropcallback, &prop, 0);
  4049. if (rc != SQLITE_OK) throw DBError();
  4050. if (!prop) return "";
  4051. string prop_str(prop);
  4052. delete [] prop;
  4053. return prop_str;
  4054. }
  4055. string GameList::getSGF(int i) throw(DBError) {
  4056. if (!p_op->sgfInDB) return "";
  4057. return getCurrentProperty(i, "sgf");
  4058. }
  4059. string GameList::getCurrentProperty(int i, string tag) throw(DBError) {
  4060. if (i < 0 || i >= (int)currentList->size()) {
  4061. // printf("index out of range\n");
  4062. return "";
  4063. }
  4064. int index = (*all)[(*currentList)[i].second]->id;
  4065. char* prop = 0;
  4066. char sql[200];
  4067. sprintf(sql, "select %s from games where id = %d;", tag.c_str(), index);
  4068. // printf("%s\n", sql);
  4069. int rc = sqlite3_exec(db, sql, getpropcallback, &prop, 0);
  4070. if (rc != SQLITE_OK) throw DBError();
  4071. if (!prop) return "";
  4072. string prop_str(prop);
  4073. delete [] prop;
  4074. return prop_str;
  4075. }
  4076. void GameList::search(Pattern& pattern, SearchOptions* so) throw(DBError) {
  4077. if (mrs_pattern) delete mrs_pattern;
  4078. mrs_pattern = new Pattern(pattern);
  4079. if (searchOptions) delete searchOptions;
  4080. if (so) searchOptions = new SearchOptions(*so);
  4081. else searchOptions = new SearchOptions();
  4082. PatternList pl(pattern, searchOptions->fixedColor, searchOptions->nextMove);
  4083. vector<int>::iterator it = boardsizes.begin();
  4084. int bs_index = 0;
  4085. while (it != boardsizes.end() && *it != pattern.boardsize) {
  4086. bs_index++;
  4087. it++;
  4088. }
  4089. if (it == boardsizes.end()) {
  4090. delete searchOptions;
  4091. searchOptions = 0;
  4092. if (oldList) delete oldList;
  4093. oldList = 0;
  4094. if (currentList) delete currentList;
  4095. currentList = new vector<pair<int,int> >;
  4096. return;
  4097. }
  4098. if (boardsizes.size() != 1) {
  4099. char buf[20];
  4100. sprintf(buf, "sz = %d", pattern.boardsize);
  4101. gisearch(buf);
  4102. }
  4103. if (!readDBs) {
  4104. for(unsigned int a=0; a < 20*boardsizes.size(); a++) if (algo_ps[a]) algo_ps[a]->readDB(algo_dbs[a]);
  4105. readDBs = 1;
  4106. }
  4107. int hash_result = -1;
  4108. // FULL BOARD PATTERN?
  4109. if ((searchOptions->algos & ALGO_HASH_FULL) && pattern.sizeX == pattern.boardsize && pattern.sizeY == pattern.boardsize && algo_ps[algo_hash_full+20*bs_index]) {
  4110. 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]);
  4111. if (hash_result == 1) {
  4112. } else if (hash_result == 0) {
  4113. if (searchOptions->algos & ALGO_MOVELIST && algo_ps[algo_movelist+20*bs_index])
  4114. algo_ps[algo_movelist+20*bs_index]->search(pl, *this, *searchOptions);
  4115. }
  4116. }
  4117. if (hash_result == -1) { // not a full board pattern (or not hashable)
  4118. // CORNER PATTERN?
  4119. if ((searchOptions->algos & ALGO_HASH_CORNER) && pattern.sizeX >= 7 && pattern.sizeY >= 7 && algo_ps[algo_hash_corner+20*bs_index]) {
  4120. 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]);
  4121. if (hash_result == 0) {
  4122. if (searchOptions->algos & ALGO_MOVELIST && algo_ps[algo_movelist+20*bs_index])
  4123. algo_ps[algo_movelist+20*bs_index]->search(pl, *this, *searchOptions);
  4124. }
  4125. }
  4126. if (hash_result == -1) {
  4127. if (searchOptions->algos & ALGO_FINALPOS && algo_ps[algo_finalpos+20*bs_index])
  4128. algo_ps[algo_finalpos+20*bs_index]->search(pl, *this, *searchOptions);
  4129. if (searchOptions->algos & ALGO_MOVELIST && algo_ps[algo_movelist+20*bs_index])
  4130. algo_ps[algo_movelist+20*bs_index]->search(pl, *this, *searchOptions);
  4131. }
  4132. }
  4133. if (labels) delete [] labels;
  4134. labels = pl.sortContinuations();
  4135. if (continuations) delete [] continuations;
  4136. continuations = pl.continuations;
  4137. pl.continuations = new Continuation[pattern.sizeX*pattern.sizeY];
  4138. // FIXME: delete all candidate lists!
  4139. }
  4140. int GameList::plSize() {
  4141. return pl.size();
  4142. }
  4143. string GameList::plEntry(int i) {
  4144. if (i < 0 || i >= (int)pl.size()) return "";
  4145. else return pl[i];
  4146. }
  4147. int rpl_callback(void *pl, int argc, char **argv, char **azColName) {
  4148. if (!argc) return 1;
  4149. ((vector<string>*)pl)->push_back(string(argv[0]));
  4150. return 0;
  4151. }
  4152. void GameList::readPlayersList() throw(DBError) {
  4153. if (pl.size()) pl = vector<string>();
  4154. 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);
  4155. // we ignore possible errors, since the table might not yet exist
  4156. }
  4157. void GameList::createGamesDB() throw(DBError) {
  4158. SGFtags = p_op->SGFTagsAsStrings();
  4159. string sql1 = "create table GAMES ( ";
  4160. sql1 += "id integer primary key, ";
  4161. sql1 += "path text, ";
  4162. sql1 += "filename text, ";
  4163. sql1 += "pos integer default 0, ";
  4164. sql1 += "duplicate integer, ";
  4165. sql1 += "dbtree text, ";
  4166. sql1 += "date date";
  4167. sql_ins_rnp = "insert into games (path, filename, pos, dbtree, date";
  4168. string question_marks = "?,?,?,?,?";
  4169. if (p_op->sgfInDB) {
  4170. sql1 += ", sgf text";
  4171. sql_ins_rnp += ", sgf";
  4172. question_marks += ",?";
  4173. }
  4174. SGFtagsSize = SGFtags->size();
  4175. int ctr = 0;
  4176. posDT = posSZ = posWR = posBR = posHA = -1;
  4177. for(vector<string>::iterator it = SGFtags->begin(); it != SGFtags->end(); it++) {
  4178. sql1 += ", " + *it + " text";
  4179. sql_ins_rnp += ", " + *it;
  4180. question_marks += ",?";
  4181. if (*it == "DT") posDT = ctr;
  4182. if (*it == "SZ") posSZ = ctr;
  4183. if (*it == "WR") posWR = ctr;
  4184. if (*it == "BR") posBR = ctr;
  4185. if (*it == "HA") posHA = ctr;
  4186. ctr++;
  4187. }
  4188. if (posDT == -1) throw DBError();
  4189. if (posSZ == -1) {
  4190. posSZ = SGFtags->size();
  4191. SGFtags->push_back("SZ");
  4192. }
  4193. if (posWR == -1) {
  4194. posWR = SGFtags->size();
  4195. SGFtags->push_back("WR");
  4196. }
  4197. if (posBR == -1) {
  4198. posBR = SGFtags->size();
  4199. SGFtags->push_back("BR");
  4200. }
  4201. if (posHA == -1) {
  4202. posHA = SGFtags->size();
  4203. SGFtags->push_back("HA");
  4204. }
  4205. sql1 += ");";
  4206. sql_ins_rnp += ") values (" + question_marks + ");";
  4207. int rc = sqlite3_exec(db, sql1.c_str(), 0, 0, 0);
  4208. //if(rc != SQLITE_OK) throw DBError();
  4209. sql1 = "create table TAGS ( id integer primary key, name text, visible integer default 1 );";
  4210. rc = sqlite3_exec(db, sql1.c_str(), 0, 0, 0);
  4211. //if (rc != SQLITE_OK) throw DBError();
  4212. char sql[100];
  4213. sprintf(sql, "insert into TAGS (id, name) values (%d, '%d');", HANDI_TAG, HANDI_TAG);
  4214. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4215. // if (rc != SQLITE_OK) throw DBError();
  4216. sprintf(sql, "insert into TAGS (id, name) values (%d, '%d');", PROFESSIONAL_TAG, PROFESSIONAL_TAG);
  4217. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4218. // if (rc != SQLITE_OK) throw DBError();
  4219. sql1 = "create table GAME_TAGS ( id integer primary key, game_id integer, tag_id integer );";
  4220. rc = sqlite3_exec(db, sql1.c_str(), 0, 0, 0);
  4221. //if (rc != SQLITE_OK) throw DBError();
  4222. }
  4223. void GameList::start_processing(int PROCESSVARIATIONS) throw(DBError) {
  4224. // printf("enter start_processing %p\n", p_op);
  4225. delete_all_snapshots();
  4226. if (PROCESSVARIATIONS != -1) processVariations = PROCESSVARIATIONS;
  4227. else processVariations = p_op->processVariations;
  4228. readDBs = 0;
  4229. // printf("dt %d sz %d\n", posDT, posSZ);
  4230. int rc;
  4231. createGamesDB();
  4232. char* sql = "begin transaction;";
  4233. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4234. if (rc) { throw DBError(); }
  4235. rc = sqlite3_exec(algo_db1, sql, 0, 0, 0);
  4236. if (rc) { throw DBError(); }
  4237. rc = sqlite3_exec(algo_db2, sql, 0, 0, 0);
  4238. if (rc) { throw DBError(); }
  4239. current = 0;
  4240. for(unsigned int a=0; a < 20*boardsizes.size(); a++) {
  4241. if (algo_ps[a]) algo_ps[a]->initialize_process(algo_dbs[a]);
  4242. }
  4243. }
  4244. void GameList::finalize_processing() throw(DBError) {
  4245. for(unsigned int a=0; a<20*boardsizes.size(); a++)
  4246. if (algo_ps[a]) algo_ps[a]->finalize_process();
  4247. int rc = sqlite3_exec(db, "commit;", 0, 0, 0);
  4248. if (rc != SQLITE_OK) {
  4249. sqlite3_close(db);
  4250. db = 0;
  4251. throw DBError();
  4252. }
  4253. rc = sqlite3_exec(algo_db1, "commit;", 0, 0, 0);
  4254. if (rc != SQLITE_OK) {
  4255. sqlite3_close(algo_db1);
  4256. algo_db1 = 0;
  4257. throw DBError();
  4258. }
  4259. rc = sqlite3_exec(algo_db2, "commit;", 0, 0, 0);
  4260. if (rc != SQLITE_OK) {
  4261. sqlite3_close(algo_db2);
  4262. algo_db2 = 0;
  4263. throw DBError();
  4264. }
  4265. string sql = "update db_info set info = '";
  4266. for(vector<int>::iterator it = boardsizes.begin(); it != boardsizes.end(); it++) {
  4267. char buf[20];
  4268. sprintf(buf, "%d,", *it);
  4269. sql += buf;
  4270. }
  4271. sql += "' WHERE rowid = 2;";
  4272. rc = sqlite3_exec(db, sql.c_str(), 0, 0, 0);
  4273. if (rc != SQLITE_OK) throw DBError();
  4274. // sqlite3_close(db);
  4275. // db = 0;
  4276. readDBs = 0;
  4277. readDB();
  4278. delete SGFtags;
  4279. }
  4280. int GameList::process(const char* sgf, const char* path, const char* fn,
  4281. const char* DBTREE, int flags) throw(SGFError,DBError) {
  4282. process_results_vector.clear();
  4283. const char* dbtree = "";
  4284. if (DBTREE) dbtree = DBTREE;
  4285. Cursor* c = 0;
  4286. try {
  4287. c = new Cursor(sgf, 1); // parse sgf sloppily
  4288. } catch (SGFError) {
  4289. return 0;
  4290. }
  4291. Node* root = c->root->next;
  4292. int pos = 0;
  4293. while (root) {
  4294. current++;
  4295. int return_val = 0;
  4296. // if (!(current%1000)) {
  4297. // char* sql = "end transaction;";
  4298. // int rc = sqlite3_exec(db, sql, 0, 0, 0);
  4299. // if (rc) {
  4300. // sqlite3_close(db);
  4301. // db = 0;
  4302. // throw DBError();
  4303. // }
  4304. // sql = "begin transaction;";
  4305. // rc = sqlite3_exec(db, sql, 0, 0, 0);
  4306. // if (rc) {
  4307. // sqlite3_close(db);
  4308. // db = 0;
  4309. // throw DBError();
  4310. // }
  4311. // }
  4312. vector<string>* rootNodeProperties = parseRootNode(root, SGFtags);
  4313. // for(vector<string>::iterator rnp = rootNodeProperties->begin(); rnp != rootNodeProperties->end(); rnp++)
  4314. // printf("rnp %s\n", rnp->c_str());
  4315. // check board size
  4316. string sz = (*rootNodeProperties)[posSZ];
  4317. // printf("sz %s\n", sz.c_str());
  4318. if (sz=="") sz = "19";
  4319. int bs = atoi(sz.c_str());
  4320. if (bs < 1) {
  4321. return_val |= UNACCEPTABLE_BOARDSIZE;
  4322. process_results_vector.push_back(return_val);
  4323. delete rootNodeProperties;
  4324. root = root->down;
  4325. pos++;
  4326. continue;
  4327. }
  4328. int algo_offset = -1;
  4329. int bs_ctr = 0;
  4330. for(vector<int>::iterator it = boardsizes.begin(); it != boardsizes.end(); it++) {
  4331. if (*it == bs) {
  4332. algo_offset = bs_ctr;
  4333. break;
  4334. }
  4335. bs_ctr++;
  4336. }
  4337. if (algo_offset == -1) { // not found
  4338. boardsizes.push_back(bs);
  4339. addAlgos(bs);
  4340. algo_offset = algo_ps.size()/20 - 1;
  4341. // printf("algo_offset %d %d \n", algo_offset, algo_ps.size());
  4342. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++) {
  4343. // printf("a %d\n", a);
  4344. // printf("%p\n", algo_ps[a]);
  4345. if (algo_ps[a]) algo_ps[a]->initialize_process(algo_dbs[a]);
  4346. }
  4347. }
  4348. // parse DT tag
  4349. string dt = (*rootNodeProperties)[posDT];
  4350. // printf("dt %s\n", dt.c_str());
  4351. string date;
  4352. bool year_found = false;
  4353. int p = 0;
  4354. while (!year_found && p < (int)dt.size()) {
  4355. p = dt.find_first_of("0123456789", p);
  4356. if (p == (int)string::npos || p+4 > (int)dt.size() ) break;
  4357. else {
  4358. 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'));
  4359. if (year_found && (int)dt.find_first_of("0123456789", p+4) != p+4) { // success: found 4 digits in a row
  4360. date += dt.substr(p,4);
  4361. date += '-';
  4362. dt.erase(p,4);
  4363. } else {
  4364. while ('0' <= dt[p] && dt[p] <= '9') p++;
  4365. year_found = false;
  4366. continue;
  4367. }
  4368. }
  4369. }
  4370. if (!year_found) date = "0000-00-00";
  4371. else {
  4372. bool month_found = false;
  4373. p = 0;
  4374. while (!month_found && p < (int)dt.size()) {
  4375. p = dt.find_first_of("0123456789", p);
  4376. if (p == (int)string::npos || p+2 > (int)dt.size() ) break;
  4377. else {
  4378. month_found = ('0' <= dt[p] && dt[p] <= '9' && '0' <= dt[p+1] && dt[p+1] <= '9');
  4379. if (month_found && (int)dt.find_first_of("0123456789", p+2) != p+2) {
  4380. date += dt.substr(p,2);
  4381. date += '-';
  4382. dt.erase(p,2);
  4383. } else {
  4384. while ('0' <= dt[p] && dt[p] <= '9') p++;
  4385. month_found = false;
  4386. continue;
  4387. }
  4388. }
  4389. }
  4390. if (!month_found) date += "00-00";
  4391. else {
  4392. bool day_found = false;
  4393. p = 0;
  4394. while (!day_found && p < (int)dt.size()) {
  4395. p = dt.find_first_of("0123456789", p);
  4396. if (p == (int)string::npos || p+2 > (int)dt.size() ) break;
  4397. else {
  4398. day_found = ('0' <= dt[p] && dt[p] <= '9' && '0' <= dt[p+1] && dt[p+1] <= '9');
  4399. if (day_found && (int)dt.find_first_of("0123456789", p+2) != p+2) {
  4400. date += dt.substr(p,2);
  4401. } else {
  4402. while ('0' <= dt[p] && dt[p] <= '9') p++;
  4403. day_found = false;
  4404. continue;
  4405. }
  4406. }
  4407. }
  4408. if (!day_found) date += "00";
  4409. }
  4410. }
  4411. // printf("sql %s\n", sql_ins_rnp.c_str());
  4412. sqlite3_stmt *ppStmt=0;
  4413. int rc = sqlite3_prepare(db, sql_ins_rnp.c_str(), -1, &ppStmt, 0);
  4414. if (rc != SQLITE_OK || ppStmt==0) {
  4415. throw DBError(); // FIXME: catch busy error, (and/or throw DBError?)
  4416. }
  4417. int stmt_ctr = 1;
  4418. rc = sqlite3_bind_text(ppStmt, stmt_ctr++, path, -1, SQLITE_TRANSIENT);
  4419. if (rc != SQLITE_OK) throw DBError();
  4420. rc = sqlite3_bind_text(ppStmt, stmt_ctr++, fn, -1, SQLITE_TRANSIENT);
  4421. if (rc != SQLITE_OK) throw DBError();
  4422. rc = sqlite3_bind_int(ppStmt, stmt_ctr++, pos);
  4423. if (rc != SQLITE_OK) throw DBError();
  4424. rc = sqlite3_bind_text(ppStmt, stmt_ctr++, dbtree, -1, SQLITE_TRANSIENT);
  4425. if (rc != SQLITE_OK) throw DBError();
  4426. rc = sqlite3_bind_text(ppStmt, stmt_ctr++, date.c_str(), -1, SQLITE_TRANSIENT);
  4427. if (rc != SQLITE_OK) throw DBError();
  4428. if (p_op->sgfInDB) {
  4429. if (c->root->numChildren == 1) rc = sqlite3_bind_text(ppStmt, stmt_ctr++, sgf, -1, SQLITE_TRANSIENT);
  4430. else {
  4431. string s= "(";
  4432. s += c->outputVar(root);
  4433. s+= ")";
  4434. rc = sqlite3_bind_text(ppStmt, stmt_ctr++, s.c_str(), -1, SQLITE_TRANSIENT);
  4435. }
  4436. if (rc != SQLITE_OK) throw DBError();
  4437. }
  4438. for(int i=0; i < SGFtagsSize; i++) {
  4439. rc = sqlite3_bind_text(ppStmt, stmt_ctr++, (*rootNodeProperties)[i].c_str(), -1, SQLITE_TRANSIENT);
  4440. if (rc != SQLITE_OK) throw DBError();
  4441. }
  4442. rc = sqlite3_step(ppStmt);
  4443. if (rc != SQLITE_DONE) throw DBError();
  4444. rc = sqlite3_finalize(ppStmt);
  4445. if (rc != SQLITE_OK) throw DBError();
  4446. int game_id = sqlite3_last_insert_rowid(db);
  4447. // printf("play through the game\n");
  4448. bool commit = true;
  4449. Node* currentN = root;
  4450. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4451. if (algo_ps[a]) algo_ps[a]->newgame_process(game_id);
  4452. abstractBoard b = abstractBoard(bs);
  4453. int whichVar = 0;
  4454. stack<VarInfo> branchpoints;
  4455. while (currentN) {
  4456. // printf("nn\n");
  4457. bool caughtSGFError = false;
  4458. char* propValue = 0;
  4459. try {
  4460. // parse current node, watch out for B, W, AB, AW, AE properties
  4461. const char* s = currentN->SGFstring.c_str();
  4462. int lSGFstring = strlen(s);
  4463. int i = 0;
  4464. while (i < lSGFstring && s[i] != ';' && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  4465. i++;
  4466. if (i>=lSGFstring || s[i] != ';') throw SGFError();
  4467. i++;
  4468. while (i < lSGFstring) { // while parsing
  4469. while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
  4470. i++;
  4471. if (i >= lSGFstring) break;
  4472. char ID[30];
  4473. int IDindex = 0;
  4474. while (i < lSGFstring && s[i] != '[' && IDindex < 30) {
  4475. if (65 <= s[i] && s[i] <= 90)
  4476. ID[IDindex++] = s[i];
  4477. else if (!(97 <= s[i] && s[i] <= 122) && !(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) {
  4478. throw SGFError();
  4479. }
  4480. i++;
  4481. }
  4482. i++;
  4483. if (i >= lSGFstring || IDindex >= 30 || !IDindex) {
  4484. throw SGFError();
  4485. }
  4486. ID[IDindex] = 0; // found next property ID
  4487. bool IDrelevant= (!strcmp(ID,"B") || !strcmp(ID,"W") || !strcmp(ID,"AB") || !strcmp(ID,"AW") || !strcmp(ID,"AE"));
  4488. propValue = new char[100000];
  4489. int propValueIndex = 0;
  4490. int oldPropValueIndex = 0;
  4491. while (i < lSGFstring) { // while looking for property values of the current property
  4492. while (s[i] != ']' && i < lSGFstring) {
  4493. if (s[i] == '\\') i++;
  4494. if (!IDrelevant || s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n') {
  4495. i++;
  4496. continue;
  4497. }
  4498. if (97 <= s[i] && s[i] <= 96+bs) { // valid board coordinate?
  4499. propValue[propValueIndex++] = s[i];
  4500. if (propValueIndex > 99990) throw SGFError();
  4501. } else if (s[i] == 't') { ; // allow passes, but do not record them (we handle them a little sloppily here)
  4502. } else if (s[i] == ':') {
  4503. if (propValueIndex - oldPropValueIndex != 2)
  4504. throw SGFError();
  4505. char rect1 = 'a';
  4506. char rect2 = 'a';
  4507. i++;
  4508. while (i<lSGFstring && (s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n')) i++;
  4509. if (i >= lSGFstring) throw SGFError();
  4510. if (97 <= s[i] && s[i] <= 96+bs) // valid board coordinate?
  4511. rect1 = s[i];
  4512. else throw SGFError();
  4513. i++;
  4514. while (i<lSGFstring && (s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n')) i++;
  4515. if (i >= lSGFstring) throw SGFError();
  4516. if (97 <= s[i] && s[i] <= 96+bs) // valid board coordinate?
  4517. rect2 = s[i];
  4518. else throw SGFError();
  4519. i++;
  4520. while (i<lSGFstring && (s[i] == '\t' || s[i] == ' ' || s[i] == '\r' || s[i] == '\n')) i++;
  4521. if (i >= lSGFstring) throw SGFError();
  4522. if (s[i] == ']') {
  4523. char st1 = propValue[propValueIndex-2];
  4524. char st2 = propValue[propValueIndex-1];
  4525. propValueIndex -= 2; // do not want to have the first entry twice!
  4526. for(char x1 = st1; x1 <= rect1; x1++) {
  4527. for(char x2 = st2; x2 <= rect2; x2++) {
  4528. propValue[propValueIndex++] = x1;
  4529. propValue[propValueIndex++] = x2;
  4530. if (propValueIndex > 99990) throw SGFError();
  4531. }
  4532. }
  4533. oldPropValueIndex = propValueIndex;
  4534. break;
  4535. } else throw SGFError();
  4536. } else {
  4537. throw SGFError();
  4538. }
  4539. i++;
  4540. }
  4541. if (i >= lSGFstring) throw SGFError();
  4542. if (propValueIndex - oldPropValueIndex != 0 && propValueIndex - oldPropValueIndex != 2) {
  4543. throw SGFError();
  4544. }
  4545. oldPropValueIndex = propValueIndex;
  4546. i++;
  4547. while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) i++;
  4548. if (i >= lSGFstring || s[i] != '[') break; // end of node, or found next property
  4549. else i++; // s[i] == '[', so another property value follows.
  4550. }
  4551. int p_len = propValueIndex/2;
  4552. if (!propValueIndex) { // in particular, this happens if !IDrelevant
  4553. if (!strcmp(ID, "B") || !strcmp(ID, "W")) {
  4554. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4555. if (algo_ps[a]) algo_ps[a]->pass_process();
  4556. }
  4557. delete [] propValue;
  4558. propValue = 0;
  4559. continue;
  4560. }
  4561. if (!strcmp(ID, "B") || !strcmp(ID, "W")) {
  4562. char x = propValue[0]-97; // 97 == ord('a'), (0,0) <= (x,y) <= (bs-1, bs-1)
  4563. char y = propValue[1]-97;
  4564. if (!b.play(x, y, ID)) throw SGFError();
  4565. Move m = b.undostack.top();
  4566. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4567. if (algo_ps[a]) algo_ps[a]->move_process(m);
  4568. } else
  4569. if (!strcmp(ID, "AB")) {
  4570. for(int pp=0; pp < p_len; pp++) {
  4571. char x = propValue[2*pp]-97;
  4572. char y = propValue[2*pp+1]-97;
  4573. if (!b.play(x, y, "B")) throw SGFError();
  4574. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4575. if (algo_ps[a]) algo_ps[a]->AB_process(x, y);
  4576. }
  4577. } else
  4578. if (!strcmp(ID, "AW")) {
  4579. for(int pp=0; pp < p_len; pp++) {
  4580. char x = propValue[2*pp]-97;
  4581. char y = propValue[2*pp+1]-97;
  4582. if (!b.play(x, y, "W")) throw SGFError();
  4583. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4584. if (algo_ps[a]) algo_ps[a]->AW_process(x, y);
  4585. }
  4586. } else {
  4587. if (!strcmp(ID, "AE")) {
  4588. for(int pp=0; pp < p_len; pp++) {
  4589. char x = propValue[2*pp]-97;
  4590. char y = propValue[2*pp+1]-97;
  4591. char removed = b.getStatus(x,y);
  4592. if (removed==' ') throw SGFError();
  4593. b.remove(x, y);
  4594. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4595. if (algo_ps[a]) algo_ps[a]->AE_process(x, y, removed);
  4596. }
  4597. }
  4598. }
  4599. delete [] propValue;
  4600. propValue = 0;
  4601. }
  4602. } catch (SGFError) {
  4603. if (propValue) {
  4604. delete [] propValue;
  4605. propValue = 0;
  4606. }
  4607. return_val |= SGF_ERROR;
  4608. caughtSGFError = true;
  4609. if (flags & OMIT_GAMES_WITH_SGF_ERRORS) {
  4610. commit = false;
  4611. // (FIXME should exit from the loop here)
  4612. }
  4613. }
  4614. {
  4615. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4616. if (algo_ps[a]) algo_ps[a]->endOfNode_process();
  4617. }
  4618. if (processVariations && currentN->numChildren > 1) { // several variations start from this node;
  4619. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4620. if (algo_ps[a]) algo_ps[a]->branchpoint_process();
  4621. branchpoints.push(VarInfo(currentN, new abstractBoard(b), 0));
  4622. }
  4623. if (caughtSGFError) currentN = 0; // stop here with this branch
  4624. else currentN = currentN->next;
  4625. if (!currentN && branchpoints.size()) {
  4626. currentN = branchpoints.top().n;
  4627. b = abstractBoard(*branchpoints.top().b);
  4628. whichVar = branchpoints.top().i;
  4629. branchpoints.pop();
  4630. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4631. if (algo_ps[a]) algo_ps[a]->endOfVariation_process();
  4632. if (whichVar+2 < currentN->numChildren) {
  4633. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++)
  4634. if (algo_ps[a]) algo_ps[a]->branchpoint_process();
  4635. branchpoints.push(VarInfo(currentN, new abstractBoard(b), whichVar+1));
  4636. }
  4637. currentN = currentN->next;
  4638. for(int vi=0; vi < whichVar+1; vi++) currentN = currentN->down;
  4639. }
  4640. } // while
  4641. {
  4642. // check for duplicates (if desired)
  4643. bool is_duplicate = false;
  4644. if (flags & (CHECK_FOR_DUPLICATES|CHECK_FOR_DUPLICATES_STRICT)) {
  4645. char* sig = ((Algo_signature*)algo_ps[20*algo_offset])->get_current_signature();
  4646. vector<int> all_duplicates = ((Algo_signature*)algo_ps[20*algo_offset])->search_signature(sig);
  4647. if (all_duplicates.size()) {
  4648. // printf("dupl %d\n", all_duplicates.size());
  4649. is_duplicate = true;
  4650. if ((flags & CHECK_FOR_DUPLICATES_STRICT) && (p_op->algos & ALGO_FINALPOS)) {
  4651. vector<int>::iterator d_it = all_duplicates.begin();
  4652. while (d_it != all_duplicates.end() && !((Algo_finalpos*)algo_ps[20*algo_offset + algo_finalpos])->equals_current(*d_it))
  4653. d_it++;
  4654. if (d_it == all_duplicates.end()) is_duplicate = false;
  4655. }
  4656. if (is_duplicate) {
  4657. return_val |= IS_DUPLICATE;
  4658. if (flags & OMIT_DUPLICATES) commit = false;
  4659. }
  4660. }
  4661. delete [] sig;
  4662. }
  4663. if (commit) {
  4664. // evaluate tags
  4665. if ((*rootNodeProperties)[posHA] != "") { // handicap game
  4666. char sql[100];
  4667. sprintf(sql, "insert into GAME_TAGS (game_id, tag_id) values (%d, %d);", game_id, HANDI_TAG);
  4668. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4669. if (rc != SQLITE_OK) throw DBError();
  4670. }
  4671. if ((*rootNodeProperties)[posWR].find('p') != string::npos ||
  4672. (*rootNodeProperties)[posBR].find('p') != string::npos) {
  4673. // at least one of the players is professional
  4674. char sql[100];
  4675. sprintf(sql, "insert into GAME_TAGS (game_id, tag_id) values (%d, %d);", game_id, PROFESSIONAL_TAG);
  4676. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4677. if (rc != SQLITE_OK) throw DBError();
  4678. }
  4679. } else {
  4680. return_val |= NOT_INSERTED_INTO_DB;
  4681. char sql[200];
  4682. sprintf(sql, "delete from GAMES where id=%d", game_id);
  4683. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4684. if (rc) printf("ouch %d\n", rc);
  4685. }
  4686. for(int a=20*algo_offset; a < 20*(algo_offset+1); a++) {
  4687. // printf("endgame %d\n", a);
  4688. if (algo_ps[a]) algo_ps[a]->endgame_process(commit);
  4689. }
  4690. }
  4691. delete rootNodeProperties;
  4692. process_results_vector.push_back(return_val);
  4693. root = root->down;
  4694. pos++;
  4695. }
  4696. delete c;
  4697. return process_results_vector.size();
  4698. }
  4699. int GameList::process_results(unsigned int i) {
  4700. if (i<0 || i>=process_results_vector.size()) return INDEX_OUT_OF_RANGE;
  4701. return process_results_vector[i];
  4702. }
  4703. int GameList::snapshot() throw(DBError) {
  4704. // return a handle to a snapshot stored in the main GameList db
  4705. // the snapshot contains copies of
  4706. // - orderby, format1, format2
  4707. // - currentList
  4708. // - all hits in the GameListEntry's of currentList
  4709. // - pattern, labels, continuations, num_hits, num_switched, Bwins, Wwins
  4710. SnapshotVector snapshot;
  4711. snapshot.pb_string(orderby);
  4712. snapshot.pb_string(format1);
  4713. snapshot.pb_string(format2);
  4714. snapshot.pb_int(currentList->size());
  4715. for(vector<pair<int,int> >::iterator it = currentList->begin(); it != currentList->end(); it++) {
  4716. snapshot.pb_int(it->first);
  4717. snapshot.pb_int(it->second);
  4718. vector<Hit* >* hits = (*all)[it->second]->hits;
  4719. snapshot.pb_int(hits->size());
  4720. for (vector<Hit* >::iterator it_h = hits->begin(); it_h != hits->end(); it_h++) {
  4721. (*it_h)->to_snv(snapshot);
  4722. }
  4723. }
  4724. if (mrs_pattern) {
  4725. snapshot.pb_char(1);
  4726. mrs_pattern->to_snv(snapshot);
  4727. } else snapshot.pb_char(0);
  4728. if (searchOptions) {
  4729. snapshot.pb_char(1);
  4730. searchOptions->to_snv(snapshot);
  4731. } else snapshot.pb_char(0);
  4732. if (mrs_pattern && labels && continuations) {
  4733. snapshot.pb_char(1);
  4734. snapshot.pb_charp(labels, mrs_pattern->sizeX * mrs_pattern->sizeY);
  4735. for(int i=0; i<mrs_pattern->sizeX * mrs_pattern->sizeY; i++) continuations[i].to_snv(snapshot);
  4736. } else snapshot.pb_char(0);
  4737. snapshot.pb_int(num_hits);
  4738. snapshot.pb_int(num_switched);
  4739. snapshot.pb_int(Bwins);
  4740. snapshot.pb_int(Wwins);
  4741. // insert snapshot into database
  4742. sqlite3_stmt *ppStmt=0;
  4743. int rc = sqlite3_prepare(db, "insert into snapshots (data) values (?)", -1, &ppStmt, 0);
  4744. if (rc != SQLITE_OK || ppStmt==0) throw DBError();
  4745. char* snchp = snapshot.to_charp();
  4746. rc = sqlite3_bind_blob(ppStmt, 1, snchp, snapshot.size(), SQLITE_TRANSIENT);
  4747. delete [] snchp;
  4748. if (rc != SQLITE_OK) throw DBError();
  4749. rc = sqlite3_step(ppStmt);
  4750. if (rc != SQLITE_DONE) throw DBError();
  4751. rc = sqlite3_finalize(ppStmt);
  4752. if (rc != SQLITE_OK) throw DBError();
  4753. return sqlite3_last_insert_rowid(db);
  4754. }
  4755. void GameList::restore(int handle, bool del) throw(DBError) {
  4756. // restore the state of the GameList associated with handle
  4757. // retrieve info associated with handle from db
  4758. char* sn = 0;
  4759. int sn_size = 0;
  4760. sqlite3_stmt *ppStmt=0;
  4761. int rc = sqlite3_prepare(db, "select data from snapshots where rowid = ?", -1, &ppStmt, 0);
  4762. if (rc != SQLITE_OK || ppStmt==0) {
  4763. throw DBError();
  4764. }
  4765. rc = sqlite3_bind_int(ppStmt, 1, handle);
  4766. if (rc != SQLITE_OK) throw DBError();
  4767. rc = sqlite3_step(ppStmt);
  4768. if (rc == SQLITE_ROW) {
  4769. sn = (char*)sqlite3_column_blob(ppStmt, 0);
  4770. sn_size = sqlite3_column_bytes(ppStmt, 0);
  4771. } else throw DBError();
  4772. SnapshotVector snapshot(sn, sn_size);
  4773. // parse info
  4774. string ob = snapshot.retrieve_string();
  4775. string f1 = snapshot.retrieve_string();
  4776. string f2 = snapshot.retrieve_string();
  4777. if (ob != orderby || f1 != format1 || f2 != format2) resetFormat();
  4778. if (oldList) delete oldList;
  4779. oldList = 0;
  4780. if (currentList) delete currentList;
  4781. currentList = new vector<pair<int,int> >;
  4782. for(vector<GameListEntry* >::iterator it = all->begin(); it != all->end(); it++) {
  4783. if ((*it)->hits) {
  4784. for(vector<Hit* >::iterator ith = (*it)->hits->begin(); ith != (*it)->hits->end(); ith++)
  4785. delete *ith;
  4786. delete (*it)->hits;
  4787. (*it)->hits = 0;
  4788. }
  4789. if ((*it)->candidates) {
  4790. for(vector<Candidate* >::iterator itc = (*it)->candidates->begin(); itc != (*it)->candidates->end(); itc++)
  4791. delete *itc;
  4792. delete (*it)->candidates;
  4793. (*it)->candidates = 0;
  4794. }
  4795. }
  4796. int cl_size = snapshot.retrieve_int();
  4797. for(int i=0; i<cl_size; i++) {
  4798. int i1 = snapshot.retrieve_int();
  4799. int i2 = snapshot.retrieve_int();
  4800. currentList->push_back(make_pair(i1, i2));
  4801. // if ((*currentList)[currentList->size()-1].second >= all->size()) printf("ouch %d\n", (*currentList)[currentList->size()-1].second);
  4802. (*all)[(*currentList)[currentList->size()-1].second]->hits_from_snv(snapshot);
  4803. }
  4804. if (mrs_pattern) delete mrs_pattern;
  4805. if (snapshot.retrieve_char()) mrs_pattern = new Pattern(snapshot);
  4806. else mrs_pattern = 0;
  4807. if (searchOptions) delete searchOptions;
  4808. if (snapshot.retrieve_char()) searchOptions = new SearchOptions(snapshot);
  4809. else searchOptions = 0;
  4810. if (labels) delete [] labels;
  4811. if (continuations) delete [] continuations; // FIXME check (cf. ~GameList)
  4812. if (snapshot.retrieve_char()) {
  4813. labels = snapshot.retrieve_charp();
  4814. continuations = new Continuation[mrs_pattern->sizeX * mrs_pattern->sizeY];
  4815. for(int i=0; i<mrs_pattern->sizeX * mrs_pattern->sizeY; i++)
  4816. continuations[i].from_snv(snapshot);
  4817. } else {
  4818. labels = 0;
  4819. continuations = 0;
  4820. }
  4821. num_hits = snapshot.retrieve_int();
  4822. num_switched = snapshot.retrieve_int();
  4823. Bwins = snapshot.retrieve_int();
  4824. Wwins = snapshot.retrieve_int();
  4825. rc = sqlite3_finalize(ppStmt);
  4826. if (rc != SQLITE_OK) throw DBError();
  4827. if (del) { // delete snapshot from db
  4828. char sql[100];
  4829. sprintf(sql, "delete from snapshots where rowid = %d", handle);
  4830. rc = sqlite3_exec(db, sql, 0, 0, 0);
  4831. if (rc != SQLITE_OK) throw DBError();
  4832. }
  4833. }
  4834. void GameList::delete_snapshot(int handle) throw(DBError) {
  4835. char sql[100];
  4836. sprintf(sql, "delete from snapshots where rowid = %d", handle);
  4837. int rc = sqlite3_exec(db, sql, 0, 0, 0);
  4838. if (rc != SQLITE_OK) throw DBError();
  4839. }
  4840. void GameList::delete_all_snapshots() throw(DBError) {
  4841. int rc = sqlite3_exec(db, "delete from snapshots", 0, 0, 0);
  4842. if (rc != SQLITE_OK) throw DBError();
  4843. }
  4844. VarInfo::VarInfo(Node* N, abstractBoard* B, int I) {
  4845. n = N;
  4846. b = B;
  4847. i = I;
  4848. }
  4849. VarInfo::VarInfo(const VarInfo& v) {
  4850. n = v.n;
  4851. b = new abstractBoard(*v.b);
  4852. i = v.i;
  4853. }
  4854. VarInfo::~VarInfo() {
  4855. delete b;
  4856. }