forked from pmcastro/danasah-500
-
Notifications
You must be signed in to change notification settings - Fork 0
/
libro.c
472 lines (383 loc) · 19.8 KB
/
libro.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/*
< DanaSah is a chess engine winboard. >
Copyright (C) <2011> <Pedro Castro Elgarresta>
E-mail <pecastro@msn.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
DanaSah desde la versión 3.02 accede al libro de aperturas del programa rebel/prodeo. El libro de aperturas
es creado por Jeroen Noomen, el código de acceso al libro proporcionado por Ed Shröeder, danasah utiliza una
variante de la dll creada por Fonzy, ahora incluida en el código del programa.
El libro de aperturas es iniciado en la función xboard() y se utiliza en la búsqueda.
*/
/* Opening Book Module for Chess Programs
written by Ed Schröder
Version 1.00
This information provides the way how to include the Pro Deo 1.4 opening
book (author Jeroen Noomen) into your chess engine.
Include BOOK.C into your project and compile.
MAINBOOK.BIN - The big mainbook.
TOURBOOK.BIN - A selection of favoured opening lines called the Tournament Book.
Initialization - Call the routine "INITIALIZE()" once.
Operation - Create an EPD string from the current position and strcpy it into
the string "EPD", then call the routine "FIND_OPENING()" to search
the opening book.
- When a move is found it is stored into the strings FROM and TO
in Ascii format, so E2 and E4, else the strings are empty. Play
this move. That's basically it.
- Alternatively you can also make a choice yourself from the list
of found opening moves, see: FROM1,FROM2,TO1,TO2 and AZ. See the
demonstration code in the "main" section.
Remarks - Although not recommended it's possible to turn off the Tournament
Book and play from the (very varied) big Main Book only. Just
empty the variable "TOERFILE" before you call "INITIALIZE()".
- To create an EPD string from the current board position check
chapter 16 from: http://www.tim-mann.org/Standard
Castling status and en-passant information are not needed to
include in the EPD string, the module only needs the current
position and the colour to move.
- As far as I remember the longest book line is 30 moves so out of
speed reasons don't call the opening book after move 30.
History - The opening book is the intellectual work of Jeroen Noomen who
started his work in 1989 for the Mephisto MM4 module from
Hegener & Glaser which later became the base of the REBEL series.
The book is the result of 15 years diligent hand-typed work.
The book was created and maintained by the TASC ChessMachine
software so there currently is no neat way to modify the
opening book.
Future work - For the next version I plan to add a simple book learn algorithm
that avoids your program to lose every time on the same book
opening line.
- Also planned is a simple way to fix possible holes in the book
and/or to add new opening lines.
- But what is really needed is an new editor and I feel not called.
Technical - Short description of the book format:
Each book move has 2 bytes
Byte1: - bit 0-5 square FROM (a1,b1,c1 etc.)
- bit 6 there is another subtree available
- bit 7 end of a variation
Byte2: - bit 0-5 square TO (a1,b1,c1 etc.)
- bit 6 unused
- bit 7 good or bad move (play or not play)
Copyright - This file and its components although distributed as freeware in
no way may become subject to any form of commerce. Permission
must be asked first.
- This file and its components come as is and can only be used as
such. It's forbidden to change, add, delete any of its components
and only can be distributed in original form.
Questions - For questions, suggestions, bug reports etc. contact me at the
CCC forum: http://216.25.93.108/forum
Ed Schröder
Deventer, March 2007
matador@home.nl
www.top-5000.nl
*/
/*Includes*/
#if _WIN32 || _WIN64
#include <windows.h> /*perror*/
#else
#include <errno.h> /*perror*/
#endif
#include <stdio.h> /*prinft, scanf, sprinft, sscanf, fgets...*/
#include <stdlib.h> /*rand, srand*/
#include <time.h>
#include "definiciones.h"
#include "variables.h"
#include "funciones.h"
static int BORDPOS[] =
{ 8,18,28,38,48,58,68,78,
7,17,27,37,47,57,67,77,
6,16,26,36,46,56,66,76,
5,15,25,35,45,55,65,75,
4,14,24,34,44,54,64,74,
3,13,23,33,43,53,63,73,
2,12,22,32,42,52,62,72,
1,11,21,31,41,51,61,71,0 };
static char BVELD[] = { 1,11,21,31,41,51,61,71, /*MVS format to*/
2,12,22,32,42,52,62,72, /*REBEL format*/
3,13,23,33,43,53,63,73,
4,14,24,34,44,54,64,74,
5,15,25,35,45,55,65,75,
6,16,26,36,46,56,66,76,
7,17,27,37,47,57,67,77,
8,18,28,38,48,58,68,78 };
static char TA[] = { /*ASCII output REBEL moves*/
'X',
'a','a','a','a','a','a','a','a','X','X',
'b','b','b','b','b','b','b','b','X','X',
'c','c','c','c','c','c','c','c','X','X',
'd','d','d','d','d','d','d','d','X','X',
'e','e','e','e','e','e','e','e','X','X',
'f','f','f','f','f','f','f','f','X','X',
'g','g','g','g','g','g','g','g','X','X',
'h','h','h','h','h','h','h','h' };
static char TN[] = { /*ASCII output REBEL moves*/
'X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8','X','X',
'1','2','3','4','5','6','7','8' };
static char BOEKRND[] = { 8,4,2,1,1,1,1,1,1,1,1,1,1 };
int Error;
static long RANDOM1[1120];
static long RANDOM2[1120];
static char _BORD[256];
static long *p_BORD = (long *) _BORD; /*32 bit redefinition BORD*/
static long HK1,HK2;
static int XD,XE;
int AZ;
int r1, r2;
static unsigned char *_GB=NULL; /*TOERBOEK.BIN*/
static unsigned char *_MNB=NULL; /*MAINBOOK.BIN*/
int INITIALIZE(const char *Toerfile,const char *Bookfile) /*read hashkeys in memory*/
{ int x,y; FILE *fp1; FILE *fp2;
long fsize;
/*en el pocketpc las rutas tienen que ser completas*/
#if UNDER_CE
TCHAR BookPath[256], *pos;
char fullPath1[256], fullPath2[256], fullPath3[256], fullPath4[256];
GetModuleFileName(NULL, BookPath, 256);
pos = wcsrchr(BookPath, '\\');
*(pos + 1) = '\0';
wcstombs(fullPath1, BookPath, 256);
strcat(fullPath1, "random1.bin");
wcstombs(fullPath2, BookPath, 256);
strcat(fullPath2, "random2.bin");
wcstombs(fullPath3, BookPath, 256);
strcat(fullPath3, Bookfile);
wcstombs(fullPath4, BookPath, 256);
strcat(fullPath4, Toerfile);
Error=0;
srand(GetTickCount()); //init the random number generator
if((fp1 = fopen(fullPath1, "rb"))==NULL)
{ Error=2; return Error; }
if((fp2 = fopen(fullPath2, "rb"))==NULL)
{ Error=2; fclose(fp1); return Error; }
for (x=0; x<1120; x++) { r1=fread(&RANDOM1[x],4,1,fp1); r2=fread(&RANDOM2[x],4,1,fp2); }
fclose(fp1);
fclose(fp2);
fp1=fopen(fullPath3,"rb"); /*read mainbook in memory*/
if (fp1==NULL) /*no mainbook book?*/
{ Error=3; return Error; }
fseek(fp1,0L,SEEK_END); /*get to end*/
fsize=ftell(fp1); /*get number of bytes*/
fseek(fp1,0L,SEEK_SET); /*rewind (!)*/
if(fsize <=0L){Error = 4;return Error;}
_MNB=(unsigned char*)malloc(fsize+2);/*add 2 endmarkers...*/
if (_MNB == NULL) {puts("malloc failed"); Error=4; return Error;}
memset(_MNB,0,fsize+2);
y=0; while ((x=getc(fp1))!=EOF) { _MNB[y]=x; y++; }
if (y&1){_MNB[y-1]=255;}
_MNB[y]=255; _MNB[y+1]=255;
fclose(fp1);
fp1=fopen(fullPath4,"rb"); /*read tournament book in memory*/
if (fp1==NULL) { /*no tournament book*/
Error=1; /*non-fatal error, to continue is possible...*/
_GB=NULL;
return Error; }
fseek(fp1,0L,SEEK_END); /*get to end*/
fsize=ftell(fp1); /*get number of bytes*/
fseek(fp1,0L,SEEK_SET); /*rewind (!)*/
if(fsize <=0L){Error = 1; _GB=NULL;return Error;} /*if i cannot alloc ,ignore it...*/
_GB=(unsigned char*)malloc(fsize+2);//2 endmarkers...
if (_GB == NULL) {puts("malloc failed"); Error=4; return Error;}
memset(_GB,0,fsize+2);
#else
int errno;
Error=0;
srand((unsigned)time(NULL)); /*init the random number generator*/
if((fp1 = fopen("random1.bin","rb"))==NULL)
{ Error=2; return Error; }
if((fp2 = fopen("random2.bin","rb"))==NULL)
{ Error=2; fclose(fp1); return Error; }
for (x=0; x<1120; x++) { r1=fread(&RANDOM1[x],4,1,fp1); r2=fread(&RANDOM2[x],4,1,fp2); }
fclose(fp1);
fclose(fp2);
fp1=fopen(Bookfile,"rb");
if (fp1==NULL) /*no mainbook book?*/
{ Error=3; return Error; }
fseek(fp1,0L,SEEK_END); /*get to end*/
fsize=ftell(fp1); /*get number of bytes*/
fseek(fp1,0L,SEEK_SET); /*rewind (!)*/
if(fsize <=0L){Error = 4;return Error;}
errno=0;
_MNB=calloc(fsize+2,1);/*add 2 endmarkers...*/
if(errno){perror("memory failure");Error=4; return Error;}
y=0; while ((x=getc(fp1))!=EOF) { _MNB[y]=x; y++; }
if (y&1){_MNB[y-1]=255;}
_MNB[y]=255; _MNB[y+1]=255;
fclose(fp1);
fp1=fopen(Toerfile,"rb"); /*read tournament book in memory*/
if (fp1==NULL) { /*no tournament book*/
Error=1; /*non-fatal error, to continue is possible...*/
_GB=NULL;
return Error; }
fseek(fp1,0L,SEEK_END); /*get to end*/
fsize=ftell(fp1); /*get number of bytes*/
fseek(fp1,0L,SEEK_SET); /*rewind (!)*/
if(fsize <=0L){Error = 1; _GB=NULL;return Error;} /*if i cannot alloc ,ignore it...*/
errno=0;
_GB=calloc(fsize+2,1);/*2 endmarkers...*/
if(errno){perror("memory failure");Error=4; return Error;}
#endif
y=0; while ((x=getc(fp1))!=EOF) { _GB[y]=x; y++; }
_GB[y-1]=255; _GB[y-2]=255; /*strange but true... :-) gave a big headache*/
fclose(fp1);
return Error;
}
int FIND_OPENING(const char *EPD,char *From,char *To, char *From1,char *From2,char *To1,char *To2,int *Bookmvs)
/*input : BOOKFILE / EPD*/
/*output: FROM and TO as E2 and E4 and ERROR*/
{ int xl,px,x,y,rnd,bhk1,bhk2,xd,xe;
int ch,by,v,kleur,boekfase;
char db[100],eb[100];
unsigned char zcd[200],zce[200],vb[100];
char fentab[] = "??PNBRQKpnbrqk??";
char fenkleur[] = "wb??";
Error=0;
From[0]=0; To[0]=0;
db[0]=0; eb[0]=0; vb[0]=255;
rnd = rand() % 9999;
AZ=0; /*number of found book moves*/
boekfase=0; /*search tournament book first*/
if (_GB==NULL) boekfase=1; /*no tournament book selected -> search main book*/
/* retrieve EPD*/
/* ============*/
for (x=1; x<=78; x++) if (_BORD[x] > 0) _BORD[x]=1; /*empty board*/
x=-1; y=0;
next: x++; ch=EPD[x];
if (ch=='/') goto next;
if (ch >= '1' && ch <= '8') { v=ch-48; y=y+v; goto test; }
for (v=2; v<=15; v++)
if (fentab[v]==ch) { _BORD[BORDPOS[y]]=v; y++; break; }
if (v>13) goto error;
test: if (y < 64) goto next;
x++; if (EPD[x] != ' ') goto error;
x++; if (EPD[x]==fenkleur[0]) { kleur=0; goto done; } /*white to move*/
if (EPD[x]==fenkleur[1]) { kleur=1; goto done; } /*black to move*/
error: Error=3; return Error; /*error in EPD string*/
done: MAKE_HASHKEY(); bhk1=HK1; bhk2=HK2; /*make hashkey of retrieved EPD*/
again: xl=0; px=-1;
boek10: px++;
boek12: if (boekfase){ /*read main book*/
if( _MNB[xl] ==255 && _MNB[xl+1]==255) goto boek90;
zce[px]=_MNB[xl+1];
zcd[px]=_MNB[xl];
}
else
{ if (_GB[xl]==255 && _GB[xl+1]==255) goto boek90; /*read tournament book*/
if (_GB[xl+1]==255 && _GB[xl+2]==255) goto boek90;
zce[px]=_GB[xl+1]; zcd[px]=_GB[xl];}
xl+=2;
if (zcd[px] < 128) goto boek10; /*collect moves till end of variation*/
/* Search the filled stack for possible bookmove*/
/* =============================================*/
x=0; BOEK_BEGIN(); HK1=0x05035c45; HK2=0xf1b92b1f; /*hashkey values start position*/
boek14: if (bhk1==HK1 && bhk2==HK2) goto boek16; /*hashkeys match, bookmove found*/
XD=BVELD[zcd[x] & 0x3f];
XE=BVELD[zce[x] & 0x3f];
BOEKIN(); /*update board and hashkeys*/
x++; if (x > px) goto boek20; /*end of variantion, check for next*/
goto boek14;
/* Bookmove found, insert in table*/
/* ===============================*/
boek16: if (zce[x]<64) goto boek20; /*Bad book move, no insert*/
if ((x&1) != (kleur&1)) goto boek20; /*colours don't match, no insert*/
xd=BVELD[zcd[x]&0x3f]; xe=BVELD[zce[x]&0x3f]; /*Bookmove found*/
for (v=0; v<AZ; v++) /*skip possible doubles*/
{ if (db[v]==xd && eb[v]==xe && vb[v]<64) vb[v]=zce[x];
if (db[v]==xd && eb[v]==xe) goto boek20; }
db[AZ]=xd; eb[AZ]=xe; vb[AZ]=zce[x]; /*store move in internal format*/
From1[AZ]=TA[xd]; From2[AZ]=TN[xd]; /*store move in ascii format*/
To1[AZ]=TA[xe]; To2[AZ]=TN[xe];
AZ++; /*number of found book moves*/
/* Spool back till bit-6 becomes zero*/
/* ==================================*/
boek20: if (zcd[px] < 192) goto boek12; /*there is another one !*/
boek22: px--;
if (px < 0) goto boek10;
if (zcd[px] >= 64) goto boek22;
goto boek12;
/* End of File, decide move to play*/
/* ================================*/
boek90: if (boekfase==0 && AZ==0) { boekfase=1; goto again; } /*nothing found in tournament book*/
/*search now the main book*/
if (AZ==0) goto einde; /*no book move(s) found*/
boek92: rnd=rnd & 63; by=-1;
boek94: by++; if (by >= AZ) goto boek92;
rnd=rnd-BOEKRND[by];
if (rnd > 0) goto boek94;
x=db[by]; From[0]=TA[x]; From[1]=TN[x]; From[2]=0;
x=eb[by]; To[0]=TA[x]; To[1]=TN[x]; To[2]=0;
einde:
*Bookmvs=AZ;
return Error;
}
void CLOSE_BOOK(void)
{
free(_GB);
free(_MNB);
}
void BOEK_BEGIN(void) /*start position to BORD*/
{ p_BORD[0]=0x01020500; /*a0/a1/a2/a3*/
p_BORD[1]=0x08010101; /*a4/a5/a6/a7*/
p_BORD[2]=0x0300000b; /*a8/a9/a0/b1*/
p_BORD[3]=0x01010102; /*b2/b3/b4/b5*/
p_BORD[4]=0x00090801; /*b6/b7/b8/b9*/
p_BORD[5]=0x01020400; /*b0/c1/c2/c3*/
p_BORD[6]=0x08010101; /*c4/c5/c6/c7*/
p_BORD[7]=0x0600000a; /*c8/c9/c0/d1*/
p_BORD[8]=0x01010102; /*d2/d3/d4/d5*/
p_BORD[9]=0x000c0801; /*d6/d7/d8/d9*/
p_BORD[10]=0x01020700; /*d0/e1/e2/e3*/
p_BORD[11]=0x08010101; /*e4/e5/e6/e7*/
p_BORD[12]=0x0400000d; /*e8/e9/e0/f1*/
p_BORD[13]=0x01010102; /*f2/f3/f4/f5*/
p_BORD[14]=0x000a0801; /*f6/f7/f8/f9*/
p_BORD[15]=0x01020300; /*f0/g1/g2/g3*/
p_BORD[16]=0x08010101; /*g4/g5/g6/g7*/
p_BORD[17]=0x05000009; /*g8/g9/g0/h1*/
p_BORD[18]=0x01010102; /*h2/h3/h4/h5*/
p_BORD[19]=0x000b0801; /*h6/h7/h8/h9*/
}
void MAKE_HASHKEY(void)
{ int x,y,v,sc;
HK1=0; HK2=0;
for (x=1; x<=78; x++)
{ if (_BORD[x]<2) continue;
sc=_BORD[x]; v=sc<<6; y=sc<<4; y=y+v;
HK1=HK1 ^ RANDOM1[y+x];
HK2=HK2 ^ RANDOM2[y+x];
}
}
void BOEKIN(void) /*update BORD and HASHKEY*/
{ int sc,z,y0;
char kntab[] = { 0,0,2,0,0,0,0,1,3,0,0,0,0,1 };
sc=_BORD[XD]; y0=_BORD[XE];
z=sc<<6; z=z+(sc<<4);
HK1=HK1 ^ RANDOM1[z+XD]; HK1=HK1 ^ RANDOM1[z+XE];
HK2=HK2 ^ RANDOM2[z+XD]; HK2=HK2 ^ RANDOM2[z+XE];
_BORD[XE]=sc; _BORD[XD]=1;
if (y0!=1) /*remove captured piece from hashkey*/
{ z=y0<<6; z=z+(y0<<4);
HK1=HK1 ^ RANDOM1[z+XE];
HK2=HK2 ^ RANDOM2[z+XE]; }
if (kntab[sc]==1) /*handle castling*/
{ if (XE-XD==20) { _BORD[XE+10]=1; _BORD[XE-10]=sc-2; MAKE_HASHKEY(); }
if (XE-XD==-20) { _BORD[XE-20]=1; _BORD[XE+10]=sc-2; MAKE_HASHKEY(); } }
if (sc==2 && y0==1 && XE-XD!=1 && XE-XD!=2) { _BORD[XE-1]=1; MAKE_HASHKEY(); } /*ep (white)*/
if (sc==8 && y0==1 && XD-XE!=1 && XD-XE!=2) { _BORD[XE+1]=1; MAKE_HASHKEY(); } /*ep (black)*/
}