2 // part of libkombilo, http://www.u-go.net/kombilo/
4 // Copyright (c) 2006-7 Ulrich Goertz <u@g0ertz.de>
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 // this software and associated documentation files (the "Software"), to deal in
8 // the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 // of the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include "sgfparser.h"
25 #include "abstractboard.h"
46 SnapshotVector::SnapshotVector() : vector
<unsigned char>() {
50 SnapshotVector::SnapshotVector(char* c
, int size
) : vector
<unsigned char>() {
51 for(int i
=0; i
<size
; i
++) push_back(c
[i
]);
55 void SnapshotVector::pb_int(int d
) {
56 for(int i
= 0; i
< 4; i
++) {
57 push_back((unsigned char)(d
% 256));
62 void SnapshotVector::pb_charp(char* c
, int size
) {
64 for(int i
=0; i
<size
; i
++) push_back(c
[i
]);
67 void SnapshotVector::pb_intp(int* p
, int size
) {
69 for(int i
=0; i
<size
; i
++) pb_int(p
[i
]);
72 void SnapshotVector::pb_string(string s
) {
74 for(unsigned int i
=0; i
<s
.size(); i
++) push_back(s
[i
]);
78 void SnapshotVector::pb_char(char c
) {
82 int SnapshotVector::retrieve_int() {
84 for(int i
=0; i
<4; i
++) {
85 result
+= *current
<< (i
*8);
91 int* SnapshotVector::retrieve_intp() {
92 int sz
= retrieve_int();
93 int* result
= new int[sz
];
94 for(int i
=0; i
<sz
; i
++)
95 result
[i
] = retrieve_int();
99 char SnapshotVector::retrieve_char() {
105 char* SnapshotVector::retrieve_charp() {
106 int sz
= retrieve_int();
107 char* result
= new char[sz
];
108 for(int i
=0; i
<sz
; i
++) {
109 result
[i
] = *current
;
115 string
SnapshotVector::retrieve_string() {
116 char* cp
= retrieve_charp();
122 char* SnapshotVector::to_charp() {
123 char* result
= new char[size()];
125 for(SnapshotVector::iterator it
= begin(); it
!= end(); it
++) result
[counter
++] = *it
;
130 PatternError::PatternError() {}
132 Continuation::Continuation() {
143 void Continuation::from_snv(SnapshotVector
& snv
) {
144 B
= snv
.retrieve_int();
145 W
= snv
.retrieve_int();
146 tB
= snv
.retrieve_int();
147 tW
= snv
.retrieve_int();
148 wB
= snv
.retrieve_int();
149 lB
= snv
.retrieve_int();
150 wW
= snv
.retrieve_int();
151 lW
= snv
.retrieve_int();
154 void Continuation::to_snv(SnapshotVector
& snv
) {
165 Symmetries::Symmetries(char sX
, char sY
) {
168 dataX
= new char[sizeX
*sizeY
];
169 dataY
= new char[sizeX
*sizeY
];
170 dataCS
= new char[sizeX
*sizeY
];
171 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
178 Symmetries::~Symmetries() {
184 Symmetries::Symmetries(const Symmetries
& s
) {
187 dataX
= new char[sizeX
*sizeY
];
188 dataY
= new char[sizeX
*sizeY
];
189 dataCS
= new char[sizeX
*sizeY
];
190 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
191 dataX
[i
] = s
.dataX
[i
];
192 dataY
[i
] = s
.dataY
[i
];
193 dataCS
[i
] = s
.dataCS
[i
];
197 Symmetries
& Symmetries::operator=(const Symmetries
& s
) {
204 dataX
= new char[sizeX
*sizeY
];
205 dataY
= new char[sizeX
*sizeY
];
206 dataCS
= new char[sizeX
*sizeY
];
207 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
208 dataX
[i
] = s
.dataX
[i
];
209 dataY
[i
] = s
.dataY
[i
];
210 dataCS
[i
] = s
.dataCS
[i
];
216 void Symmetries::set(char i
, char j
, char k
, char l
, char cs
) throw(PatternError
) {
217 if (0 <= i
&& i
< sizeX
&& 0 <= j
&& j
< sizeY
) {
218 dataX
[i
+ j
*sizeX
] = k
;
219 dataY
[i
+ j
*sizeX
] = l
;
220 dataCS
[i
+ j
*sizeX
] = cs
;
222 else throw PatternError();
225 char Symmetries::getX(char i
, char j
) throw(PatternError
) {
226 if (0 <= i
&& i
< sizeX
&& 0 <= j
&& j
< sizeY
) return dataX
[i
+ j
*sizeX
];
227 else throw PatternError();
231 char Symmetries::getY(char i
, char j
) throw(PatternError
) {
232 if (0 <= i
&& i
< sizeX
&& 0 <= j
&& j
< sizeY
) return dataY
[i
+ j
*sizeX
];
233 else throw PatternError();
237 char Symmetries::getCS(char i
, char j
) throw(PatternError
) {
238 if (0 <= i
&& i
< sizeX
&& 0 <= j
&& j
< sizeY
) return dataCS
[i
+ j
*sizeX
];
239 else throw PatternError();
243 char Symmetries::has_key(char i
, char j
) throw(PatternError
) {
244 if (0 <= i
&& i
< sizeX
&& 0 <= j
&& j
< sizeY
) {
245 if (dataX
[i
+ j
*sizeX
] == -1) return 0;
248 else throw PatternError();
253 // ----------- class Pattern -----------------------------------------------
255 int Pattern::operator==(const Pattern
& p
) {
256 if (boardsize
!= p
.boardsize
) return 0;
257 if (sizeX
!= p
.sizeX
|| sizeY
!= p
.sizeY
) return 0;
258 if (left
!= p
.left
|| right
!= p
.right
|| top
!= p
.top
|| bottom
!= p
.bottom
) return 0;
259 for(int i
=0; i
< sizeX
*sizeY
; i
++)
260 if (initialPos
[i
] != p
.initialPos
[i
]) return 0;
261 if (contList
!= p
.contList
) return 0;
266 char Pattern::BW2XO(char c
) {
267 if (c
== 'B') return 'X';
268 if (c
== 'W') return 'O';
272 char Pattern::getInitial(int i
, int j
) {
273 return initialPos
[i
+ sizeX
*j
];
276 char Pattern::getFinal(int i
, int j
) {
277 return finalPos
[i
+ sizeX
*j
];
293 Pattern::Pattern(int type
, int BOARDSIZE
, int sX
, int sY
, char* iPos
, char* CONTLABELS
) {
298 boardsize
= BOARDSIZE
;
300 contLabels
= new char[sizeX
* sizeY
];
301 for(int i
=0; i
<sizeX
*sizeY
; i
++) contLabels
[i
] = CONTLABELS
[i
];
302 } else contLabels
= 0;
304 if (type
== CORNER_NW_PATTERN
|| type
== FULLBOARD_PATTERN
) {
305 left
= right
= top
= bottom
= 0;
306 } else if (type
== CORNER_NE_PATTERN
) {
308 left
= right
= boardsize
- sizeX
;
309 } else if (type
== CORNER_SE_PATTERN
) {
310 top
= bottom
= boardsize
- sizeY
;
311 left
= right
= boardsize
- sizeX
;
312 } else if (type
== CORNER_SW_PATTERN
) {
313 top
= bottom
= boardsize
- sizeY
;
315 } else if (type
== SIDE_N_PATTERN
) {
318 right
= boardsize
-1 - sizeX
;
319 } else if (type
== SIDE_E_PATTERN
) {
320 left
= right
= boardsize
- sizeX
;
322 bottom
= boardsize
-1 - sizeY
;
323 } else if (type
== SIDE_W_PATTERN
) {
326 bottom
= boardsize
-1 - sizeY
;
327 } else if (type
== SIDE_S_PATTERN
) {
328 top
= bottom
= boardsize
- sizeY
;
330 right
= boardsize
-1 - sizeX
;
331 } else if (type
== CENTER_PATTERN
) {
333 right
= boardsize
-1 - sizeX
;
334 bottom
= boardsize
-1 - sizeY
;
337 initialPos
= new char[sizeX
* sizeY
];
338 finalPos
= new char[sizeX
*sizeY
];
339 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
340 initialPos
[i
] = iPos
[i
];
341 finalPos
[i
] = iPos
[i
];
345 Pattern::Pattern(int type
, int BOARDSIZE
, int sX
, int sY
,
346 char* iPos
, vector
<MoveNC
> CONTLIST
, char* CONTLABELS
) {
351 boardsize
= BOARDSIZE
;
353 contLabels
= new char[sizeX
* sizeY
];
354 for(int i
=0; i
<sizeX
*sizeY
; i
++) contLabels
[i
] = CONTLABELS
[i
];
355 } else contLabels
= 0;
357 if (type
== CORNER_NW_PATTERN
|| type
== FULLBOARD_PATTERN
) {
358 left
= right
= top
= bottom
= 0;
359 } else if (type
== CORNER_NE_PATTERN
) {
361 left
= right
= boardsize
- sizeX
;
362 } else if (type
== CORNER_SE_PATTERN
) {
363 top
= bottom
= boardsize
- sizeY
;
364 left
= right
= boardsize
- sizeX
;
365 } else if (type
== CORNER_SW_PATTERN
) {
366 top
= bottom
= boardsize
- sizeY
;
368 } else if (type
== SIDE_N_PATTERN
) {
371 right
= boardsize
-1 - sizeX
;
372 } else if (type
== SIDE_E_PATTERN
) {
373 left
= right
= boardsize
- sizeX
;
375 bottom
= boardsize
-1 - sizeY
;
376 } else if (type
== SIDE_W_PATTERN
) {
379 bottom
= boardsize
-1 - sizeY
;
380 } else if (type
== SIDE_S_PATTERN
) {
381 top
= bottom
= boardsize
- sizeY
;
383 right
= boardsize
-1 - sizeX
;
384 } else if (type
== CENTER_PATTERN
) {
386 right
= boardsize
-1 - sizeX
;
387 bottom
= boardsize
-1 - sizeY
;
390 initialPos
= new char[sizeX
* sizeY
];
391 finalPos
= new char[sizeX
*sizeY
];
392 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
393 initialPos
[i
] = iPos
[i
];
394 finalPos
[i
] = iPos
[i
];
400 Pattern::Pattern(int le
, int ri
, int to
, int bo
, int BOARDSIZE
, int sX
, int sY
,
401 char* iPos
, const vector
<MoveNC
>& CONTLIST
, char* CONTLABELS
) throw(PatternError
) {
402 // check whether anchor rectangle is valid
403 if (le
< 0 || ri
+sX
> BOARDSIZE
|| to
< 0 || bo
+sY
> BOARDSIZE
|| ri
< le
|| bo
< to
) throw PatternError();
412 boardsize
= BOARDSIZE
;
417 contLabels
= new char[sizeX
* sizeY
];
418 for(int i
=0; i
<sizeX
*sizeY
; i
++) contLabels
[i
] = CONTLABELS
[i
];
419 } else contLabels
= 0;
421 initialPos
= new char[sizeX
* sizeY
];
422 finalPos
= new char[sizeX
*sizeY
];
423 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
424 initialPos
[i
] = iPos
[i
];
425 finalPos
[i
] = iPos
[i
];
431 Pattern::Pattern(SnapshotVector
& snv
) {
432 flip
= snv
.retrieve_int();
433 colorSwitch
= snv
.retrieve_int();
434 left
= snv
.retrieve_int();
435 right
= snv
.retrieve_int();
436 top
= snv
.retrieve_int();
437 bottom
= snv
.retrieve_int();
438 boardsize
= snv
.retrieve_int();
439 sizeX
= snv
.retrieve_int();
440 sizeY
= snv
.retrieve_int();
441 if (snv
.retrieve_char()) { // contLabels?
442 contLabels
= snv
.retrieve_charp();
443 } else contLabels
= 0;
444 initialPos
= snv
.retrieve_charp();
445 finalPos
= snv
.retrieve_charp();
447 int size
= snv
.retrieve_int();
448 for(int i
=0; i
<size
; i
++)
449 contList
.push_back(MoveNC(snv
.retrieve_char(), snv
.retrieve_char(), snv
.retrieve_char())); // x, y, color
452 void Pattern::to_snv(SnapshotVector
& snv
) {
454 snv
.pb_int(colorSwitch
);
459 snv
.pb_int(boardsize
);
464 snv
.pb_charp(contLabels
, sizeX
*sizeY
);
465 } else snv
.pb_char(0);
466 snv
.pb_charp(initialPos
, sizeX
*sizeY
);
467 snv
.pb_charp(finalPos
, sizeX
*sizeY
);
468 snv
.pb_int(contList
.size());
469 for(vector
<MoveNC
>::iterator it
= contList
.begin(); it
!= contList
.end(); it
++) {
472 snv
.pb_char(it
->color
);
476 Pattern::~Pattern() {
477 if (initialPos
) delete [] initialPos
;
478 if (finalPos
) delete [] finalPos
;
479 if (contLabels
) delete [] contLabels
;
482 Pattern::Pattern(const Pattern
& p
) {
487 boardsize
= p
.boardsize
;
491 colorSwitch
= p
.colorSwitch
;
493 initialPos
= new char[sizeX
*sizeY
];
494 finalPos
= new char[sizeX
*sizeY
];
495 if (p
.contLabels
) contLabels
= new char[sizeX
*sizeY
];
497 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
498 initialPos
[i
] = p
.initialPos
[i
];
499 finalPos
[i
] = p
.finalPos
[i
];
500 if (p
.contLabels
) contLabels
[i
] = p
.contLabels
[i
];
502 contList
= p
.contList
;
505 Pattern
& Pattern::operator=(const Pattern
& p
) {
511 boardsize
= p
.boardsize
;
515 colorSwitch
= p
.colorSwitch
;
517 if (initialPos
) delete [] initialPos
;
518 if (finalPos
) delete [] finalPos
;
519 if (contLabels
) delete [] contLabels
;
521 initialPos
= new char[sizeX
*sizeY
];
522 finalPos
= new char[sizeX
*sizeY
];
523 if (p
.contLabels
) contLabels
= new char[sizeX
*sizeY
];
525 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
526 initialPos
[i
] = p
.initialPos
[i
];
527 finalPos
[i
] = p
.finalPos
[i
];
528 if (p
.contLabels
) contLabels
[i
] = p
.contLabels
[i
];
530 contList
= p
.contList
;
536 Pattern
& Pattern::copy(const Pattern
& p
) {
542 boardsize
= p
.boardsize
;
546 colorSwitch
= p
.colorSwitch
;
548 if (initialPos
) delete [] initialPos
;
549 if (finalPos
) delete [] finalPos
;
551 initialPos
= new char[sizeX
*sizeY
];
552 finalPos
= new char[sizeX
*sizeY
];
553 if (p
.contLabels
) contLabels
= new char[sizeX
*sizeY
];
555 for(int i
=0; i
<sizeX
*sizeY
; i
++) {
556 initialPos
[i
] = p
.initialPos
[i
];
557 finalPos
[i
] = p
.finalPos
[i
];
558 if (p
.contLabels
) contLabels
[i
] = p
.contLabels
[i
];
560 contList
= p
.contList
;
565 string
Pattern::printPattern() {
568 sprintf(buf
, "boardsize: %d, area: %d, %d, %d, %d\nsize: %d, %d\n", boardsize
, left
, right
, top
, bottom
, sizeX
, sizeY
);
570 for(int i
=0; i
<sizeY
; i
++) {
571 for(int j
=0; j
<sizeX
; j
++) {
572 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
];
582 int Pattern::flipsX(int i
, int x
, int y
, int XX
, int YY
) {
584 if (i
==1) return XX
-x
;
586 if (i
==3) return XX
-x
;
588 if (i
==5) return YY
-y
;
590 if (i
==7) return YY
-y
;
594 int Pattern::flipsY(int i
, int x
, int y
, int XX
, int YY
) {
597 if (i
==2) return YY
-y
;
598 if (i
==3) return YY
-y
;
601 if (i
==6) return XX
-x
;
602 if (i
==7) return XX
-x
;
607 int Pattern::PatternInvFlip(int i
) {
608 if (i
== 5) return 6;
609 if (i
== 6) return 5;
613 const int composition_table
[] = {
614 0, 1, 2, 3, 4, 5, 6, 7,
615 1, 0, 3, 2, 5, 4, 7, 6,
616 2, 3, 0, 1, 6, 7, 4, 5,
617 3, 2, 1, 0, 7, 6, 5, 4,
618 4, 6, 5, 7, 0, 2, 1, 3,
619 5, 7, 4, 6, 1, 3, 0, 2,
620 6, 4, 7, 5, 2, 0, 3, 1,
621 7, 5, 6, 4, 3, 1, 2, 0 };
623 int Pattern::compose_flips(int i
, int j
) {
624 return composition_table
[j
+8*i
];
627 PatternList::PatternList(Pattern
& p
, int fColor
, int nMove
) throw(PatternError
) {
632 flipTable
= new int[16];
633 for(int i
=0; i
<16; i
++) flipTable
[i
] = -1; // (patternList() relies on this)
636 continuations
= new Continuation
[pattern
.sizeX
* pattern
.sizeY
];
639 PatternList::~PatternList() {
640 delete [] continuations
;
644 char PatternList::invertColor(char co
) {
645 if (co
== 'X') return 'O';
646 if (co
== 'x') return 'o';
648 if (co
== 'O') return 'X';
649 if (co
== 'o') return 'x';
654 void PatternList::patternList() {
656 vector
<pair
<int,int> > sy
;
657 int boardsize
= pattern
.boardsize
;
659 for(int f
= 0; f
< 8; f
++) {
660 int newSizeX
= max(Pattern::flipsX(f
,0,0,pattern
.sizeX
,pattern
.sizeY
),
661 Pattern::flipsX(f
,pattern
.sizeX
,pattern
.sizeY
,pattern
.sizeX
,pattern
.sizeY
));
662 int newSizeY
= max(Pattern::flipsY(f
,0,0,pattern
.sizeX
,pattern
.sizeY
),
663 Pattern::flipsY(f
,pattern
.sizeX
,pattern
.sizeY
,pattern
.sizeX
,pattern
.sizeY
));
665 int newLeft
= min(Pattern::flipsX(f
,pattern
.left
,pattern
.top
,boardsize
-1,boardsize
-1),
666 Pattern::flipsX(f
,pattern
.right
+pattern
.sizeX
-1,pattern
.bottom
+pattern
.sizeY
-1,
667 boardsize
-1,boardsize
-1));
668 int newRight
= max(Pattern::flipsX(f
,pattern
.left
,pattern
.top
,boardsize
-1,boardsize
-1),
669 Pattern::flipsX(f
,pattern
.right
+pattern
.sizeX
-1,pattern
.bottom
+pattern
.sizeY
-1,
670 boardsize
-1,boardsize
-1)) - (newSizeX
-1);
671 int newTop
= min(Pattern::flipsY(f
,pattern
.left
,pattern
.top
,boardsize
-1,boardsize
-1),
672 Pattern::flipsY(f
,pattern
.right
+pattern
.sizeX
-1,pattern
.bottom
+pattern
.sizeY
-1,
673 boardsize
-1,boardsize
-1));
674 int newBottom
= max(Pattern::flipsY(f
,pattern
.left
,pattern
.top
,boardsize
-1,boardsize
-1),
675 Pattern::flipsY(f
,pattern
.right
+pattern
.sizeX
-1,pattern
.bottom
+pattern
.sizeY
-1,
676 boardsize
-1,boardsize
-1)) - (newSizeY
- 1);
678 // printf("%d, %d, %d, %d, %d, %d, %d\n", f, newSizeX, newSizeY, newLeft, newRight, newTop, newBottom);
679 char* newInitialPos
= new char[pattern
.sizeX
*pattern
.sizeY
];
681 for(i
=0; i
<pattern
.sizeX
; i
++) {
682 for(int j
=0; j
<pattern
.sizeY
; j
++) {
683 newInitialPos
[Pattern::flipsX(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1) + \
684 newSizeX
*Pattern::flipsY(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1)] = pattern
.getInitial(i
, j
);
688 vector
<MoveNC
> newContList
;
689 for(i
=0; (unsigned int)i
<pattern
.contList
.size(); i
++) {
690 newContList
.push_back(MoveNC(Pattern::flipsX(f
, pattern
.contList
[i
].x
, pattern
.contList
[i
].y
,
691 pattern
.sizeX
-1,pattern
.sizeY
-1),
692 Pattern::flipsY(f
, pattern
.contList
[i
].x
, pattern
.contList
[i
].y
,
693 pattern
.sizeX
-1,pattern
.sizeY
-1),
694 pattern
.contList
[i
].color
));
697 Pattern
pNew(newLeft
, newRight
, newTop
, newBottom
, pattern
.boardsize
, newSizeX
, newSizeY
,
698 newInitialPos
, newContList
);
701 // printf("new size %d %d\n", pNew.sizeX, pNew.sizeY);
703 delete [] newInitialPos
;
705 vector
<Pattern
>::iterator it
;
706 bool foundNewPattern
= true;
707 for(it
= data
.begin(); it
!= data
.end(); it
++) {
709 foundNewPattern
= false;
710 flipTable
[f
] = flipTable
[it
->flip
];
714 if (foundNewPattern
) {
715 flipTable
[f
] = data
.size();
716 data
.push_back(pNew
);
719 if (pNew
== pattern
) sy
.push_back(pair
<int,int>(f
,0));
721 if (nextMove
|| !fixedColor
) {
722 char* newInitialPos
= new char[pattern
.sizeX
*pattern
.sizeY
];
723 for(int i
=0; i
<pattern
.sizeX
; i
++) {
724 for(int j
=0; j
<pattern
.sizeY
; j
++) {
725 newInitialPos
[Pattern::flipsX(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1) + newSizeX
*Pattern::flipsY(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1)] =
726 invertColor(pattern
.getInitial(i
, j
));
729 vector
<MoveNC
> newContList
;
731 for(unsigned int i
=0; i
<pattern
.contList
.size(); i
++) {
732 newContList
.push_back(MoveNC(Pattern::flipsX(f
, pattern
.contList
[i
].x
, pattern
.contList
[i
].y
,
733 pattern
.sizeX
-1,pattern
.sizeY
-1),
734 Pattern::flipsY(f
, pattern
.contList
[i
].x
, pattern
.contList
[i
].y
,
735 pattern
.sizeX
-1,pattern
.sizeY
-1),
736 invertColor(pattern
.contList
[i
].color
)));
741 // printf("new size %d %d", newSizeX, newSizeY);
742 Pattern
pNew1(newLeft
, newRight
, newTop
, newBottom
, pattern
.boardsize
, newSizeX
, newSizeY
,
743 newInitialPos
, newContList
);
745 pNew1
.colorSwitch
= 1;
747 delete [] newInitialPos
;
750 bool foundNewPattern
= true;
752 for(vector
<Pattern
>::iterator it
= lCS
.begin(); it
!= lCS
.end(); it
++) {
754 foundNewPattern
= false;
755 flipTable
[f
+8] = lCS_ctr
;
760 if (foundNewPattern
) {
761 lCS
.push_back(pNew1
);
765 if (pNew1
== pattern
) {
766 if (!fixedColor
) sy
.push_back(pair
<int,int>(f
,1));
767 if (nextMove
) special
= Pattern::PatternInvFlip(f
);
773 for(vector
<Pattern
>::iterator it
= lCS
.begin(); it
!= lCS
.end(); it
++) {
774 bool contained_in_l
= false;
775 for(vector
<Pattern
>::iterator it_l
= data
.begin(); it_l
!= data
.end(); it_l
++)
777 contained_in_l
= true;
778 flipTable
[8+it
->flip
] = flipTable
[it_l
->flip
];
781 if (!contained_in_l
) {
782 flipTable
[8+it
->flip
] = data
.size();
785 for(int ii
=it
->flip
+1; ii
<8; ii
++)
786 if (flipTable
[8+ii
] == lCS_ctr
) flipTable
[8+ii
] = flipTable
[8+it
->flip
];
790 Symmetries
symm(pattern
.sizeX
, pattern
.sizeY
);
791 for(int i
=0; i
<symm
.sizeX
; i
++)
792 for(int j
=0; j
<symm
.sizeY
; j
++)
793 symm
.set(i
,j
, i
,j
,0);
795 for(vector
<pair
<int,int> >::iterator it_s
=sy
.begin(); it_s
!=sy
.end(); it_s
++) {
797 int newSizeX
= max(Pattern::flipsX(s
,0,0,pattern
.sizeX
,pattern
.sizeY
),
798 Pattern::flipsX(s
,pattern
.sizeX
,pattern
.sizeY
,pattern
.sizeX
,pattern
.sizeY
));
799 int newSizeY
= max(Pattern::flipsY(s
,0,0,pattern
.sizeX
,pattern
.sizeY
),
800 Pattern::flipsY(s
,pattern
.sizeX
,pattern
.sizeY
,pattern
.sizeX
,pattern
.sizeY
));
801 int c
= it_s
->second
;
802 Symmetries
symm1(newSizeX
, newSizeY
);
804 for(int i
=0; i
< pattern
.sizeX
; i
++) {
805 for(int j
=0; j
< pattern
.sizeY
; j
++) {
806 int fX
= Pattern::flipsX(s
, i
, j
, pattern
.sizeX
-1, pattern
.sizeY
-1);
807 int fY
= Pattern::flipsY(s
, i
, j
, pattern
.sizeX
-1, pattern
.sizeY
-1);
808 if ((i
!= fX
|| j
!= fY
) && !symm1
.has_key(fX
, fY
))
809 symm1
.set(i
,j
, fX
, fY
, c
);
815 for(int i
=0; i
<symm
.sizeX
; i
++)
816 for(int j
=0; j
<symm
.sizeY
; j
++)
817 if (symm1
.has_key(symm
.getX(i
,j
), symm
.getY(i
,j
))) {
818 if ((symm1
.getCS(symm
.getX(i
,j
),symm
.getY(i
,j
)) || symm
.getCS(i
,j
)) &&
819 !(symm1
.getCS(symm
.getX(i
,j
),symm
.getY(i
,j
)) && symm
.getCS(i
,j
)))
822 symm
.set(i
,j
,symm1
.getX(symm
.getX(i
,j
),symm
.getY(i
,j
)),
823 symm1
.getY(symm
.getX(i
,j
),symm
.getY(i
,j
)), cs
);
828 symmetries
.push_back(symm
);
830 vector
<Pattern
>::iterator it
= data
.begin();
832 for(; it
!= data
.end(); it
++) {
833 // printf("ne %d, %d\n", it->sizeX, it->sizeY);
835 Symmetries
s(it
->sizeX
, it
->sizeY
);
836 for(int i
=0; i
<pattern
.sizeX
; i
++) {
837 for(int j
=0; j
<pattern
.sizeY
; j
++) {
838 if (!it
->colorSwitch
) {
839 s
.set(Pattern::flipsX(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1),
840 Pattern::flipsY(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1),
841 symm
.getX(i
,j
), symm
.getY(i
,j
), symm
.getCS(i
,j
));
843 s
.set(Pattern::flipsX(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1),
844 Pattern::flipsY(f
,i
,j
,pattern
.sizeX
-1,pattern
.sizeY
-1),
845 symm
.getX(i
,j
), symm
.getY(i
,j
), 1-symm
.getCS(i
,j
));
849 symmetries
.push_back(s
);
855 Pattern
PatternList::get(int i
) {
860 int PatternList::size() {
865 char* PatternList::updateContinuations(int index
, int x
, int y
, char co
, bool tenuki
, char winner
) {
870 xx
= symmetries
[index
].getX(x
,y
);
871 yy
= symmetries
[index
].getY(x
,y
);
872 cSymm
= symmetries
[index
].getCS(x
,y
);
873 if (co
== 'X' || co
== 'B') {
874 if (cSymm
) cc
= 'W'; else cc
= 'B';
876 if (cSymm
) cc
= 'B'; else cc
= 'W';
879 if ((nextMove
== 1 && cc
== 'W') || (nextMove
== 2 && cc
== 'B')) {
882 // printf("s1 xx %d, yy %d sp %d\n", xx, yy, special);
883 xx
= Pattern::flipsX(special
, xx
, yy
, pattern
.sizeX
-1, pattern
.sizeY
-1);
884 yy
= Pattern::flipsY(special
, xx1
, yy
, pattern
.sizeX
-1, pattern
.sizeY
-1);
885 // printf("s2 xx %d, yy %d\n", xx, yy);
886 if (cc
== 'B') cc
= 'W';
895 continuations
[xx
+ pattern
.sizeX
*yy
].B
++;
896 if (tenuki
) continuations
[xx
+ pattern
.sizeX
*yy
].tB
++;
897 if ((winner
== 'B' && !cSymm
) || (winner
== 'W' && cSymm
)) continuations
[xx
+ pattern
.sizeX
*yy
].wB
++;
898 else if ((winner
== 'W' && !cSymm
) || (winner
== 'B' && cSymm
)) continuations
[xx
+ pattern
.sizeX
*yy
].lB
++;
900 // printf("xx %d, yy %d\n", xx, yy);
901 continuations
[xx
+ pattern
.sizeX
*yy
].W
++;
902 if (tenuki
) continuations
[xx
+ pattern
.sizeX
*yy
].tW
++;
903 if ((winner
== 'B' && !cSymm
) || (winner
== 'W' && cSymm
)) continuations
[xx
+ pattern
.sizeX
*yy
].wW
++;
904 else if ((winner
== 'W' && !cSymm
) || (winner
='B' && cSymm
)) continuations
[xx
+ pattern
.sizeX
*yy
].lW
++;
906 char* result
= new char[3];
914 char* PatternList::sortContinuations() {
915 char* labels
= new char[pattern
.sizeX
*pattern
.sizeY
+1];
916 labels
[pattern
.sizeX
* pattern
.sizeY
] = 0; // so we can just printf the labels as a string
917 for(int i
=0; i
<pattern
.sizeX
*pattern
.sizeY
; i
++) {
918 if (continuations
[i
].B
|| continuations
[i
].W
) labels
[i
] = '?'; // need to assign label
919 else labels
[i
] = '.';
921 string labelList
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
922 unsigned int labelIndex
= 0;
924 // assign labels which are in the contLabels array passed to the original pattern
925 // (these will usually be labels "already present in the SGF file")
927 if (pattern
.contLabels
) {
928 for(int i
=0; i
<pattern
.sizeX
*pattern
.sizeY
; i
++) {
929 if (pattern
.contLabels
[i
] != '.') {
930 labels
[i
] = pattern
.contLabels
[i
];
931 unsigned int j
= labelList
.find(pattern
.contLabels
[i
]);
932 if (j
!= string::npos
) labelList
.erase(j
,1);
937 // now give labels to the remaining points, starting with the one with
941 int max_hits_index
= 0;
942 while (max_hits
!= -1 && labelIndex
< labelList
.size()) {
943 for(int i
=0; i
<pattern
.sizeX
*pattern
.sizeY
; i
++) {
944 if (labels
[i
] == '?' && continuations
[i
].B
+ continuations
[i
].W
> max_hits
) {
945 max_hits
= continuations
[i
].B
+ continuations
[i
].W
;
949 if (max_hits
!= 0) { // found another point needing a label
950 labels
[max_hits_index
] = labelList
[labelIndex
++];
952 } else max_hits
= -1; // done
960 int dbinsert1blob(sqlite3
* db
, char* sql
, int id
, char* blob
, int size
) {
961 sqlite3_stmt
*ppStmt
=0;
962 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
963 if (rc
!= SQLITE_OK
|| ppStmt
==0) return rc
;
964 rc
= sqlite3_bind_int(ppStmt
, 1, id
);
965 if (rc
!= SQLITE_OK
) return rc
;
966 rc
= sqlite3_bind_blob(ppStmt
, 2, blob
, size
, SQLITE_TRANSIENT
);
967 if (rc
!= SQLITE_OK
) return rc
;
968 rc
= sqlite3_step(ppStmt
);
969 if (rc
!= SQLITE_DONE
) return rc
;
970 rc
= sqlite3_finalize(ppStmt
);
971 if (rc
!= SQLITE_OK
) return rc
;
975 int dbinsert2blobs(sqlite3
* db
, char* sql
, int id
, char* blob1
, int size1
, char* blob2
, int size2
) {
976 sqlite3_stmt
*ppStmt
=0;
977 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
978 if (rc
!= SQLITE_OK
|| ppStmt
==0) return rc
;
979 rc
= sqlite3_bind_int(ppStmt
, 1, id
);
980 if (rc
!= SQLITE_OK
) return rc
;
981 rc
= sqlite3_bind_blob(ppStmt
, 2, blob1
, size1
, SQLITE_TRANSIENT
);
982 if (rc
!= SQLITE_OK
) return rc
;
983 rc
= sqlite3_bind_blob(ppStmt
, 3, blob2
, size2
, SQLITE_TRANSIENT
);
984 if (rc
!= SQLITE_OK
) return rc
;
985 rc
= sqlite3_step(ppStmt
);
986 if (rc
!= SQLITE_DONE
) return rc
;
987 rc
= sqlite3_finalize(ppStmt
);
988 if (rc
!= SQLITE_OK
) return rc
;
992 Algorithm::Algorithm(int bsize
) {
997 Algorithm::~Algorithm() {}
999 void Algorithm::initialize_process(sqlite3
* DB
) {}
1000 void Algorithm::newgame_process(int game_id
) {}
1001 void Algorithm::AB_process(int x
, int y
) {}
1002 void Algorithm::AW_process(int x
, int y
) {}
1003 void Algorithm::AE_process(int x
, int y
, char removed
) {}
1004 void Algorithm::endOfNode_process() {}
1005 void Algorithm::move_process(Move m
) {}
1006 void Algorithm::pass_process() {}
1007 void Algorithm::branchpoint_process() {}
1008 void Algorithm::endOfVariation_process() {}
1009 void Algorithm::endgame_process(bool commit
) {}
1010 void Algorithm::finalize_process() {}
1011 int Algorithm::readDB(sqlite3
* DB
) { return 0; }
1012 int Algorithm::search(PatternList
& patternList
, GameList
& gl
, SearchOptions
& options
) {
1016 Algo_signature::Algo_signature(int bsize
) : Algorithm(bsize
) {
1017 main_variation
= true;
1020 Algo_signature::~Algo_signature() {
1023 void Algo_signature::initialize_process(sqlite3
* DB
) throw(DBError
) {
1026 sprintf(sql
, "create table algo_signature_%d ( id integer primary key, signature varchar(12) );", boardsize
);
1027 int rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
1028 //if (rc != SQLITE_OK) throw DBError();
1029 sprintf(sql
, "create index sig_idx on algo_signature_%d(signature);", boardsize
);
1030 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
1031 //if (rc != SQLITE_OK) throw DBError();
1034 void Algo_signature::newgame_process(int game_id
) {
1035 main_variation
= true;
1038 signature
= new char[12];
1039 for(int i
=0; i
<12; i
++) signature
[i
] = '?';
1042 void Algo_signature::AB_process(int x
, int y
) {
1045 void Algo_signature::AW_process(int x
, int y
) {
1048 void Algo_signature::AE_process(int x
, int y
, char removed
) {
1051 void Algo_signature::endOfNode_process() {
1054 void Algo_signature::move_process(Move m
) {
1055 if (!main_variation
) return;
1059 signature
[0] = m
.x
+ 97;
1060 signature
[1] = m
.y
+ 97;
1063 signature
[2] = m
.x
+ 97;
1064 signature
[3] = m
.y
+ 97;
1067 signature
[4] = m
.x
+ 97;
1068 signature
[5] = m
.y
+ 97;
1071 signature
[6] = m
.x
+ 97;
1072 signature
[7] = m
.y
+ 97;
1075 signature
[8] = m
.x
+ 97;
1076 signature
[9] = m
.y
+ 97;
1079 signature
[10] = m
.x
+ 97;
1080 signature
[11] = m
.y
+ 97;
1084 void Algo_signature::pass_process() {
1085 if (main_variation
) move_process(Move(19,19,'p'));
1088 void Algo_signature::branchpoint_process() {
1092 void Algo_signature::endOfVariation_process() {
1093 main_variation
= false;
1096 char* symmetrize(char* signature
, int boardsize
) {
1097 // symmetrize signature
1098 char* min_signature
= new char[12];
1099 for(int i
=0; i
<12; i
++) min_signature
[i
] = signature
[i
];
1100 for (int f
=0; f
<8; f
++) { // for all flips
1101 // compute flipped signature
1102 char* next
= new char[12];
1103 for(int i
=0; i
<6; i
++) {
1104 if ('a' <= signature
[2*i
] && signature
[2*i
] <= 's')
1105 next
[2*i
] = Pattern::flipsX(f
, signature
[2*i
]-'a', signature
[2*i
+1]-'a', boardsize
-1, boardsize
-1)+'a';
1106 else next
[2*i
] = signature
[2*i
];
1107 if ('a' <= signature
[2*i
+1] && signature
[2*i
+1] <= 's')
1108 next
[2*i
+1] = Pattern::flipsY(f
, signature
[2*i
]-'a', signature
[2*i
+1]-'a', boardsize
-1, boardsize
-1)+'a';
1109 else next
[2*i
+1] = signature
[2*i
+1];
1111 // if next < min_signature, then swap
1112 for(int j
=0; j
<12; j
++) {
1113 if (next
[j
] > min_signature
[j
]) break;
1114 if (next
[j
] < min_signature
[j
]) {
1116 next
= min_signature
;
1117 min_signature
= help
;
1123 return min_signature
;
1126 void Algo_signature::endgame_process(bool commit
) throw(DBError
) {
1128 char* min_signature
= symmetrize(signature
, boardsize
);
1130 sprintf(sql
, "insert into algo_signature_%d (id, signature) values (?,?);", boardsize
);
1131 if (dbinsert1blob(db
, sql
, gid
, min_signature
, 12)) throw DBError();
1132 // for(int i=0; i<12; i++) printf("%c", min_signature[i]); printf("\n");
1133 delete [] min_signature
;
1135 delete [] signature
;
1138 void Algo_signature::finalize_process() {
1141 char* Algo_signature::get_current_signature() {
1142 return symmetrize(signature
, boardsize
);
1145 vector
<int> Algo_signature::search_signature(char* sig
) {
1146 // to be used during processing! (because we need the db)
1148 sprintf(sql
, "select id from algo_signature_%d where signature=? order by id", boardsize
);
1149 sqlite3_stmt
*ppStmt
=0;
1151 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
1152 if (rc
!= SQLITE_OK
|| ppStmt
==0) throw DBError();
1153 rc
= sqlite3_bind_blob(ppStmt
, 1, sig
, 12, SQLITE_TRANSIENT
);
1154 if (rc
!= SQLITE_OK
|| ppStmt
==0) throw DBError();
1156 rc
= sqlite3_step(ppStmt
);
1157 if (rc
!= SQLITE_DONE
&& rc
!= SQLITE_ROW
) throw DBError();
1158 if (rc
== SQLITE_ROW
) {
1159 result
.push_back(sqlite3_column_int(ppStmt
, 0));
1161 } while (rc
== SQLITE_ROW
);
1162 rc
= sqlite3_finalize(ppStmt
);
1163 if (rc
!= SQLITE_OK
) throw DBError();
1167 Algo_finalpos::Algo_finalpos(int bsize
) : Algorithm(bsize
) {
1173 Algo_finalpos::~Algo_finalpos() {
1175 for(map
<int, char* >::iterator it
= data
->begin(); it
!= data
->end(); it
++) delete [] it
->second
;
1180 void Algo_finalpos::initialize_process(sqlite3
* DB
) throw(DBError
) {
1181 // printf("init Algo_finalpos\n");
1184 sprintf(sql
, "create table algo_finalpos_%d ( id integer primary key, data blob );", boardsize
);
1185 int rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
1186 if (rc
!= SQLITE_OK
) {
1189 // printf("init Algo_finalpos\n");
1192 void Algo_finalpos::newgame_process(int game_id
) {
1195 for(int i
=0; i
<100; i
++) fp
[i
] = 255;
1198 void Algo_finalpos::AB_process(int x
, int y
) {
1199 fp
[y
/2 + 10*(x
/2)] &= ~(1 << (2*(x
%2 + 2*(y
%2))));
1202 void Algo_finalpos::AW_process(int x
, int y
) {
1203 fp
[y
/2 + 10*(x
/2)] &= ~(1 << (2*(x
%2 + 2*(y
%2))+1));
1206 void Algo_finalpos::AE_process(int x
, int y
, char removed
) {
1209 void Algo_finalpos::endOfNode_process() {
1212 void Algo_finalpos::move_process(Move m
) {
1214 fp
[m
.y
/2 + 10*(m
.x
/2)] &= ~(1 << (2*(m
.x
%2 + 2*(m
.y
%2))));
1215 else if (m
.color
== 'W')
1216 fp
[m
.y
/2 + 10*(m
.x
/2)] &= ~(1 << (2*(m
.x
%2 + 2*(m
.y
%2))+1));
1219 void Algo_finalpos::pass_process() {
1222 void Algo_finalpos::branchpoint_process() {
1225 void Algo_finalpos::endOfVariation_process() {
1228 void Algo_finalpos::endgame_process(bool commit
) throw(DBError
) {
1231 sprintf(sql
, "insert into algo_finalpos_%d (id, data) values (?,?);", boardsize
);
1232 if (dbinsert1blob(db
, sql
, gid
, fp
, 100)) throw DBError();
1237 void Algo_finalpos::finalize_process() {
1240 int Algo_finalpos::readDB(sqlite3
* DB
) {
1243 for(map
<int, char* >::iterator it
= data
->begin(); it
!= data
->end(); it
++) delete [] it
->second
;
1246 data
= new map
<int, char* >;
1247 int rc
= sqlite3_exec(db
, "begin transaction;", 0, 0, 0);
1248 if (rc
) throw DBError();
1249 sqlite3_stmt
*ppStmt
=0;
1251 sprintf(sql
, "select id, data from algo_finalpos_%d order by id", boardsize
);
1252 rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
1253 if (rc
!= SQLITE_OK
|| ppStmt
==0) return rc
; // FIXME: catch certain errors, (and/or throw DBError?)
1254 while (sqlite3_step(ppStmt
) == SQLITE_ROW
) {
1255 // printf("step0\n");
1256 int index
= sqlite3_column_int(ppStmt
, 0);
1257 char* d
= (char*)sqlite3_column_blob(ppStmt
, 1);
1258 // printf("step1\n");
1259 char* d1
= new char[100];
1260 // printf("step2\n");
1261 for(int i
=0; i
<100; i
++) d1
[i
] = d
[i
];
1262 // printf("step3\n");
1263 // printf("insert %d %p\n", index, d1);
1264 data
->insert(make_pair(index
, d1
));
1266 // printf("done\n");
1267 rc
= sqlite3_finalize(ppStmt
);
1268 if (rc
!= SQLITE_OK
) return rc
;
1269 rc
= sqlite3_exec(db
, "commit;", 0, 0, 0);
1270 if (rc
!= SQLITE_OK
) throw DBError();
1274 int Algo_finalpos::search(PatternList
& patternList
, GameList
& gl
, SearchOptions
& options
) { // progress bar?!
1276 // Put the pattern into bitmap format, which is the format the final
1277 // positions are stored in in the database. This makes the comparisons
1280 int plS
= patternList
.size();
1281 char_p
** allbits
= new char_p
*[plS
];
1282 int** allbitlengths
= new int*[plS
];
1283 for(int N
=0; N
<plS
; N
++) {
1284 Pattern
* pattern
= &patternList
.data
[N
];
1285 allbits
[N
] = new char_p
[4];
1286 allbitlengths
[N
] = new int[4];
1288 for(int i
=0; i
<2; i
++) {
1289 for(int j
=0; j
<2; j
++) {
1290 int xBlocks
= (pattern
->sizeY
+i
+1)/2;
1291 int yBlocks
= (pattern
->sizeX
+j
+1)/2;
1292 char* nextBlock
= new char[400];
1293 int nextBlockIndex
= 0;
1294 nextBlock
[nextBlockIndex
++] = yBlocks
;
1296 for(int k1
=0; k1
< yBlocks
; k1
++) {
1300 for(int k2
=0; k2
< xBlocks
; k2
++) {
1302 for(int x
=0; x
<2; x
++) {
1303 for(int y
=0; y
<2; y
++) {
1304 int indexX
= k1
* 2 + y
- j
;
1305 int indexY
= k2
* 2 + x
- i
;
1306 if (0 <= indexX
&& indexX
< pattern
->sizeX
&& 0 <= indexY
&& indexY
< pattern
->sizeY
) {
1307 if (pattern
->getFinal(indexX
,indexY
)=='X')
1308 n
|= 1 << (2*(2*x
+y
));
1309 else if (pattern
->getFinal(indexX
,indexY
)=='O')
1310 n
|= 1 << (2*(2*x
+y
)+1);
1314 nlist
[nlistIndex
++] = n
;
1318 int end
= nlistIndex
;
1320 while (start
< end
&& !nlist
[start
]) start
++;
1321 while (end
> start
&& !nlist
[end
-1]) end
--;
1323 nextBlock
[nextBlockIndex
++] = start
;
1324 nextBlock
[nextBlockIndex
++] = end
-start
;
1325 for(int current
=start
; current
< end
; current
++)
1326 nextBlock
[nextBlockIndex
++] = nlist
[current
];
1328 char* nB
= new char[nextBlockIndex
];
1329 for(int ii
=0; ii
<nextBlockIndex
; ii
++) nB
[ii
] = nextBlock
[ii
];
1330 allbitlengths
[N
][2*i
+ j
] = nextBlockIndex
;
1331 allbits
[N
][2*i
+ j
] = nB
;
1332 delete [] nextBlock
;
1337 int index
= gl
.start();
1338 // int counter = 0; // to keep track of progress bar
1339 // printf("%d patterns\n", plS);
1344 while (index
!= -1) {
1345 // if (!(counter++ % 1000)) printf("counter: %d, index: %d\n", counter, index);
1346 // if (progBar && !(counter % 100))
1347 // progBar.redraw((progEnd-progStart)*counter/len(gl.current) + progStart);
1349 map
<int, char* >::iterator it
= data
->find(index
);
1350 if (it
== data
->end()) {
1351 // printf("skip\n");
1355 char* finalpos
= it
->second
;
1356 // printf("index %d, %p\n", index, finalpos);
1357 vector
<Candidate
* > *matchList
= new vector
<Candidate
* >;;
1359 for(int N
=0; N
<plS
; N
++) {
1360 Pattern
* pattern
= &patternList
.data
[N
];
1361 for(int a0
=pattern
->left
; a0
<= pattern
->right
; a0
++) {
1362 for(int a1
= pattern
->top
; a1
<= pattern
->bottom
; a1
++) {
1365 int pIndex
= 2*(a1
%2) + (a0
%2);
1366 char* pbits
= allbits
[N
][pIndex
];
1368 int fpIndex
= a1
/2 + (a0
/2)*10;
1370 for(x
=0; x
< pbits
[0]; x
++) {
1371 start
= pbits
[++pbIndex
];
1372 length
= pbits
[++pbIndex
];
1374 for(y
=0; y
<length
; y
++) {
1376 if (pbits
[pbIndex
] & finalpos
[fpIndex
]) {
1382 if (!matches
) break;
1383 fpIndex
+= 10 - start
- length
;
1385 if (matches
) matchList
->push_back(new Candidate(a0
,a1
,N
));
1390 if (matchList
->size()) gl
.makeCurrentCandidate(matchList
);
1391 else delete matchList
;
1396 for(int N
=0; N
<plS
; N
++) {
1397 delete [] allbitlengths
[N
];
1398 for(int i
=0; i
<4; i
++)
1399 if (allbits
[N
][i
]) delete [] allbits
[N
][i
];
1400 delete [] allbits
[N
];
1403 delete [] allbitlengths
;
1408 bool Algo_finalpos::equal(unsigned int i1
, unsigned int i2
) {
1409 // not to be used during processing
1410 // i1, i2 correspond to game id's
1411 sqlite3_stmt
*ppStmt
=0;
1413 sprintf(sql
, "select data from algo_finalpos_%d where id = %d or id = %d", boardsize
, i1
, i2
);
1414 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
1415 if (rc
!= SQLITE_OK
|| ppStmt
==0) return false; // FIXME: catch certain errors, (and/or throw DBError?)
1416 if (sqlite3_step(ppStmt
) == SQLITE_ROW
) {
1417 char* dd1
= (char*)sqlite3_column_blob(ppStmt
, 0);
1418 char* d1
= new char[100];
1419 for(int i
=0; i
<100; i
++) d1
[i
] = dd1
[i
]; // FIXME: is this necessary?
1420 if (sqlite3_step(ppStmt
) == SQLITE_ROW
) {
1421 char* d2
= (char*)sqlite3_column_blob(ppStmt
, 0);
1422 for(int i
=0; i
<100; i
++)
1423 if (d1
[i
] != d2
[i
]) {
1425 sqlite3_finalize(ppStmt
);
1429 sqlite3_finalize(ppStmt
);
1434 sqlite3_finalize(ppStmt
);
1438 bool Algo_finalpos::equals_current(unsigned int id1
) {
1439 // to be used only during processing
1440 // id1 here corresponds to a game id
1442 sqlite3_stmt
*ppStmt
=0;
1444 sprintf(sql
, "select data from algo_finalpos_%d where id = %d", boardsize
, id1
);
1445 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
1446 if (rc
!= SQLITE_OK
|| ppStmt
==0) return false; // FIXME: catch certain errors, (and/or throw DBError?)
1447 if (sqlite3_step(ppStmt
) == SQLITE_ROW
) {
1448 char* d
= (char*)sqlite3_column_blob(ppStmt
, 0);
1449 for(int i
=0; i
<100; i
++)
1450 if (d
[i
] != fp
[i
]) {
1454 } else result
= false;
1455 sqlite3_finalize(ppStmt
);
1460 Algo_movelist::Algo_movelist(int bsize
) : Algorithm(bsize
) {
1466 Algo_movelist::~Algo_movelist() {
1468 for(map
<int, char* >::iterator it
= data1
->begin(); it
!= data1
->end(); it
++) {
1469 delete [] it
->second
;
1474 for(map
<int, char* >::iterator it
= data2
->begin(); it
!= data2
->end(); it
++) {
1475 delete [] it
->second
;
1479 if (data1l
) delete data1l
;
1482 void Algo_movelist::initialize_process(sqlite3
* DB
) throw(DBError
) {
1483 // printf("init Algo_movelist\n");
1486 sprintf(sql
, "create table algo_movelist_%d ( id integer primary key, movelist blob, fpC blob );", boardsize
);
1487 int rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
1488 //if (rc != SQLITE_OK) throw DBError();
1489 // printf("init Algo_movelist\n");
1492 void Algo_movelist::newgame_process(int game_id
) {
1494 movelist
= vector
<char>();
1497 for(int i
=0; i
<50; i
++) fpC
[i
] = 0;
1500 void Algo_movelist::AB_process(int x
, int y
) {
1501 movelist
.push_back((char)x
);
1502 movelist
.push_back((char)(y
| BLACK
));
1506 void Algo_movelist::AW_process(int x
, int y
) {
1507 movelist
.push_back((char)x
);
1508 movelist
.push_back((char)(y
| WHITE
));
1512 void Algo_movelist::AE_process(int x
, int y
, char removed
) {
1513 movelist
.push_back((char)x
);
1514 if (removed
== 'B') movelist
.push_back((char)(y
| REMOVE
| BLACK
));
1515 else if (removed
== 'W') movelist
.push_back((char)(y
| REMOVE
| WHITE
));
1518 void Algo_movelist::endOfNode_process() {
1519 if (movelist
.size()>1) {
1520 if (movelist
[movelist
.size()-2] & (ENDOFNODE
| BRANCHPOINT
| ENDOFVARIATION
)) {
1521 movelist
.push_back(ENDOFNODE
);
1522 movelist
.push_back(0);
1524 movelist
[movelist
.size()-2] |= ENDOFNODE
;
1527 movelist
.push_back(ENDOFNODE
);
1528 movelist
.push_back(0);
1532 void Algo_movelist::move_process(Move m
) {
1533 if (!movelist
.size()) {
1534 movelist
.push_back(ENDOFNODE
);
1535 movelist
.push_back(0);
1537 movelist
.push_back(m
.x
);
1538 if (m
.color
=='B') movelist
.push_back(m
.y
| BLACK
);
1539 else movelist
.push_back(m
.y
| WHITE
);
1542 vector
<p_cc
>::iterator it
;
1543 for(it
= m
.captures
->begin(); it
!= m
.captures
->end(); it
++) {
1545 int yy
= it
->second
;
1547 movelist
.push_back(xx
);
1548 if (m
.color
=='B') movelist
.push_back(yy
| REMOVE
| WHITE
);
1549 else movelist
.push_back(yy
| REMOVE
| BLACK
);
1550 fpC
[yy
/4 + 5*(xx
/2)] |= 1 << (xx
%2 + 2*(yy
%4));
1555 void Algo_movelist::pass_process() {
1556 movelist
.push_back(19);
1557 movelist
.push_back(19);
1560 void Algo_movelist::branchpoint_process() {
1561 movelist
.push_back(BRANCHPOINT
);
1562 movelist
.push_back(0);
1565 void Algo_movelist::endOfVariation_process() {
1566 movelist
.push_back(ENDOFVARIATION
);
1567 movelist
.push_back(0);
1570 void Algo_movelist::endgame_process(bool commit
) throw(DBError
) {
1572 char* ml
= new char[movelist
.size()];
1574 for(vector
<char>::iterator it
= movelist
.begin(); it
!= movelist
.end(); it
++) {
1575 ml
[mlIndex
++] = *it
;
1578 sprintf(sql
, "insert into algo_movelist_%d (id, movelist, fpC) values (?, ?, ?);", boardsize
);
1579 if (dbinsert2blobs(db
, sql
, gid
, ml
, mlIndex
, fpC
, 50)) throw DBError();
1585 void Algo_movelist::finalize_process() {
1588 int Algo_movelist::readDB(sqlite3
* DB
) {
1590 for(map
<int, char* >::iterator it
= data1
->begin(); it
!= data1
->end(); it
++) delete [] it
->second
;
1593 data1
= new map
<int, char* >;
1594 if (data1l
) delete data1l
;
1595 data1l
= new map
<int, int >;
1597 for(map
<int, char* >::iterator it
= data2
->begin(); it
!= data2
->end(); it
++) delete [] it
->second
;
1600 data2
= new map
<int, char* >;
1603 int rc
= sqlite3_exec(db
, "begin transaction;", 0, 0, 0);
1604 if (rc
) throw DBError();
1606 sqlite3_stmt
*ppStmt
=0;
1608 sprintf(sql
, "select movelist,fpC,id from algo_movelist_%d order by id", boardsize
);
1609 rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
1610 if (rc
!= SQLITE_OK
|| ppStmt
==0) return rc
; // FIXME: catch certain errors, (and/or throw DBError?)
1611 while (sqlite3_step(ppStmt
) == SQLITE_ROW
) {
1612 int l
= sqlite3_column_bytes(ppStmt
,0);
1613 // printf("len movelist: %d\n", l);
1614 char* d
= (char*)sqlite3_column_blob(ppStmt
, 0);
1615 char* d1
= new char[l
];
1616 for(int i
=0; i
<l
; i
++) {
1618 // printf("%c", (d[i] & 31)+97);
1620 int index
= sqlite3_column_int(ppStmt
, 2);
1622 data1
->insert(make_pair(index
, d1
));
1623 data1l
->insert(make_pair(index
, l
));
1624 d
= (char*)sqlite3_column_blob(ppStmt
, 1);
1627 for(int i
=0; i
<50; i
++) d1
[i
] = d
[i
];
1629 data2
->insert(make_pair(index
, d1
));
1631 rc
= sqlite3_finalize(ppStmt
);
1632 if (rc
!= SQLITE_OK
) return rc
;
1634 rc
= sqlite3_exec(db
, "commit;", 0, 0, 0);
1635 if (rc
!= SQLITE_OK
) throw DBError();
1636 // printf("data sizes %d, %d, %d\n", data1->size(), data1l->size(), data2->size());
1641 MovelistCand::MovelistCand(Pattern
* P
, int ORIENTATION
, char* DICTS
, int NO
, char X
, char Y
) {
1642 orientation
= ORIENTATION
;
1646 Xinterv
= make_pair(mx
, mx
+p
->sizeX
);
1647 Yinterv
= make_pair(my
, my
+p
->sizeY
);
1653 dictsFoundInitial
= false;
1655 contList
= p
->contList
; // FIXME
1658 MovelistCand::~MovelistCand() {
1662 char MovelistCand::dictsget(char x
, char y
) {
1663 return dicts
[x
-mx
+ p
->sizeX
*(y
-my
)];
1666 void MovelistCand::dictsset(char x
, char y
, char d
) {
1667 dicts
[x
-mx
+ p
->sizeX
*(y
-my
)] = d
;
1670 bool MovelistCand::in_relevant_region(char x
, char y
) {
1671 return (mx
<= x
&& x
< mx
+ p
->sizeX
&& my
<= y
&& y
< my
+ p
->sizeY
);
1675 VecMC::VecMC() : vector
<MovelistCand
* >() {
1680 for(VecMC::iterator it
= begin(); it
!= end(); it
++) {
1681 if (*it
) delete *it
;
1685 VecMC
* VecMC::deepcopy(ExtendedMoveNumber
& COUNTER
, int CANDSSIZE
) {
1686 VecMC
* result
= new VecMC
;
1687 result
->candssize
= CANDSSIZE
;
1688 result
->counter
= COUNTER
;
1689 for(VecMC::iterator it
= begin(); it
!= end(); it
++) {
1690 MovelistCand
* mlc
= 0;
1692 char* DICTS
= new char[(*it
)->p
->sizeX
* (*it
)->p
->sizeY
];
1693 for (int i
=0; i
< (*it
)->p
->sizeX
* (*it
)->p
->sizeY
; i
++) DICTS
[i
] = (*it
)->dicts
[i
];
1694 mlc
= new MovelistCand((*it
)->p
, (*it
)->orientation
, DICTS
, (*it
)->dictsNO
, (*it
)->mx
, (*it
)->my
);
1695 mlc
->contListIndex
= (*it
)->contListIndex
;
1696 mlc
->dictsFound
= (*it
)->dictsFound
;
1697 mlc
->dictsF
= (*it
)->dictsF
;
1698 mlc
->dictsFoundInitial
= (*it
)->dictsFoundInitial
;
1699 mlc
->dictsFI
= (*it
)->dictsFI
;
1700 mlc
->dictsDR
= (*it
)->dictsDR
;
1701 mlc
->contList
= mlc
->p
->contList
; // FIXME
1703 result
->push_back(mlc
);
1708 int Algo_movelist::search(PatternList
& patternList
, GameList
& gl
, SearchOptions
& options
) {
1711 // printf("Enter Algo_movelist::search\n");
1713 int self_numOfSwitched
= 0;
1717 int movelimit
= options
.moveLimit
;
1719 int index
= gl
.start();
1720 // int gameCounter = 0;
1722 while (index
!= -1) {
1725 // if (progBar && !(gameCounter % 10))
1726 // progBar.redraw((progEnd-progStart)*gameCounter/len(db.current) + progStart);
1728 // printf("Process index %d\n", index);
1730 vector
<Hit
* > * result
= new vector
<Hit
* >;
1731 int numOfSwitched
= 0;
1732 stack
<VecMC
* > branchpoints
;
1734 char* movel
= (*data1
)[index
];
1735 int movelistIndex
= 0;
1736 int endMovelist
= (*data1l
)[index
];
1737 // printf("len movelist: %d\n", (*data1l)[index]);
1739 // for(int i=0; i<endMovelist/2; i++) {
1741 // if (movel[2*i] & BRANCHPOINT) printf("BP\n");
1742 // if (movel[2*i] & ENDOFVARIATION) printf("EV\n");
1743 // if (movel[2*i+1] & BLACK) printf("B");
1744 // if (movel[2*i+1] & WHITE) printf("W");
1745 // if (movel[2*i+1] & REMOVE) printf("C");
1746 // printf("%c", (movel[2*i] & 31)+97);
1747 // printf("%c", (movel[2*i+1] & 31)+97);
1748 // if (movel[2*i] & ENDOFNODE) printf("\n%d ", nodeCtr++);
1752 char* fpC
= (*data2
)[index
];
1754 vector
<Candidate
* > *currentMatchList
= gl
.getCurrentCandidateList();
1755 int candssize
= currentMatchList
->size();
1756 VecMC
* cands
= new VecMC
;
1757 cands
->reserve(currentMatchList
->size());
1759 for(int mCounter
=0; mCounter
<(int)currentMatchList
->size(); mCounter
++) {
1760 Candidate
* m
= (*currentMatchList
)[mCounter
];
1762 Pattern
* p
= &patternList
.data
[m
->orientation
];
1763 char* d
= new char[p
->sizeX
* p
->sizeY
];
1764 for(int i
=0; i
<p
->sizeX
; i
++) {
1765 for(int j
=0; j
<p
->sizeY
; j
++) {
1766 char p_ij
= p
->getInitial(i
,j
);
1767 if (p_ij
!= '.') d
[i
+p
->sizeX
*j
] = p_ij
;
1768 else d
[i
+p
->sizeX
*j
] = 0;
1769 if (p_ij
== 'X' || p_ij
== 'O') dNO
++;
1772 cands
->push_back(new MovelistCand(p
, m
->orientation
, d
, dNO
, m
->x
, m
->y
));
1774 // printf("candssize %d\n", cands->size());
1776 ExtendedMoveNumber
counter(0);
1778 while (movelistIndex
< endMovelist
) {
1779 // printf("\nnextmove %d\n", counter.total_move_num());
1780 if (counter
.total_move_num() == movelimit
+1) {
1781 for(vector
<MovelistCand
* >::iterator it
= cands
->begin(); it
!= cands
->end(); it
++) {
1782 if (*it
== 0) continue;
1783 if (!(*it
)->dictsFound
) {
1790 if (options
.searchInVariations
&& movel
[movelistIndex
] & BRANCHPOINT
) {
1791 // printf("branchpoint\n");
1792 branchpoints
.push(cands
->deepcopy(counter
, candssize
));
1796 if (options
.searchInVariations
&& movel
[movelistIndex
] & ENDOFVARIATION
) {
1797 // printf("endofvariation\n");
1798 if (!patternList
.nextMove
) { // deal with hits w/o continuation
1799 for(vector
<MovelistCand
* >::iterator it
= cands
->begin(); it
!= cands
->end(); it
++) {
1800 if (*it
== 0) continue;
1801 if ((*it
)->dictsFound
) {
1802 if ((*it
)->p
->colorSwitch
) {
1804 char* rstr
= new char[3];
1808 result
->push_back(new Hit(new ExtendedMoveNumber((*it
)->dictsF
), rstr
));
1810 char* rstr
= new char[3];
1814 result
->push_back(new Hit(new ExtendedMoveNumber((*it
)->dictsF
), rstr
));
1821 cands
= branchpoints
.top();
1822 counter
= cands
->counter
;
1823 candssize
= cands
->candssize
;
1830 char x
= movel
[movelistIndex
] & 31;
1831 char y
= movel
[movelistIndex
+1] & 31;
1835 char lower_invco
= 'x';
1837 if (!(movel
[movelistIndex
+1] & REMOVE
) && (movel
[movelistIndex
+1] & (BLACK
| WHITE
))) {
1839 if (movel
[movelistIndex
+1] & BLACK
) {
1845 for(vector
<MovelistCand
* >::iterator it
= cands
->begin(); it
!= cands
->end(); it
++) {
1846 if (*it
== 0) continue;
1847 if ((*it
)->in_relevant_region(x
,y
)) {
1848 // printf("loop 1\n %c", (*it)->dictsget(x,y));
1849 if ((*it
)->dictsFound
) { // found, so now we have found the continuation
1850 // printf("found\n");
1852 label
= patternList
.updateContinuations(
1853 (*it
)->orientation
, // pattern in question
1854 x
-(*it
)->mx
, y
-(*it
)->my
, // pos of continuation
1855 co
, // color of continuation
1856 (counter
.total_move_num()-(*it
)->dictsF
.total_move_num())>2, // tenuki?
1857 gl
.getCurrentWinner()
1859 if (label
) { // otherwise no hit because continuation has wrong color (i.e. nextMove set)
1860 numOfSwitched
+= label
[2];
1861 result
->push_back(new Hit(new ExtendedMoveNumber((*it
)->dictsF
), label
));
1868 } else if ((*it
)->dictsFoundInitial
) { // foundInitial, so now look for contList
1869 if (MoveNC(x
, y
, co
) == ((*it
)->contList
)[(*it
)->contListIndex
]) {
1870 (*it
)->contListIndex
++;
1871 if ((*it
)->contListIndex
== (int)(*it
)->contList
.size()) {
1872 (*it
)->dictsF
= counter
;
1873 (*it
)->dictsFound
= true;
1876 if ((*it
)->dictsDR
) { // don't restore
1882 (*it
)->contListIndex
= 0;
1883 (*it
)->dictsFoundInitial
= false;
1888 if (!(*it
)->dictsget(x
,y
)) { // this move occupies a spot which should be empty
1889 if (!(fpC
[y
/4 + 5*(x
/2)] & (1 << (x
%2 + 2*(y
%4))))) {
1890 if (!(*it
)->contListIndex
) {
1895 } else (*it
)->dictsDR
= true;
1897 (*it
)->dictsset(x
,y
,'.');
1898 (*it
)->dictsNO
++; // printf("++ A\n");
1900 } else if ((*it
)->dictsget(x
,y
) == lower_invco
) {
1901 // this move occupies a wildcard spot of the wrong color
1902 if (!(fpC
[y
/4 + 5*(x
/2)] & (1 << (x
%2 + 2*(y
%4))))) {
1903 if (!(*it
)->contListIndex
) {
1908 } else (*it
)->dictsDR
= true;
1909 } else (*it
)->dictsNO
++; // printf("++ B\n");
1910 } else if ((*it
)->dictsget(x
,y
) == co
) {
1911 // this move gives us the stone we are looking for
1912 (*it
)->dictsset(x
,y
,0);
1913 (*it
)->dictsNO
--; // printf("-- A\n");
1918 else if (movel
[movelistIndex
+1] & REMOVE
) {
1919 if (movel
[movelistIndex
+1] & BLACK
) {
1923 } else if (movel
[movelistIndex
+1] & WHITE
) {
1929 for(vector
<MovelistCand
* >::iterator it
= cands
->begin(); it
!= cands
->end(); it
++) {
1930 // printf("loop 2\n");
1931 if (*it
== 0) continue;
1932 if (!(*it
)->dictsFound
) { // not found yet
1933 if ((*it
)->in_relevant_region(x
,y
)) {
1934 if ((*it
)->dictsFoundInitial
) { // foundInitial
1935 int ii
= (*it
)->contListIndex
;
1936 while (ii
< (int)(*it
)->contList
.size() && (*it
)->contList
[ii
].color
== '-' &&
1937 (x
!= (*it
)->contList
[ii
].x
|| y
!= (*it
)->contList
[ii
].y
))
1939 if (ii
< (int)(*it
)->contList
.size() && (*it
)->contList
[ii
].color
== '-') {
1940 MoveNC help
= (*it
)->contList
[ii
];
1941 (*it
)->contList
[ii
] = (*it
)->contList
[(*it
)->contListIndex
];
1942 (*it
)->contList
[(*it
)->contListIndex
] = help
;
1944 (*it
)->contListIndex
++;
1946 if ((*it
)->dictsDR
) {
1952 (*it
)->contListIndex
= 0;
1953 (*it
)->dictsFoundInitial
= false;
1957 if (!(*it
)->dictsget(x
,y
)) {
1958 // the stone at this position was what we needed,
1959 // since it was captured, we are once again looking for it:
1960 (*it
)->dictsset(x
,y
,co
);
1961 (*it
)->dictsNO
++; // printf("++ C\n");
1963 else if ((*it
)->dictsget(x
,y
) == lower_invco
) {
1964 (*it
)->dictsNO
--; // printf("-- B\n");
1966 else if ((*it
)->dictsget(x
,y
) == '.') {
1967 // we are looking for an empty spot here, so this capture is helpful:
1968 (*it
)->dictsset(x
,y
,0);
1969 (*it
)->dictsNO
--; // printf("-- C\n");
1976 if (movel
[movelistIndex
] & ENDOFNODE
) {
1977 vector
<MovelistCand
* >::iterator candsend
= cands
->end();
1978 for(vector
<MovelistCand
* >::iterator it
= cands
->begin(); it
!= candsend
; it
++) {
1979 if (*it
== 0) continue;
1980 if (!(*it
)->dictsNO
&& !(*it
)->dictsFound
) {
1981 if (!(*it
)->contList
.size()) {
1982 (*it
)->dictsF
= counter
;
1983 (*it
)->dictsFound
= true;
1984 } else if (!(*it
)->dictsFoundInitial
) {
1985 (*it
)->dictsFI
= counter
;
1986 (*it
)->dictsFoundInitial
= true;
1987 } else if (!(*it
)->dictsDR
) { // found initial position again during processing of contList
1988 char* d
= new char[(*it
)->p
->sizeX
*(*it
)->p
->sizeY
];
1989 for (int ct
=0; ct
< (*it
)->p
->sizeX
*(*it
)->p
->sizeY
; ct
++) d
[ct
] = (*it
)->dicts
[ct
];
1990 MovelistCand
* mlc
= new MovelistCand((*it
)->p
, (*it
)->orientation
, d
, 0, (*it
)->mx
, (*it
)->my
);
1991 mlc
->dictsFI
= counter
;
1992 cands
->push_back(mlc
);
2000 if (candssize
==0 && branchpoints
.size()==0) break;
2004 // printf("assemble results\n");
2006 if (!patternList
.nextMove
) { // look at matches w/o continuation
2007 for(vector
<MovelistCand
* >::iterator it
= cands
->begin(); it
!= cands
->end(); it
++) {
2008 if (*it
== 0) continue;
2009 if ((*it
)->dictsFound
) {
2010 if ((*it
)->p
->colorSwitch
) {
2012 char* rstr
= new char[3];
2016 result
->push_back(new Hit(new ExtendedMoveNumber((*it
)->dictsF
), rstr
)); // FIXME what w/ variations?
2018 char* rstr
= new char[3];
2022 result
->push_back(new Hit(new ExtendedMoveNumber((*it
)->dictsF
), rstr
));
2028 if (result
->size()) {
2029 numOfHits
+= result
->size();
2030 self_numOfSwitched
+= numOfSwitched
;
2032 if (gl
.getCurrentWinner() == 'B') {
2033 Bwins
+= result
->size() - numOfSwitched
;
2034 Wwins
+= numOfSwitched
;
2035 } else if (gl
.getCurrentWinner() == 'W') {
2036 Bwins
+= numOfSwitched
;
2037 Wwins
+= result
->size() - numOfSwitched
;
2039 gl
.makeCurrentHit(result
);
2040 } else delete result
;
2044 gl
.num_hits
= numOfHits
;
2045 gl
.num_switched
= self_numOfSwitched
;
2051 #if (defined(__BORLANDC__) || defined(_MSC_VER))
2052 const hashtype
Algo_hash::hashCodes
[] = {
2053 1448047776469843i64
, 23745670021858756i64
, 2503503679898819i64
,
2054 20893061577159209i64
, 10807838381971450i64
, 2362252468869198i64
,
2055 24259008893265414i64
, 12770534669822463i64
, 6243872632612083i64
,
2056 9878602848666731i64
, 15403460661141300i64
, 23328125617276831i64
,
2057 24399618481479321i64
, 6553504962910284i64
, 1670313139184804i64
,
2058 12980312942597170i64
, 20479559860862969i64
, 9622188310955879i64
,
2059 240315181816498i64
, 15806748501866401i64
, 11025185739521454i64
,
2060 9892014082139049i64
, 24468178939325513i64
, 18336761931886570i64
,
2061 17607110247268341i64
, 1659968630984898i64
, 15644176636883129i64
,
2062 21288430710467667i64
, 21718647773405600i64
, 8449573198599383i64
,
2063 12949198458251018i64
, 13260609204816340i64
, 15942818511406502i64
,
2064 19422389391992560i64
, 2306873372585698i64
, 13245768415868578i64
,
2065 3527685889767840i64
, 16821792770065498i64
, 14659578113224043i64
,
2066 8882299950073676i64
, 7855747638699870i64
, 11443553816792995i64
,
2067 10278034782711378i64
, 9888977721917330i64
, 8622555585025384i64
,
2068 20622776792089008i64
, 6447699412562541i64
, 21593237574254863i64
,
2069 4100056509197325i64
, 8358405560798101i64
, 24120904895822569i64
,
2070 21004758159739407i64
, 4380824971205155i64
, 23810250238005035i64
,
2071 11573868012372637i64
, 21740007761325076i64
, 20569500166060069i64
,
2072 23367084743140030i64
, 832128940274250i64
, 3863567854976796i64
,
2073 8401188629788306i64
, 20293444021869434i64
, 12476938100997420i64
,
2074 5997141871489394i64
, 777596196611050i64
, 8407423122275781i64
,
2075 23742268390341663i64
, 6606677504119583i64
, 17099083579458611i64
,
2076 128040681345920i64
, 7441253945309846i64
, 17672412151152227i64
,
2077 14657002484427869i64
, 3764334613856311i64
, 7399928989161192i64
,
2078 24730167942169592i64
, 13814924480574978i64
, 5810810907567287i64
,
2079 7008927747711241i64
, 3714629224790215i64
, 9946435535599731i64
,
2080 20057491299504334i64
, 15866852457019228i64
, 123155262761331i64
,
2081 1315783062254243i64
, 24497766846727950i64
, 12902532251391440i64
,
2082 16788431106050494i64
, 15993209359043506i64
, 6163570598235227i64
,
2083 23479274902645580i64
, 12086295521073246i64
, 14074331278381816i64
,
2084 1049820141442769i64
, 5160957003350972i64
, 24302799572195320i64
,
2085 23881606652035662i64
, 23969818184919245i64
, 19374430422494128i64
,
2086 9346353622623467i64
, 13646698673919768i64
, 20787456987251805i64
,
2087 19834903548127921i64
, 8194151691638546i64
, 7687885124853709i64
,
2088 4843137186034754i64
, 23141719256229263i64
, 5528755394284040i64
,
2089 22362536622784133i64
, 7624654257445620i64
, 8792845080211956i64
,
2090 24991012676161170i64
, 5382030845010972i64
, 1942150054817210i64
,
2091 1024267612932772i64
, 14257279792025309i64
, 11127353401828247i64
,
2092 4123063511789286i64
, 363215666444395i64
, 15523634951795520i64
,
2093 21114031740764324i64
, 12549698630972549i64
, 7906682572409157i64
,
2094 9682658163949194i64
, 14445831019902887i64
, 19796086007848283i64
,
2095 25041651202294181i64
, 434144873391024i64
, 24468825775827696i64
,
2096 16436890395501393i64
, 16373785289815135i64
, 16626551488832360i64
,
2097 7748715007439309i64
, 22731617567631698i64
, 14232800365889972i64
,
2098 10951727445457549i64
, 8041373240290953i64
, 24930514145406896i64
,
2099 9591184974667554i64
, 24880672410562956i64
, 23221721160805093i64
,
2100 20593543181655919i64
, 23599230930155014i64
, 15520097083998302i64
,
2101 14424914931817466i64
, 7073972177203460i64
, 16674214483955582i64
,
2102 4557916889838393i64
, 14520120252661131i64
, 2948253205366287i64
,
2103 18549806070390636i64
, 10409566723123418i64
, 18398906015238963i64
,
2104 21169009649313417i64
, 18391044531337716i64
, 2911838512392375i64
,
2105 13771057876708721i64
, 11955633853535396i64
, 18911960208175147i64
,
2106 1483143365895487i64
, 5864164841327281i64
, 16798674080914657i64
,
2107 21169543712647072i64
, 2554895121282201i64
, 12465286616181485i64
,
2108 5756888636558955i64
, 2597276631190750i64
, 2560624395830604i64
,
2109 20296901708171088i64
, 14642976680682096i64
, 12194169777111940i64
,
2110 938262584370639i64
, 7206443811292574i64
, 501111636607822i64
,
2111 5705951146039127i64
, 19098237626875269i64
, 5726006303511723i64
,
2112 5717532750720198i64
, 4848344546021481i64
, 7407311808156422i64
,
2113 2061821731974308i64
, 8556380079387133i64
, 13575103943220600i64
,
2114 10594365938844562i64
, 19966653780019989i64
, 24412404083453688i64
,
2115 8019373982039936i64
, 7753495706295280i64
, 838015840877266i64
,
2116 5235642127051968i64
, 10225916255867901i64
, 14975561937408701i64
,
2117 4914762527221109i64
, 16273933213731410i64
, 25240707945233645i64
,
2118 6477894775523777i64
, 16128190602024745i64
, 12452291569329611i64
,
2119 51030855211419i64
, 1848783942303739i64
, 2537297571305471i64
,
2120 24811709277564335i64
, 23354767332363093i64
, 11338712562024830i64
,
2121 10845782284945582i64
, 20710115514013598i64
, 19611282767915684i64
,
2122 11160258605900113i64
, 17875966449141620i64
, 8400967803093668i64
,
2123 6871997953834029i64
, 13914235659320051i64
, 8949576634650339i64
,
2124 2143755776666584i64
, 13309009078638265i64
, 17871461210902733i64
,
2125 11987276750060947i64
, 19212042799964345i64
, 9684310155516547i64
,
2126 1307858104678668i64
, 8369225045337652i64
, 11470364009363081i64
,
2127 10726698770860164i64
, 22857364846703600i64
, 25284735055035435i64
,
2128 19224377054148393i64
, 16403807100295998i64
, 4653376186522389i64
,
2129 15242640882406966i64
, 15315275662931969i64
, 11642086728644568i64
,
2130 12158439227609947i64
, 5366950703441186i64
, 21989897136444615i64
,
2131 21241101455718813i64
, 1591417368086590i64
, 14579493634035095i64
,
2132 23329624772309429i64
, 4022767503269837i64
, 12858990365780377i64
,
2133 1546772101519453i64
, 23839228242060485i64
, 3152020333001361i64
,
2134 7700997223270546i64
, 7886359803633970i64
, 18794372628879385i64
,
2135 22159114735365084i64
, 7999390508114986i64
, 17413096555746886i64
,
2136 9385231705999634i64
, 15875377080359488i64
, 4319895571584052i64
,
2137 15831501864738265i64
, 23927036136254152i64
, 9023165779396619i64
,
2138 6131245054225200i64
, 20314359892927215i64
, 1896686091879468i64
,
2139 14130616725563771i64
, 22653904323575475i64
, 9831497463521490i64
,
2140 13110057076369419i64
, 5902087517632052i64
, 23714067728868348i64
,
2141 10422641883492326i64
, 10327276345146850i64
, 795518417987648i64
,
2142 25452954487907785i64
, 3500196309207718i64
, 14513995844064906i64
,
2143 7844549909962914i64
, 9407804562184273i64
, 15229768031797498i64
,
2144 14111656085687927i64
, 16834184600349678i64
, 7291182384885469i64
,
2145 17771577974633552i64
, 21586473553657942i64
, 18166326806718423i64
,
2146 10928317030329388i64
, 13135712137024532i64
, 12947681282864548i64
,
2147 21220312239923983i64
, 9606249244876101i64
, 4653965165819933i64
,
2148 5039148287631156i64
, 3987726544496362i64
, 11235885894214833i64
,
2149 3549024987193191i64
, 6369560450327424i64
, 5296536600431238i64
,
2150 10833371878822587i64
, 5746338282416722i64
, 20335144029844343i64
,
2151 14857534135172842i64
, 13933887642921338i64
, 3610489245941154i64
,
2152 7780064458218242i64
, 18217608762631328i64
, 4861734558486078i64
,
2153 19138089389909524i64
, 162404484845663i64
, 6326150309736266i64
,
2154 5691634479075905i64
, 14377989390160001i64
, 7788436404648140i64
,
2155 20312143630017606i64
, 6781467023516504i64
, 7265384191721189i64
,
2156 13990392558924592i64
, 4811546322556989i64
, 3891404257596968i64
,
2157 19222546653408634i64
, 9733466771346453i64
, 20011679489309705i64
,
2158 11556921572925005i64
, 13429005557512149i64
, 16680841455593148i64
,
2159 394589115298971i64
, 22224576785554448i64
, 18262625753524808i64
,
2160 20893780129453860i64
, 25064972830160559i64
, 241970110039610i64
,
2161 7452533933839720i64
, 10726026396546933i64
, 17312051917081899i64
,
2162 17281553837379637i64
, 24008819488103387i64
, 5193878516496164i64
,
2163 21529615734706496i64
, 22844915602846365i64
, 17118246686087168i64
,
2164 6560869056902581i64
, 10553021967047717i64
, 3729950813036887i64
,
2165 14459986099519295i64
, 15808907290234758i64
, 6234512969275540i64
,
2166 18690008075805909i64
, 492531108753402i64
, 7721002928884704i64
,
2167 4886156035126456i64
, 21716374046066558i64
, 11035311630511661i64
,
2168 16837692753538891i64
, 20172053977953882i64
, 15488511700491202i64
,
2169 17477921115358343i64
, 24726937211646877i64
, 22480504880004621i64
,
2170 18521326635500559i64
, 8076560603417178i64
, 22382516625473209i64
,
2171 21696842111535623i64
, 12559160944089288i64
, 1661142873895453i64
,
2172 18379772814447567i64
, 10295321430586466i64
, 12378145201769592i64
,
2173 11815752235866582i64
};
2175 const hashtype
Algo_hash::hashCodes
[] = {
2176 1448047776469843LL , 23745670021858756LL , 2503503679898819LL ,
2177 20893061577159209LL , 10807838381971450LL , 2362252468869198LL ,
2178 24259008893265414LL , 12770534669822463LL , 6243872632612083LL ,
2179 9878602848666731LL , 15403460661141300LL , 23328125617276831LL ,
2180 24399618481479321LL , 6553504962910284LL , 1670313139184804LL ,
2181 12980312942597170LL , 20479559860862969LL , 9622188310955879LL ,
2182 240315181816498LL , 15806748501866401LL , 11025185739521454LL ,
2183 9892014082139049LL , 24468178939325513LL , 18336761931886570LL ,
2184 17607110247268341LL , 1659968630984898LL , 15644176636883129LL ,
2185 21288430710467667LL , 21718647773405600LL , 8449573198599383LL ,
2186 12949198458251018LL , 13260609204816340LL , 15942818511406502LL ,
2187 19422389391992560LL , 2306873372585698LL , 13245768415868578LL ,
2188 3527685889767840LL , 16821792770065498LL , 14659578113224043LL ,
2189 8882299950073676LL , 7855747638699870LL , 11443553816792995LL ,
2190 10278034782711378LL , 9888977721917330LL , 8622555585025384LL ,
2191 20622776792089008LL , 6447699412562541LL , 21593237574254863LL ,
2192 4100056509197325LL , 8358405560798101LL , 24120904895822569LL ,
2193 21004758159739407LL , 4380824971205155LL , 23810250238005035LL ,
2194 11573868012372637LL , 21740007761325076LL , 20569500166060069LL ,
2195 23367084743140030LL , 832128940274250LL , 3863567854976796LL ,
2196 8401188629788306LL , 20293444021869434LL , 12476938100997420LL ,
2197 5997141871489394LL , 777596196611050LL , 8407423122275781LL ,
2198 23742268390341663LL , 6606677504119583LL , 17099083579458611LL ,
2199 128040681345920LL , 7441253945309846LL , 17672412151152227LL ,
2200 14657002484427869LL , 3764334613856311LL , 7399928989161192LL ,
2201 24730167942169592LL , 13814924480574978LL , 5810810907567287LL ,
2202 7008927747711241LL , 3714629224790215LL , 9946435535599731LL ,
2203 20057491299504334LL , 15866852457019228LL , 123155262761331LL ,
2204 1315783062254243LL , 24497766846727950LL , 12902532251391440LL ,
2205 16788431106050494LL , 15993209359043506LL , 6163570598235227LL ,
2206 23479274902645580LL , 12086295521073246LL , 14074331278381816LL ,
2207 1049820141442769LL , 5160957003350972LL , 24302799572195320LL ,
2208 23881606652035662LL , 23969818184919245LL , 19374430422494128LL ,
2209 9346353622623467LL , 13646698673919768LL , 20787456987251805LL ,
2210 19834903548127921LL , 8194151691638546LL , 7687885124853709LL ,
2211 4843137186034754LL , 23141719256229263LL , 5528755394284040LL ,
2212 22362536622784133LL , 7624654257445620LL , 8792845080211956LL ,
2213 24991012676161170LL , 5382030845010972LL , 1942150054817210LL ,
2214 1024267612932772LL , 14257279792025309LL , 11127353401828247LL ,
2215 4123063511789286LL , 363215666444395LL , 15523634951795520LL ,
2216 21114031740764324LL , 12549698630972549LL , 7906682572409157LL ,
2217 9682658163949194LL , 14445831019902887LL , 19796086007848283LL ,
2218 25041651202294181LL , 434144873391024LL , 24468825775827696LL ,
2219 16436890395501393LL , 16373785289815135LL , 16626551488832360LL ,
2220 7748715007439309LL , 22731617567631698LL , 14232800365889972LL ,
2221 10951727445457549LL , 8041373240290953LL , 24930514145406896LL ,
2222 9591184974667554LL , 24880672410562956LL , 23221721160805093LL ,
2223 20593543181655919LL , 23599230930155014LL , 15520097083998302LL ,
2224 14424914931817466LL , 7073972177203460LL , 16674214483955582LL ,
2225 4557916889838393LL , 14520120252661131LL , 2948253205366287LL ,
2226 18549806070390636LL , 10409566723123418LL , 18398906015238963LL ,
2227 21169009649313417LL , 18391044531337716LL , 2911838512392375LL ,
2228 13771057876708721LL , 11955633853535396LL , 18911960208175147LL ,
2229 1483143365895487LL , 5864164841327281LL , 16798674080914657LL ,
2230 21169543712647072LL , 2554895121282201LL , 12465286616181485LL ,
2231 5756888636558955LL , 2597276631190750LL , 2560624395830604LL ,
2232 20296901708171088LL , 14642976680682096LL , 12194169777111940LL ,
2233 938262584370639LL , 7206443811292574LL , 501111636607822LL ,
2234 5705951146039127LL , 19098237626875269LL , 5726006303511723LL ,
2235 5717532750720198LL , 4848344546021481LL , 7407311808156422LL ,
2236 2061821731974308LL , 8556380079387133LL , 13575103943220600LL ,
2237 10594365938844562LL , 19966653780019989LL , 24412404083453688LL ,
2238 8019373982039936LL , 7753495706295280LL , 838015840877266LL ,
2239 5235642127051968LL , 10225916255867901LL , 14975561937408701LL ,
2240 4914762527221109LL , 16273933213731410LL , 25240707945233645LL ,
2241 6477894775523777LL , 16128190602024745LL , 12452291569329611LL ,
2242 51030855211419LL , 1848783942303739LL , 2537297571305471LL ,
2243 24811709277564335LL , 23354767332363093LL , 11338712562024830LL ,
2244 10845782284945582LL , 20710115514013598LL , 19611282767915684LL ,
2245 11160258605900113LL , 17875966449141620LL , 8400967803093668LL ,
2246 6871997953834029LL , 13914235659320051LL , 8949576634650339LL ,
2247 2143755776666584LL , 13309009078638265LL , 17871461210902733LL ,
2248 11987276750060947LL , 19212042799964345LL , 9684310155516547LL ,
2249 1307858104678668LL , 8369225045337652LL , 11470364009363081LL ,
2250 10726698770860164LL , 22857364846703600LL , 25284735055035435LL ,
2251 19224377054148393LL , 16403807100295998LL , 4653376186522389LL ,
2252 15242640882406966LL , 15315275662931969LL , 11642086728644568LL ,
2253 12158439227609947LL , 5366950703441186LL , 21989897136444615LL ,
2254 21241101455718813LL , 1591417368086590LL , 14579493634035095LL ,
2255 23329624772309429LL , 4022767503269837LL , 12858990365780377LL ,
2256 1546772101519453LL , 23839228242060485LL , 3152020333001361LL ,
2257 7700997223270546LL , 7886359803633970LL , 18794372628879385LL ,
2258 22159114735365084LL , 7999390508114986LL , 17413096555746886LL ,
2259 9385231705999634LL , 15875377080359488LL , 4319895571584052LL ,
2260 15831501864738265LL , 23927036136254152LL , 9023165779396619LL ,
2261 6131245054225200LL , 20314359892927215LL , 1896686091879468LL ,
2262 14130616725563771LL , 22653904323575475LL , 9831497463521490LL ,
2263 13110057076369419LL , 5902087517632052LL , 23714067728868348LL ,
2264 10422641883492326LL , 10327276345146850LL , 795518417987648LL ,
2265 25452954487907785LL , 3500196309207718LL , 14513995844064906LL ,
2266 7844549909962914LL , 9407804562184273LL , 15229768031797498LL ,
2267 14111656085687927LL , 16834184600349678LL , 7291182384885469LL ,
2268 17771577974633552LL , 21586473553657942LL , 18166326806718423LL ,
2269 10928317030329388LL , 13135712137024532LL , 12947681282864548LL ,
2270 21220312239923983LL , 9606249244876101LL , 4653965165819933LL ,
2271 5039148287631156LL , 3987726544496362LL , 11235885894214833LL ,
2272 3549024987193191LL , 6369560450327424LL , 5296536600431238LL ,
2273 10833371878822587LL , 5746338282416722LL , 20335144029844343LL ,
2274 14857534135172842LL , 13933887642921338LL , 3610489245941154LL ,
2275 7780064458218242LL , 18217608762631328LL , 4861734558486078LL ,
2276 19138089389909524LL , 162404484845663LL , 6326150309736266LL ,
2277 5691634479075905LL , 14377989390160001LL , 7788436404648140LL ,
2278 20312143630017606LL , 6781467023516504LL , 7265384191721189LL ,
2279 13990392558924592LL , 4811546322556989LL , 3891404257596968LL ,
2280 19222546653408634LL , 9733466771346453LL , 20011679489309705LL ,
2281 11556921572925005LL , 13429005557512149LL , 16680841455593148LL ,
2282 394589115298971LL , 22224576785554448LL , 18262625753524808LL ,
2283 20893780129453860LL , 25064972830160559LL , 241970110039610LL ,
2284 7452533933839720LL , 10726026396546933LL , 17312051917081899LL ,
2285 17281553837379637LL , 24008819488103387LL , 5193878516496164LL ,
2286 21529615734706496LL , 22844915602846365LL , 17118246686087168LL ,
2287 6560869056902581LL , 10553021967047717LL , 3729950813036887LL ,
2288 14459986099519295LL , 15808907290234758LL , 6234512969275540LL ,
2289 18690008075805909LL , 492531108753402LL , 7721002928884704LL ,
2290 4886156035126456LL , 21716374046066558LL , 11035311630511661LL ,
2291 16837692753538891LL , 20172053977953882LL , 15488511700491202LL ,
2292 17477921115358343LL , 24726937211646877LL , 22480504880004621LL ,
2293 18521326635500559LL , 8076560603417178LL , 22382516625473209LL ,
2294 21696842111535623LL , 12559160944089288LL , 1661142873895453LL ,
2295 18379772814447567LL , 10295321430586466LL , 12378145201769592LL ,
2296 11815752235866582LL };
2299 HashFEntry::HashFEntry(hashtype HASHCODE
, char* BUF
, int LENGTH
) {
2300 hashCode
= HASHCODE
;
2305 HashFEntry::HashFEntry(const HashFEntry
& hfe
) {
2306 hashCode
= hfe
.hashCode
;
2307 length
= hfe
.length
;
2308 buf
= new char[length
];
2309 for(int i
=0; i
<length
; i
++) buf
[i
] = hfe
.buf
[i
];
2312 HashFEntry::~HashFEntry() {
2319 HashhitF::HashhitF(int GAMEID
, char ORIENTATION
, char* blob
) {
2321 orientation
= ORIENTATION
;
2322 cont
= new MoveNC(blob
[0], blob
[1], blob
[2]);
2323 emn
= new ExtendedMoveNumber
;
2324 emn
->length
= blob
[3] * 256 + blob
[4];
2325 emn
->data
= new int[emn
->length
];
2326 for(int i
=0; i
<emn
->length
; i
++) {
2327 emn
->data
[i
] = blob
[5+2*i
]*256 + blob
[6+2*i
];
2331 HashhitF::HashhitF() {
2336 HashhitF::~HashhitF() {
2337 if (cont
) delete cont
;
2338 if (emn
) delete emn
;
2341 bool cmp_HashhitF(const HashhitF
* a
, const HashhitF
* b
) {
2342 return a
->gameid
< b
->gameid
;
2345 HashhitCS::HashhitCS(int GAMEID
, int POSITION
, bool CS
) {
2347 position
= POSITION
;
2351 bool cmp_HashhitCS(const HashhitCS
* a
, const HashhitCS
* b
) {
2352 return a
->gameid
< b
->gameid
;
2356 typedef vector
<HashhitF
* >* vpsip
;
2359 HashVarInfo::HashVarInfo(hashtype CHC
, vector
<pair
<hashtype
, ExtendedMoveNumber
>* > * LFC
,
2360 ExtendedMoveNumber
* MOVENUMBER
, int NUMSTONES
) {
2362 numStones
= NUMSTONES
;
2363 moveNumber
= new ExtendedMoveNumber(*MOVENUMBER
);
2364 lfc
= new vector
<pair
<hashtype
, ExtendedMoveNumber
>* >;
2365 for(vector
<pair
<hashtype
, ExtendedMoveNumber
>* >::iterator it
= LFC
->begin(); it
!= LFC
->end(); it
++) {
2366 lfc
->push_back(new pair
<hashtype
, ExtendedMoveNumber
>((*it
)->first
, (*it
)->second
));
2371 Algo_hash_full::Algo_hash_full(int bsize
, int MAXNUMSTONES
) : Algorithm(bsize
) {
2373 maxNumStones
= MAXNUMSTONES
;
2376 Algo_hash_full::~Algo_hash_full() {
2379 int Algo_hash_full::insert_hash(hashtype hashCode
, ExtendedMoveNumber
& mn
, Move
* continuation
) {
2380 // printf("insert %lld\n", hashCode);
2381 char* buf
= new char[30 + mn
.length
*2];
2383 buf
[0] = continuation
->x
;
2384 buf
[1] = continuation
->y
;
2385 buf
[2] = continuation
->color
;
2391 buf
[3] = mn
.length
/256;
2392 buf
[4] = mn
.length
%256;
2393 for (int i
=0; i
<mn
.length
; i
++) {
2394 buf
[5+2*i
] = mn
.data
[i
]/265;
2395 buf
[6+2*i
] = mn
.data
[i
]%256;
2397 hash_vector
.push_back(HashFEntry(hashCode
, buf
, 5+2*mn
.length
));
2401 int Algo_hash_full::insert_all_hashes() {
2403 sprintf(sql
, "insert into algo_hash_full_%d (hash, gameid, hit) values (?,?,?);", boardsize
);
2404 sqlite3_stmt
*ppStmt
=0;
2405 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
2406 if (rc
!= SQLITE_OK
|| ppStmt
==0) return rc
;
2407 for(vector
<HashFEntry
>::iterator it
= hash_vector
.begin(); it
!= hash_vector
.end(); it
++) {
2408 rc
= sqlite3_bind_int64(ppStmt
, 1, it
->hashCode
);
2409 if (rc
!= SQLITE_OK
) return rc
;
2410 rc
= sqlite3_bind_int(ppStmt
, 2, gid
);
2411 if (rc
!= SQLITE_OK
) return rc
;
2412 rc
= sqlite3_bind_blob(ppStmt
, 3, it
->buf
, it
->length
, SQLITE_TRANSIENT
);
2413 if (rc
!= SQLITE_OK
) return rc
;
2414 rc
= sqlite3_step(ppStmt
);
2415 if (rc
!= SQLITE_DONE
) return rc
;
2416 rc
= sqlite3_reset(ppStmt
);
2417 if (rc
!= SQLITE_OK
) return rc
;
2419 rc
= sqlite3_finalize(ppStmt
);
2420 if (rc
!= SQLITE_OK
) return rc
;
2421 hash_vector
.clear();
2422 return 0; // success
2425 void Algo_hash_full::initialize_process(sqlite3
* DB
) throw(DBError
) {
2426 // printf("enter algo_hash_full::initialize_processing\n");
2429 sprintf(sql
, "create table algo_hash_full_%d ( id integer primary key, hash integer, gameid integer, hit text );", boardsize
);
2430 int rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
2431 //if (rc != SQLITE_OK) throw DBError();
2432 sprintf(sql
, "create index hash_idx on algo_hash_full_%d(hash);", boardsize
);
2433 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
2434 //if (rc != SQLITE_OK) throw DBError();
2435 // printf("leave algo_hash_full::initialize_processing\n");
2438 void Algo_hash_full::newgame_process(int game_id
) {
2441 moveNumber
= new ExtendedMoveNumber(0);
2442 currentHashCode
= 0; // start with empty board
2443 lfc
= new vector
<pair
<hashtype
, ExtendedMoveNumber
>* >;
2444 branchpoints
= new stack
<HashVarInfo
>;
2447 void Algo_hash_full::AB_process(int x
, int y
) {
2448 for(vector
<pair
<hashtype
, ExtendedMoveNumber
>* >::iterator it
= lfc
->begin(); it
!= lfc
->end(); it
++) {
2449 Move
* continuation
= new Move(x
,y
,'B');
2450 if (insert_hash((*it
)->first
, (*it
)->second
, continuation
) != 0) throw DBError();
2451 delete continuation
;
2455 lfc
= new vector
<pair
<hashtype
, ExtendedMoveNumber
>* >;
2456 currentHashCode
+= Algo_hash::hashCodes
[x
+ boardsize
*y
];
2460 void Algo_hash_full::AW_process(int x
, int y
) {
2461 for(vector
<pair
<hashtype
, ExtendedMoveNumber
>* >::iterator it
= lfc
->begin(); it
!= lfc
->end(); it
++) {
2462 Move
* continuation
= new Move(x
,y
,'W');
2463 if (insert_hash((*it
)->first
, (*it
)->second
, continuation
) != 0) throw DBError();
2464 delete continuation
;
2468 lfc
= new vector
<pair
<hashtype
, ExtendedMoveNumber
>* >;
2469 currentHashCode
-= Algo_hash::hashCodes
[x
+ boardsize
*y
];
2473 void Algo_hash_full::AE_process(int x
, int y
, char removed
) {
2474 if (removed
== 'B') currentHashCode
-= Algo_hash::hashCodes
[x
+ boardsize
*y
];
2475 else currentHashCode
+= Algo_hash::hashCodes
[x
+ boardsize
*y
];
2479 void Algo_hash_full::endOfNode_process() {
2480 if (numStones
<= maxNumStones
) lfc
->push_back(new pair
<hashtype
, ExtendedMoveNumber
>(currentHashCode
, *moveNumber
));
2484 void Algo_hash_full::pass_process() {
2485 // (we do not count pass as continuation)
2488 void Algo_hash_full::move_process(Move m
) throw(DBError
) {
2489 for(vector
<pair
<hashtype
, ExtendedMoveNumber
>* >::iterator it
= lfc
->begin(); it
!= lfc
->end(); it
++) {
2490 Move
* continuation
= new Move(m
);
2491 int rc
= insert_hash((*it
)->first
, (*it
)->second
, continuation
);
2492 if (rc
!= 0) throw DBError();
2493 delete continuation
;
2497 lfc
= new vector
<pair
<hashtype
, ExtendedMoveNumber
>* >;
2498 int epsilon
= (m
.color
== 'B' || m
.color
== 'X' ? 1 : -1);
2499 currentHashCode
+= epsilon
* Algo_hash::hashCodes
[m
.x
+ boardsize
*m
.y
];
2503 vector
<p_cc
>::iterator it
;
2504 for(it
= m
.captures
->begin(); it
!= m
.captures
->end(); it
++) {
2506 int yy
= it
->second
;
2508 currentHashCode
+= epsilon
* Algo_hash::hashCodes
[xx
+ boardsize
*yy
];
2514 void Algo_hash_full::branchpoint_process() {
2515 branchpoints
->push(HashVarInfo(currentHashCode
, lfc
, moveNumber
, numStones
));
2516 // printf("push %lld\n", currentHashCode);
2519 void Algo_hash_full::endOfVariation_process() throw(DBError
) {
2520 for(vector
<pair
<hashtype
, ExtendedMoveNumber
>* >::iterator it
= lfc
->begin(); it
!= lfc
->end(); it
++) {
2521 int rc
= insert_hash((*it
)->first
, (*it
)->second
, 0);
2522 if (rc
!= 0) throw DBError();
2527 currentHashCode
= branchpoints
->top().chc
;
2528 lfc
= branchpoints
->top().lfc
;
2529 moveNumber
= branchpoints
->top().moveNumber
;
2530 numStones
= branchpoints
->top().numStones
;
2531 // printf("pop %lld\n", currentHashCode);
2532 branchpoints
->pop();
2535 void Algo_hash_full::endgame_process(bool commit
) throw(DBError
) {
2536 for(vector
<pair
<hashtype
, ExtendedMoveNumber
>* >::iterator it
= lfc
->begin(); it
!= lfc
->end(); it
++) {
2537 Move
* continuation
= 0;
2538 int rc
= insert_hash((*it
)->first
, (*it
)->second
, continuation
);
2539 if (rc
!= 0) throw DBError();
2543 int rc
= insert_all_hashes();
2544 if (rc
) printf("ouch %d\n",rc
);
2545 } else hash_vector
.clear();
2548 delete branchpoints
;
2551 void Algo_hash_full::finalize_process() {
2555 hashtype
Algo_hash_full::compute_hashkey(Pattern
& pattern
) {
2556 if (pattern
.sizeX
!= boardsize
|| pattern
.sizeY
!= boardsize
)
2557 return NOT_HASHABLE
;
2558 hashtype hashkey
= 0;
2560 for(int i
=0; i
<boardsize
; i
++) {
2561 for(int j
=0; j
<boardsize
; j
++) {
2562 char p
= pattern
.finalPos
[i
+ boardsize
*j
];
2563 if (p
== 'x' || p
== 'o' || p
== '*') return NOT_HASHABLE
;
2564 else if (p
== 'X') {
2565 hashkey
+= Algo_hash::hashCodes
[i
+ boardsize
*j
];
2567 } else if (p
== 'O') {
2568 hashkey
-= Algo_hash::hashCodes
[i
+ boardsize
*j
];
2573 if (ns
> maxNumStones
) return NOT_HASHABLE
;
2577 int insert_result_hf(void *results
, int argc
, char **argv
, char **azColName
) throw (DBError
) {
2578 vpsip res
= ((pair
<vpsip
, int>*)results
)->first
;
2579 int orientation
= ((pair
<vpsip
, int>*)results
)->second
;
2580 if (argc
==2 && argv
[0]) {
2581 res
->push_back(new HashhitF(atoi(argv
[0]), orientation
, argv
[1]));
2582 } else throw DBError();
2587 int Algo_hash_full::search(PatternList
& patternList
, GameList
& gl
, SearchOptions
& options
, sqlite3
* db
) {
2588 // printf("enter algo_hash_full::search\n");
2590 int self_numOfSwitched
= 0;
2594 int hash_result
= -1; // -1 = failure; 0 = ok, but have to check w/ Algo_movelist, 1 = ok, produced final result
2595 int plS
= patternList
.size();
2596 vpsip results
= new vector
<HashhitF
* >;
2597 for(int N
=0; N
<plS
; N
++) {
2598 hashtype hashCode
= compute_hashkey(patternList
.data
[N
]);
2599 if (hashCode
== NOT_HASHABLE
) return -1; // failure
2602 #if (defined(__BORLANDC__) || defined(_MSC_VER))
2603 sprintf(sql
, "select gameid,hit from algo_hash_full_%d where hash = %I64d", boardsize
, hashCode
);
2605 sprintf(sql
, "select gameid,hit from algo_hash_full_%d where hash = %lld", boardsize
, hashCode
);
2607 // printf("hc %lld, %s\n", hashCode, sql);
2608 pair
<vpsip
, int> rN(results
, N
);
2609 sqlite3_exec(db
, sql
, insert_result_hf
, &rN
, 0);
2611 if (options
.trustHashFull
&& patternList
.pattern
.contList
.size()==0) hash_result
= 1;
2612 else hash_result
= 0;
2613 if (gl
.start_sorted() == 0) {
2614 sort(results
->begin(), results
->end(), cmp_HashhitF
);
2615 // printf("res-size %d\n", results->size());
2616 vector
<HashhitF
* >::iterator resultIT
= results
->begin();
2617 while (resultIT
!= results
->end()) {
2618 int index
= (*resultIT
)->gameid
;
2621 gl
.setCurrentFromIndex(index
);
2622 int numOfSwitched
= 0;
2623 vector
<Hit
* >* hits
= new vector
<Hit
* >;
2624 while ((*resultIT
)->gameid
== index
) {
2625 if ((*resultIT
)->emn
->total_move_num() > options
.moveLimit
) {
2630 if ((*resultIT
)->cont
->x
!= NO_CONT
) { // continuation
2631 label
= patternList
.updateContinuations((*resultIT
)->orientation
,
2632 (*resultIT
)->cont
->x
, (*resultIT
)->cont
->y
, (*resultIT
)->cont
->color
,
2633 false, // tenuki impossible with full board pattern
2634 gl
.getCurrentWinner());
2636 hits
->push_back(new Hit((*resultIT
)->emn
, label
));
2637 (*resultIT
)->emn
= 0;
2638 numOfSwitched
+= label
[2];
2641 label
= new char[3];
2644 label
[2] = patternList
.data
[(*resultIT
)->orientation
].colorSwitch
;
2645 numOfSwitched
+= label
[2];
2646 hits
->push_back(new Hit((*resultIT
)->emn
, label
));
2647 (*resultIT
)->emn
= 0;
2650 if (resultIT
== results
->end()) break;
2653 numOfHits
+= hits
->size();
2654 self_numOfSwitched
+= numOfSwitched
;
2655 if (gl
.getCurrentWinner() == 'B') {
2656 Bwins
+= hits
->size() - numOfSwitched
;
2657 Wwins
+= numOfSwitched
;
2658 } else if (gl
.getCurrentWinner() == 'W') {
2659 Bwins
+= numOfSwitched
;
2660 Wwins
+= hits
->size() - numOfSwitched
;
2662 gl
.makeCurrentHit(hits
);
2664 } else { // produce Candidate list, check using another algorithm
2665 vector
<Candidate
* >* candidates
= new vector
<Candidate
* >;
2666 while ((*resultIT
)->gameid
== index
) {
2667 if ((*resultIT
)->emn
->total_move_num() > options
.moveLimit
) continue;
2668 candidates
->push_back(new Candidate(0,0,(*resultIT
)->orientation
));
2670 if (resultIT
== results
->end()) break;
2672 gl
.makeIndexCandidate(index
, candidates
);
2675 for(vector
<HashhitF
* >::iterator it
= results
->begin(); it
!= results
->end(); it
++) delete *it
;
2679 gl
.num_hits
= numOfHits
;
2680 gl
.num_switched
= self_numOfSwitched
;
2686 // -----------------------------------------------------------------------------------
2688 Algo_hash::Algo_hash(int bsize
, const string
& DBNAMEEXT
, int MAXNUMSTONES
) : Algorithm(bsize
) {
2689 dbnameext
= DBNAMEEXT
;
2691 maxNumStones
= MAXNUMSTONES
;
2694 Algo_hash::~Algo_hash() {
2698 int Algo_hash::insert_hash(hashtype hashCode
, int pos
) {
2699 hash_vector
.push_back(make_pair(hashCode
, pos
));
2703 int Algo_hash::insert_all_hashes() {
2704 // printf("insert all hashes %d\n", hash_vector.size());
2706 sprintf(sql
, "insert into algo_hash_%d_%s (hash, gameid, position) values (?,?,?);", boardsize
, dbnameext
.c_str());
2707 sqlite3_stmt
*ppStmt
=0;
2708 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
2709 if (rc
!= SQLITE_OK
|| ppStmt
==0) return rc
;
2710 rc
= sqlite3_bind_int(ppStmt
, 2, gid
);
2711 if (rc
!= SQLITE_OK
) return rc
;
2712 for(vector
<pair
<hashtype
, int> >::iterator it
= hash_vector
.begin(); it
!= hash_vector
.end(); it
++) {
2713 // printf("insert %d %d\n", it->first, it->second);
2714 rc
= sqlite3_bind_int64(ppStmt
, 1, it
->first
);
2715 if (rc
!= SQLITE_OK
) return rc
;
2716 rc
= sqlite3_bind_int(ppStmt
, 3, it
->second
);
2717 if (rc
!= SQLITE_OK
) return rc
;
2718 rc
= sqlite3_step(ppStmt
);
2719 if (rc
!= SQLITE_DONE
) return rc
;
2720 rc
= sqlite3_reset(ppStmt
);
2721 if (rc
!= SQLITE_OK
) return rc
;
2723 rc
= sqlite3_finalize(ppStmt
);
2724 if (rc
!= SQLITE_OK
) return rc
;
2725 return 0; // success
2728 void Algo_hash::initialize_process(sqlite3
* DB
) throw(DBError
) {
2729 // printf("enter algo_hash::initialize_processing\n");
2732 sprintf(buf
, "create table algo_hash_%d_%s ( hash integer, gameid integer, position integer );", boardsize
, dbnameext
.c_str());
2733 int rc
= sqlite3_exec(db
, buf
, 0, 0, 0);
2734 //if (rc != SQLITE_OK) throw DBError();
2735 sprintf(buf
, "create index hash_idx_%d_%s on algo_hash_%d_%s(hash);", boardsize
, dbnameext
.c_str(), boardsize
, dbnameext
.c_str());
2736 rc
= sqlite3_exec(db
, buf
, 0, 0, 0);
2737 //if (rc != SQLITE_OK) throw DBError();
2738 // printf("leave algo_hash::initialize_processing\n");
2741 void Algo_hash::newgame_process(int game_id
) {
2743 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2747 void Algo_hash::AB_process(int x
, int y
) {
2748 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2752 void Algo_hash::AW_process(int x
, int y
) {
2753 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2757 void Algo_hash::AE_process(int x
, int y
, char removed
) {
2758 if (removed
== 'B') {
2759 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++) it
->removeB(x
,y
);
2761 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++) it
->removeW(x
,y
);
2765 void Algo_hash::endOfNode_process() {
2766 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++) {
2767 if (it
->numStones
<= maxNumStones
&& it
->changed
) {
2768 it
->changed
= false;
2769 pair
<hashtype
,int> phi
= it
->cHC();
2770 insert_hash(phi
.first
, phi
.second
);
2771 // printf("insert hash CORNER %d %d\n", phi.first, phi.second);
2776 void Algo_hash::pass_process() {
2777 // (we do not count pass as continuation)
2780 void Algo_hash::move_process(Move m
) throw(DBError
) {
2781 if (m
.color
== 'B') {
2782 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2785 for(vector
<p_cc
>::iterator cap_it
= m
.captures
->begin(); cap_it
!= m
.captures
->end(); cap_it
++) {
2786 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2787 it
->removeW(cap_it
->first
, cap_it
->second
);
2791 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2794 for(vector
<p_cc
>::iterator cap_it
= m
.captures
->begin(); cap_it
!= m
.captures
->end(); cap_it
++) {
2795 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2796 it
->removeB(cap_it
->first
, cap_it
->second
);
2802 void Algo_hash::branchpoint_process() {
2803 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2807 void Algo_hash::endOfVariation_process() {
2808 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2812 void Algo_hash::endgame_process(bool commit
) {
2813 for(vector
<HashInstance
>::iterator it
= hi
->begin(); it
!= hi
->end(); it
++)
2816 int rc
= insert_all_hashes();
2817 if (rc
) printf("ouch %d\n",rc
);
2818 hash_vector
.clear();
2819 } else hash_vector
.clear();
2822 void Algo_hash::finalize_process() {
2826 pair
<hashtype
,int> Algo_hash::compute_hashkey(PatternList
& pl
, int CS
) {
2827 return make_pair(NOT_HASHABLE
,0);
2830 int insert_result(void *rN
, int argc
, char **argv
, char **azColName
) throw (DBError
) {
2831 vector
<HashhitCS
* >* results
= ((pair
<vector
<HashhitCS
* >*, hashtype
>*)rN
)->first
;
2832 hashtype hashCode
= ((pair
<vector
<HashhitCS
* >*, hashtype
>*)rN
)->second
;
2834 if (argc
==3 && argv
[0] && argv
[1] && argv
[2]) {
2835 // printf("found %s, %lld", argv[2], atoi(argv[2]));
2836 #if (defined(__BORLANDC__) || defined(_MSC_VER))
2837 ((vector
<HashhitCS
* >*)results
)->push_back(new HashhitCS(atoi(argv
[0]), atoi(argv
[1]), _atoi64(argv
[2])!=hashCode
));
2839 ((vector
<HashhitCS
* >*)results
)->push_back(new HashhitCS(atoi(argv
[0]), atoi(argv
[1]), atoll(argv
[2])!=hashCode
));
2841 } else throw DBError();
2846 int Algo_hash::search(PatternList
& patternList
, GameList
& gl
, SearchOptions
& options
, sqlite3
* db
) {
2847 // return value: -1 = failure; 0 = ok, but have to check w/ Algo_movelist
2849 vector
<HashhitCS
* >* results
= new vector
<HashhitCS
* >;
2851 pair
<hashtype
, int> hco
= compute_hashkey(patternList
, 0);
2852 hashtype hashCode
= hco
.first
;
2853 // printf("HC %lld\n", hashCode);
2854 hashtype hashCode2
= hashCode
;
2855 if (hashCode
== NOT_HASHABLE
) {
2857 return -1; // failure
2859 int fl
= patternList
.data
[hco
.second
].flip
;
2862 #if (defined(__BORLANDC__) || defined(_MSC_VER))
2863 sprintf(buf
, "select gameid,position,hash from algo_hash_%d_%s where hash = %I64d",
2864 boardsize
, dbnameext
.c_str(), hashCode
);
2866 sprintf(buf
, "select gameid,position,hash from algo_hash_%d_%s where hash = %lld",
2867 boardsize
, dbnameext
.c_str(), hashCode
);
2871 bool cs
= patternList
.data
[patternList
.size()-1].colorSwitch
;
2873 pair
<hashtype
, int> hco
= compute_hashkey(patternList
, 1);
2874 hashCode2
= hco
.first
;
2875 // printf("HC2 %lld\n", hashCode2);
2876 if (hashCode
== NOT_HASHABLE
) {
2878 return -1; // failure
2880 fl2
= patternList
.data
[hco
.second
].flip
;
2882 if (hashCode
!= hashCode2
) {
2883 #if (defined(__BORLANDC__) || defined(_MSC_VER))
2884 sprintf(buf
, " or hash = %I64d", hashCode2
);
2886 sprintf(buf
, " or hash = %lld", hashCode2
);
2891 sql
+= " order by gameid";
2893 if (gl
.start_sorted() == 0) {
2896 // printf("%s\n", sql);
2897 pair
<vector
<HashhitCS
* >*, hashtype
> rN(results
, hashCode
);
2898 sqlite3_exec(db
, sql
.c_str(), insert_result
, &rN
, 0);
2899 // printf("results->size() %d\n", results->size());
2901 // communicate results of query to database
2903 vector
<HashhitCS
* >::iterator resultIT
= results
->begin();
2904 while (resultIT
!= results
->end()) {
2905 // printf("gid %d\n", (*resultIT)->gameid);
2906 int index
= (*resultIT
)->gameid
;
2908 vector
<Candidate
* >* candidates
= new vector
<Candidate
* >;
2909 while ((*resultIT
)->gameid
== index
) {
2910 // int pos = (*resultIT)->position % (1<<16);
2911 int ori
= (*resultIT
)->position
/ (1<<16);
2912 // printf("%d %d\n", pos, ori);
2913 if (cs
&& hashCode
== hashCode2
) { // this is a somewhat pathological case ...
2914 int ind
= patternList
.flipTable
[Pattern::compose_flips(Pattern::PatternInvFlip(ori
),fl
)];
2915 candidates
->push_back(new Candidate(patternList
.data
[ind
].left
, patternList
.data
[ind
].top
, ind
));
2916 ind
= patternList
.flipTable
[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori
),fl2
)];
2917 candidates
->push_back(new Candidate(patternList
.data
[ind
].left
, patternList
.data
[ind
].top
, ind
));
2919 if ((*resultIT
)->cs
) {
2920 // FIXME works only for corner patterns right now!
2921 int ind
= patternList
.flipTable
[8+Pattern::compose_flips(Pattern::PatternInvFlip(ori
),fl2
)];
2922 // 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);
2923 candidates
->push_back(new Candidate(patternList
.data
[ind
].left
, patternList
.data
[ind
].top
, ind
));
2925 int ind
= patternList
.flipTable
[Pattern::compose_flips(Pattern::PatternInvFlip(ori
),fl
)];
2926 // printf("cand %d %d %d\n", patternList.flipTable[Pattern::compose_flips(Pattern::PatternInvFlip(ori),fl)], patternList.data[ind].left, patternList.data[ind].top);
2927 candidates
->push_back(new Candidate(patternList
.data
[ind
].left
, patternList
.data
[ind
].top
, ind
));
2931 if (resultIT
== results
->end()) break;
2933 gl
.makeIndexCandidate(index
, candidates
);
2935 for(vector
<HashhitCS
* >::iterator it
= results
->begin(); it
!= results
->end(); it
++) delete *it
;
2942 Algo_hash_corner::Algo_hash_corner(int bsize
, int SIZE
, int MAXNUMSTONES
) : Algo_hash(bsize
, "CORNER", MAXNUMSTONES
) {
2945 sprintf(buf
, "%d", size
);
2947 hi
= new vector
<HashInstance
>;
2948 hi
->push_back(HashInstance(0,0,size
,size
,boardsize
));
2949 hi
->push_back(HashInstance(0,bsize
-size
,size
,size
,boardsize
));
2950 hi
->push_back(HashInstance(bsize
-size
,0,size
,size
,boardsize
));
2951 hi
->push_back(HashInstance(bsize
-size
, bsize
-size
, size
, size
,boardsize
));
2954 pair
<hashtype
,int> Algo_hash_corner::compute_hashkey(PatternList
& pl
, int CS
) {
2955 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);
2956 hashtype hk
= NOT_HASHABLE
;
2958 vector
<hashtype
> hCodes
;
2959 for(int pCtr
=0; pCtr
<pl
.size(); pCtr
++) {
2960 if (CS
== pl
.data
[pCtr
].colorSwitch
) {
2961 hashtype hashkey
= 0;
2964 Pattern
*pattern
= & pl
.data
[pCtr
];
2967 if (pattern
->left
> 0) offsetX
= boardsize
-size
-pattern
->left
; // pattern located on east side of board
2968 if (pattern
->top
> 0) offsetY
= boardsize
-size
-pattern
->top
; // ... south ...
2969 for(int i
=0; i
<size
; i
++) {
2970 for(int j
=0; j
<size
; j
++) {
2971 char p
= pattern
->finalPos
[i
+offsetX
+ pattern
->sizeX
*(j
+offsetY
)];
2972 if (p
== 'x' || p
== 'o' || p
== '*') return make_pair(NOT_HASHABLE
,0);
2973 else if (p
== 'X') {
2974 hashkey
+= hashCodes
[i
+offsetX
+pattern
->left
+ boardsize
*(j
+offsetY
+pattern
->top
)];
2976 } else if (p
== 'O') {
2977 hashkey
-= hashCodes
[i
+offsetX
+pattern
->left
+ boardsize
*(j
+offsetY
+pattern
->top
)];
2982 if (ns
< 3 || ns
> maxNumStones
) return make_pair(NOT_HASHABLE
,0);
2984 // make sure all hash keys are unique
2985 for(vector
<hashtype
>::iterator it
= hCodes
.begin(); it
!= hCodes
.end(); it
++)
2986 if (*it
== hashkey
) return make_pair(NOT_HASHABLE
, 0);
2987 hCodes
.push_back(hashkey
);
2989 if (hk
==NOT_HASHABLE
|| hashkey
<hk
) {
2995 return make_pair(hk
, f
);
2998 // Algo_hash_side::Algo_hash_side(int bsize, int SIZEX, int SIZEY) : Algo_hash(bsize, "SIDE") {
3002 // sprintf(buf, "%d_%d", sizeX, sizeY);
3003 // dbnameext += buf;
3005 // hi = new vector<HashInstance>;
3006 // for(int i=1; i<bsize-1-sizeX; i++)
3007 // hi->push_back(HashInstance(i,0,sizeX, sizeY,boardsize));
3008 // for(int i=1; i<bsize-1-sizeX; i++)
3009 // hi->push_back(HashInstance(i,bsize-sizeY,sizeX, sizeY,boardsize));
3010 // for(int i=1; i<bsize-1-sizeX; i++)
3011 // hi->push_back(HashInstance(0, i, sizeY, sizeX,boardsize));
3012 // for(int i=1; i<bsize-1-sizeX; i++)
3013 // hi->push_back(HashInstance(bsize-sizeY, i, sizeY, sizeX,boardsize));
3016 HashInstance::HashInstance(char X
, char Y
, char SIZEX
, char SIZEY
, int BOARDSIZE
) {
3017 boardsize
= BOARDSIZE
;
3020 pos
= xx
+ boardsize
*yy
;
3024 currentHashCode
= 0;
3029 HashInstance::~HashInstance() {
3033 void HashInstance::finalize() {
3035 while (branchpoints
->size()) {
3036 delete [] branchpoints
->top().first
;
3037 branchpoints
->pop();
3039 delete branchpoints
;
3042 if (currentHashCode
) {
3043 delete [] currentHashCode
;
3044 currentHashCode
= 0;
3048 bool HashInstance::inRelevantRegion(char X
, char Y
) {
3049 if (xx
<= X
&& X
< xx
+sizeX
&& yy
<= Y
&& Y
< yy
+sizeY
) return true;
3053 void HashInstance::initialize() {
3054 currentHashCode
= new hashtype
[8];
3055 for(int i
=0; i
<8; i
++) currentHashCode
[i
] = 0; // start with empty board
3057 branchpoints
= new stack
<pair
<hashtype
*,int> >;
3058 changed
= true; // do record empty pattern ...
3061 void HashInstance::addB(char x
, char y
) {
3062 if (inRelevantRegion(x
,y
)) {
3064 for(int i
=0; i
<8; i
++) {
3065 currentHashCode
[i
] += Algo_hash::hashCodes
[Pattern::flipsX(i
,x
,y
,boardsize
-1, boardsize
-1) + boardsize
*Pattern::flipsY(i
,x
,y
,boardsize
-1, boardsize
-1)];
3071 void HashInstance::addW(char x
, char y
) {
3072 if (inRelevantRegion(x
,y
)) {
3074 for(int i
=0; i
<8; i
++) {
3075 currentHashCode
[i
] -= Algo_hash::hashCodes
[Pattern::flipsX(i
,x
,y
,boardsize
-1, boardsize
-1) + boardsize
*Pattern::flipsY(i
,x
,y
,boardsize
-1, boardsize
-1)];
3081 void HashInstance::removeB(char x
, char y
) {
3082 if (inRelevantRegion(x
,y
)) {
3084 for(int i
=0; i
<8; i
++) {
3085 currentHashCode
[i
] -= Algo_hash::hashCodes
[Pattern::flipsX(i
,x
,y
,boardsize
-1, boardsize
-1) + boardsize
*Pattern::flipsY(i
,x
,y
,boardsize
-1, boardsize
-1)];
3091 void HashInstance::removeW(char x
, char y
) {
3092 if (inRelevantRegion(x
,y
)) {
3094 for(int i
=0; i
<8; i
++) {
3095 currentHashCode
[i
] += Algo_hash::hashCodes
[Pattern::flipsX(i
,x
,y
,boardsize
-1, boardsize
-1) + boardsize
*Pattern::flipsY(i
,x
,y
,boardsize
-1, boardsize
-1)];
3101 pair
<hashtype
,int> HashInstance::cHC() {
3103 hashtype minCHC
= currentHashCode
[0];
3104 for(int i
=1; i
<8; i
++) {
3105 if (currentHashCode
[i
] < minCHC
) {
3106 minCHC
= currentHashCode
[i
];
3110 return make_pair(minCHC
, flip
*(1<<16) + pos
);
3113 void HashInstance::bppush() {
3114 hashtype
* chc
= new hashtype
[8];
3115 for(int i
=0; i
<8; i
++) chc
[i
] = currentHashCode
[i
];
3116 branchpoints
->push(make_pair(chc
, numStones
));
3119 void HashInstance::bppop() {
3120 delete [] currentHashCode
;
3121 currentHashCode
= branchpoints
->top().first
;
3122 numStones
= branchpoints
->top().second
;
3123 branchpoints
->pop();
3127 // UIntervals::UIntervals(intervs = []) {
3132 // void UIntervals::first() {
3133 // if (data->size()) return data[0].first;
3134 // else return -1; // FIXME ?!
3137 // void UIntervals::append(int interv_start, int interv_end) {
3138 // data.push_back(pair<int,int>(interv_start, interv_end));
3142 // void UIntervals::inters(UIntervals& uinterv) {
3143 // int current2low = 0;
3144 // int current2high = 0;
3146 // vector<pair<int,int>> newUInt();
3148 // for(int current1=0; current1 < data.size(); current1++) {
3149 // while (current2low < uinterv.data.size && !(uinterv.data[current2low].second > data[current1].first))
3151 // current2high = current2low;
3152 // while (current2high < uinterv.data.size() && uinterv.data[current2high].first < data[current1].second)
3156 // if (current2low == uinterv.data.size()) break;
3157 // if (current2high < current2low) continue;
3159 // newUInt.append(max(self.data[current1][0], uinterv.data[current2low][0]),
3160 // min(self.data[current1][1], uinterv.data[current2low][1]));
3162 // for(int c=current2low+1; c < current2high; c++)
3163 // newUInt.append(uinterv.data[c].first, uninterv.data[c].second);
3165 // if (current2high > current2low)
3166 // newUInt.append(uinterv.data[current2high].first, min(uinterv.data[current2high].second, data[current1].second));
3168 // current2low = current2high;
3173 // void UIntervals::isEmpty() {
3175 // for(int i=0; i<data.size(); i++)
3176 // if (data[i].first < data[i].second) isEmpty = 0;
3182 // Algo_intervals::Algo_intervals(int bsize) {
3183 // boardsize = bsize;
3187 // void Algo_intervals::initialize_process(int l) {
3189 // movesArr = vector<long>();
3190 // moveIntsArr = vector<long>();
3193 // void Algo_intervals::newgame_process() {
3196 // for(int i=0; i<boardsize*boardsize; i++) moves.append([]);
3200 // void Algo_intervals::AB_process(int x, int y) {
3201 // if (ignore) return;
3202 // moves[boardsize*x+y]->push_back(counter | FLAG_BLACK);
3206 // void Algo_intervals::AW_process(int x, int y) {
3207 // if (ignore) return;
3208 // moves[boardsize*x+y]->push_back(counter | FLAG_WHITE);
3211 // void Algo_intervals::AE_process(int x, int y, char removed) {
3212 // if (ignore) return;
3213 // self.moves[self.boardsize*x+y]->push_back(counter | FLAG_REMOVE);
3216 // void Algo_intervals::endOfNode_process() {
3217 // if (ignore) return;
3221 // void Algo_intervals::B_process(int x, int y, cap) {
3222 // if (ignore) return;
3223 // moves[self.boardsize*x+y]->push_back(counter | FLAG_BLACK);
3225 // moves[self.boardsize*c[0] + c[1]]->push_back(counter | FLAG_REMOVE);
3228 // void Algo_intervals::W_process(int x, int y, cap) {
3229 // if (ignore) return;
3230 // moves[self.boardsize*x+y]->push_back(counter | FLAG_WHITE);
3232 // moves[self.boardsize*c[0] + c[1]]->push_back(counter | FLAG_REMOVE);
3235 // void Algo_intervals::branchpoint_process() {
3239 // void Algo_intervals::endOfVariation_process() {
3244 // void Algo_intervals::endgame_process() {
3245 // for(int x=0; x < boardsize; x++) {
3246 // for(int y=0; y < boardsize; y++) {
3247 // if (!moves[self.boardsize*x+y]->size())
3248 // movesArr.push_back(0);
3249 // else if (moves[self.boardsize*x+y]->size() == 1) {
3250 // long d = (*moves[self.boardsize*x+y])[0];
3251 // self.movesArr.append(d);
3254 // vector<int>* mvs = moves[self.boardsize*x+y];
3255 // long d = moveIntsArr.size() | FLAG_POINTER;
3257 // vector<long> Blist;
3258 // vector<long> Wlist;
3259 // vector<long> Elist;
3261 // Elist.push_back(0);
3263 // int moveIndex = 0;
3264 // while (moveIndex < mvs.size()) {
3265 // if (mvs[moveIndex] & FLAG_BLACK) {
3266 // d = d | FLAG_BLACK;
3267 // Blist.push_back(mvs[moveIndex] & ~FLAG_BLACK);
3268 // Elist.push_back(mvs[moveIndex] & ~FLAG_BLACK);
3269 // if (moveIndex + 1 < mvs->size()) {
3270 // Blist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
3271 // Elist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
3273 // else Blist.push_back(MAXNOMOVES);
3275 // if (mvs[moveIndex] & FLAG_WHITE) {
3276 // d = d | FLAG_WHITE;
3277 // Wlist.push_back(mvs[moveIndex] & ~FLAG_WHITE);
3278 // Elist.push_back(mvs[moveIndex] & ~FLAG_WHITE);
3279 // if (moveIndex + 1 < mvs->size()) {
3280 // Wlist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
3281 // Elist.push_back(mvs[moveIndex+1] & ~(FLAG_BLACK|FLAG_WHITE|FLAG_REMOVE));
3283 // else Wlist.append(MAXNOMOVES);
3288 // if ((!Blist.size() || Blist[Blist.size()-1] != MAXNOMOVES) &&
3289 // (!Wlist.size() || Wlist[Wlist.size()-1] != MAXNOMOVES))
3290 // Elist.push_back(MAXNOMOVES);
3292 // moveIntsArr.push_back(Blist.size());
3293 // moveIntsArr.push_back(Wlist.size());
3294 // moveIntsArr.push_back(Elist.size());
3295 // moveIntsArr.extend(Blist);
3296 // moveIntsArr.extend(Wlist);
3297 // moveIntsArr.extend(Elist);
3299 // movesArr.push_back(d);
3305 // void Algo_intervals::finalize_process(datap) {
3307 // extract datap0, datap1 from datap
3309 // String fn = datap0 + "/movesarr" + datap1 + ".db"; // FIXME: linux specific!?
3310 // ofstream file(fn, ios::out|ios::trunc|ios::binary) // FIXME: careful with ios::trunc
3311 // file.write(movesArr, movesArrSize);
3314 // fn = datap0 + "/moveints" + datap1 + ".db"; // FIXME: linux specific!?
3315 // file(fn, ios::out|ios::trunc|ios::binary) // FIXME: careful with ios::trunc
3316 // file.write(moveIntsArr, moveIntsArrSize);
3322 // int Algo_intervals::retrieve_db(datap) {
3323 // String fn = ... "/movesarr" ...; // FIXME
3324 // ifstream file (fn, ios::in|ios::binary|ios::ate);
3325 // if (file.is_open()) {
3326 // ifstream::pos_type size = file.tellg();
3327 // delete [] movesArr;
3328 // movesArr = new char[size]; // FIXME: not a char array?
3329 // file.seekg (0, ios::beg);
3330 // file.read (memblock, size);
3336 // String fn = ... "/moveints" ...; // FIXME
3337 // ifstream file (fn, ios::in|ios::binary|ios::ate);
3338 // if (file.is_open()) {
3339 // ifstream::pos_type size = file.tellg();
3340 // delete [] moveIntsArr;
3341 // moveIntsArr = new char[size]; // FIXME: not a char array?
3342 // file.seekg (0, ios::beg);
3343 // file.read (memblock, size);
3352 // void Algo_intervals::getUInterv(mves, vector<long> mves1, int gameno, int x, int y, char color) {
3354 // UIntervals UInterv();
3355 // int typeInterv = 0;
3356 // long d = mves[gameno*boardsize*boardsize + boardsize*x + y];
3358 // if (d & FLAG_POINTER) {
3360 // if (color == 'X' && !(d & FLAG_BLACK)) return 0, UIntervals();
3361 // if (color == 'O' && !(d & FLAG_WHITE)) return 0, UIntervals();
3363 // long p = d & MAXNOMOVES;
3364 // long lenB = moves1[p];
3365 // long lenW = moves1[p+1];
3366 // long lenE = moves1[p+2];
3370 // if (color == 'X') {
3374 // else if (color == 'O') {
3375 // start = p + 3 + lenB;
3378 // else if (color == '.') {
3379 // start = p + 3 + lenB + lenW;
3384 // for(int i=0; i<length/2; i++)
3385 // l.append((moves1[start+2*i], moves1[start+2*i+1]));
3387 // if (l[-1][1] == MAXNOMOVES) typeInterv = length-1;
3388 // else typeInterv = length;
3389 // return typeInterv, UIntervals(l);
3392 // if (color == 'X' && (d & FLAG_BLACK))
3393 // return 1, UIntervals([( d & MAXNOMOVES , MAXNOMOVES)]);
3394 // else if (color == 'O' && (d & FLAG_WHITE))
3395 // return 1, UIntervals([( d & MAXNOMOVES , MAXNOMOVES)]);
3396 // else if (color == '.') {
3397 // if (!d) return -1, UIntervals([(0, MAXNOMOVES)]);
3398 // else return 1, UIntervals([(0, d & MAXNOMOVES)]);
3401 // return 0, UIntervals();
3405 // void Algo_intervals::search(patternList, options, db,
3406 // continuations, contLabelsIndex, contLabels,
3407 // progBar, progStart, progEnd) {
3409 // int numOfHits = 0;
3410 // int overallSwitched = 0;
3413 // int index = db.start();
3415 // if (!self.retrieve_db(db.datapath)) {
3416 // printf("Error!\n"); // FIXME
3420 // int movelimit = MAXNOMOVES;
3421 // if (options.has_key('movelimit')) movelimit = options['movelimit'];
3423 // // moves, moves1 = self.movesArr, self.moveIntsArr;
3425 // while (index != -1) {
3428 // matchList = db.getCurrentMatchlist();
3430 // int numOfSwitched = 0;
3432 // if (progBar && !(ctr % 10))
3433 // progBar.redraw((progEnd-progStart)*ctr/len(db.current) + progStart);
3435 // for(m in matchList) {
3436 // Pattern p = patternList.get(m[0]);
3439 // UIntervals currentUInterv([(0, self.movelimit)]);
3442 // cont = [(MAXNOMOVES, -1,-1)];
3446 // while (i < p.sizeX && !currentUInterv.isEmpty()) {
3448 // if (p.data[i][j] == '*') {
3449 // Bint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
3450 // if (Bint.data) cont.extend([(x,i,j) for x in [z[0] for z in Bint.data]]);
3451 // Wint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
3452 // if (Wint.data) cont.extend([(x,i,j) for x in [z[0] for z in Wint.data]]);
3454 // else if p.data[i][j] == 'x': printf("oops\n"); // FIXME
3455 // else if p.data[i][j] == 'o': printf("oops\n"); // FIXME
3458 // typeInt, nextInt = self.getUInterv(moves, moves1, index, i+a0, j+a1, p.data[i][j]);
3460 // if (typeInt == -1) ;
3461 // else if (typeInt == 0) currentUInterv = UIntervals();
3462 // else if (typeInt == 1) {
3463 // if (p.data[i][j] == '.' && cont[0][0] > nextInt.data[0][1]) {
3464 // Bi = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
3465 // Wi = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
3466 // counter = nextInt.data[0][1];
3467 // cont[0] = (nextInt.data[0][1], i, j);
3469 // currentUInterv.inters(nextInt);
3472 // if (toDo.has_key(typeInt)) toDo[typeInt].append((i,j,nextInt));
3473 // else toDo[typeInt] = [(i, j, nextInt)];
3477 // if (j == p.sizeY) {
3484 // for(ii in toDo.keys()) toDoList.extend(toDo[ii]);
3486 // while (toDoList && !currentUInterv.isEmpty()) {
3487 // i, j, nextInt = toDoList[0];
3490 // currentUInterv.inters(nextInt);
3491 // if (currentUInterv.isEmpty()) break;
3493 // if (p.data[i][j] == 'X') Bint = nextInt;
3494 // else Bint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'X')[1];
3495 // if (Bint.data) cont.extend([(x,i,j) for x in [z[0] for z in Bint.data]]);
3496 // if (p.data[i][j] == 'O') Wint = nextInt;
3497 // else Wint = self.getUInterv(moves, moves1, index, i+a0, j+a1, 'O')[1];
3498 // if (Wint.data) cont.extend([(x,i,j) for x in [z[0] for z in Wint.data]]);
3501 // if (!currentUInterv.isEmpty()) {
3504 // for(counter, x, y in cont)
3505 // if (counter > currentUInterv.first()) break;
3507 // if (counter == MAXNOMOVES || counter <= currentUInterv.first()) {
3510 // switched = p.colorSwitch;
3513 // Xint = (m[1][0], m[1][0] + patternList.get(m[0]).sizeX);
3514 // Yint = (m[1][1], m[1][1] + patternList.get(m[0]).sizeY);
3516 // Bint = self.getUInterv(moves, moves1, index, x+a0, y+a1, 'X')[1];
3517 // Wint = self.getUInterv(moves, moves1, index, x+a0, y+a1, 'O')[1];
3518 // if (counter in [z[0] for z in Bint.data]) co = 'W'; // !!! FIXME (cf. Algo_movelist.search)
3519 // else if (counter in [z[0] for z in Wint.data]) co = 'B'; // !!!
3520 // else raise Exception; // FIXME
3522 // hit, label, contLabelsIndex, switched =
3523 // patternList.updateContinuations(m[0], x+a0, y+a1, co, Xint, Yint,
3524 // currentUInterv.first(), counter-1,
3525 // continuations, contLabels, contLabelsIndex,
3526 // gl.getCurrentWinner());
3530 // numOfSwitched += switched;
3531 // if (switched) result.append(str(currentUInterv.first())+label+'-');
3532 // else result.append(str(currentUInterv.first())+label);
3539 // db.makeCurrentHit(join(result, ', '));
3540 // numOfHits = numOfHits + len(result);
3541 // overallSwitched += numOfSwitched;
3543 // if (gl.getCurrentWinner() == 'B') {
3544 // Bwins = Bwins + len(result) - numOfSwitched;
3545 // Wwins = Wwins + numOfSwitched;
3547 // else if (gl.getCurrentWinner() == 'W') {
3548 // Bwins = Bwins + numOfSwitched;
3549 // Wwins = Wwins + len(result) - numOfSwitched;
3552 // else db.discardCurrent();
3554 // index = db.next();
3556 // return numOfHits, Bwins, Wwins, overallSwitched;
3562 // ----------------------------------------------------------------------------------------------
3564 // GameList and related stuff
3566 Candidate::Candidate(char X
, char Y
, char ORIENTATION
) {
3569 orientation
= ORIENTATION
;
3572 Hit::Hit(ExtendedMoveNumber
* POS
, char* LABEL
) { // LABEL is a char[3]
3573 pos
= POS
; // note that we do not copy these!
3582 Hit::Hit(SnapshotVector
& snv
) {
3583 int length
= snv
.retrieve_int();
3584 int* data
= snv
.retrieve_intp();
3585 pos
= new ExtendedMoveNumber(length
, data
);
3587 label
= snv
.retrieve_charp();
3590 void Hit::to_snv(SnapshotVector
& snv
) {
3591 snv
.pb_int(pos
->length
);
3592 snv
.pb_intp(pos
->data
, pos
->length
);
3593 snv
.pb_charp(label
, 3);
3596 bool Hit::cmp_pts(Hit
* a
, Hit
* b
) {
3597 if (a
->pos
->length
!= b
->pos
->length
) return a
->pos
->length
< b
->pos
->length
;
3598 for(int i
=0; i
< a
->pos
->length
; i
++)
3599 if (a
->pos
->data
[i
] != b
->pos
->data
[i
]) return a
->pos
->data
[i
] < b
->pos
->data
[i
];
3603 SearchOptions::SearchOptions() {
3607 trustHashFull
= false;
3608 searchInVariations
= true;
3609 algos
= (1<<30) - 1; // use all available algorithms
3612 SearchOptions::SearchOptions(int FIXEDCOLOR
, int NEXTMOVE
, int MOVELIMIT
) {
3613 fixedColor
= FIXEDCOLOR
;
3614 moveLimit
= MOVELIMIT
;
3615 nextMove
= NEXTMOVE
;
3616 trustHashFull
= false;
3617 searchInVariations
= true;
3618 algos
= (1<<30) - 1; // use all available algorithms
3621 SearchOptions::SearchOptions(SnapshotVector
& snv
) {
3622 fixedColor
= snv
.retrieve_int();
3623 moveLimit
= snv
.retrieve_int();
3624 nextMove
= snv
.retrieve_int();
3625 trustHashFull
= snv
.retrieve_int();
3626 searchInVariations
= snv
.retrieve_int();
3627 algos
= snv
.retrieve_int();
3630 void SearchOptions::to_snv(SnapshotVector
& snv
) {
3631 snv
.pb_int(fixedColor
);
3632 snv
.pb_int(moveLimit
);
3633 snv
.pb_int(nextMove
);
3634 snv
.pb_int(trustHashFull
);
3635 snv
.pb_int(searchInVariations
);
3639 ProcessOptions::ProcessOptions() {
3640 processVariations
= true;
3642 rootNodeTags
= "BR,CA,DT,EV,HA,KM,PB,PC,PW,RE,RO,RU,SZ,US,WR";
3643 algos
= ALGO_FINALPOS
| ALGO_MOVELIST
| ALGO_HASH_FULL
| ALGO_HASH_CORNER
;
3644 algo_hash_full_maxNumStones
= 50;
3645 algo_hash_corner_maxNumStones
= 20;
3648 ProcessOptions::ProcessOptions(string s
) {
3650 if (s
[p
++] == 't') processVariations
= true;
3651 else processVariations
= false;
3653 if (s
[p
++] == 't') sgfInDB
= true;
3654 else sgfInDB
= false;
3657 int pn
= s
.find('|', p
) + 1;
3658 algos
= atoi(s
.substr(p
, pn
-p
-1).c_str());
3661 pn
= s
.find('|', p
) + 1;
3662 algo_hash_full_maxNumStones
= atoi(s
.substr(p
, pn
-p
-1).c_str());
3665 pn
= s
.find('|', p
) + 1;
3666 algo_hash_corner_maxNumStones
= atoi(s
.substr(p
, pn
-p
-1).c_str());
3668 rootNodeTags
= s
.substr(pn
);
3671 string
ProcessOptions::asString() {
3673 if (processVariations
) result
+= "t";
3675 if (sgfInDB
) result
+= "t";
3678 sprintf(buf
, "|%d|%d|%d|%s", algos
, algo_hash_full_maxNumStones
, algo_hash_corner_maxNumStones
, rootNodeTags
.c_str());
3683 void ProcessOptions::validate() {
3684 string::iterator it
= rootNodeTags
.begin();
3685 while (it
!= rootNodeTags
.end()) {
3686 if (*it
== ' ') it
= rootNodeTags
.erase(it
);
3689 if (rootNodeTags
.find("PB") == string::npos
) rootNodeTags
+= ",PB";
3690 if (rootNodeTags
.find("PW") == string::npos
) rootNodeTags
+= ",PW";
3691 if (rootNodeTags
.find("RE") == string::npos
) rootNodeTags
+= ",RE";
3692 if (rootNodeTags
.find("DT") == string::npos
) rootNodeTags
+= ",DT";
3694 algos
|= ALGO_FINALPOS
| ALGO_MOVELIST
; // these are mandatory at the moment
3697 vector
<string
>* ProcessOptions::SGFTagsAsStrings() {
3698 vector
<string
>* SGFtags
= new vector
<string
>;
3701 unsigned int pn
= rootNodeTags
.find(',', p
);
3702 while (pn
!= string::npos
) {
3703 SGFtags
->push_back(rootNodeTags
.substr(p
,pn
-p
));
3706 pn
= rootNodeTags
.find(',', p
);
3708 SGFtags
->push_back(rootNodeTags
.substr(p
));
3712 GameListEntry::GameListEntry(int ID
, char WINNER
, string GAMEINFOSTR
) {
3713 // printf("GLE %d %c %s\n", ID, WINNER, GAMEINFOSTR);
3715 if (WINNER
== 'B' || WINNER
== 'b') winner
= 'B';
3716 else if (WINNER
== 'W' || WINNER
== 'w') winner
= 'W';
3717 else if (WINNER
== 'J' || WINNER
== 'j') winner
= 'J';
3719 gameInfoStr
= GAMEINFOSTR
;
3724 GameListEntry::~GameListEntry() {
3726 for(vector
<Hit
* >::iterator it
= hits
->begin(); it
!= hits
->end(); it
++) delete *it
;
3731 for(vector
<Candidate
* >::iterator it
= candidates
->begin(); it
!= candidates
->end(); it
++) delete *it
;
3737 void GameListEntry::hits_from_snv(SnapshotVector
& snv
) {
3738 int h_size
= snv
.retrieve_int();
3739 hits
= new vector
<Hit
* >;
3740 for(int j
=0; j
<h_size
; j
++) {
3741 hits
->push_back(new Hit(snv
));
3745 int insertEntry(void *gl
, int argc
, char **argv
, char **azColName
) {
3747 if (argv
[1] && (argv
[1][0] == 'B' || argv
[1][0] == 'W' || argv
[1][0] == 'J')) winner
= argv
[1][0];
3748 string gameInfoStr
= ((GameList
*)gl
)->format2
;
3749 for(int i
=0; i
<((GameList
*)gl
)->numColumns
; i
++) {
3751 sprintf(strpip1
, "[[%d[[F", i
);
3752 unsigned int p
= gameInfoStr
.find(strpip1
);
3753 if (p
!= string::npos
) {
3755 string fn
= argv
[i
];
3756 if (fn
.substr(fn
.size()-4) == ".sgf" || fn
.substr(fn
.size()-4) == ".mgt")
3757 gameInfoStr
.replace(p
, strlen(strpip1
), fn
.substr(0,fn
.size()-4));
3758 else gameInfoStr
.replace(p
, strlen(strpip1
), fn
);
3759 } else gameInfoStr
.erase(gameInfoStr
.find(strpip1
), strlen(strpip1
));
3763 sprintf(strpip1
, "[[%d", i
);
3764 p
= gameInfoStr
.find(strpip1
);
3765 if (p
!= string::npos
) {
3766 if (argv
[i
]) gameInfoStr
.replace(p
, strlen(strpip1
), argv
[i
]);
3767 else gameInfoStr
.erase(gameInfoStr
.find(strpip1
), strlen(strpip1
));
3770 unsigned int p
= gameInfoStr
.find("[[W");
3771 if (p
!= string::npos
) gameInfoStr
.replace(p
, 3, 1, winner
);
3773 // printf("id %s\n", argv[0]);
3774 ((GameList
*)gl
)->all
->push_back(new GameListEntry(atoi(argv
[0]), winner
, gameInfoStr
));
3778 int dbinfo_callback(void *s
, int argc
, char **argv
, char **asColName
) {
3779 char** cpp
= (char**)s
;
3780 if (argc
&& argv
[0]) {
3781 // printf("dbi_cb %s\n", argv[0]);
3782 *cpp
= new char[strlen(argv
[0])+1];
3783 strcpy(*cpp
, argv
[0]);
3788 GameList::GameList(char* DBNAME
, string ORDERBY
, string FORMAT
, ProcessOptions
* p_options
, int cache
) throw(DBError
) {
3794 dbname
= new char[strlen(DBNAME
)+2];
3795 strcpy(dbname
, DBNAME
);
3796 db
= algo_db1
= algo_db2
= 0;
3798 dbname
[strlen(DBNAME
)] = '1';
3799 dbname
[strlen(DBNAME
)+1] = 0;
3800 int rc
= sqlite3_open(dbname
, &algo_db1
);
3802 sqlite3_close(algo_db1
);
3806 rc
= sqlite3_busy_timeout(algo_db1
, 200);
3807 if (rc
) throw DBError();
3808 rc
= sqlite3_exec(algo_db1
, "pragma synchronous = off;", 0, 0, 0);
3809 if (rc
) throw DBError();
3810 char cache_str
[100];
3811 sprintf(cache_str
, "pragma cache_size = %d", cache
*1000);
3812 rc
= sqlite3_exec(algo_db1
, cache_str
, 0, 0, 0);
3813 if (rc
) throw DBError();
3814 dbname
[strlen(DBNAME
)] = '2';
3815 dbname
[strlen(DBNAME
)+1] = 0;
3816 rc
= sqlite3_open(dbname
, &algo_db2
);
3818 sqlite3_close(algo_db2
);
3822 rc
= sqlite3_busy_timeout(algo_db2
, 200);
3823 if (rc
) throw DBError();
3824 rc
= sqlite3_exec(algo_db2
, "pragma synchronous = off;", 0, 0, 0);
3825 if (rc
) throw DBError();
3826 sprintf(cache_str
, "pragma cache_size = %d", cache
*7000);
3827 rc
= sqlite3_exec(algo_db2
, cache_str
, 0, 0, 0);
3828 if (rc
) throw DBError();
3830 // try to retrieve basic options from database
3831 dbname
[strlen(DBNAME
)] = 0;
3832 rc
= sqlite3_open(dbname
, &db
);
3838 rc
= sqlite3_busy_timeout(db
, 200);
3839 if (rc
) throw DBError();
3840 rc
= sqlite3_exec(db
, "pragma synchronous = off;", 0, 0, 0);
3841 if (rc
) throw DBError();
3842 sprintf(cache_str
, "pragma cache_size = %d", cache
*1000);
3843 rc
= sqlite3_exec(db
, cache_str
, 0, 0, 0);
3844 if (rc
) throw DBError();
3846 rc
= sqlite3_exec(db
, "create table db_info ( info text );", 0, 0, 0);
3847 //if (rc != SQLITE_OK) throw DBError();
3849 rc
= sqlite3_exec(db
, "select * from db_info where rowid = 1;", dbinfo_callback
, &dbinfo
, 0);
3850 if (rc
!= SQLITE_OK
) throw DBError();
3853 // printf("dbinfo: %s\n", dbinfo);
3854 p_op
= new ProcessOptions(dbinfo
);
3857 rc
= sqlite3_exec(db
, "select * from db_info where rowid = 2;", dbinfo_callback
, &bsizes
, 0);
3858 if (rc
!= SQLITE_OK
) throw DBError();
3860 // printf("board sizes %s\n", bsizes); // should be a comma-sep. list of integers *ending w/ a comma*
3861 string
bsizes_str(bsizes
);
3864 unsigned int pn
= bsizes_str
.find(",",p
);
3865 while (pn
> p
&& pn
!= string::npos
) {
3866 boardsizes
.push_back(atoi(bsizes_str
.substr(p
, pn
-p
).c_str()));
3868 pn
= bsizes_str
.find(",",p
);
3871 } else { // if this does not work: create database and read p_options (or use defaults)
3872 // printf("retrieving dbinfo failed\n");
3873 if (p_options
== 0) p_op
= new ProcessOptions(); // use default values
3875 // printf("use p_options\n");
3876 p_op
= new ProcessOptions(*p_options
);
3877 p_op
->validate(); // make sure the most important information is contained in rootNodeTags list
3879 string sql
= "insert into db_info (rowid,info) values (1,'";
3880 sql
+= p_op
->asString();
3882 rc
= sqlite3_exec(db
, sql
.c_str(), 0, 0, 0);
3883 if (rc
!= SQLITE_OK
) throw DBError();
3884 rc
= sqlite3_exec(db
, "insert into db_info (rowid, info) values (2, ',');", 0, 0, 0);
3885 if (rc
!= SQLITE_OK
) throw DBError();
3888 // set up snapshot db
3889 rc
= sqlite3_exec(db
, "create table snapshots ( data text );", 0, 0, 0);
3890 //if (rc != SQLITE_OK) throw DBError();
3892 // printf("set up Algorithm instances\n");
3893 for(vector
<int>::iterator it
= boardsizes
.begin(); it
!= boardsizes
.end(); it
++)
3896 currentList
= oldList
= 0;
3898 resetFormat(ORDERBY
, FORMAT
);
3901 void GameList::resetFormat(string ORDERBY
, string FORMAT
) {
3902 // printf("enter resetFormat\n");
3903 if (FORMAT
== "") { // use default format string
3905 format1
= "id,re,pw,pb,dt";
3906 format2
= "[[2 - [[3 ([[W), [[4, ";
3914 while (p
!= string::npos
) {
3915 p
= format2
.find("[[",p
);
3916 q
= format2
.find("]]",p
);
3917 if (p
+2 < format2
.size() && q
!= string::npos
) {
3918 string col
= format2
.substr(p
+2, q
-p
-2);
3919 // check availability
3920 if (col
== "id" || col
== "filename" || col
== "pos" || col
== "duplicate" || col
== "date" || p_op
->rootNodeTags
.find(col
) != string::npos
) {
3921 sprintf(buf
, "[[%d", numColumns
++);
3922 format2
.replace(p
,q
+2-p
, buf
);
3925 } else if (col
== "winner") format2
.replace(p
,q
+2-p
, "[[W");
3926 else if (col
== "filename.") {
3927 sprintf(buf
, "[[%d[[F", numColumns
++);
3928 format2
.replace(p
, q
+2-p
, buf
);
3929 format1
+= ",filename";
3935 if (ORDERBY
== "" || ORDERBY
== "id" || ORDERBY
== "ID" || ORDERBY
== "Id" || ORDERBY
== "iD") orderby
= "id";
3936 else orderby
= ORDERBY
+ ",id";
3937 // printf("finished parsing\n");
3943 void GameList::addAlgos(int bs
) {
3944 int ctr
= algo_ps
.size()/20;
3945 // printf("add algos %d %d %d\n", bs, ctr, p_op->algos);
3946 for(int i
=0; i
<20; i
++) {
3947 algo_ps
.push_back(0);
3948 algo_dbs
.push_back(0);
3951 algo_ps
[20*ctr
] = new Algo_signature(bs
);
3952 algo_dbs
[20*ctr
] = db
;
3953 if (p_op
->algos
& ALGO_FINALPOS
) {
3954 algo_ps
[algo_finalpos
+20*ctr
] = new Algo_finalpos(bs
);
3955 algo_dbs
[algo_finalpos
+20*ctr
] = algo_db1
;
3957 if (p_op
->algos
& ALGO_MOVELIST
) {
3958 algo_ps
[algo_movelist
+20*ctr
] = new Algo_movelist(bs
);
3959 algo_dbs
[algo_movelist
+20*ctr
] = algo_db1
;
3961 if (p_op
->algos
& ALGO_HASH_FULL
) {
3962 algo_ps
[algo_hash_full
+20*ctr
] = new Algo_hash_full(bs
, p_op
->algo_hash_corner_maxNumStones
);
3963 algo_dbs
[algo_hash_full
+20*ctr
] = algo_db2
;
3965 if (p_op
->algos
& ALGO_HASH_CORNER
) {
3966 algo_ps
[algo_hash_corner
+20*ctr
] = new Algo_hash_corner(bs
, 7, p_op
->algo_hash_corner_maxNumStones
);
3967 algo_dbs
[algo_hash_corner
+20*ctr
] = algo_db2
;
3969 // for(int a=20*ctr; a<20*(ctr+1); a++) printf("aa %d %p\n", a, algo_ps[a]);
3970 // if (algos & ALGO_HASH_SIDE)
3971 // algo_ps[algo_hash_side] = new Algo_hash_side(boardsize, 6, 4, p_op->algo_hash_side_maxNumStones);
3974 void GameList::readDB() throw(DBError
) {
3975 // printf("read dbs\n");
3976 if (oldList
) delete oldList
;
3977 if (currentList
) delete currentList
;
3979 for(vector
<GameListEntry
* >::iterator it
= all
->begin(); it
!= all
->end(); it
++)
3984 all
= new vector
<GameListEntry
* >;
3989 rc
= sqlite3_exec(db
, "begin transaction;", 0, 0, 0);
3990 if (rc
) throw DBError();
3992 string sql
= "select ";
3994 sql
+= " from games order by ";
3996 // printf("sql: %s\n", sql.c_str());
3997 rc
= sqlite3_exec(db
, sql
.c_str(), insertEntry
, this, 0);
3998 if (rc
!= SQLITE_OK
&& rc
!= SQLITE_ERROR
) {
4001 // printf("read.\n");
4002 // SQLITE_ERROR may occur since table might not yet exist
4005 rc
= sqlite3_exec(db
, "commit;", 0, 0, 0);
4006 if (rc
!= SQLITE_OK
) throw DBError();
4008 if (rc
== SQLITE_OK
&& !readDBs
) {
4009 for(unsigned int a
=0; a
< 20*boardsizes
.size(); a
++) {
4010 if (algo_ps
[a
]) algo_ps
[a
]->readDB(algo_dbs
[a
]);
4014 // printf("read.\n");
4017 // printf("leave readDB\n");
4020 GameList::~GameList() {
4021 // printf("enter ~GameList\n");
4022 if (mrs_pattern
) delete mrs_pattern
;
4023 if (searchOptions
) delete searchOptions
;
4024 if (p_op
) delete p_op
;
4025 if (labels
) delete [] labels
;
4026 if (continuations
) delete [] continuations
; // FIXME CHECK whether the Continuation destructor is invoked!
4027 if (duplicates
) delete duplicates
;
4030 for(vector
<GameListEntry
* >::iterator it
= all
->begin(); it
!= all
->end(); it
++)
4034 if (currentList
) delete currentList
;
4035 if (oldList
) delete oldList
;
4036 for(unsigned int i
=0; i
<20*boardsizes
.size(); i
++)
4037 if (algo_ps
[i
]) delete algo_ps
[i
];
4038 if (db
) sqlite3_close(db
);
4040 if (algo_db1
) sqlite3_close(algo_db1
);
4042 if (algo_db2
) sqlite3_close(algo_db2
);
4044 // printf("leave ~GameList\n");
4048 int GameList::start() {
4050 if (oldList
) delete oldList
;
4051 oldList
= currentList
;
4052 currentList
= new vector
<pair
<int,int> >;
4053 if (oldList
&& oldList
->size()) return (*oldList
)[0].first
;
4055 if (oldList
) delete oldList
;
4061 int GameList::next() {
4063 if (current
< (int)oldList
->size()) return (*oldList
)[current
].first
;
4065 if (oldList
) delete oldList
;
4071 bool sndcomp(const pair
<int,int>& a
, const pair
<int,int>& b
) {
4072 return a
.second
< b
.second
;
4075 int GameList::start_sorted() {
4077 if (oldList
) delete oldList
;
4078 oldList
= currentList
;
4079 currentList
= new vector
<pair
<int,int> >;
4080 if (!oldList
|| !oldList
->size()) {
4081 if (oldList
) delete oldList
;
4085 sort(oldList
->begin(), oldList
->end());
4089 int GameList::end_sorted() {
4090 // printf("end sorted\n");
4091 sort(currentList
->begin(), currentList
->end(), sndcomp
);
4097 char GameList::getCurrentWinner() {
4098 return (*all
)[(*oldList
)[current
].second
]->winner
;
4101 vector
<Candidate
* > * GameList::getCurrentCandidateList() {
4102 return (*all
)[(*oldList
)[current
].second
]->candidates
;
4105 void GameList::makeCurrentCandidate(vector
<Candidate
* > * candidates
) {
4106 GameListEntry
* gle
= (*all
)[(*oldList
)[current
].second
];
4107 if (gle
->candidates
) delete gle
->candidates
;
4108 gle
->candidates
= candidates
;
4109 currentList
->push_back((*oldList
)[current
]);
4112 void GameList::makeCurrentHit(vector
<Hit
* > * hits
) {
4113 GameListEntry
* gle
= (*all
)[(*oldList
)[current
].second
];
4114 if (gle
->hits
) delete gle
->hits
;
4116 sort(gle
->hits
->begin(), gle
->hits
->end(), Hit::cmp_pts
);
4117 currentList
->push_back((*oldList
)[current
]);
4120 void GameList::setCurrentFromIndex(int index
) {
4121 int start
= current
;
4122 int end
= oldList
->size();
4124 while (start
< end
) {
4126 if (index
== (*oldList
)[m
].first
) {
4129 if (index
< (*oldList
)[m
].first
) end
= m
;
4136 void GameList::makeIndexHit(int index
, vector
<Hit
* > * hits
) {
4137 int m
= get_current_index(index
, ¤t
);
4139 currentList
->push_back((*oldList
)[m
]);
4141 if ((*all
)[(*oldList
)[m
].second
]->hits
) delete (*all
)[(*oldList
)[m
].second
]->hits
;
4142 (*all
)[(*oldList
)[m
].second
]->hits
= hits
;
4147 void GameList::makeIndexCandidate(int index
, vector
<Candidate
* > * candidates
) {
4148 int m
= get_current_index(index
, ¤t
);
4150 currentList
->push_back((*oldList
)[m
]);
4152 if ((*all
)[(*oldList
)[m
].second
]->candidates
) delete (*all
)[(*oldList
)[m
].second
]->candidates
;
4153 (*all
)[(*oldList
)[m
].second
]->candidates
= candidates
;
4159 void GameList::reset() {
4160 if (oldList
) delete oldList
;
4162 if (currentList
) delete currentList
;
4163 currentList
= new vector
<pair
<int,int> >;
4165 for(vector
<GameListEntry
* >::iterator it
= all
->begin(); it
!= all
->end(); it
++) {
4167 for(vector
<Hit
* >::iterator ith
= (*it
)->hits
->begin(); ith
!= (*it
)->hits
->end(); ith
++)
4172 if ((*it
)->candidates
) {
4173 for(vector
<Candidate
* >::iterator itc
= (*it
)->candidates
->begin(); itc
!= (*it
)->candidates
->end(); itc
++)
4175 delete (*it
)->candidates
;
4176 (*it
)->candidates
= 0;
4178 currentList
->push_back(make_pair((*it
)->id
, counter
++));
4186 void GameList::tagsearch(int tag
) throw(DBError
) {
4191 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
);
4193 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
);
4198 void GameList::setTag(int tag
, int start
, int end
) throw(DBError
) {
4199 if (end
==0) end
= currentList
->size();
4200 if (start
>end
|| end
> (int)currentList
->size()) return;
4201 int rc
= sqlite3_exec(db
, "begin transaction", 0, 0, 0);
4202 if (rc
!= SQLITE_OK
) throw DBError();
4203 for(int i
= start
; i
< end
; i
++) {
4204 if (getTags(i
, tag
).size()) continue;
4206 sprintf(sql
, "insert into game_tags (game_id, tag_id) values (%d, %d)", (*all
)[(*currentList
)[i
].second
]->id
, tag
);
4207 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
4208 if (rc
!= SQLITE_OK
) throw DBError();
4210 rc
= sqlite3_exec(db
, "commit", 0, 0, 0);
4211 if (rc
!= SQLITE_OK
) throw DBError();
4214 void GameList::deleteTag(int tag
, int i
) throw(DBError
) {
4216 if (i
== -1) sprintf(sql
, "delete from game_tags where tag_id=%d", tag
);
4217 else sprintf(sql
, "delete from game_tags where game_id=%d and tag_id=%d", (*all
)[(*currentList
)[i
].second
]->id
, tag
);
4218 int rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
4219 if (rc
!= SQLITE_OK
) throw DBError();
4222 int gettags_callback(void *res
, int argc
, char **argv
, char **azColName
) {
4223 if (!argc
) return 1;
4224 ((vector
<int>*)res
)->push_back(atoi(argv
[0]));
4228 vector
<int> GameList::getTags(int i
, int tag
) throw(DBError
) {
4231 if (tag
==0) sprintf(sql
, "select tag_id from game_tags where game_id=%d", (*all
)[(*currentList
)[i
].second
]->id
);
4232 else sprintf(sql
, "select tag_id from game_tags where game_id=%d and tag_id=%d", (*all
)[(*currentList
)[i
].second
]->id
, tag
);
4233 int rc
= sqlite3_exec(db
, sql
, gettags_callback
, &result
, 0);
4234 if (rc
!= SQLITE_OK
) throw DBError();
4238 void GameList::insert_duplicate(int i1
, int i2
, vector
<vector
<int> >* dupl
) {
4239 int ii1
= get_current_index_CL(i1
);
4240 int ii2
= get_current_index_CL(i2
);
4241 // printf("insert_duplicate %d, %d\n", ii1, ii2);
4242 if (ii1
== -1 || ii2
== -1) return;
4243 bool inserted
= false;
4244 for(vector
<vector
<int> >::iterator it
= dupl
->begin(); it
!= dupl
->end(); it
++) {
4245 vector
<int>::iterator i
= it
->begin();
4246 while(i
!= it
->end() && *i
!= ii1
&& *i
!= ii2
) i
++;
4247 if (i
== it
->end()) continue;
4249 if (*i
== ii1
) insert
= ii2
;
4250 while (i
!= it
->end() && *i
!= insert
) i
++;
4251 if (i
== it
->end()) it
->push_back(insert
);
4252 sort(it
->begin(), it
->end());
4257 vector
<int> new_list
;
4259 new_list
.push_back(ii1
);
4260 new_list
.push_back(ii2
);
4262 new_list
.push_back(ii2
);
4263 new_list
.push_back(ii1
);
4265 dupl
->push_back(new_list
);
4269 int GameList::find_duplicates(int bs
, bool strict
) throw(DBError
) {
4270 if (!currentList
->size()) return 0; // this also deals with the case of an empty db
4272 if (duplicates
) delete duplicates
;
4273 duplicates
= new vector
<vector
<int> >;
4275 vector
<int>::iterator it
= boardsizes
.begin();
4276 while (it
!= boardsizes
.end() && *it
!= bs
) {
4280 if (it
== boardsizes
.end()) {
4284 sort(currentList
->begin(), currentList
->end());
4285 sqlite3_stmt
*ppStmt
=0;
4287 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
);
4288 int rc
= sqlite3_prepare(db
, sql
, -1, &ppStmt
, 0);
4289 if (rc
!= SQLITE_OK
|| ppStmt
==0) throw DBError();
4291 rc
= sqlite3_step(ppStmt
);
4292 if (rc
!= SQLITE_DONE
&& rc
!= SQLITE_ROW
) throw DBError();
4293 if (rc
== SQLITE_ROW
) {
4294 if (!strict
|| ((Algo_finalpos
*)algo_ps
[20*bs_index
+algo_finalpos
])->equal(sqlite3_column_int(ppStmt
, 0), sqlite3_column_int(ppStmt
, 1)))
4295 insert_duplicate(sqlite3_column_int(ppStmt
, 0), sqlite3_column_int(ppStmt
, 1), duplicates
);
4297 } while (rc
== SQLITE_ROW
);
4298 rc
= sqlite3_finalize(ppStmt
);
4299 if (rc
!= SQLITE_OK
) throw DBError();
4300 sort(currentList
->begin(), currentList
->end(), sndcomp
);
4301 return duplicates
->size();
4304 vector
<int> GameList::retrieve_duplicates_VI(unsigned int i
) {
4305 if (i
>=duplicates
->size()) return vector
<int>();
4306 return (*duplicates
)[i
];
4309 int* GameList::retrieve_duplicates_PI(unsigned int i
) {
4310 if (i
>=duplicates
->size()) return 0;
4311 int* result
= new int[(*duplicates
)[i
].size()+1];
4313 for(vector
<int>::iterator it
= (*duplicates
)[i
].begin(); it
!= (*duplicates
)[i
].end(); it
++)
4315 result
[(*duplicates
)[i
].size()] = -1;
4320 int GameList::get_current_index(int id
, int* start
) {
4321 // use this in between start_sorted() and end_sorted() only!
4322 int end
= oldList
->size();
4324 while (*start
< end
) {
4326 if (id
== (*oldList
)[m
].first
) {
4330 if (id
< (*oldList
)[m
].first
) end
= m
;
4337 int GameList::get_current_index_CL(int id
, int start
) {
4338 // use this in between start_sorted() and end_sorted() only!
4339 int end
= currentList
->size();
4341 while (start
< end
) {
4343 if (id
== (*currentList
)[m
].first
) return m
;
4345 if (id
< (*currentList
)[m
].first
) end
= m
;
4352 void GameList::sigsearch(char* sig
, int boardsize
) throw(DBError
) {
4353 if (start_sorted() == 0) {
4354 char* symmetrized_sig
= 0;
4355 if (boardsize
) symmetrized_sig
= symmetrize(sig
, boardsize
);
4357 // for(int i=0; i<12; i++) ssig[i] = symmetrized_sig[i];
4359 // printf("ssig: %s\n", ssig);
4360 string query
= "select id from algo_signature_19 where signature like ? order by id";
4361 // int rc = sqlite3_exec(db, query.c_str(), sigs_callback, this, 0);
4362 sqlite3_stmt
*ppStmt
=0;
4363 int rc
= sqlite3_prepare(db
, query
.c_str(), -1, &ppStmt
, 0);
4364 if (rc
!= SQLITE_OK
|| ppStmt
==0) throw DBError();
4365 if (boardsize
) rc
= sqlite3_bind_blob(ppStmt
, 1, symmetrized_sig
, 12, SQLITE_TRANSIENT
);
4366 else rc
= sqlite3_bind_blob(ppStmt
, 1, sig
, 12, SQLITE_TRANSIENT
);
4367 if (rc
!= SQLITE_OK
|| ppStmt
==0) throw DBError();
4369 rc
= sqlite3_step(ppStmt
);
4370 if (rc
!= SQLITE_DONE
&& rc
!= SQLITE_ROW
) throw DBError();
4371 if (rc
== SQLITE_ROW
) {
4372 makeIndexHit(sqlite3_column_int(ppStmt
, 0), 0);
4374 } while (rc
== SQLITE_ROW
);
4375 rc
= sqlite3_finalize(ppStmt
);
4376 if (symmetrized_sig
) delete [] symmetrized_sig
;
4377 if (rc
!= SQLITE_OK
) throw DBError();
4383 int gis_callback(void *gl
, int argc
, char **argv
, char **azColName
) {
4384 if (!argc
) return 1;
4385 ((GameList
*)gl
)->makeIndexHit(atoi(argv
[0]), 0);
4389 void GameList::gisearch(char* sql
, int complete
) throw(DBError
) {
4390 if (start_sorted() == 0) {
4392 if (!complete
) query
= "select id from games where ";
4394 if (!complete
) query
+= " order by id";
4395 // printf("%s\n", query.c_str());
4396 int rc
= sqlite3_exec(db
, query
.c_str(), gis_callback
, this, 0);
4397 if( rc
!=SQLITE_OK
) throw DBError();
4403 int GameList::numHits() {
4407 int GameList::size() {
4408 return currentList
->size();
4411 string
GameList::resultsStr(GameListEntry
* gle
) {
4413 if (!gle
->hits
) return result
;
4415 result
.reserve(gle
->hits
->size()*8);
4416 for(vector
<Hit
* >::iterator it
= gle
->hits
->begin(); it
!= gle
->hits
->end(); it
++) {
4417 sprintf(buf
, "%d", (*it
)->pos
->data
[0]);
4419 for(int i
=1; i
<(*it
)->pos
->length
; i
++) {
4420 sprintf(buf
, "-%d", (*it
)->pos
->data
[i
]);
4423 if ((*it
)->label
[0] != NO_CONT
) result
+= lookupLabel((*it
)->label
[0], (*it
)->label
[1]); // coordinates of Hit
4424 if ((*it
)->label
[2]) result
+= "-, ";
4425 else result
+= ", ";
4430 char GameList::lookupLabel(char x
, char y
) {
4431 if (!labels
|| !mrs_pattern
|| x
< 0 || x
>= mrs_pattern
->sizeX
|| y
< 0 || y
>= mrs_pattern
->sizeY
) return '?';
4432 return labels
[x
+y
*mrs_pattern
->sizeX
];
4435 Continuation
GameList::lookupContinuation(char x
, char y
) {
4436 if (!continuations
|| !mrs_pattern
|| x
< 0 || x
>= mrs_pattern
->sizeX
|| y
< 0 || y
>= mrs_pattern
->sizeY
) return Continuation();
4437 return continuations
[x
+y
*mrs_pattern
->sizeX
];
4440 vector
<string
> GameList::currentEntriesAsStrings(int start
, int end
) {
4441 if (end
==0) end
= currentList
->size();
4442 vector
<string
> result
;
4443 if (start
>end
|| end
> (int)currentList
->size()) return result
;
4444 for(int i
=start
; i
<end
; i
++) {
4445 result
.push_back((*all
)[(*currentList
)[i
].second
]->gameInfoStr
+ resultsStr((*all
)[(*currentList
)[i
].second
]));
4450 string
GameList::currentEntryAsString(int i
) {
4451 if (i
< 0 || i
>= (int)currentList
->size()) {
4453 } else return (*all
)[(*currentList
)[i
].second
]->gameInfoStr
+ resultsStr((*all
)[(*currentList
)[i
].second
]);
4456 int getpropcallback(void *s
, int argc
, char **argv
, char **azColName
) {
4457 char** prop
= (char**)s
;
4458 if (argc
&& argv
[0]) {
4459 *prop
= new char[strlen(argv
[0])+1];
4460 strcpy(*prop
, argv
[0]);
4465 string
GameList::getSignature(int i
) throw(DBError
) {
4466 if (i
< 0 || i
>= (int)currentList
->size()) {
4467 // printf("index out of range\n");
4470 int index
= (*all
)[(*currentList
)[i
].second
]->id
;
4473 sprintf(sql
, "select signature from algo_signature_19 where id = %d;", index
);
4474 // printf("%s\n", sql);
4475 int rc
= sqlite3_exec(db
, sql
, getpropcallback
, &prop
, 0);
4476 if (rc
!= SQLITE_OK
) throw DBError();
4478 if (!prop
) return "";
4479 string
prop_str(prop
);
4484 string
GameList::getSGF(int i
) throw(DBError
) {
4485 if (!p_op
->sgfInDB
) return "";
4486 return getCurrentProperty(i
, "sgf");
4489 string
GameList::getCurrentProperty(int i
, string tag
) throw(DBError
) {
4490 if (i
< 0 || i
>= (int)currentList
->size()) {
4491 // printf("index out of range\n");
4494 int index
= (*all
)[(*currentList
)[i
].second
]->id
;
4497 sprintf(sql
, "select %s from games where id = %d;", tag
.c_str(), index
);
4498 // printf("%s\n", sql);
4499 int rc
= sqlite3_exec(db
, sql
, getpropcallback
, &prop
, 0);
4500 if (rc
!= SQLITE_OK
) throw DBError();
4502 if (!prop
) return "";
4503 string
prop_str(prop
);
4508 void GameList::search(Pattern
& pattern
, SearchOptions
* so
) throw(DBError
) {
4509 if (mrs_pattern
) delete mrs_pattern
;
4510 mrs_pattern
= new Pattern(pattern
);
4511 if (searchOptions
) delete searchOptions
;
4512 if (so
) searchOptions
= new SearchOptions(*so
);
4513 else searchOptions
= new SearchOptions();
4514 PatternList
pl(pattern
, searchOptions
->fixedColor
, searchOptions
->nextMove
);
4516 vector
<int>::iterator it
= boardsizes
.begin();
4518 while (it
!= boardsizes
.end() && *it
!= pattern
.boardsize
) {
4522 if (it
== boardsizes
.end()) {
4523 delete searchOptions
;
4525 if (oldList
) delete oldList
;
4527 if (currentList
) delete currentList
;
4528 currentList
= new vector
<pair
<int,int> >;
4532 if (boardsizes
.size() != 1) {
4534 sprintf(buf
, "sz = %d", pattern
.boardsize
);
4538 for(unsigned int a
=0; a
< 20*boardsizes
.size(); a
++) if (algo_ps
[a
]) algo_ps
[a
]->readDB(algo_dbs
[a
]);
4542 int hash_result
= -1;
4543 // FULL BOARD PATTERN?
4544 if ((searchOptions
->algos
& ALGO_HASH_FULL
) && pattern
.sizeX
== pattern
.boardsize
&& pattern
.sizeY
== pattern
.boardsize
&& algo_ps
[algo_hash_full
+20*bs_index
]) {
4545 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
]);
4546 if (hash_result
== 1) {
4547 } else if (hash_result
== 0) {
4548 if (searchOptions
->algos
& ALGO_MOVELIST
&& algo_ps
[algo_movelist
+20*bs_index
])
4549 algo_ps
[algo_movelist
+20*bs_index
]->search(pl
, *this, *searchOptions
);
4552 if (hash_result
== -1) { // not a full board pattern (or not hashable)
4555 if ((searchOptions
->algos
& ALGO_HASH_CORNER
) && pattern
.sizeX
>= 7 && pattern
.sizeY
>= 7 && algo_ps
[algo_hash_corner
+20*bs_index
]) {
4556 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
]);
4557 if (hash_result
== 0) {
4558 if (searchOptions
->algos
& ALGO_MOVELIST
&& algo_ps
[algo_movelist
+20*bs_index
])
4559 algo_ps
[algo_movelist
+20*bs_index
]->search(pl
, *this, *searchOptions
);
4563 if (hash_result
== -1) {
4564 if (searchOptions
->algos
& ALGO_FINALPOS
&& algo_ps
[algo_finalpos
+20*bs_index
])
4565 algo_ps
[algo_finalpos
+20*bs_index
]->search(pl
, *this, *searchOptions
);
4566 if (searchOptions
->algos
& ALGO_MOVELIST
&& algo_ps
[algo_movelist
+20*bs_index
])
4567 algo_ps
[algo_movelist
+20*bs_index
]->search(pl
, *this, *searchOptions
);
4570 if (labels
) delete [] labels
;
4571 labels
= pl
.sortContinuations();
4572 if (continuations
) delete [] continuations
;
4573 continuations
= pl
.continuations
;
4574 pl
.continuations
= new Continuation
[pattern
.sizeX
*pattern
.sizeY
];
4576 // FIXME: delete all candidate lists!
4580 int GameList::plSize() {
4584 string
GameList::plEntry(int i
) {
4585 if (i
< 0 || i
>= (int)pl
.size()) return "";
4589 int rpl_callback(void *pl
, int argc
, char **argv
, char **azColName
) {
4590 if (!argc
) return 1;
4591 ((vector
<string
>*)pl
)->push_back(string(argv
[0]));
4595 void GameList::readPlayersList() throw(DBError
) {
4596 if (pl
.size()) pl
= vector
<string
>();
4597 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);
4598 // we ignore possible errors, since the table might not yet exist
4601 void GameList::createGamesDB() throw(DBError
) {
4602 SGFtags
= p_op
->SGFTagsAsStrings();
4604 string sql1
= "create table GAMES ( ";
4605 sql1
+= "id integer primary key, ";
4606 sql1
+= "path text, ";
4607 sql1
+= "filename text, ";
4608 sql1
+= "pos integer default 0, ";
4609 sql1
+= "duplicate integer, ";
4610 sql1
+= "dbtree text, ";
4611 sql1
+= "date date";
4613 sql_ins_rnp
= "insert into games (path, filename, pos, dbtree, date";
4614 string question_marks
= "?,?,?,?,?";
4616 if (p_op
->sgfInDB
) {
4617 sql1
+= ", sgf text";
4618 sql_ins_rnp
+= ", sgf";
4619 question_marks
+= ",?";
4622 SGFtagsSize
= SGFtags
->size();
4624 posDT
= posSZ
= posWR
= posBR
= posHA
= -1;
4625 for(vector
<string
>::iterator it
= SGFtags
->begin(); it
!= SGFtags
->end(); it
++) {
4626 sql1
+= ", " + *it
+ " text";
4627 sql_ins_rnp
+= ", " + *it
;
4628 question_marks
+= ",?";
4629 if (*it
== "DT") posDT
= ctr
;
4631 if (*it
== "SZ") posSZ
= ctr
;
4632 if (*it
== "WR") posWR
= ctr
;
4633 if (*it
== "BR") posBR
= ctr
;
4634 if (*it
== "HA") posHA
= ctr
;
4637 if (posDT
== -1) throw DBError();
4639 posSZ
= SGFtags
->size();
4640 SGFtags
->push_back("SZ");
4643 posWR
= SGFtags
->size();
4644 SGFtags
->push_back("WR");
4647 posBR
= SGFtags
->size();
4648 SGFtags
->push_back("BR");
4651 posHA
= SGFtags
->size();
4652 SGFtags
->push_back("HA");
4656 sql_ins_rnp
+= ") values (" + question_marks
+ ");";
4658 int rc
= sqlite3_exec(db
, sql1
.c_str(), 0, 0, 0);
4659 //if(rc != SQLITE_OK) throw DBError();
4661 sql1
= "create table TAGS ( id integer primary key, name text, visible integer default 1 );";
4662 rc
= sqlite3_exec(db
, sql1
.c_str(), 0, 0, 0);
4663 //if (rc != SQLITE_OK) throw DBError();
4665 sprintf(sql
, "insert into TAGS (id, name) values (%d, '%d');", HANDI_TAG
, HANDI_TAG
);
4666 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
4667 // if (rc != SQLITE_OK) throw DBError();
4668 sprintf(sql
, "insert into TAGS (id, name) values (%d, '%d');", PROFESSIONAL_TAG
, PROFESSIONAL_TAG
);
4669 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
4670 // if (rc != SQLITE_OK) throw DBError();
4671 sql1
= "create table GAME_TAGS ( id integer primary key, game_id integer, tag_id integer );";
4672 rc
= sqlite3_exec(db
, sql1
.c_str(), 0, 0, 0);
4673 //if (rc != SQLITE_OK) throw DBError();
4676 void GameList::start_processing(int PROCESSVARIATIONS
) throw(DBError
) {
4677 // printf("enter start_processing %p\n", p_op);
4679 delete_all_snapshots();
4681 if (PROCESSVARIATIONS
!= -1) processVariations
= PROCESSVARIATIONS
;
4682 else processVariations
= p_op
->processVariations
;
4684 // printf("dt %d sz %d\n", posDT, posSZ);
4690 char* sql
= "begin transaction;";
4691 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
4692 if (rc
) { throw DBError(); }
4693 rc
= sqlite3_exec(algo_db1
, sql
, 0, 0, 0);
4694 if (rc
) { throw DBError(); }
4695 rc
= sqlite3_exec(algo_db2
, sql
, 0, 0, 0);
4696 if (rc
) { throw DBError(); }
4698 for(unsigned int a
=0; a
< 20*boardsizes
.size(); a
++) {
4699 if (algo_ps
[a
]) algo_ps
[a
]->initialize_process(algo_dbs
[a
]);
4703 void GameList::finalize_processing() throw(DBError
) {
4704 for(unsigned int a
=0; a
<20*boardsizes
.size(); a
++)
4705 if (algo_ps
[a
]) algo_ps
[a
]->finalize_process();
4706 int rc
= sqlite3_exec(db
, "commit;", 0, 0, 0);
4707 if (rc
!= SQLITE_OK
) {
4712 rc
= sqlite3_exec(algo_db1
, "commit;", 0, 0, 0);
4713 if (rc
!= SQLITE_OK
) {
4714 sqlite3_close(algo_db1
);
4718 rc
= sqlite3_exec(algo_db2
, "commit;", 0, 0, 0);
4719 if (rc
!= SQLITE_OK
) {
4720 sqlite3_close(algo_db2
);
4724 string sql
= "update db_info set info = '";
4725 for(vector
<int>::iterator it
= boardsizes
.begin(); it
!= boardsizes
.end(); it
++) {
4727 sprintf(buf
, "%d,", *it
);
4730 sql
+= "' WHERE rowid = 2;";
4731 rc
= sqlite3_exec(db
, sql
.c_str(), 0, 0, 0);
4732 if (rc
!= SQLITE_OK
) throw DBError();
4733 // sqlite3_close(db);
4740 int GameList::process(const char* sgf
, const char* path
, const char* fn
,
4741 const char* DBTREE
, int flags
) throw(SGFError
,DBError
) {
4742 process_results_vector
.clear();
4743 const char* dbtree
= "";
4744 if (DBTREE
) dbtree
= DBTREE
;
4748 c
= new Cursor(sgf
, 1); // parse sgf sloppily
4749 } catch (SGFError
) {
4753 Node
* root
= c
->root
->next
;
4759 // if (!(current%1000)) {
4760 // char* sql = "end transaction;";
4761 // int rc = sqlite3_exec(db, sql, 0, 0, 0);
4763 // sqlite3_close(db);
4767 // sql = "begin transaction;";
4768 // rc = sqlite3_exec(db, sql, 0, 0, 0);
4770 // sqlite3_close(db);
4775 vector
<string
>* rootNodeProperties
= parseRootNode(root
, SGFtags
);
4776 // for(vector<string>::iterator rnp = rootNodeProperties->begin(); rnp != rootNodeProperties->end(); rnp++)
4777 // printf("rnp %s\n", rnp->c_str());
4780 string sz
= (*rootNodeProperties
)[posSZ
];
4781 // printf("sz %s\n", sz.c_str());
4782 if (sz
=="") sz
= "19";
4783 int bs
= atoi(sz
.c_str());
4785 return_val
|= UNACCEPTABLE_BOARDSIZE
;
4786 process_results_vector
.push_back(return_val
);
4787 delete rootNodeProperties
;
4792 int algo_offset
= -1;
4794 for(vector
<int>::iterator it
= boardsizes
.begin(); it
!= boardsizes
.end(); it
++) {
4796 algo_offset
= bs_ctr
;
4801 if (algo_offset
== -1) { // not found
4802 boardsizes
.push_back(bs
);
4804 algo_offset
= algo_ps
.size()/20 - 1;
4805 // printf("algo_offset %d %d \n", algo_offset, algo_ps.size());
4806 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++) {
4807 // printf("a %d\n", a);
4808 // printf("%p\n", algo_ps[a]);
4809 if (algo_ps
[a
]) algo_ps
[a
]->initialize_process(algo_dbs
[a
]);
4814 string dt
= (*rootNodeProperties
)[posDT
];
4815 // printf("dt %s\n", dt.c_str());
4818 bool year_found
= false;
4820 while (!year_found
&& p
< (int)dt
.size()) {
4821 p
= dt
.find_first_of("0123456789", p
);
4822 if (p
== (int)string::npos
|| p
+4 > (int)dt
.size() ) break;
4824 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'));
4825 if (year_found
&& (int)dt
.find_first_of("0123456789", p
+4) != p
+4) { // success: found 4 digits in a row
4826 date
+= dt
.substr(p
,4);
4830 while ('0' <= dt
[p
] && dt
[p
] <= '9') p
++;
4836 if (!year_found
) date
= "0000-00-00";
4838 bool month_found
= false;
4840 while (!month_found
&& p
< (int)dt
.size()) {
4841 p
= dt
.find_first_of("0123456789", p
);
4842 if (p
== (int)string::npos
|| p
+2 > (int)dt
.size() ) break;
4844 month_found
= ('0' <= dt
[p
] && dt
[p
] <= '9' && '0' <= dt
[p
+1] && dt
[p
+1] <= '9');
4845 if (month_found
&& (int)dt
.find_first_of("0123456789", p
+2) != p
+2) {
4846 date
+= dt
.substr(p
,2);
4850 while ('0' <= dt
[p
] && dt
[p
] <= '9') p
++;
4851 month_found
= false;
4856 if (!month_found
) date
+= "00-00";
4858 bool day_found
= false;
4860 while (!day_found
&& p
< (int)dt
.size()) {
4861 p
= dt
.find_first_of("0123456789", p
);
4862 if (p
== (int)string::npos
|| p
+2 > (int)dt
.size() ) break;
4864 day_found
= ('0' <= dt
[p
] && dt
[p
] <= '9' && '0' <= dt
[p
+1] && dt
[p
+1] <= '9');
4865 if (day_found
&& (int)dt
.find_first_of("0123456789", p
+2) != p
+2) {
4866 date
+= dt
.substr(p
,2);
4868 while ('0' <= dt
[p
] && dt
[p
] <= '9') p
++;
4874 if (!day_found
) date
+= "00";
4878 // printf("sql %s\n", sql_ins_rnp.c_str());
4879 sqlite3_stmt
*ppStmt
=0;
4880 int rc
= sqlite3_prepare(db
, sql_ins_rnp
.c_str(), -1, &ppStmt
, 0);
4881 if (rc
!= SQLITE_OK
|| ppStmt
==0) {
4882 throw DBError(); // FIXME: catch busy error, (and/or throw DBError?)
4886 rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, path
, -1, SQLITE_TRANSIENT
);
4887 if (rc
!= SQLITE_OK
) throw DBError();
4888 rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, fn
, -1, SQLITE_TRANSIENT
);
4889 if (rc
!= SQLITE_OK
) throw DBError();
4890 rc
= sqlite3_bind_int(ppStmt
, stmt_ctr
++, pos
);
4891 if (rc
!= SQLITE_OK
) throw DBError();
4892 rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, dbtree
, -1, SQLITE_TRANSIENT
);
4893 if (rc
!= SQLITE_OK
) throw DBError();
4894 rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, date
.c_str(), -1, SQLITE_TRANSIENT
);
4895 if (rc
!= SQLITE_OK
) throw DBError();
4897 if (p_op
->sgfInDB
) {
4898 if (c
->root
->numChildren
== 1) rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, sgf
, -1, SQLITE_TRANSIENT
);
4901 s
+= c
->outputVar(root
);
4903 rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, s
.c_str(), -1, SQLITE_TRANSIENT
);
4905 if (rc
!= SQLITE_OK
) throw DBError();
4908 for(int i
=0; i
< SGFtagsSize
; i
++) {
4909 rc
= sqlite3_bind_text(ppStmt
, stmt_ctr
++, (*rootNodeProperties
)[i
].c_str(), -1, SQLITE_TRANSIENT
);
4910 if (rc
!= SQLITE_OK
) throw DBError();
4913 rc
= sqlite3_step(ppStmt
);
4914 if (rc
!= SQLITE_DONE
) throw DBError();
4915 rc
= sqlite3_finalize(ppStmt
);
4916 if (rc
!= SQLITE_OK
) throw DBError();
4917 int game_id
= sqlite3_last_insert_rowid(db
);
4920 // printf("play through the game\n");
4923 Node
* currentN
= root
;
4924 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
4925 if (algo_ps
[a
]) algo_ps
[a
]->newgame_process(game_id
);
4927 abstractBoard b
= abstractBoard(bs
);
4929 stack
<VarInfo
> branchpoints
;
4933 bool caughtSGFError
= false;
4934 char* propValue
= 0;
4938 // parse current node, watch out for B, W, AB, AW, AE properties
4939 const char* s
= currentN
->SGFstring
.c_str();
4940 int lSGFstring
= strlen(s
);
4942 while (i
< lSGFstring
&& s
[i
] != ';' && (s
[i
]==' ' || s
[i
]=='\n' || s
[i
]=='\r' || s
[i
]=='\t'))
4945 if (i
>=lSGFstring
|| s
[i
] != ';') throw SGFError();
4948 while (i
< lSGFstring
) { // while parsing
4950 while (i
< lSGFstring
&& (s
[i
]==' ' || s
[i
]=='\n' || s
[i
]=='\r' || s
[i
]=='\t'))
4952 if (i
>= lSGFstring
) break;
4957 while (i
< lSGFstring
&& s
[i
] != '[' && IDindex
< 30) {
4958 if (65 <= s
[i
] && s
[i
] <= 90)
4959 ID
[IDindex
++] = s
[i
];
4960 else if (!(97 <= s
[i
] && s
[i
] <= 122) && !(s
[i
]==' ' || s
[i
]=='\n' || s
[i
]=='\r' || s
[i
]=='\t')) {
4968 if (i
>= lSGFstring
|| IDindex
>= 30 || !IDindex
) {
4971 ID
[IDindex
] = 0; // found next property ID
4972 bool IDrelevant
= (!strcmp(ID
,"B") || !strcmp(ID
,"W") || !strcmp(ID
,"AB") || !strcmp(ID
,"AW") || !strcmp(ID
,"AE"));
4973 propValue
= new char[100000];
4974 int propValueIndex
= 0;
4975 int oldPropValueIndex
= 0;
4977 while (i
< lSGFstring
) { // while looking for property values of the current property
4978 while (s
[i
] != ']' && i
< lSGFstring
) {
4979 if (s
[i
] == '\\') i
++;
4980 if (!IDrelevant
|| s
[i
] == '\t' || s
[i
] == ' ' || s
[i
] == '\r' || s
[i
] == '\n') {
4984 if (97 <= s
[i
] && s
[i
] <= 96+bs
) { // valid board coordinate?
4985 propValue
[propValueIndex
++] = s
[i
];
4986 if (propValueIndex
> 99990) throw SGFError();
4987 } else if (s
[i
] == 't') { ; // allow passes, but do not record them (we handle them a little sloppily here)
4988 } else if (s
[i
] == ':') {
4989 if (propValueIndex
- oldPropValueIndex
!= 2)
4994 while (i
<lSGFstring
&& (s
[i
] == '\t' || s
[i
] == ' ' || s
[i
] == '\r' || s
[i
] == '\n')) i
++;
4995 if (i
>= lSGFstring
) throw SGFError();
4996 if (97 <= s
[i
] && s
[i
] <= 96+bs
) // valid board coordinate?
4998 else throw SGFError();
5000 while (i
<lSGFstring
&& (s
[i
] == '\t' || s
[i
] == ' ' || s
[i
] == '\r' || s
[i
] == '\n')) i
++;
5001 if (i
>= lSGFstring
) throw SGFError();
5002 if (97 <= s
[i
] && s
[i
] <= 96+bs
) // valid board coordinate?
5004 else throw SGFError();
5006 while (i
<lSGFstring
&& (s
[i
] == '\t' || s
[i
] == ' ' || s
[i
] == '\r' || s
[i
] == '\n')) i
++;
5007 if (i
>= lSGFstring
) throw SGFError();
5009 char st1
= propValue
[propValueIndex
-2];
5010 char st2
= propValue
[propValueIndex
-1];
5011 propValueIndex
-= 2; // do not want to have the first entry twice!
5012 for(char x1
= st1
; x1
<= rect1
; x1
++) {
5013 for(char x2
= st2
; x2
<= rect2
; x2
++) {
5014 propValue
[propValueIndex
++] = x1
;
5015 propValue
[propValueIndex
++] = x2
;
5016 if (propValueIndex
> 99990) throw SGFError();
5019 oldPropValueIndex
= propValueIndex
;
5021 } else throw SGFError();
5027 if (i
>= lSGFstring
) throw SGFError();
5029 if (propValueIndex
- oldPropValueIndex
!= 0 && propValueIndex
- oldPropValueIndex
!= 2) {
5032 oldPropValueIndex
= propValueIndex
;
5035 while (i
< lSGFstring
&& (s
[i
]==' ' || s
[i
]=='\n' || s
[i
]=='\r' || s
[i
]=='\t')) i
++;
5037 if (i
>= lSGFstring
|| s
[i
] != '[') break; // end of node, or found next property
5038 else i
++; // s[i] == '[', so another property value follows.
5040 int p_len
= propValueIndex
/2;
5042 if (!propValueIndex
) { // in particular, this happens if !IDrelevant
5043 if (!strcmp(ID
, "B") || !strcmp(ID
, "W")) {
5044 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5045 if (algo_ps
[a
]) algo_ps
[a
]->pass_process();
5047 delete [] propValue
;
5052 if (!strcmp(ID
, "B") || !strcmp(ID
, "W")) {
5053 char x
= propValue
[0]-97; // 97 == ord('a'), (0,0) <= (x,y) <= (bs-1, bs-1)
5054 char y
= propValue
[1]-97;
5056 if (!b
.play(x
, y
, ID
)) throw SGFError();
5057 Move m
= b
.undostack
.top();
5059 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5060 if (algo_ps
[a
]) algo_ps
[a
]->move_process(m
);
5062 if (!strcmp(ID
, "AB")) {
5063 for(int pp
=0; pp
< p_len
; pp
++) {
5064 char x
= propValue
[2*pp
]-97;
5065 char y
= propValue
[2*pp
+1]-97;
5066 if (!b
.play(x
, y
, "B")) throw SGFError();
5067 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5068 if (algo_ps
[a
]) algo_ps
[a
]->AB_process(x
, y
);
5071 if (!strcmp(ID
, "AW")) {
5072 for(int pp
=0; pp
< p_len
; pp
++) {
5073 char x
= propValue
[2*pp
]-97;
5074 char y
= propValue
[2*pp
+1]-97;
5075 if (!b
.play(x
, y
, "W")) throw SGFError();
5076 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5077 if (algo_ps
[a
]) algo_ps
[a
]->AW_process(x
, y
);
5080 if (!strcmp(ID
, "AE")) {
5081 for(int pp
=0; pp
< p_len
; pp
++) {
5082 char x
= propValue
[2*pp
]-97;
5083 char y
= propValue
[2*pp
+1]-97;
5084 char removed
= b
.getStatus(x
,y
);
5085 if (removed
==' ') throw SGFError();
5087 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5088 if (algo_ps
[a
]) algo_ps
[a
]->AE_process(x
, y
, removed
);
5092 delete [] propValue
;
5095 } catch (SGFError
) {
5097 delete [] propValue
;
5100 return_val
|= SGF_ERROR
;
5101 caughtSGFError
= true;
5102 if (flags
& OMIT_GAMES_WITH_SGF_ERRORS
) {
5104 // (FIXME should exit from the loop here)
5109 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5110 if (algo_ps
[a
]) algo_ps
[a
]->endOfNode_process();
5113 if (processVariations
&& currentN
->numChildren
> 1) { // several variations start from this node;
5114 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5115 if (algo_ps
[a
]) algo_ps
[a
]->branchpoint_process();
5116 branchpoints
.push(VarInfo(currentN
, new abstractBoard(b
), 0));
5119 if (caughtSGFError
) currentN
= 0; // stop here with this branch
5120 else currentN
= currentN
->next
;
5122 if (!currentN
&& branchpoints
.size()) {
5123 currentN
= branchpoints
.top().n
;
5124 b
= abstractBoard(*branchpoints
.top().b
);
5125 whichVar
= branchpoints
.top().i
;
5127 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5128 if (algo_ps
[a
]) algo_ps
[a
]->endOfVariation_process();
5129 if (whichVar
+2 < currentN
->numChildren
) {
5130 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++)
5131 if (algo_ps
[a
]) algo_ps
[a
]->branchpoint_process();
5132 branchpoints
.push(VarInfo(currentN
, new abstractBoard(b
), whichVar
+1));
5134 currentN
= currentN
->next
;
5135 for(int vi
=0; vi
< whichVar
+1; vi
++) currentN
= currentN
->down
;
5139 // check for duplicates (if desired)
5140 bool is_duplicate
= false;
5141 if (flags
& (CHECK_FOR_DUPLICATES
|CHECK_FOR_DUPLICATES_STRICT
)) {
5142 char* sig
= ((Algo_signature
*)algo_ps
[20*algo_offset
])->get_current_signature();
5143 vector
<int> all_duplicates
= ((Algo_signature
*)algo_ps
[20*algo_offset
])->search_signature(sig
);
5144 if (all_duplicates
.size()) {
5145 // printf("dupl %d\n", all_duplicates.size());
5146 is_duplicate
= true;
5147 if ((flags
& CHECK_FOR_DUPLICATES_STRICT
) && (p_op
->algos
& ALGO_FINALPOS
)) {
5148 vector
<int>::iterator d_it
= all_duplicates
.begin();
5149 while (d_it
!= all_duplicates
.end() && !((Algo_finalpos
*)algo_ps
[20*algo_offset
+ algo_finalpos
])->equals_current(*d_it
))
5151 if (d_it
== all_duplicates
.end()) is_duplicate
= false;
5154 return_val
|= IS_DUPLICATE
;
5155 if (flags
& OMIT_DUPLICATES
) commit
= false;
5163 if ((*rootNodeProperties
)[posHA
] != "") { // handicap game
5165 sprintf(sql
, "insert into GAME_TAGS (game_id, tag_id) values (%d, %d);", game_id
, HANDI_TAG
);
5166 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
5167 if (rc
!= SQLITE_OK
) throw DBError();
5169 if ((*rootNodeProperties
)[posWR
].find('p') != string::npos
||
5170 (*rootNodeProperties
)[posBR
].find('p') != string::npos
) {
5171 // at least one of the players is professional
5173 sprintf(sql
, "insert into GAME_TAGS (game_id, tag_id) values (%d, %d);", game_id
, PROFESSIONAL_TAG
);
5174 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
5175 if (rc
!= SQLITE_OK
) throw DBError();
5178 return_val
|= NOT_INSERTED_INTO_DB
;
5180 sprintf(sql
, "delete from GAMES where id=%d", game_id
);
5181 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
5182 if (rc
) printf("ouch %d\n", rc
);
5184 for(int a
=20*algo_offset
; a
< 20*(algo_offset
+1); a
++) {
5185 // printf("endgame %d\n", a);
5186 if (algo_ps
[a
]) algo_ps
[a
]->endgame_process(commit
);
5189 delete rootNodeProperties
;
5190 process_results_vector
.push_back(return_val
);
5195 return process_results_vector
.size();
5198 int GameList::process_results(unsigned int i
) {
5199 if (i
<0 || i
>=process_results_vector
.size()) return INDEX_OUT_OF_RANGE
;
5200 return process_results_vector
[i
];
5204 int GameList::snapshot() throw(DBError
) {
5205 // return a handle to a snapshot stored in the main GameList db
5206 // the snapshot contains copies of
5207 // - orderby, format1, format2
5209 // - all hits in the GameListEntry's of currentList
5210 // - pattern, labels, continuations, num_hits, num_switched, Bwins, Wwins
5212 SnapshotVector snapshot
;
5213 snapshot
.pb_string(orderby
);
5214 snapshot
.pb_string(format1
);
5215 snapshot
.pb_string(format2
);
5217 snapshot
.pb_int(currentList
->size());
5218 for(vector
<pair
<int,int> >::iterator it
= currentList
->begin(); it
!= currentList
->end(); it
++) {
5219 snapshot
.pb_int(it
->first
);
5220 snapshot
.pb_int(it
->second
);
5221 vector
<Hit
* >* hits
= (*all
)[it
->second
]->hits
;
5222 snapshot
.pb_int(hits
->size());
5223 for (vector
<Hit
* >::iterator it_h
= hits
->begin(); it_h
!= hits
->end(); it_h
++) {
5224 (*it_h
)->to_snv(snapshot
);
5229 snapshot
.pb_char(1);
5230 mrs_pattern
->to_snv(snapshot
);
5231 } else snapshot
.pb_char(0);
5232 if (searchOptions
) {
5233 snapshot
.pb_char(1);
5234 searchOptions
->to_snv(snapshot
);
5235 } else snapshot
.pb_char(0);
5236 if (mrs_pattern
&& labels
&& continuations
) {
5237 snapshot
.pb_char(1);
5238 snapshot
.pb_charp(labels
, mrs_pattern
->sizeX
* mrs_pattern
->sizeY
);
5239 for(int i
=0; i
<mrs_pattern
->sizeX
* mrs_pattern
->sizeY
; i
++) continuations
[i
].to_snv(snapshot
);
5240 } else snapshot
.pb_char(0);
5241 snapshot
.pb_int(num_hits
);
5242 snapshot
.pb_int(num_switched
);
5243 snapshot
.pb_int(Bwins
);
5244 snapshot
.pb_int(Wwins
);
5246 // insert snapshot into database
5247 sqlite3_stmt
*ppStmt
=0;
5248 int rc
= sqlite3_prepare(db
, "insert into snapshots (data) values (?)", -1, &ppStmt
, 0);
5249 if (rc
!= SQLITE_OK
|| ppStmt
==0) throw DBError();
5250 char* snchp
= snapshot
.to_charp();
5251 rc
= sqlite3_bind_blob(ppStmt
, 1, snchp
, snapshot
.size(), SQLITE_TRANSIENT
);
5253 if (rc
!= SQLITE_OK
) throw DBError();
5254 rc
= sqlite3_step(ppStmt
);
5255 if (rc
!= SQLITE_DONE
) throw DBError();
5256 rc
= sqlite3_finalize(ppStmt
);
5257 if (rc
!= SQLITE_OK
) throw DBError();
5258 return sqlite3_last_insert_rowid(db
);
5261 void GameList::restore(int handle
, bool del
) throw(DBError
) {
5262 // restore the state of the GameList associated with handle
5264 // retrieve info associated with handle from db
5268 sqlite3_stmt
*ppStmt
=0;
5269 int rc
= sqlite3_prepare(db
, "select data from snapshots where rowid = ?", -1, &ppStmt
, 0);
5270 if (rc
!= SQLITE_OK
|| ppStmt
==0) {
5273 rc
= sqlite3_bind_int(ppStmt
, 1, handle
);
5274 if (rc
!= SQLITE_OK
) throw DBError();
5275 rc
= sqlite3_step(ppStmt
);
5276 if (rc
== SQLITE_ROW
) {
5277 sn
= (char*)sqlite3_column_blob(ppStmt
, 0);
5278 sn_size
= sqlite3_column_bytes(ppStmt
, 0);
5279 } else throw DBError();
5281 SnapshotVector
snapshot(sn
, sn_size
);
5285 string ob
= snapshot
.retrieve_string();
5286 string f1
= snapshot
.retrieve_string();
5287 string f2
= snapshot
.retrieve_string();
5288 if (ob
!= orderby
|| f1
!= format1
|| f2
!= format2
) resetFormat();
5290 if (oldList
) delete oldList
;
5292 if (currentList
) delete currentList
;
5293 currentList
= new vector
<pair
<int,int> >;
5294 for(vector
<GameListEntry
* >::iterator it
= all
->begin(); it
!= all
->end(); it
++) {
5296 for(vector
<Hit
* >::iterator ith
= (*it
)->hits
->begin(); ith
!= (*it
)->hits
->end(); ith
++)
5301 if ((*it
)->candidates
) {
5302 for(vector
<Candidate
* >::iterator itc
= (*it
)->candidates
->begin(); itc
!= (*it
)->candidates
->end(); itc
++)
5304 delete (*it
)->candidates
;
5305 (*it
)->candidates
= 0;
5309 int cl_size
= snapshot
.retrieve_int();
5310 for(int i
=0; i
<cl_size
; i
++) {
5311 int i1
= snapshot
.retrieve_int();
5312 int i2
= snapshot
.retrieve_int();
5314 currentList
->push_back(make_pair(i1
, i2
));
5315 // if ((*currentList)[currentList->size()-1].second >= all->size()) printf("ouch %d\n", (*currentList)[currentList->size()-1].second);
5316 (*all
)[(*currentList
)[currentList
->size()-1].second
]->hits_from_snv(snapshot
);
5319 if (mrs_pattern
) delete mrs_pattern
;
5320 if (snapshot
.retrieve_char()) mrs_pattern
= new Pattern(snapshot
);
5321 else mrs_pattern
= 0;
5323 if (searchOptions
) delete searchOptions
;
5324 if (snapshot
.retrieve_char()) searchOptions
= new SearchOptions(snapshot
);
5325 else searchOptions
= 0;
5327 if (labels
) delete [] labels
;
5328 if (continuations
) delete [] continuations
; // FIXME check (cf. ~GameList)
5329 if (snapshot
.retrieve_char()) {
5330 labels
= snapshot
.retrieve_charp();
5331 continuations
= new Continuation
[mrs_pattern
->sizeX
* mrs_pattern
->sizeY
];
5332 for(int i
=0; i
<mrs_pattern
->sizeX
* mrs_pattern
->sizeY
; i
++)
5333 continuations
[i
].from_snv(snapshot
);
5338 num_hits
= snapshot
.retrieve_int();
5339 num_switched
= snapshot
.retrieve_int();
5340 Bwins
= snapshot
.retrieve_int();
5341 Wwins
= snapshot
.retrieve_int();
5343 rc
= sqlite3_finalize(ppStmt
);
5344 if (rc
!= SQLITE_OK
) throw DBError();
5345 if (del
) { // delete snapshot from db
5347 sprintf(sql
, "delete from snapshots where rowid = %d", handle
);
5348 rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
5349 if (rc
!= SQLITE_OK
) throw DBError();
5353 void GameList::delete_snapshot(int handle
) throw(DBError
) {
5355 sprintf(sql
, "delete from snapshots where rowid = %d", handle
);
5356 int rc
= sqlite3_exec(db
, sql
, 0, 0, 0);
5357 if (rc
!= SQLITE_OK
) throw DBError();
5360 void GameList::delete_all_snapshots() throw(DBError
) {
5361 int rc
= sqlite3_exec(db
, "delete from snapshots", 0, 0, 0);
5362 if (rc
!= SQLITE_OK
) throw DBError();
5365 VarInfo::VarInfo(Node
* N
, abstractBoard
* B
, int I
) {
5371 VarInfo::VarInfo(const VarInfo
& v
) {
5373 b
= new abstractBoard(*v
.b
);
5377 VarInfo::~VarInfo() {