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