1 /*
2 Sjeng - a chess variants playing program
3 Copyright (C) 2000-2001 Gian-Carlo Pascutto
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 As a special exception, Gian-Carlo Pascutto gives permission
20 to link this program with the Nalimov endgame database access
21 code. See the Copying/Distribution section in the README file
22 for more details.
23
24 File: probe.c
25 Purpose: access Nalimov endgame databases
26
27 */
28 #include "sjeng.h"
29 #include "protos.h"
30 #include "extvars.h"
31
32 #undef USE_EGTB
33
34 #define XX 127
35 #define KINGCAP 50000
36
37 typedef unsigned int INDEX;
38 typedef int square;
39
40 #if defined (_MSC_VER)
41 #define TB_FASTCALL __fastcall
42 #else
43 #define TB_FASTCALL
44 #endif
45
46 typedef int color;
47 #define x_colorWhite 0
48 #define x_colorBlack 1
49 #define x_colorNeutral 2
50 #define COLOR_DECLARED
51
52 typedef int piece;
53 #define x_pieceNone 0
54 #define x_piecePawn 1
55 #define x_pieceKnight 2
56 #define x_pieceBishop 3
57 #define x_pieceRook 4
58 #define x_pieceQueen 5
59 #define x_pieceKing 6
60 #define PIECES_DECLARED
61
62 typedef signed char tb_t;
63
64 #define pageL 65536
65 #define tbbe_ssL ((pageL-4)/2)
66 #define bev_broken (tbbe_ssL+1) /* illegal or busted */
67 #define bev_mi1 tbbe_ssL /* mate in 1 move */
68 #define bev_mimin 1 /* mate in max moves */
69 #define bev_draw 0 /* draw */
70 #define bev_limax (-1) /* mated in max moves */
71 #define bev_li0 (-tbbe_ssL) /* mated in 0 moves */
72
73 typedef INDEX (TB_FASTCALL * PfnCalcIndex)
74 (square*, square*, square, int fInverse);
75
76 extern int IDescFindFromCounters (int*);
77 extern int FRegisteredFun (int, color);
78 extern PfnCalcIndex PfnIndCalcFun (int, color);
79 extern int TB_FASTCALL L_TbtProbeTable (int, color, INDEX);
80
81 extern int IInitializeTb (char*);
82 extern int FTbSetCacheSize(void *pv, unsigned long cbSize);
83
84 #define PfnIndCalc PfnIndCalcFun
85 #define FRegistered FRegisteredFun
86
87 int EGTBProbes;
88 int EGTBHits;
89 int EGTBPieces;
90 int EGTBCacheSize;
91 char EGTBDir[STR_BUFF];
92
init_egtb(void)93 void init_egtb(void)
94 {
95 #ifdef USE_EGTB
96 void *buffer;
97
98 buffer = malloc(EGTBCacheSize);
99
100 if (buffer == NULL && (EGTBCacheSize != 0))
101 {
102 printf("Could not allocate EGTB buffer.\n");
103 exit(EXIT_FAILURE);
104 };
105
106 EGTBPieces = IInitializeTb (EGTBDir);
107
108 printf("%d piece endgame tablebases found\n", EGTBPieces);
109 printf("Allocated %dKb for indices and tables.\n",((cbEGTBCompBytes+1023)/1024));
110
111 if(FTbSetCacheSize (buffer, EGTBCacheSize) == FALSE
112 && (EGTBCacheSize != 0))
113 {
114 printf("Could not enable EGTB buffer.\n");
115 exit(EXIT_FAILURE);
116 };
117
118 return;
119 #else
120 return;
121 #endif
122 }
123
EGTranslate(int sqidx)124 const static int EGTranslate(int sqidx)
125 {
126 int r;
127
128 r = (((rank(sqidx)-1)*8)+(file(sqidx)-1));
129
130 return r;
131 }
132
probe_egtb(void)133 int probe_egtb(void)
134 {
135 #ifdef USE_EGTB
136 int *psqW, *psqB;
137 int rgiCounters[10] = {0,0,0,0,0,0,0,0,0,0};
138 int side;
139 int fInvert;
140 int sqEnP;
141 int wi = 1, W[8] = {6,0,0,0,0,0};
142 int bi = 1, B[8] = {6,0,0,0,0,0};
143 int tbScore;
144 INDEX ind;
145 int j, a, i;
146 int iTb;
147
148 EGTBProbes++;
149
150 W[4] = EGTranslate(wking_loc);
151 B[4] = EGTranslate(bking_loc);
152
153 for (j = 1, a = 1;(a <= piece_count); j++)
154 {
155 i = pieces[j];
156 if (!i)
157 continue;
158 else
159 a++;
160 switch(board[i])
161 {
162 case wpawn:
163 rgiCounters[0]++;
164 W[wi] = 1;
165 W[wi+4] = EGTranslate(i);
166 wi++;
167 break;
168 case wknight:
169 rgiCounters[1]++;
170 W[wi] = 2;
171 W[wi+4] = EGTranslate(i);
172 wi++;
173 break;
174 case wbishop:
175 rgiCounters[2]++;
176 W[wi] = 3;
177 W[wi+4] = EGTranslate(i);
178 wi++;
179 break;
180 case wrook:
181 rgiCounters[3]++;
182 W[wi] = 4;
183 W[wi+4] = EGTranslate(i);
184 wi++;
185 break;
186 case wqueen:
187 rgiCounters[4]++;
188 W[wi] = 5;
189 W[wi+4] = EGTranslate(i);
190 wi++;
191 break;
192 case bpawn:
193 rgiCounters[5]++;
194 B[bi] = 1;
195 B[bi+4] = EGTranslate(i);
196 bi++;
197 break;
198 case bknight:
199 rgiCounters[6]++;
200 B[bi] = 2;
201 B[bi+4] = EGTranslate(i);
202 bi++;
203 break;
204 case bbishop:
205 rgiCounters[7]++;
206 B[bi] = 3;
207 B[bi+4] = EGTranslate(i);
208 bi++;
209 break;
210 case brook:
211 rgiCounters[8]++;
212 B[bi] = 4;
213 B[bi+4] = EGTranslate(i);
214 bi++;
215 break;
216 case bqueen:
217 rgiCounters[9]++;
218 B[bi] = 5;
219 B[bi+4] = EGTranslate(i);
220 bi++;
221 break;
222 }
223 }
224
225 /* more than 4 pieces for one side: not a class we can index */
226 if (wi >= 4 || bi >= 4)
227 {
228 return KINGCAP;
229 }
230
231 iTb = IDescFindFromCounters (rgiCounters);
232 if (0 == iTb)
233 {
234 return KINGCAP;
235 }
236 else if (iTb > 0)
237 {
238 /* white = 0*/
239 side = !white_to_move;
240 fInvert = 0;
241 psqW = W;
242 psqB = B;
243 }
244 else
245 {
246 side = white_to_move;
247 fInvert = 1;
248 psqW = B;
249 psqB = W;
250 iTb = -iTb;
251 }
252 if (!FRegistered(iTb, side))
253 return KINGCAP;
254
255 if (ep_square == 0)
256 {
257 sqEnP = XX;
258 }
259 else
260 {
261 if (white_to_move)
262 {
263 if (board[ep_square - 11] == wpawn || board[ep_square - 13] == wpawn)
264 sqEnP = EGTranslate(ep_square);
265 else
266 sqEnP = XX;
267 }
268 else
269 {
270 if (board[ep_square + 11] == bpawn || board[ep_square + 13] == bpawn)
271 sqEnP = EGTranslate(ep_square);
272 else
273 sqEnP = XX;
274
275 }
276 }
277
278 ind = PfnIndCalc(iTb, side) (psqW, psqB, sqEnP, fInvert);
279
280 tbScore = L_TbtProbeTable( iTb, side, ind);
281
282 if (tbScore == bev_broken) return KINGCAP;
283
284 EGTBHits++;
285
286 if (tbScore > 0)
287 {
288 return ((tbScore-bev_mi1)*2+INF-ply-1);
289 }
290 else if (tbScore < 0)
291 {
292 return ((tbScore+bev_mi1)*2-INF+ply);
293 }
294 return 0;
295 #else
296 return KINGCAP;
297 #endif
298 }
299