1 #include "phalanx.h"
2
3 #undef SHOWREADS
4 #undef SHOWDUPS
5
6 tsbook Sbook;
7 tpbook Pbook;
8
9 int Bookout=0;
10
11 /*
12 * myfwrite(), myfread() to fix the endianess problem.
13 */
14
15 # define ISI ((int)sizeof(int))
16
myfwrite(void * ptr,int size,FILE * stream)17 void myfwrite( void *ptr, int size, FILE *stream )
18 {
19 int i,j;
20 for( i=0; i<size-ISI; i+=ISI )
21 { for( j=0; j!=ISI; j++ ) fwrite( (char*)ptr+i+j, 1, 1, stream ); }
22 for( j=0; i+j<size; j++ ) fwrite( (char*)ptr+i+j, 1, 1, stream );
23 }
24
myfread(void * ptr,int size,FILE * stream)25 void myfread( void *ptr, int size, FILE *stream )
26 {
27 int i,j;
28 for( i=0; i<size-ISI; i+=ISI )
29 { for( j=0; j!=ISI; j++ ) fread( (char*)ptr+i+j, 1, 1, stream ); }
30 for( j=0; i+j<size; j++ ) fread( (char*)ptr+i+j, 1, 1, stream );
31 }
32
33 /*
34 * write position into string s, to be saved in book or
35 * compared with another position string.
36 * Format: pieces as usual, black pieces by capital P,N,B,...
37 * empty squares are stored as numbers, e.g. '24' means
38 * 24 empty sq.
39 */
postr(char * s)40 void postr(char *s)
41 {
42 int i, counter, lenght;
43 const char P[14]=
44 {'-','-','p','P','n','N','b','B','r','R','q','Q','k','K'};
45
46 sprintf( s, "%1X%1X", (Color==BLACK), G[Counter].castling & 0xF );
47
48 counter=0; lenght=2;
49 for(i=A1;i!=H9;i++) if( B[i] && B[i] != 3 )
50 {
51 if(counter)
52 {
53 sprintf(&s[lenght],"%i",counter);
54 if(counter>9) lenght++;
55 lenght++; counter=0;
56 }
57 sprintf(&s[lenght],"%c",P[B[i]/8+(color(B[i])==BLACK)]);
58 lenght++;
59 }
60 else if( B[i]==0 ) counter++;
61
62 if(counter) sprintf(&s[lenght],"%i ",counter);
63 else sprintf(&s[lenght]," ");
64 }
65
66
67
68
69 /*
70 * Compare position strings p1 and p2.
71 * p1==p2 ... returns 0
72 * p1>p2 ... 1; p1<p2 ... -1
73 */
poscmp(char * p1,char * p2)74 int poscmp(char *p1, char *p2)
75 {
76 register int i;
77 for(i=0; i!=80; i++)
78 {
79 if(p1[i]=='\0') p1[i]=' ';
80 if(p2[i]=='\0') p2[i]=' ';
81
82 if(p1[i]<p2[i]) return -1;
83 if(p1[i]>p2[i]) return 1;
84 if(p1[i]==' ') return 0;
85 }
86 fprintf(stderr,"Phalanx error: Opening book corrupted.\n");
87 exit(2);
88 }
89
90
91
92 /*
93 * Now the book searching functions. If there is less than
94 * 512 bytes to search, the book is searched linearly.
95 */
linSB(FILE * f,long from,long to,char * p,char * s)96 int linSB(FILE *f, long from, long to, char *p, char *s)
97 {
98 if( fseek(f,from,SEEK_SET)!=0 ) { return -1; }
99 if(!feof(f)) fgets(s,80,f); /* skip to the first \n */
100
101 while(ftell(f)<=to && !feof(f))
102 {
103 fgets(s,100,f);
104 if( poscmp(p,s)==0 ) return 0;
105 }
106
107 return -1;
108 }
109
110
111
112 /*
113 * There is more than 512 bytes to search -> use binary search.
114 */
binSB(FILE * f,long from,long to,char * p,char * s)115 int binSB(FILE *f, long from, long to, char *p, char *s)
116 {
117 long mid;
118
119 if( to-from < 512 ) return( linSB(f,from,to,p,s) );
120
121 mid=(to+from)/2;
122 if( fseek(f,mid,SEEK_SET)!=0 ) return -1;
123 if(!feof(f)) fgets(s,80,f); /* skip to the first \n */
124
125 if(!feof(f)) fgets(s,100,f);
126
127 switch(poscmp(p,s))
128 {
129 case 0: return(0);
130 case 1: return( binSB(f,mid,to,p,s) );
131 case -1: return( binSB(f,from,mid,p,s) );
132 default: return -1;
133 }
134 }
135
136
137
parsemove(char * inp,tmove * m,int n)138 int parsemove( char *inp, tmove *m, int n )
139 {
140 int special, from, to, in2a, i;
141
142 special = 0;
143 from = inp[0]-'a'+1 + 10*(inp[1]-'1') + 20;
144 to = inp[2]-'a'+1 + 10*(inp[3]-'1') + 20;
145 in2a = 0;
146
147 if( strncmp(inp,"o-o-o",5)==0
148 || strncmp(inp,"0-0-0",5)==0
149 || strncmp(inp,"O-O-O",5)==0
150 || ( B[E1]==WK && strncmp(inp,"e1c1",4)==0 )
151 || ( B[E8]==BK && strncmp(inp,"e8c8",4)==0 ) )
152 special = LONG_CASTLING;
153 else if( strncmp(inp,"o-o",3)==0
154 || strncmp(inp,"0-0",3)==0
155 || strncmp(inp,"O-O",3)==0
156 || ( B[E1]==WK && strncmp(inp,"e1g1",4)==0 )
157 || ( B[E8]==BK && strncmp(inp,"e8g8",4)==0 ) )
158 special = SHORT_CASTLING;
159
160 switch(inp[4])
161 {
162 case 'Q': case 'q': in2a=QUEEN+Color; break;
163 case 'R': case 'r': in2a=ROOK+Color; break;
164 case 'B': case 'b': in2a=BISHOP+Color; break;
165 case 'N': case 'n': in2a=KNIGHT+Color; break;
166 default : in2a=B[from];
167 }
168
169 for(i=0; i!=n; i++)
170 {
171 if( ( special>0 && special<A1 && m[i].special == special ) ||
172 ( (m[i].from==from) && (m[i].to==to) && (m[i].in2a==in2a) )
173 ) return(i);
174 }
175
176 return(-1);
177 }
178
179
180
181 /* binary book */
sbookmoves(int * moves,int * values,tmove * m,int n)182 int sbookmoves( int *moves, int *values, tmove *m, int n )
183 {
184 int idx, i;
185 int64 first, last=0, middle=0;
186 unsigned fkey, lkey;
187 unsigned pos;
188 long booksize; /* filesize in bytes */
189 FILE *f;
190 int hits=0;
191
192 if( (f=Sbook.f) == NULL ) return -1;
193
194 if( G[Counter].hashboard < Sbook.firstkey
195 || G[Counter].hashboard > Sbook.lastkey ) return -1;
196
197 fkey = Sbook.firstkey; lkey = Sbook.lastkey;
198
199 booksize = Sbook.filesize/6;
200
201 first = 0; last = booksize-1;
202 if( G[Counter].hashboard == Sbook.firstkey ) middle=0;
203 else if( G[Counter].hashboard == Sbook.lastkey ) middle=booksize-1;
204 else
205 while( first < last )
206 {
207 /* middle = (first+last) / 2; */
208
209 middle = (G[Counter].hashboard-fkey)*(last-first)
210 / (lkey-fkey) + first;
211
212 if(middle==first) middle++; if(middle==last) middle--;
213 if(middle==first)
214 {
215 #ifdef SHOWREADS
216 printf("notfoundinbook %i\n", hits );
217 #endif
218 return -1;
219 }
220
221 if( fseek(f,middle*6,SEEK_SET)!=0 ) return -1;
222 myfread( &pos, sizeof(unsigned), f ); hits++;
223
224 if( pos < G[Counter].hashboard ) { first=middle; fkey=pos; }
225 else if( pos == G[Counter].hashboard ) break;
226 else { last=middle; lkey=pos; }
227 }
228
229 /*
230 printf("[%i %i %i %i] [%08X %08X]\n",
231 first,middle,last,booksize,pos,G[Counter].hashboard);
232 */
233
234 #ifdef SHOWREADS
235 printf("yesfoundinbook %i\n",hits);
236 #endif
237
238 if( middle == 0 ) pos = G[Counter].hashboard;
239 else
240 do
241 {
242 middle --;
243 if( fseek(f,middle*6,SEEK_SET)!=0 ) return -1;
244 myfread( &pos, sizeof(unsigned), f );
245 } while( middle>0 && pos==G[Counter].hashboard );
246
247 if(pos!=G[Counter].hashboard)
248 { middle ++; pos = G[Counter].hashboard; }
249
250 /*** Position found in book! ***/
251 idx=0;
252 if( fseek(f,middle*6+4,SEEK_SET)!=0 ) return -1;
253 while( middle<booksize && pos==G[Counter].hashboard )
254 {
255 unsigned short sm;
256
257 myfread( &sm, sizeof(unsigned short), f );
258 for( i=0; i!=n; i++ ) if( sm == smove(m+i) )
259 { moves[idx]=i; values[idx]=100; idx++; }
260
261 myfread( &pos, sizeof(unsigned), f );
262 }
263
264 return idx;
265 }
266
267
268
269 /*
270 * bookmoves() returns number of moves found in book, or 0,
271 * if no move is found. moves[0],...,moves[index-1] are indexes
272 * to the bookmoves in m[], n is numer of moves. Moves must
273 * be generated before.
274 */
bookmoves(int * moves,int * values,tmove * m,int n)275 int bookmoves( int *moves, int *values, tmove *m, int n )
276 {
277 char s[256], p[256];
278 int idx, i;
279 long booksize; /* filesize in bytes */
280 FILE *f;
281
282 if( (f=Pbook.f) == NULL ) return -1;
283
284 booksize = Pbook.filesize;
285
286 postr(p); /* Current position to string */
287 if( binSB(f,0,booksize,p,s) == -1 )
288 { return -1; }
289
290 /*** Position found in book! ***/
291 idx=0;
292 for(i=0; s[i]!='\n'; i++)
293 {
294 int pm;
295 while(s[i]!=' ' && s[i]!='\n')
296 {
297 if(s[i]=='!' && idx) values[idx-1]+=100;
298 i++;
299 }
300 if(s[i]=='\n') break; i++; if(s[i]=='\n') break;
301 if( (pm=parsemove(&s[i],m,n)) != -1 )
302 { moves[idx]=pm; values[idx]=100; idx++; }
303 }
304
305 return idx;
306 }
307
308
309
310 /*
311 * This function returns index of a random move found in book
312 * or -1, if no move was found. Moves must be generated.
313 */
bookmove(tmove * m,int n)314 int bookmove( tmove *m, int n )
315 {
316 int moves[80], values[80], idx;
317 int foundtxt=0;
318
319 idx = bookmoves(moves,values,m,n);
320 if( idx <= 0 ) idx = sbookmoves(moves,values,m,n);
321 else
322 {
323 #ifdef SHOWDUPS
324 int moves2[80]; int values2[80], idx2;
325 idx2 = sbookmoves(moves2,values,m,n);
326 if( idx2>=1 && idx>=1 && Counter>8 )
327 {
328 char p[256]; int i;
329 postr(p);
330 puts("found in both sbook and pbook");
331 printboard(NULL);
332 puts(p);
333 printf(" 0 0 0 0 book2 ");
334 for( i=0; i!=idx2; i++ )
335 if( i==0 || moves2[i-1]!=moves2[i] )
336 { printm( m[moves2[i]], NULL ); }
337 puts("");
338 }
339 #endif
340 foundtxt=1;
341 }
342
343 if( idx > 0 )
344 {
345 int ii, sumvalues=0, rn;
346 for( ii=0; ii!=idx; ii++ )
347 { sumvalues += values[ii]; }
348
349 rn = rand()%sumvalues;
350
351 sumvalues = 0;
352 for( ii=0; ii!=idx; ii++ )
353 { sumvalues += values[ii]; if( sumvalues >= rn ) break; }
354
355 if( Flag.post )
356 { int i;
357 char s[128];
358 if( Flag.xboard )
359 sprintf(s," 0 0 0 0 (");
360 // sprintf(s," 0 0 0 0 book");
361 else
362 sprintf(s,"Book moves ");
363 for( i=0; i!=idx; i++ )
364 { printm( m[moves[i]], s+strlen(s) ); }
365
366 // hacked by S.A. to show bookX at end of line
367 if( foundtxt ) sprintf(s+strlen(s),", book1)");
368 else sprintf(s+strlen(s),", book2)");
369
370 sprintf(s+strlen(s),"\n");
371 printf("%s",s);
372 if( Flag.log!=NULL && Flag.ponder<2 )
373 {
374 char sm[64];
375 if(Flag.xboard) fprintf(Flag.log,"%s",s+26);
376 else fprintf(Flag.log,"%s",s);
377 fprintf(Flag.log," selected move ");
378 printm( m[moves[ii]], sm );
379 fprintf(Flag.log,"%s\n",sm);
380 }
381 }
382 return ( moves[ii] );
383 }
384
385 return( -1 );
386 }
387
388
389
390 /*
391 * Print all book moves (command bk)
392 */
393 FILE * Eco = NULL;
bk(tmove * m,int n)394 void bk( tmove *m, int n )
395 {
396 int moves[80], values[80], idx;
397 int pass;
398 int sumvalues=0;
399
400 #define SHOWECO
401 #ifdef SHOWECO
402 static int att=1;
403 static int seco=0;
404 if( att != 0 && Eco!=NULL )
405 {
406 typedef struct teco { unsigned hashboard; unsigned point; } teco;
407 static struct teco * peco = NULL;
408 if( att==1 && Counter==0 && G[Counter].hashboard==0x39512910 /*init*/)
409 {
410 int c; tmove * move;
411 peco = malloc(2048*sizeof(teco));
412 if( peco == NULL )
413 { puts(" telluser cannot alloc memory for ECO");
414 att=0; goto abort; }
415
416 printf("telluser creating ECO index, please wait\n");
417
418 while( (c=fgetc(Eco))!='[' ) if( c==EOF ) goto doneinit;
419 for(;;)
420 {
421 tmove m[128];
422 char ms[32]; int msi; int n;
423 (peco+seco)->point=ftell(Eco)-1;
424 while( (c=getc(Eco))!=']' ) if( c==EOF ) goto doneinit;
425 if( c==EOF ) goto doneinit;
426 setfen(initialpos);
427 for(;;)
428 {
429 msi=0;
430 while( (c=getc(Eco))==' ' || c=='\n' ) {}
431 ungetc(c,Eco);
432 while( (c=getc(Eco))!=' ' && c!='\n' && msi<=30 )
433 { ms[msi]=c; msi++;
434 if( c==EOF || c=='[' )
435 { ungetc(c,Eco); goto nextgame; }
436 }
437 ms[msi]='\0'; /* printf("%s ",ms); */
438 generate_legal_moves( m, &n, checktest(Color) );
439 move=sandex(ms,m,n);
440 if( move==NULL ) goto nextgame;
441 do_move(move);
442 if( c==EOF ) goto doneinit;
443 }
444 nextgame:;
445 peco[seco].hashboard=G[Counter].hashboard;
446 seco++;
447 while( (c=fgetc(Eco))!='[' ) if( c==EOF ) goto doneinit;
448 }
449
450 doneinit:;
451 printf(" parsed %i ECO records\n",seco);
452 att=2;
453 setfen(initialpos);
454 }
455
456 if( Counter>0 && att>1 )
457 {
458 int counter=Counter;
459 int text=-1;
460 while( Counter > 0 )
461 {
462 int i;
463 for(i=0;i!=seco;i++)
464 if(peco[i].hashboard==G[Counter].hashboard)
465 { text=peco[i].point; goto foundeco; }
466 undo_move( & G[Counter-1].m );
467 }
468 foundeco:;
469 while( counter > Counter ) do_move( & G[Counter].m );
470 if( text==-1 ) printf(" no eco found\n");
471 else
472 { char t[128], * c;
473 fseek(Eco,text,SEEK_SET);
474 fgets(t,126,Eco);
475 t[127]='\0';
476 c=strchr(t,'['); if(c!=NULL) *c = ' ';
477 c=strrchr(t,']'); if(c!=NULL) *c = '\0';
478 puts(t);
479 }
480 }
481 abort:;
482 }
483 #endif
484
485 for( pass=0; pass!=2; pass++ )
486 {
487 if( pass==0 )
488 {
489 int i;
490 idx = bookmoves(moves,values,m,n);
491 if( idx != -1 ) for(i=0;i!=idx;i++) sumvalues += values[i];
492 printf(" primary book moves\n");
493 }
494 else
495 {
496 idx = sbookmoves(moves,values,m,n);
497 printf(" secondary book moves\n");
498 }
499
500 if( idx > 0 )
501 { int i;
502 for( i=0; i!=idx; i++ )
503 if( i==0 || moves[i-1]!=moves[i] )
504 {
505 printf(" ");
506 printm( m[moves[i]], NULL );
507 if(pass==0)
508 printf("%3d%%\n",values[i]*100/sumvalues);
509 else printf("\n");
510 }
511 }
512 else
513 printf(" no move found\n");
514
515 }
516
517 if( Flag.xboard>1 ) puts("");
518
519 { char c[128]; postr(c); printf("%s\n",c); }
520
521 }
522
523
524