| 1 | #include <Python.h> |
|---|
| 2 | |
|---|
| 3 | void invert(char *s) { |
|---|
| 4 | int c,i,j; |
|---|
| 5 | for (i=0,j=strlen(s)-1;i<j;i++,j--) { |
|---|
| 6 | c=s[i]; |
|---|
| 7 | s[i]=s[j]; |
|---|
| 8 | s[j]=c; |
|---|
| 9 | } |
|---|
| 10 | } |
|---|
| 11 | |
|---|
| 12 | char* itoa(int n) { // convert a non-negative integer to a char* |
|---|
| 13 | char *s = new char[15]; |
|---|
| 14 | int i; |
|---|
| 15 | |
|---|
| 16 | i=0; |
|---|
| 17 | do { s[i++] = n%10+'0'; |
|---|
| 18 | } while ((n/=10)>0); |
|---|
| 19 | |
|---|
| 20 | s[i]='\0'; |
|---|
| 21 | invert(s); |
|---|
| 22 | return s; |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | bool greater(long* a, unsigned long i, unsigned long j) { |
|---|
| 27 | if (a[2*i]>a[2*j] || (a[2*i]==a[2*j] && a[2*i+1]>a[2*j+1])) return true; |
|---|
| 28 | return false; |
|---|
| 29 | } |
|---|
| 30 | |
|---|
| 31 | void swap(long* a, unsigned long i, unsigned long j) { |
|---|
| 32 | long help1, help2; |
|---|
| 33 | |
|---|
| 34 | help1 = a[2*i]; |
|---|
| 35 | help2 = a[2*i+1]; |
|---|
| 36 | a[2*i] = a[2*j]; |
|---|
| 37 | a[2*i+1] = a[2*j+1]; |
|---|
| 38 | a[2*j] = help1; |
|---|
| 39 | a[2*j+1] = help2; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | void sortCArray(long* a, long l, long r) { |
|---|
| 44 | |
|---|
| 45 | long left, right, li11; |
|---|
| 46 | |
|---|
| 47 | long stack[250]; |
|---|
| 48 | stack[0] = l; |
|---|
| 49 | stack[1] = r; |
|---|
| 50 | unsigned char stackIndex = 1; |
|---|
| 51 | |
|---|
| 52 | long help1, help2; |
|---|
| 53 | |
|---|
| 54 | while (stackIndex) { |
|---|
| 55 | if (r > l) { |
|---|
| 56 | if (r-l == 1) { |
|---|
| 57 | if (greater(a, l, r)) swap(a, l, r); |
|---|
| 58 | |
|---|
| 59 | stackIndex--; |
|---|
| 60 | l = stack[2*stackIndex]; |
|---|
| 61 | r = stack[2*stackIndex+1]; |
|---|
| 62 | |
|---|
| 63 | } else { |
|---|
| 64 | |
|---|
| 65 | if (greater(a, (r+l)/2, l)) { |
|---|
| 66 | if (greater(a, l, r)) li11 = l; |
|---|
| 67 | else { |
|---|
| 68 | if (greater(a, r, (r+l)/2)) li11 = (r+l)/2; |
|---|
| 69 | else li11 = r; |
|---|
| 70 | } |
|---|
| 71 | } else { |
|---|
| 72 | if (greater(a, (r+l)/2, r)) li11 = (r+l)/2; |
|---|
| 73 | else { |
|---|
| 74 | if (greater(a, r, l)) li11 = l; |
|---|
| 75 | else li11 = r; |
|---|
| 76 | } |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | swap(a, li11, r); |
|---|
| 80 | help1 = a[2*r]; |
|---|
| 81 | help2 = a[2*r+1]; |
|---|
| 82 | |
|---|
| 83 | left = l; |
|---|
| 84 | right = r-1; |
|---|
| 85 | |
|---|
| 86 | while (1) { |
|---|
| 87 | while (a[2*left] < help1 || (a[2*left]==help1 && a[2*left+1]<help2)) left++; |
|---|
| 88 | while (a[2*right] > help1 || (a[2*right]==help1 && a[2*right+1]>help2)) right--; |
|---|
| 89 | |
|---|
| 90 | if (right <= left) break; |
|---|
| 91 | |
|---|
| 92 | swap(a, left, right); |
|---|
| 93 | |
|---|
| 94 | left++; |
|---|
| 95 | right--; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | swap(a, left, r); |
|---|
| 99 | |
|---|
| 100 | if (left-l > r-left) { |
|---|
| 101 | stack[2*stackIndex] = l; |
|---|
| 102 | stack[2*stackIndex+1] = left-1; |
|---|
| 103 | stackIndex++; |
|---|
| 104 | l = left+1; |
|---|
| 105 | } else { |
|---|
| 106 | stack[2*stackIndex] = left+1; |
|---|
| 107 | stack[2*stackIndex+1] = r; |
|---|
| 108 | stackIndex++; |
|---|
| 109 | r = left-1; |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | } else { |
|---|
| 113 | stackIndex--; |
|---|
| 114 | l = stack[2*stackIndex]; |
|---|
| 115 | r = stack[2*stackIndex+1]; |
|---|
| 116 | } |
|---|
| 117 | } |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | static const int COLORSWITCH = 1024; |
|---|
| 121 | |
|---|
| 122 | static char flipX(char flipNO, char x, char y) { |
|---|
| 123 | if (flipNO==0) return x; |
|---|
| 124 | if (flipNO==1) return 18-x; |
|---|
| 125 | if (flipNO==2) return x; |
|---|
| 126 | if (flipNO==3) return 18-x; |
|---|
| 127 | if (flipNO==4) return y; |
|---|
| 128 | if (flipNO==5) return 18-y; |
|---|
| 129 | if (flipNO==6) return y; |
|---|
| 130 | if (flipNO==7) return 18-y; |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | static char flipY(char flipNO, char x, char y) { |
|---|
| 134 | if (flipNO==0) return y; |
|---|
| 135 | if (flipNO==1) return y; |
|---|
| 136 | if (flipNO==2) return 18-y; |
|---|
| 137 | if (flipNO==3) return 18-y; |
|---|
| 138 | if (flipNO==4) return x; |
|---|
| 139 | if (flipNO==5) return x; |
|---|
| 140 | if (flipNO==6) return 18-x; |
|---|
| 141 | if (flipNO==7) return 18-x; |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | static PyObject* match(PyObject* self, PyObject* args) { |
|---|
| 145 | int noPatterns; |
|---|
| 146 | char *Patterns; |
|---|
| 147 | char *PSize; |
|---|
| 148 | char *PInvFlips; |
|---|
| 149 | char *PColorSwitch; |
|---|
| 150 | char *PAnchors; |
|---|
| 151 | unsigned long *PBitsTable; |
|---|
| 152 | unsigned char *PBits; |
|---|
| 153 | unsigned char *fp; |
|---|
| 154 | unsigned char *mainlist; |
|---|
| 155 | unsigned long *posTable; |
|---|
| 156 | |
|---|
| 157 | unsigned long *hashIndices; |
|---|
| 158 | unsigned char *hash; |
|---|
| 159 | |
|---|
| 160 | char* contLabels; |
|---|
| 161 | |
|---|
| 162 | int PCSlength, PAlength, PBTlength, PBlength, fplength, MLlength, PTlength, HLlength, |
|---|
| 163 | hashIlength, hashlength, contLabelsLength, contLabelsIndex, |
|---|
| 164 | showColorSwitch; |
|---|
| 165 | int moveLimit; |
|---|
| 166 | unsigned long* helplist; |
|---|
| 167 | |
|---|
| 168 | PyObject *progBarUpdate; |
|---|
| 169 | PyObject *continuations; |
|---|
| 170 | PyObject *symmetries; |
|---|
| 171 | PyObject *dbData; |
|---|
| 172 | float pB_start, pB_end; |
|---|
| 173 | |
|---|
| 174 | if (!PyArg_ParseTuple(args, "sss#s#s#s#s#is#s#s#s#s#s#Offs#iOOOi", &Patterns, &PSize, |
|---|
| 175 | &PInvFlips, &noPatterns, &PColorSwitch, &PCSlength, |
|---|
| 176 | &PAnchors, &PAlength, &PBitsTable, &PBTlength, &PBits, &PBlength, &moveLimit, |
|---|
| 177 | &helplist, &HLlength, &fp, &fplength, |
|---|
| 178 | &mainlist, &MLlength, &posTable, &PTlength, |
|---|
| 179 | &hashIndices, &hashIlength, &hash, &hashlength, |
|---|
| 180 | &progBarUpdate, &pB_start, &pB_end, |
|---|
| 181 | &contLabels, &contLabelsLength, &contLabelsIndex, |
|---|
| 182 | &continuations, &symmetries, &dbData, |
|---|
| 183 | &showColorSwitch)) |
|---|
| 184 | return NULL; |
|---|
| 185 | |
|---|
| 186 | HLlength /= sizeof(unsigned long); |
|---|
| 187 | |
|---|
| 188 | int foundgamesSize = 5000; |
|---|
| 189 | int unsigned long *foundgames = PyMem_New(unsigned long, foundgamesSize); // stored here: no. of found game |
|---|
| 190 | int foundgamesIndex=0; |
|---|
| 191 | |
|---|
| 192 | PyObject *result = PyList_New(0); |
|---|
| 193 | |
|---|
| 194 | int Bwins = 0; |
|---|
| 195 | int Wwins = 0; |
|---|
| 196 | int noSwitched = 0; |
|---|
| 197 | int noMatchesFinal = 0; |
|---|
| 198 | |
|---|
| 199 | int patternSize = PSize[0] * PSize[1]; |
|---|
| 200 | |
|---|
| 201 | unsigned long* hashInd = new unsigned long[noPatterns]; |
|---|
| 202 | if (hashIlength) { |
|---|
| 203 | for(int i=0; i<noPatterns; i++) hashInd[i] = hashIndices[2*i]; // set hashInd to hash_start's |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | for(int game=0; game < HLlength; game++) { |
|---|
| 207 | |
|---|
| 208 | if (game % 600 == 0) { |
|---|
| 209 | float percent = game * (pB_end - pB_start) / HLlength + pB_start; |
|---|
| 210 | PyObject* arglist = Py_BuildValue("(f)", percent); |
|---|
| 211 | PyEval_CallObject(progBarUpdate, arglist); |
|---|
| 212 | Py_DECREF(arglist); |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | unsigned long index = helplist[game]; |
|---|
| 216 | |
|---|
| 217 | char matchlist[13000]; |
|---|
| 218 | int matchlistIndex = 0; |
|---|
| 219 | |
|---|
| 220 | for(char N=0; N<noPatterns; N++) { |
|---|
| 221 | |
|---|
| 222 | if (hashIlength) { |
|---|
| 223 | while ((hashInd[N]+1<hashIndices[2*N+1]) && (index > 256*hash[hashInd[N]] + hash[hashInd[N]+1])) hashInd[N]+=2; |
|---|
| 224 | if (index < 256*hash[hashInd[N]] + hash[hashInd[N]+1]) continue; |
|---|
| 225 | if (index == 256*hash[hashInd[N]] + hash[hashInd[N]+1]) { |
|---|
| 226 | hashInd[N] += 2; |
|---|
| 227 | matchlist[matchlistIndex++] = N; |
|---|
| 228 | matchlist[matchlistIndex++] = PAnchors[4*N]; |
|---|
| 229 | matchlist[matchlistIndex++] = PAnchors[4*N+1]; |
|---|
| 230 | } |
|---|
| 231 | } |
|---|
| 232 | else { |
|---|
| 233 | |
|---|
| 234 | char a00 = PAnchors[4*N]; |
|---|
| 235 | char a01 = PAnchors[4*N+1]; |
|---|
| 236 | char a10 = PAnchors[4*N+2]; |
|---|
| 237 | char a11 = PAnchors[4*N+3]; |
|---|
| 238 | |
|---|
| 239 | for(char a0=a00; a0 <= a10; a0++) |
|---|
| 240 | for(char a1=a01; a1 <= a11; a1++) { |
|---|
| 241 | |
|---|
| 242 | int matches = 1; |
|---|
| 243 | |
|---|
| 244 | int pIndex = 2*(a1%2) + (a0%2); |
|---|
| 245 | int patternBits = PBitsTable[N*4 + pIndex]; |
|---|
| 246 | |
|---|
| 247 | int pbIndex = 0; |
|---|
| 248 | int fpIndex = index*150 + a1/2 + (a0/2)*10; |
|---|
| 249 | |
|---|
| 250 | for(int x=0; x < PBits[patternBits]; x++) { |
|---|
| 251 | |
|---|
| 252 | int start = PBits[patternBits + ++pbIndex]; |
|---|
| 253 | int length = PBits[patternBits + ++pbIndex]; |
|---|
| 254 | fpIndex += start; |
|---|
| 255 | |
|---|
| 256 | for(int y=0; y<length; y++) { |
|---|
| 257 | pbIndex++; |
|---|
| 258 | |
|---|
| 259 | if (PBits[patternBits+pbIndex] & fp[fpIndex]) { |
|---|
| 260 | matches = 0; |
|---|
| 261 | break; |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | fpIndex++; |
|---|
| 265 | } |
|---|
| 266 | if (!matches) break; |
|---|
| 267 | fpIndex += 10 - start - length; |
|---|
| 268 | |
|---|
| 269 | } |
|---|
| 270 | |
|---|
| 271 | if (matches) { |
|---|
| 272 | matchlist[matchlistIndex++] = N; |
|---|
| 273 | matchlist[matchlistIndex++] = a0; |
|---|
| 274 | matchlist[matchlistIndex++] = a1; |
|---|
| 275 | } |
|---|
| 276 | |
|---|
| 277 | } |
|---|
| 278 | } |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | if (matchlistIndex) { /* checkCandidate */ |
|---|
| 282 | |
|---|
| 283 | int noMatches = matchlistIndex/3; |
|---|
| 284 | int toBeFound = noMatches; |
|---|
| 285 | long noCurrentResults = 0; |
|---|
| 286 | long *currentResults = new long[noMatches*2]; |
|---|
| 287 | |
|---|
| 288 | char *dicts = new char[noMatches * patternSize]; |
|---|
| 289 | int *dictsNO = new int[noMatches]; |
|---|
| 290 | |
|---|
| 291 | int *found = new int[noMatches]; |
|---|
| 292 | |
|---|
| 293 | char *Xinterv = new char[2*noMatches]; |
|---|
| 294 | char *Yinterv = new char[2*noMatches]; |
|---|
| 295 | |
|---|
| 296 | for(int m=0; m<noMatches; m++) { |
|---|
| 297 | |
|---|
| 298 | found[m] = -1; |
|---|
| 299 | dictsNO[m] = 0; |
|---|
| 300 | |
|---|
| 301 | int sizeX = PSize[2*matchlist[3*m]]; |
|---|
| 302 | int sizeY = PSize[2*matchlist[3*m]+1]; |
|---|
| 303 | int Poffset = matchlist[3*m] * patternSize; |
|---|
| 304 | |
|---|
| 305 | for(int i=0; i < sizeX; i++) { |
|---|
| 306 | for(int j=0; j < sizeY; j++) { |
|---|
| 307 | if (Patterns[Poffset + sizeY*i + j] == '.') |
|---|
| 308 | dicts[m*patternSize+i*sizeY+j] = ' '; |
|---|
| 309 | else { |
|---|
| 310 | dicts[m*patternSize+i*sizeY+j] = Patterns[Poffset + sizeY*i + j]; |
|---|
| 311 | if (Patterns[Poffset + sizeY*i + j] != '*') dictsNO[m]++; |
|---|
| 312 | } |
|---|
| 313 | } |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | Xinterv[2*m] = matchlist[3*m+1]; |
|---|
| 317 | Xinterv[2*m+1] = matchlist[3*m+1] + PSize[2*matchlist[3*m]]; |
|---|
| 318 | Yinterv[2*m] = matchlist[3*m+2]; |
|---|
| 319 | Yinterv[2*m+1] = matchlist[3*m+2] + PSize[2*matchlist[3*m]+1]; |
|---|
| 320 | } |
|---|
| 321 | |
|---|
| 322 | int movelistIndex = posTable[index]+2; |
|---|
| 323 | |
|---|
| 324 | int caplistIndex = movelistIndex; |
|---|
| 325 | while (mainlist[caplistIndex] != 'z') caplistIndex++; |
|---|
| 326 | int mlLength = caplistIndex; |
|---|
| 327 | |
|---|
| 328 | if (mainlist[caplistIndex+2] == 'z') caplistIndex +=2; // caplist empty |
|---|
| 329 | else caplistIndex += 3; |
|---|
| 330 | |
|---|
| 331 | /* AB's */ |
|---|
| 332 | |
|---|
| 333 | if (mainlist[movelistIndex] == 25 && mainlist[movelistIndex+1] == 3) { |
|---|
| 334 | movelistIndex += 2; |
|---|
| 335 | while (mainlist[movelistIndex] != 25) { |
|---|
| 336 | char x = mainlist[movelistIndex++]; |
|---|
| 337 | char y = mainlist[movelistIndex++]; |
|---|
| 338 | |
|---|
| 339 | for (int m=0; m<noMatches; m++) { |
|---|
| 340 | if (found[m] != -2) { |
|---|
| 341 | if (Xinterv[2*m] <= x && x < Xinterv[2*m+1] && |
|---|
| 342 | Yinterv[2*m] <= y && y < Yinterv[2*m+1]) { /* stone played in */ |
|---|
| 343 | /* relevant region */ |
|---|
| 344 | if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]==' ') { |
|---|
| 345 | |
|---|
| 346 | if (!(fp[index*150 + 100 + y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) { |
|---|
| 347 | // this m can't become a match |
|---|
| 348 | found[m] = -2; |
|---|
| 349 | toBeFound--; |
|---|
| 350 | continue; |
|---|
| 351 | } |
|---|
| 352 | else { |
|---|
| 353 | dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]] = '.'; |
|---|
| 354 | dictsNO[m]++; |
|---|
| 355 | } |
|---|
| 356 | } |
|---|
| 357 | else if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1] |
|---|
| 358 | +y-matchlist[3*m+2]] == 'X') { |
|---|
| 359 | dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]=' '; |
|---|
| 360 | dictsNO[m]--; |
|---|
| 361 | } |
|---|
| 362 | } |
|---|
| 363 | } |
|---|
| 364 | } |
|---|
| 365 | } |
|---|
| 366 | } |
|---|
| 367 | |
|---|
| 368 | /* AW's */ |
|---|
| 369 | |
|---|
| 370 | if (mainlist[movelistIndex] == 25 && mainlist[movelistIndex+1] == 4) { |
|---|
| 371 | movelistIndex += 2; |
|---|
| 372 | while (mainlist[movelistIndex] != 25) { |
|---|
| 373 | char x = mainlist[movelistIndex]; |
|---|
| 374 | char y = mainlist[movelistIndex+1]; |
|---|
| 375 | movelistIndex += 2; |
|---|
| 376 | |
|---|
| 377 | int m; |
|---|
| 378 | for (m=0; m<noMatches; m++) { |
|---|
| 379 | if (found[m]!= -2) { |
|---|
| 380 | if (Xinterv[2*m] <= x && x < Xinterv[2*m+1] && |
|---|
| 381 | Yinterv[2*m] <= y && y < Yinterv[2*m+1]) { |
|---|
| 382 | if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]==' ') { |
|---|
| 383 | if (!(fp[index*150 + 100 + y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) { |
|---|
| 384 | // this m can't become a match |
|---|
| 385 | found[m] = -2; |
|---|
| 386 | toBeFound--; |
|---|
| 387 | continue; |
|---|
| 388 | } |
|---|
| 389 | else { |
|---|
| 390 | dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]] = '.'; |
|---|
| 391 | dictsNO[m]++; |
|---|
| 392 | } |
|---|
| 393 | } |
|---|
| 394 | else if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1] |
|---|
| 395 | +y-matchlist[3*m+2]] == 'O') { |
|---|
| 396 | dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]=' '; |
|---|
| 397 | dictsNO[m]--; |
|---|
| 398 | } |
|---|
| 399 | } |
|---|
| 400 | } |
|---|
| 401 | } |
|---|
| 402 | } |
|---|
| 403 | } |
|---|
| 404 | |
|---|
| 405 | for(int m=0; m<noMatches; m++) |
|---|
| 406 | if (found[m]==-1 && !dictsNO[m]) found[m] = 0; |
|---|
| 407 | |
|---|
| 408 | /* B's and W's */ |
|---|
| 409 | |
|---|
| 410 | char co; |
|---|
| 411 | |
|---|
| 412 | if (mainlist[movelistIndex+1] == 1) co = 'B'; |
|---|
| 413 | if (mainlist[movelistIndex+1] == 2) co = 'W'; |
|---|
| 414 | |
|---|
| 415 | int mLimit; |
|---|
| 416 | |
|---|
| 417 | if (moveLimit == 250) mLimit = 1500 + movelistIndex; // practically no limit |
|---|
| 418 | else mLimit = 2*moveLimit + movelistIndex; |
|---|
| 419 | |
|---|
| 420 | int counter = -1; |
|---|
| 421 | char c; |
|---|
| 422 | char cinv; |
|---|
| 423 | |
|---|
| 424 | while (movelistIndex < mlLength-2 && movelistIndex < mLimit) { |
|---|
| 425 | |
|---|
| 426 | movelistIndex += 2; |
|---|
| 427 | counter++; |
|---|
| 428 | |
|---|
| 429 | if (co == 'B') { |
|---|
| 430 | co = 'W'; |
|---|
| 431 | c = 'X'; |
|---|
| 432 | cinv = 'O'; |
|---|
| 433 | } else { |
|---|
| 434 | co = 'B'; |
|---|
| 435 | c = 'O'; |
|---|
| 436 | cinv = 'X'; |
|---|
| 437 | } |
|---|
| 438 | |
|---|
| 439 | char x = mainlist[movelistIndex]; |
|---|
| 440 | char y = mainlist[movelistIndex+1]; |
|---|
| 441 | |
|---|
| 442 | int clI = 0; |
|---|
| 443 | int clIend = 0; |
|---|
| 444 | |
|---|
| 445 | if (mainlist[caplistIndex] != 'z' && counter == 256*mainlist[caplistIndex] + mainlist[caplistIndex+1]) { |
|---|
| 446 | caplistIndex += 2; |
|---|
| 447 | clI = caplistIndex; |
|---|
| 448 | while (mainlist[caplistIndex] != 'z' && mainlist[caplistIndex] != 'y') caplistIndex++; |
|---|
| 449 | clIend = caplistIndex-1; |
|---|
| 450 | caplistIndex++; |
|---|
| 451 | } |
|---|
| 452 | |
|---|
| 453 | for(int m=0; m<noMatches; m++) { |
|---|
| 454 | |
|---|
| 455 | if (found[m] != -2) { |
|---|
| 456 | |
|---|
| 457 | if (Xinterv[2*m] <= x && x < Xinterv[2*m+1] && |
|---|
| 458 | Yinterv[2*m] <= y && y < Yinterv[2*m+1]) { |
|---|
| 459 | |
|---|
| 460 | if (found[m] > -1) { |
|---|
| 461 | |
|---|
| 462 | int f = PInvFlips[matchlist[3*m]]; |
|---|
| 463 | char xx = flipX(f, x, y); |
|---|
| 464 | char yy = flipY(f, x, y); |
|---|
| 465 | |
|---|
| 466 | char XX1 = flipX(f, Xinterv[2*m], Yinterv[2*m]); |
|---|
| 467 | char YY1 = flipY(f, Xinterv[2*m], Yinterv[2*m]); |
|---|
| 468 | |
|---|
| 469 | char XX2 = flipX(f, Xinterv[2*m+1]-1, Yinterv[2*m+1]-1); |
|---|
| 470 | char YY2 = flipY(f, Xinterv[2*m+1]-1, Yinterv[2*m+1]-1); |
|---|
| 471 | |
|---|
| 472 | char XX = XX1 < XX2 ? XX1 : XX2; |
|---|
| 473 | char YY = YY1 < YY2 ? YY1 : YY2; |
|---|
| 474 | |
|---|
| 475 | xx -= XX; |
|---|
| 476 | yy -= YY; |
|---|
| 477 | |
|---|
| 478 | char *cc, *wcc, *lcc, *tcc; |
|---|
| 479 | if ((PColorSwitch[matchlist[3*m]] && co == 'B') || |
|---|
| 480 | (!PColorSwitch[matchlist[3*m]] && co == 'W')) |
|---|
| 481 | cc = "B"; |
|---|
| 482 | else cc = "W"; |
|---|
| 483 | |
|---|
| 484 | PyObject *key = Py_BuildValue("ii", xx, yy); |
|---|
| 485 | PyObject *t = PyDict_GetItem(symmetries, key); |
|---|
| 486 | Py_DECREF(key); |
|---|
| 487 | |
|---|
| 488 | PyObject *xxyy = PyTuple_GetItem(t, 0); |
|---|
| 489 | long c = PyInt_AsLong(PyTuple_GetItem(t, 1)); |
|---|
| 490 | |
|---|
| 491 | if ((strcmp(cc, "W")==0 && !c) || (strcmp(cc, "B")==0 && c)) { |
|---|
| 492 | cc = "W"; |
|---|
| 493 | wcc = "wW"; |
|---|
| 494 | lcc = "lW"; |
|---|
| 495 | tcc = "tW"; |
|---|
| 496 | } |
|---|
| 497 | else { |
|---|
| 498 | cc = "B"; |
|---|
| 499 | wcc = "wB"; |
|---|
| 500 | lcc = "lB"; |
|---|
| 501 | tcc = "tB"; |
|---|
| 502 | } |
|---|
| 503 | |
|---|
| 504 | char text; |
|---|
| 505 | PyObject* scxy; |
|---|
| 506 | |
|---|
| 507 | if (scxy = PyDict_GetItem(continuations, xxyy)) { |
|---|
| 508 | PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, cc))+1); |
|---|
| 509 | PyDict_SetItemString(scxy, cc, temp); |
|---|
| 510 | Py_DECREF(temp); |
|---|
| 511 | text = PyString_AsString(PyDict_GetItemString(scxy, "N"))[0]; |
|---|
| 512 | } |
|---|
| 513 | else { |
|---|
| 514 | if (contLabelsIndex >= contLabelsLength) text = '?'; |
|---|
| 515 | else text = contLabels[contLabelsIndex++]; |
|---|
| 516 | |
|---|
| 517 | if (strcmp(cc, "B")==0) { |
|---|
| 518 | scxy = PyDict_New(); |
|---|
| 519 | PyObject* Py0 = PyInt_FromLong(0); |
|---|
| 520 | PyObject *Py1 = PyInt_FromLong(1); |
|---|
| 521 | PyDict_SetItemString(scxy, "B", Py1); |
|---|
| 522 | PyDict_SetItemString(scxy, "W", Py0); |
|---|
| 523 | PyDict_SetItemString(scxy, "tB", Py0); |
|---|
| 524 | PyDict_SetItemString(scxy, "tW", Py0); |
|---|
| 525 | PyDict_SetItemString(scxy, "wB", Py0); |
|---|
| 526 | PyDict_SetItemString(scxy, "lB", Py0); |
|---|
| 527 | PyDict_SetItemString(scxy, "wW", Py0); |
|---|
| 528 | PyDict_SetItemString(scxy, "lW", Py0); |
|---|
| 529 | PyDict_SetItemString(scxy, "N", PyString_FromStringAndSize(&text, 1)); |
|---|
| 530 | Py_DECREF(Py0); |
|---|
| 531 | Py_DECREF(Py1); |
|---|
| 532 | PyDict_SetItem(continuations, xxyy, scxy); |
|---|
| 533 | Py_DECREF(scxy); |
|---|
| 534 | } |
|---|
| 535 | else { |
|---|
| 536 | scxy = PyDict_New(); |
|---|
| 537 | PyObject *Py0 = PyInt_FromLong(0); |
|---|
| 538 | PyObject *Py1 = PyInt_FromLong(1); |
|---|
| 539 | PyDict_SetItemString(scxy, "B", Py0); |
|---|
| 540 | PyDict_SetItemString(scxy, "W", Py1); |
|---|
| 541 | PyDict_SetItemString(scxy, "tB", Py0); |
|---|
| 542 | PyDict_SetItemString(scxy, "tW", Py0); |
|---|
| 543 | PyDict_SetItemString(scxy, "wB", Py0); |
|---|
| 544 | PyDict_SetItemString(scxy, "lB", Py0); |
|---|
| 545 | PyDict_SetItemString(scxy, "wW", Py0); |
|---|
| 546 | PyDict_SetItemString(scxy, "lW", Py0); |
|---|
| 547 | PyDict_SetItemString(scxy, "N", PyString_FromStringAndSize(&text, 1)); |
|---|
| 548 | Py_DECREF(Py0); |
|---|
| 549 | Py_DECREF(Py1); |
|---|
| 550 | PyDict_SetItem(continuations, xxyy, scxy); |
|---|
| 551 | Py_DECREF(scxy); |
|---|
| 552 | } |
|---|
| 553 | } |
|---|
| 554 | |
|---|
| 555 | PyObject *d1 = PyList_GetItem(dbData, index); |
|---|
| 556 | |
|---|
| 557 | if (!PyTuple_Check(d1)) return NULL; |
|---|
| 558 | |
|---|
| 559 | PyObject *d2 = PyTuple_GetItem(d1, 4); |
|---|
| 560 | if (!PyString_Check(d2)) return NULL; |
|---|
| 561 | |
|---|
| 562 | char* winner = PyString_AsString(d2); |
|---|
| 563 | |
|---|
| 564 | if (winner[0] == 'B') |
|---|
| 565 | if (!(PColorSwitch[matchlist[3*m]] || c)) { |
|---|
| 566 | PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, wcc))+1); |
|---|
| 567 | PyDict_SetItemString(scxy, wcc, temp); |
|---|
| 568 | Py_DECREF(temp); |
|---|
| 569 | Bwins++; |
|---|
| 570 | } |
|---|
| 571 | else { |
|---|
| 572 | PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, lcc))+1); |
|---|
| 573 | PyDict_SetItemString(scxy, lcc, temp); |
|---|
| 574 | Py_DECREF(temp); |
|---|
| 575 | Wwins++; |
|---|
| 576 | } |
|---|
| 577 | if (winner[0] == 'W') |
|---|
| 578 | if (!(PColorSwitch[matchlist[ |
|---|