root/05/release-0.5l/matchC.cc

Revision 42, 23.3 kB (checked in by ug, 5 years ago)

Updated copyright notice

Line 
1 // File: matchC.cc
2
3 //   Copyright (C) 2001-4 Ulrich Goertz (u@g0ertz.de)
4
5 //   This is part of Kombilo, a go database program.
6
7 //   This program is free software; you can redistribute it and/or modify
8 //   it under the terms of the GNU General Public License as published by
9 //   the Free Software Foundation; either version 2 of the License, or
10 //   (at your option) any later version.
11
12 //   This program is distributed in the hope that it will be useful,
13 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //   GNU General Public License for more details.
16
17 //   You should have received a copy of the GNU General Public License
18 //   along with this program (see doc/license.txt); if not, write to the Free Software
19 //   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 //   The GNU GPL is also currently available at
21 //   http://www.gnu.org/copyleft/gpl.html
22
23 #include <Python.h>
24
25 void invert(char *s) {
26   int c,i,j;
27   for (i=0,j=strlen(s)-1;i<j;i++,j--) {
28     c=s[i];
29     s[i]=s[j];
30     s[j]=c;
31   }
32 }
33
34 char* itoa(int n) {             // convert a non-negative integer to a char*
35   char *s = new char[15];
36   int i;
37  
38   i=0;
39   do { s[i++] = n%10+'0';
40   } while ((n/=10)>0);
41  
42   s[i]='\0';
43   invert(s);
44   return s;
45 }
46
47
48 bool greater(long* a, unsigned long i, unsigned long j) {
49   if (a[2*i]>a[2*j] || (a[2*i]==a[2*j] && a[2*i+1]>a[2*j+1])) return true;
50   return false;
51 }
52
53 void swap(long* a, unsigned long i, unsigned long j) {
54   long help1, help2;
55
56   help1 = a[2*i];
57   help2 = a[2*i+1];
58   a[2*i] = a[2*j];
59   a[2*i+1] = a[2*j+1];
60   a[2*j] = help1;
61   a[2*j+1] = help2;
62 }
63
64
65 void sortCArray(long* a, long l, long r) {
66
67   long left, right, li11;
68
69   long stack[250];
70   stack[0] = l;
71   stack[1] = r;
72   unsigned char stackIndex = 1;
73
74   long help1, help2;
75
76   while (stackIndex) {
77     if (r > l) {
78       if (r-l == 1) {
79         if (greater(a, l, r)) swap(a, l, r);
80        
81         stackIndex--;
82         l = stack[2*stackIndex];
83         r = stack[2*stackIndex+1];
84
85       } else {
86
87         if (greater(a, (r+l)/2, l)) {
88           if (greater(a, l, r)) li11 = l;
89           else {
90             if (greater(a, r, (r+l)/2)) li11 = (r+l)/2;
91             else li11 = r;
92           }
93         } else {
94           if (greater(a, (r+l)/2, r)) li11 = (r+l)/2;
95           else {
96             if (greater(a, r, l)) li11 = l;
97             else li11 = r;
98           }
99         }
100
101         swap(a, li11, r);
102         help1 = a[2*r];
103         help2 = a[2*r+1];
104        
105         left = l;
106         right = r-1;
107        
108         while (1) {
109           while (a[2*left] < help1 || (a[2*left]==help1 && a[2*left+1]<help2)) left++;
110           while (a[2*right] > help1 || (a[2*right]==help1 && a[2*right+1]>help2)) right--;
111          
112           if (right <= left) break;
113          
114           swap(a, left, right);
115          
116           left++;
117           right--;
118         }
119
120         swap(a, left, r);
121
122         if (left-l > r-left) {
123             stack[2*stackIndex] = l;
124             stack[2*stackIndex+1] = left-1;
125             stackIndex++;
126           l = left+1;
127         } else {
128             stack[2*stackIndex] = left+1;
129             stack[2*stackIndex+1] = r;
130             stackIndex++;
131           r = left-1;
132         }
133       }
134     } else {
135       stackIndex--;
136       l = stack[2*stackIndex];
137       r = stack[2*stackIndex+1];
138     }
139   }
140 }
141
142 static const int COLORSWITCH = 1024;
143
144 static char flipX(char flipNO, char x, char y) {
145   if (flipNO==0) return x;
146   if (flipNO==1) return 18-x;
147   if (flipNO==2) return x;
148   if (flipNO==3) return 18-x;
149   if (flipNO==4) return y;
150   if (flipNO==5) return 18-y;
151   if (flipNO==6) return y;
152   if (flipNO==7) return 18-y;
153   return 0;
154 }
155
156 static char flipY(char flipNO, char x, char y) {
157   if (flipNO==0) return y;
158   if (flipNO==1) return y;
159   if (flipNO==2) return 18-y;
160   if (flipNO==3) return 18-y;
161   if (flipNO==4) return x;
162   if (flipNO==5) return x;
163   if (flipNO==6) return 18-x;
164   if (flipNO==7) return 18-x;
165   return 0;
166 }
167
168 static PyObject* match(PyObject* self, PyObject* args) {
169   int noPatterns;
170   char *Patterns;
171   char *PSize;
172   char *PInvFlips;
173   char *PColorSwitch;
174   char *PAnchors;
175   unsigned long *PBitsTable;
176   unsigned char *PBits;
177   unsigned char *fp;
178   unsigned char *mainlist;
179   unsigned long *posTable;
180
181   unsigned long *hashIndices;
182   unsigned char *hash;
183
184   char* contLabels;
185
186   int PCSlength, PAlength, PBTlength, PBlength, fplength, MLlength, PTlength, HLlength,
187     hashIlength, hashlength, contLabelsLength, contLabelsIndex,
188     showColorSwitch, nextMoveVar, fixedColorVar;
189   int moveLimit;
190   unsigned long* helplist;
191
192   PyObject *progBarUpdate;
193   PyObject *continuations;
194   PyObject *symmetries;
195   PyObject *dbData;
196   float pB_start, pB_end;
197
198   if (!PyArg_ParseTuple(args, "sss#s#s#s#s#is#s#s#s#s#s#Offs#iOOOiii", &Patterns, &PSize,
199                         &PInvFlips, &noPatterns, &PColorSwitch, &PCSlength,
200                         &PAnchors, &PAlength, &PBitsTable, &PBTlength, &PBits, &PBlength, &moveLimit,
201                         &helplist, &HLlength, &fp, &fplength,
202                         &mainlist, &MLlength, &posTable, &PTlength,
203                         &hashIndices, &hashIlength, &hash, &hashlength,
204                         &progBarUpdate, &pB_start, &pB_end,
205                         &contLabels, &contLabelsLength, &contLabelsIndex,
206                         &continuations, &symmetries, &dbData,
207                         &showColorSwitch, &nextMoveVar, &fixedColorVar))
208       return NULL;
209
210   HLlength /= sizeof(unsigned long);
211
212   int foundgamesSize = 5000;
213   int unsigned long *foundgames = PyMem_New(unsigned long, foundgamesSize);    // stored here: no. of found game
214   int foundgamesIndex=0;
215
216   PyObject *result = PyList_New(0);
217
218   int Bwins = 0;
219   int Wwins = 0;
220   int noSwitched = 0;
221   int noMatchesFinal = 0;
222
223   int patternSize = PSize[0] * PSize[1];
224
225   unsigned long* hashInd = new unsigned long[noPatterns];
226   if (hashIlength) {
227     for(int i=0; i<noPatterns; i++) hashInd[i] = hashIndices[2*i];     // set hashInd to hash_start's
228   }
229
230   for(int game=0; game < HLlength; game++) {
231
232     if (game % 600 == 0) {     
233       float percent = game * (pB_end - pB_start) / HLlength + pB_start;
234       PyObject* arglist = Py_BuildValue("(f)", percent);
235       PyEval_CallObject(progBarUpdate, arglist);
236       Py_DECREF(arglist);
237     }
238
239     unsigned long index = helplist[game];
240
241     char matchlist[13000];
242     int matchlistIndex = 0;
243
244     for(char N=0; N<noPatterns; N++) {           
245
246       if (hashIlength) {
247         while ((hashInd[N]+1<hashIndices[2*N+1]) && (index > 256*hash[hashInd[N]] + hash[hashInd[N]+1])) hashInd[N]+=2;
248         if (index < 256*hash[hashInd[N]] + hash[hashInd[N]+1]) continue;
249         if (index == 256*hash[hashInd[N]] + hash[hashInd[N]+1]) {
250           hashInd[N] += 2;
251           matchlist[matchlistIndex++] = N;
252           matchlist[matchlistIndex++] = PAnchors[4*N];
253           matchlist[matchlistIndex++] = PAnchors[4*N+1];
254         }
255       }
256       else {
257        
258         char a00 = PAnchors[4*N];
259         char a01 = PAnchors[4*N+1];
260         char a10 = PAnchors[4*N+2];
261         char a11 = PAnchors[4*N+3];
262        
263         for(char a0=a00; a0 <= a10; a0++)
264           for(char a1=a01; a1 <= a11; a1++) {
265            
266             int matches = 1;
267            
268             int pIndex = 2*(a1%2) + (a0%2);
269             int patternBits = PBitsTable[N*4 + pIndex];
270            
271             int pbIndex = 0;
272             int fpIndex = index*150 + a1/2 + (a0/2)*10;
273            
274             for(int x=0; x < PBits[patternBits]; x++) {
275              
276               int start = PBits[patternBits + ++pbIndex];
277               int length = PBits[patternBits + ++pbIndex];
278               fpIndex += start;
279              
280               for(int y=0; y<length; y++) {
281                 pbIndex++;
282                
283                 if (PBits[patternBits+pbIndex] & fp[fpIndex]) {
284                   matches = 0;
285                   break;
286                 }
287                
288                 fpIndex++;
289               }
290               if (!matches) break;
291               fpIndex += 10 - start - length;
292              
293             }
294            
295             if (matches) {
296               matchlist[matchlistIndex++] = N;
297               matchlist[matchlistIndex++] = a0;
298               matchlist[matchlistIndex++] = a1;
299             }
300            
301           }
302       }
303     }
304    
305     if (matchlistIndex) {    /* checkCandidate */
306
307       int noMatches = matchlistIndex/3;
308       int toBeFound = noMatches;       
309       long noCurrentResults = 0;
310       long *currentResults = new long[noMatches*2];
311  
312       char *dicts = new char[noMatches * patternSize];
313       int *dictsNO = new int[noMatches];
314          
315       int *found = new int[noMatches];
316          
317       char *Xinterv = new char[2*noMatches];
318       char *Yinterv = new char[2*noMatches];
319          
320       for(int m=0; m<noMatches; m++) {
321              
322         found[m] = -1;
323         dictsNO[m] = 0;
324              
325         int sizeX = PSize[2*matchlist[3*m]];
326         int sizeY = PSize[2*matchlist[3*m]+1];
327         int Poffset = matchlist[3*m] * patternSize;
328              
329         for(int i=0; i < sizeX; i++) {
330           for(int j=0; j < sizeY; j++) {
331             if (Patterns[Poffset + sizeY*i + j] == '.')
332               dicts[m*patternSize+i*sizeY+j] = ' ';
333             else {
334               dicts[m*patternSize+i*sizeY+j] = Patterns[Poffset + sizeY*i + j];
335               if (Patterns[Poffset + sizeY*i + j] != '*') dictsNO[m]++;
336             }                   
337           }
338         }
339        
340         Xinterv[2*m] = matchlist[3*m+1];
341         Xinterv[2*m+1] = matchlist[3*m+1] + PSize[2*matchlist[3*m]];
342         Yinterv[2*m] = matchlist[3*m+2];
343         Yinterv[2*m+1] = matchlist[3*m+2] + PSize[2*matchlist[3*m]+1];
344       }
345
346       int movelistIndex = posTable[index]+2;
347      
348       int caplistIndex = movelistIndex;
349       while (mainlist[caplistIndex] != 'z') caplistIndex++;
350       int mlLength = caplistIndex;
351      
352       if (mainlist[caplistIndex+2] == 'z') caplistIndex +=2; // caplist empty
353       else caplistIndex += 3;
354      
355       /* AB's */
356      
357       if (mainlist[movelistIndex] == 25 && mainlist[movelistIndex+1] == 3) {
358         movelistIndex += 2;
359         while (mainlist[movelistIndex] != 25) {
360           char x = mainlist[movelistIndex++];
361           char y = mainlist[movelistIndex++];
362          
363           for (int m=0; m<noMatches; m++) {
364             if (found[m] != -2) {
365               if (Xinterv[2*m] <= x && x < Xinterv[2*m+1] &&
366                   Yinterv[2*m] <= y && y < Yinterv[2*m+1]) {     /* stone played in */
367                 /* relevant region */
368                 if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]==' ') {
369                  
370                   if (!(fp[index*150 + 100 + y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) { 
371                     // this m can't become a match
372                     found[m] = -2;
373                     toBeFound--;
374                     continue;
375                   }
376                   else {
377                     dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]] = '.';
378                     dictsNO[m]++;
379                   }
380                 }
381                 else if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
382                               +y-matchlist[3*m+2]] == 'X') {
383                   dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]=' ';
384                   dictsNO[m]--;
385                 }
386               }
387             }
388           }
389         }
390       }
391      
392       /* AW's */
393      
394       if (mainlist[movelistIndex] == 25 && mainlist[movelistIndex+1] == 4) {
395         movelistIndex += 2;
396         while (mainlist[movelistIndex] != 25) {
397           char x = mainlist[movelistIndex];
398           char y = mainlist[movelistIndex+1];
399           movelistIndex += 2;
400          
401           int m;
402           for (m=0; m<noMatches; m++) {
403             if (found[m]!= -2) {
404               if (Xinterv[2*m] <= x && x < Xinterv[2*m+1] &&
405                   Yinterv[2*m] <= y && y < Yinterv[2*m+1]) {     
406                 if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]==' ') {
407                   if (!(fp[index*150 + 100 + y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) {           
408                     // this m can't become a match
409                     found[m] = -2;
410                     toBeFound--;
411                     continue;
412                   }
413                   else {
414                     dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]] = '.';
415                     dictsNO[m]++;
416                   }
417                 }
418                 else if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
419                               +y-matchlist[3*m+2]] == 'O') {
420                   dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]]=' ';
421                   dictsNO[m]--;
422                 }
423               }
424             }
425           }
426         }
427       }
428      
429       for(int m=0; m<noMatches; m++)
430         if (found[m]==-1 && !dictsNO[m]) found[m] = 0;       
431      
432       /* B's and W's */
433      
434       char co = 'B';
435      
436       if (mainlist[movelistIndex+1] == 1) co = 'B';
437       if (mainlist[movelistIndex+1] == 2) co = 'W';
438      
439       int mLimit;
440      
441       if (moveLimit == 250) mLimit = 1500 + movelistIndex;         // practically no limit
442       else mLimit = 2*moveLimit + movelistIndex;
443      
444       int counter = -1;
445       char c;
446       char cinv;
447      
448       while (movelistIndex < mlLength-2 && movelistIndex < mLimit) {
449        
450         movelistIndex += 2;
451         counter++;
452        
453         if (co == 'B') {
454           co = 'W';
455           c = 'X';
456           cinv = 'O';
457         } else {
458           co = 'B';
459           c = 'O';
460           cinv = 'X';
461         }
462        
463         char x = mainlist[movelistIndex];
464         char y = mainlist[movelistIndex+1];
465        
466         int clI = 0;
467         int clIend = 0;
468        
469         if (mainlist[caplistIndex] != 'z' && counter == 256*mainlist[caplistIndex] + mainlist[caplistIndex+1]) {
470           caplistIndex += 2;
471           clI = caplistIndex;
472           while (mainlist[caplistIndex] != 'z' && mainlist[caplistIndex] != 'y') caplistIndex++;
473           clIend = caplistIndex-1;
474           caplistIndex++;
475         }
476        
477         for(int m=0; m<noMatches; m++) {
478
479           if (found[m] != -2) {
480
481             if (Xinterv[2*m] <= x && x < Xinterv[2*m+1] &&
482                 Yinterv[2*m] <= y && y < Yinterv[2*m+1]) {
483              
484               if (found[m] > -1) {
485                 int colorSwitch = 0;
486                
487                 int f = PInvFlips[matchlist[3*m]];
488                 char xx = flipX(f, x, y);
489                 char yy = flipY(f, x, y);
490                
491                 char XX1 = flipX(f, Xinterv[2*m], Yinterv[2*m]);
492                 char YY1 = flipY(f, Xinterv[2*m], Yinterv[2*m]);
493                
494                 char XX2 = flipX(f, Xinterv[2*m+1]-1, Yinterv[2*m+1]-1);
495                 char YY2 = flipY(f, Xinterv[2*m+1]-1, Yinterv[2*m+1]-1);
496                
497                 char XX = XX1 < XX2 ? XX1 : XX2;
498                 char YY = YY1 < YY2 ? YY1 : YY2;
499                
500                 xx -= XX;
501                 yy -= YY;
502
503                 char *cc, *wcc, *lcc, *tcc;
504                 if ((PColorSwitch[matchlist[3*m]] && co == 'B') ||
505                     (!PColorSwitch[matchlist[3*m]] && co == 'W'))
506                   cc = "B";
507                 else cc = "W";
508                
509                 PyObject *key = Py_BuildValue("ii", xx, yy);
510                 PyObject *t = PyDict_GetItem(symmetries, key);
511                 Py_DECREF(key);
512
513                 PyObject *xxyy = PyTuple_GetItem(t, 0);
514                 Py_INCREF(xxyy);
515                
516                 xx = PyInt_AsLong(PyTuple_GetItem(xxyy, 0));
517                 yy = PyInt_AsLong(PyTuple_GetItem(xxyy, 1));
518                 long cSymm = PyInt_AsLong(PyTuple_GetItem(t, 1));
519
520                 if ((strcmp(cc, "W")==0 && !cSymm) || (strcmp(cc, "B")==0 && cSymm)) {
521                   cc = "W";
522                   wcc = "wW";
523                   lcc = "lW";
524                   tcc = "tW";
525                 }
526                 else {
527                   cc = "B";
528                   wcc = "wB";
529                   lcc = "lB";
530                   tcc = "tB";
531                 }
532                
533                 if (nextMoveVar) {
534                   if ((nextMoveVar==2 && cc=="B") || (nextMoveVar==1 && cc=="W")) {
535                     PyObject *key1 = PyInt_FromLong(-1);
536                     PyObject *t1 = PyDict_GetItem(symmetries, key1);
537                     Py_DECREF(key1);
538
539                     long ssymm = PyInt_AsLong(t1);
540                     if (ssymm != -1 && !fixedColorVar) {
541
542                       if (cc == "B") {
543                         cc = "W";
544                         wcc = "wW";
545                         lcc = "lW";
546                         tcc = "tW";
547                       }
548                       else {
549                         cc = "B";
550                         wcc = "wB";
551                         lcc = "lB";
552                         tcc = "tB";
553                       }           
554
555                      
556                       xx += XX;
557                       yy += YY;
558  
559                       int xx_n = flipX(ssymm, xx, yy);
560                       int yy_n = flipY(ssymm, xx, yy);
561                       int XX1_n = flipX(ssymm, XX1, YY1);
562                       int YY1_n = flipY(ssymm, XX1, YY1);
563                       int XX2_n = flipX(ssymm, XX2, YY2);
564                       int YY2_n = flipY(ssymm, XX2, YY2);
565
566                       XX = XX1_n < XX2_n ? XX1_n : XX2_n;
567                       YY = YY1_n < YY2_n ? YY1_n : YY2_n;
568
569                       xx = xx_n - XX;
570                       yy = yy_n - YY;
571
572                       PyObject *key2 = Py_BuildValue("ii", xx, yy);
573                       PyObject *t2 = PyDict_GetItem(symmetries, key);
574
575                       PyObject *xxyy2 = PyTuple_GetItem(t2, 0);
576                       long cSymm1 = PyInt_AsLong(PyTuple_GetItem(t2, 1));
577
578                       if (!cSymm1) {
579                         Py_DECREF(xxyy);
580                         xxyy = xxyy2;
581                         Py_DECREF(key2);
582                         Py_INCREF(xxyy);
583                       }
584                       else {
585                         Py_DECREF(xxyy);
586                         xxyy = key2;
587                       }
588
589                       colorSwitch = 1-cSymm;
590                       if (colorSwitch) noSwitched++;     
591                     }
592                     else {
593                       found[m] = -2;
594                       toBeFound--;
595                       continue;
596                     }
597                   }
598                   else {
599                     colorSwitch = cSymm;
600                     if (colorSwitch) noSwitched++;
601                   }
602                 }
603                 else colorSwitch = cSymm;
604                
605                 char text;
606                 PyObject* scxy;
607
608                 if ((scxy = PyDict_GetItem(continuations, xxyy))) {
609                   PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, cc))+1);
610                   PyDict_SetItemString(scxy, cc, temp);
611                   Py_DECREF(temp);
612                   text = PyString_AsString(PyDict_GetItemString(scxy, "N"))[0];
613                 }
614                 else {
615                   if (contLabelsIndex >= contLabelsLength) text = '?';
616                   else text = contLabels[contLabelsIndex++];
617                  
618                   if (strcmp(cc, "B")==0) {
619                     scxy = PyDict_New();
620                     PyObject* Py0 = PyInt_FromLong(0);
621                     PyObject *Py1 = PyInt_FromLong(1);
622                     PyDict_SetItemString(scxy, "B", Py1);
623                     PyDict_SetItemString(scxy, "W", Py0);
624                     PyDict_SetItemString(scxy, "tB", Py0);
625                     PyDict_SetItemString(scxy, "tW", Py0);
626                     PyDict_SetItemString(scxy, "wB", Py0);
627                     PyDict_SetItemString(scxy, "lB", Py0);
628                     PyDict_SetItemString(scxy, "wW", Py0);
629                     PyDict_SetItemString(scxy, "lW", Py0);
630                     PyDict_SetItemString(scxy, "N", PyString_FromStringAndSize(&text, 1));
631                     Py_DECREF(Py0);
632                     Py_DECREF(Py1);
633                     PyDict_SetItem(continuations, xxyy, scxy);
634                     Py_DECREF(scxy);
635                   }
636                   else {
637                     scxy = PyDict_New();
638                     PyObject *Py0 = PyInt_FromLong(0);
639                     PyObject *Py1 = PyInt_FromLong(1);
640                     PyDict_SetItemString(scxy, "B", Py0);
641                     PyDict_SetItemString(scxy, "W", Py1);
642                     PyDict_SetItemString(scxy, "tB", Py0);
643                     PyDict_SetItemString(scxy, "tW", Py0);
644                     PyDict_SetItemString(scxy, "wB", Py0);
645                     PyDict_SetItemString(scxy, "lB", Py0);
646                     PyDict_SetItemString(scxy, "wW", Py0);
647                     PyDict_SetItemString(scxy, "lW", Py0);
648                     PyDict_SetItemString(scxy, "N", PyString_FromStringAndSize(&text, 1));
649                     Py_DECREF(Py0);
650                     Py_DECREF(Py1);
651                     PyDict_SetItem(continuations, xxyy, scxy);
652                     Py_DECREF(scxy);
653                   }
654                 }
655
656                 Py_DECREF(xxyy);
657
658                 PyObject *d1 = PyList_GetItem(dbData, index);
659
660                 if (!PyTuple_Check(d1)) return NULL;
661
662                 PyObject *d2 = PyTuple_GetItem(d1, 4);
663                 if (!PyString_Check(d2)) return NULL;
664
665                 char* winner = PyString_AsString(d2);
666
667                 if (winner[0] == 'B')
668                   if (!(PColorSwitch[matchlist[3*m]] || colorSwitch)) {
669                     PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, wcc))+1);
670                     PyDict_SetItemString(scxy, wcc, temp);
671                     Py_DECREF(temp);
672                     Bwins++;
673                   }
674                   else {
675                     PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, lcc))+1);
676                     PyDict_SetItemString(scxy, lcc, temp);
677                     Py_DECREF(temp);
678                     Wwins++;
679                   }
680                 if (winner[0] == 'W')
681                   if (!(PColorSwitch[matchlist[3*m]] || colorSwitch)) {
682                     PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, lcc))+1);
683                     PyDict_SetItemString(scxy, lcc, temp);
684                     Py_DECREF(temp);
685                     Wwins++;
686                   }
687                   else {
688                     PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, wcc))+1);
689                     PyDict_SetItemString(scxy, wcc, temp);
690                     Py_DECREF(temp);
691                     Bwins++;
692                   }
693
694                 if (!(found[m]==counter || found[m]==counter+1)) {
695                   PyObject *temp = PyInt_FromLong(PyInt_AsLong(PyDict_GetItemString(scxy, tcc))+1);
696                   PyDict_SetItemString(scxy, tcc, temp);
697                   Py_DECREF(temp);
698                 }
699
700                 noSwitched += PColorSwitch[matchlist[3*m]];
701
702                 currentResults[2*noCurrentResults] = found[m];
703                 currentResults[2*noCurrentResults+1] = (PColorSwitch[matchlist[3*m]]|colorSwitch) * COLORSWITCH + text;
704                 noCurrentResults++;
705
706                 found[m] = -2;
707                 toBeFound--;
708                
709                 continue;
710               }
711              
712               if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
713                        +y-matchlist[3*m+2]] == ' ') {
714                
715                 if (!(fp[index*150 + 100 + y/4 + 5*(x/2)] & (1 << (x%2 + 2*(y%4))))) {
716                   found[m] = -2;
717                   toBeFound--;
718                   continue;
719                 }
720                 else {
721                   dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]] = '.';
722                   dictsNO[m]++;
723                 }
724                
725               }
726               else if (dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
727                             +y-matchlist[3*m+2]] == c) {
728                 dicts[m*patternSize+(x-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]+y-matchlist[3*m+2]] = ' ';
729                 dictsNO[m]--;
730               }
731             }
732            
733             if (found[m] == -1) {
734
735               if (clI) {                 /* captures */
736                
737                 for(int i=clI; i<clIend; i+=2) {
738                   char xx = mainlist[i]-1;
739                   char yy = mainlist[i+1]-1;
740                  
741                   if (Xinterv[2*m] <= xx && xx < Xinterv[2*m+1] &&
742                       Yinterv[2*m] <= yy && yy < Yinterv[2*m+1]) {
743                     if (dicts[m*patternSize+(xx-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
744                              +yy-matchlist[3*m+2]] == ' ') {
745                       dicts[m*patternSize+(xx-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
746                            +yy-matchlist[3*m+2]] = cinv;
747                       dictsNO[m]++;
748                     }
749                     else if (dicts[m*patternSize+(xx-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
750                                   +yy-matchlist[3*m+2]] == '.') {
751                       dicts[m*patternSize+(xx-matchlist[3*m+1])*PSize[2*matchlist[3*m]+1]
752                            +yy-matchlist[3*m+2]] = ' ';
753                       dictsNO[m]--;
754                     }
755                   }
756                  
757                 }
758               }
759               if (!dictsNO[m]) found[m] = counter + 1;
760             }
761
762           }
763         }
764        
765         if (!toBeFound) break;
766       }
767      
768
769       if (!nextMoveVar) {
770         for(int m=0; m<noMatches; m++)
771           if (found[m] > -1) {
772
773             noSwitched += PColorSwitch[matchlist[3*m]];
774
775             currentResults[2*noCurrentResults] = found[m];
776             currentResults[2*noCurrentResults+1] = PColorSwitch[matchlist[3*m]] * COLORSWITCH;
777             noCurrentResults++;
778
779             char winner = PyString_AsString(PyTuple_GetItem(PyList_GetItem(dbData, index), 4))[0];
780
781             if (winner == 'B')
782               if (!PColorSwitch[matchlist[3*m]]) Bwins++;
783               else Wwins++;
784             if (winner == 'W')
785               if (!PColorSwitch[matchlist[3*m]]) Wwins++;
786               else Bwins++;       
787           }
788       }
789      
790       delete dicts;
791       delete dictsNO;
792       delete found;
793       delete Xinterv;
794       delete Yinterv;
795
796       if (noCurrentResults) {
797
798         if (foundgamesIndex > foundgamesSize - 2) {
799           foundgamesSize += 2000;
800           foundgames = PyMem_Resize(foundgames, unsigned long, foundgamesSize);
801         }
802      
803         foundgames[foundgamesIndex++] = index;
804         noMatchesFinal += noCurrentResults;
805
806         sortCArray(currentResults, 0, noCurrentResults-1);
807
808         char *resultStr = new char[7*noCurrentResults];
809         int resultStrIndex = 0;
810
811         for(int i=0; i<noCurrentResults; i++) {
812           char *s = itoa(currentResults[2*i]);
813           for(int j=0; j<strlen(s); j++) resultStr[resultStrIndex++] = s[j];
814           delete s;
815           if (currentResults[2*i+1] % 256) resultStr[resultStrIndex++] = currentResults[2*i+1] % 256;
816           if (showColorSwitch && (currentResults[2*i+1]&COLORSWITCH)) resultStr[resultStrIndex++] = '-';
817           resultStr[resultStrIndex++] = ',';
818           resultStr[resultStrIndex++] = ' ';
819         }       
820         resultStrIndex -= 2;
821
822         PyObject *temp = PyString_FromStringAndSize(resultStr, resultStrIndex);
823         if (PyList_Append(result, temp)) return NULL;
824         Py_DECREF(temp);
825
826         delete resultStr;
827  
828       }
829       delete currentResults;
830     }
831   }     
832  
833   PyObject *returnValue = Py_BuildValue("s#Oiiiii", foundgames, foundgamesIndex*sizeof(unsigned long), result,
834                                         noSwitched, contLabelsIndex, Wwins, Bwins, noMatchesFinal);
835
836   Py_DECREF(result);
837   delete hashInd;
838   PyMem_Free(foundgames);
839
840   return returnValue;
841 }
842
843
844 static PyObject* sortArray(PyObject* self, PyObject* args) {
845  
846   long* a;
847
848   unsigned long adr;
849   long l, r;          // it's important that these are signed!
850
851   if (!PyArg_ParseTuple(args, "lii", &adr, &l, &r))
852     return NULL;
853