PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/kombilo/search.cpp

https://github.com/eped/eidogo
C++ | 5380 lines | 4166 code | 524 blank | 690 comment | 1777 complexity | 0e1bbdbcb1b0e8ea2618a8bcc476aa52 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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->contL

Large files files are truncated, but you can click here to view the full file