Scid  4.6.5
probe.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////
2 //
3 // FILE: probe.cpp
4 // Scid interface to Nalimov Tablebase decoder
5 //
6 // Part of: Scid (Shane's Chess Information Database)
7 // Version: 3.4
8 //
9 // Notice: Copyright (c) 2000-2002 Shane Hudson. All rights reserved.
10 //
11 // Author: Shane Hudson (sgh@users.sourceforge.net)
12 //
13 //////////////////////////////////////////////////////////////////////
14 
15 #include "probe.h"
16 #include "sqmove.h"
17 
18 #ifdef SCID_USE_TB
19 
20 #define NEW
21 #define XX 127 // Invalid EP square. Can be any value greater than 63,
22  // which represents H8.
23 #define C_PIECES 3 // Maximum number of pieces of one color and type.
24 
25 // PROBE_MAX_PER_SIDE = Maximum number of pieces per side, including Kings.
26 // It will be 3, unless T41_INCLUDE is defines which allows use of the
27 // 3-plus-king vs lone king bases.
28 #ifdef T41_INCLUDE
29 #define PROBE_MAX_PER_SIDE 4
30 #else
31 #define PROBE_MAX_PER_SIDE 3
32 #endif
33 
34 
35 typedef unsigned int INDEX;
36 typedef unsigned int square;
37 
38 #define SqFindKing(psq) (psq[C_PIECES * (x_pieceKing - 1)])
39 #define SqFindOne(psq,pce) (psq[C_PIECES * (pce - 1)])
40 #define SqFindFirst(psq,pce) (psq[C_PIECES * (pce - 1)])
41 #define SqFindSecond(psq,pce) (psq[C_PIECES * (pce - 1) + 1])
42 #define SqFindThird(psq,pce) (psq[C_PIECES * (pce - 1) + 2])
43 
44 
45 #include "egtb/tbindex.cpp"
46 
47 
48 // Default, minimum and maximum Tablebase cache size:
49 static const uint EGTB_CACHE_SIZE_MIN = 512 * 1024; // 0.5 MB
50 static const uint EGTB_CACHE_SIZE_DEFAULT = 512 * 1024; // 0.5 MB
51 static const uint EGTB_CACHE_SIZE_MAX = 128 * 1024 * 1024; // 128 MB
52 
53 static void * EGTB_cache = NULL;
54 static uint EGTB_maxpieces = 0;
55 static uint EGTB_cachesize = EGTB_CACHE_SIZE_DEFAULT;
56 
57 // scid_TB_compiled:
58 // Returns true if Tablebase support has been compiled, false otherwise.
59 bool
60 scid_TB_compiled (void) {
61  return true;
62 }
63 
64 // scid_TB_MaxPieces:
65 // Returns the largest number of pieces in any registered tablebase,
66 // including kings and pawns (e.g. kpkp tablebase has 4 pieces).
67 uint
68 scid_TB_MaxPieces (void) {
69  return EGTB_maxpieces;
70 }
71 
72 uint
73 scid_TB_CacheSize (void)
74 {
75  return EGTB_cachesize;
76 }
77 
78 void
79 scid_TB_SetCacheSize (uint cachesize)
80 {
81  EGTB_cachesize = cachesize;
82  if (cachesize < EGTB_CACHE_SIZE_MIN) {
83  EGTB_cachesize = EGTB_CACHE_SIZE_MIN;
84  }
85  if (cachesize > EGTB_CACHE_SIZE_MAX) {
86  EGTB_cachesize = EGTB_CACHE_SIZE_MAX;
87  }
88 }
89 
90 // scid_TB_init:
91 // Initialises the tablebases given a directory string. All the tables
92 // to be used must be in the directory; subdirectories are not
93 // scanned. However, the directory string may have more than one
94 // dircetory in it, separated by commas (,) or semicolons (;).
95 // Returns the same value as scid_TB_MaxPieces().
96 uint
97 scid_TB_Init (const char * egtb_path)
98 {
99  EGTB_maxpieces = (uint) IInitializeTb ((char *) egtb_path);
100 #ifdef WINCE
101  if (EGTB_cache != NULL) { my_Tcl_Free( (char *) EGTB_cache); }
102  EGTB_cache = (byte *)my_Tcl_Alloc(sizeof(byte [EGTB_cachesize]));
103 #else
104  if (EGTB_cache != NULL) { delete[] (byte *) EGTB_cache; }
105  EGTB_cache = new byte [EGTB_cachesize];
106 #endif
107  FTbSetCacheSize (EGTB_cache, EGTB_cachesize);
108  return EGTB_maxpieces;
109 }
110 
111 // scid_TB_Available:
112 // Given a material configuration, returns a boolean indicating
113 // if the tablebase for that material is registered for use.
114 // Note: there are actually TWO tablebases for any material
115 // combination, one for each side to move (file suffixes .nbw.emd
116 // and .nbb.emd); this function returns true if EITHER one is
117 // registered (since having only one of the two is usually good
118 // enough to solve the endgame).
119 bool
120 scid_TB_Available (matSigT matsig)
121 {
122  if (EGTB_maxpieces == 0) { return 0; }
123 
124  int counts [10];
125  counts [0] = matsig_getCount (matsig, WP);
126  counts [1] = matsig_getCount (matsig, WN);
127  counts [2] = matsig_getCount (matsig, WB);
128  counts [3] = matsig_getCount (matsig, WR);
129  counts [4] = matsig_getCount (matsig, WQ);
130  counts [5] = matsig_getCount (matsig, BP);
131  counts [6] = matsig_getCount (matsig, BN);
132  counts [7] = matsig_getCount (matsig, BB);
133  counts [8] = matsig_getCount (matsig, BR);
134  counts [9] = matsig_getCount (matsig, BQ);
135 
136  // Quickly check that there is not too much material:
137 
138  uint wc = 1 + counts[0] + counts[1] + counts[2] + counts[3] + counts[4];
139  uint bc = 1 + counts[5] + counts[6] + counts[7] + counts[8] + counts[9];
140  uint bothc = wc + bc;
141  if (bothc > EGTB_maxpieces || wc > PROBE_MAX_PER_SIDE ||
142  bc > PROBE_MAX_PER_SIDE) { return false; }
143 
144  // If two lone Kings, just return true:
145  if (bothc == 2) { return true; }
146 
147  // If KB-K or KN-K, return true because they are all-drawn tablebases:
148  if (bothc == 3) {
149  if (counts[1] == 1 || counts[2] == 1 ||
150  counts[6] == 1 || counts[7] == 1) {
151  return true;
152  }
153  }
154 
155  int iTb = IDescFindFromCounters (counts);
156  if (iTb == 0) { return false; }
157  if (iTb < 0) { iTb = -iTb; }
158 
159  // Return true if either of the two TBs for this material is available:
160 
161  if (FRegistered (iTb, 0)) { return true; }
162  if (FRegistered (iTb, 1)) { return true; }
163  return false;
164 }
165 
166 
167 // scid_TB_Probe:
168 // Given a position, probes the appropriate tablebase and puts the
169 // result in the integer pointed to by <score>.
170 // Returns OK if the probe was successful, or ERROR_NotFound otherwise.
171 //
172 // The value placed in score is as follows, where STM is the side to move:
173 // 3 STM mates in 3, etc.
174 // 2 STM mates in 2.
175 // 1 STM mates in 1.
176 // 0 Draw.
177 // -1 STM is checkmated.
178 // -2 STM mated in 1.
179 // -3 STM mated in 2, etc.
180 //
181 errorT
182 scid_TB_Probe (Position * pos, int * score)
183 {
184  int pieceCounts [10];
185  uint wSquares [C_PIECES * 6], bSquares [C_PIECES * 6];
186  uint * wSqs, * bSqs;
187  int iTb, color, flip;
188  uint npieces = pos->GetCount(WHITE) + pos->GetCount(BLACK);
189 
190  // Check that position has few enough pieces on each side:
191 
192  if (npieces > EGTB_maxpieces) { return ERROR_NotFound; }
193  if (pos->GetCount(WHITE) > PROBE_MAX_PER_SIDE) { return ERROR_NotFound; }
194  if (pos->GetCount(BLACK) > PROBE_MAX_PER_SIDE) { return ERROR_NotFound; }
195 
196  // If just two Kings, return "draw" now:
197  if (npieces <= 2) { *score = 0; return OK; }
198 
199  // If just a lone bishop or knight and kings, return draw now:
200  if (npieces == 3) {
201  if (pos->PieceCount(WB) == 1 || pos->PieceCount(BB) == 1 ||
202  pos->PieceCount(WN) == 1 || pos->PieceCount(WN) == 1) {
203  *score = 0;
204  return OK;
205  }
206  }
207 
208  // Fill in array of piece counts and find if the tablebase for this
209  // material configuration and side to move is registered:
210 
211  pieceCounts [0] = pos->PieceCount(WP);
212  pieceCounts [1] = pos->PieceCount(WN);
213  pieceCounts [2] = pos->PieceCount(WB);
214  pieceCounts [3] = pos->PieceCount(WR);
215  pieceCounts [4] = pos->PieceCount(WQ);
216  pieceCounts [5] = pos->PieceCount(BP);
217  pieceCounts [6] = pos->PieceCount(BN);
218  pieceCounts [7] = pos->PieceCount(BB);
219  pieceCounts [8] = pos->PieceCount(BR);
220  pieceCounts [9] = pos->PieceCount(BQ);
221 
222  iTb = IDescFindFromCounters (pieceCounts);
223  if (iTb == 0) { return ERROR_NotFound; }
224 
225  if (iTb > 0) {
226  color = (pos->GetToMove() == WHITE) ? 0 : 1;
227  flip = 0;
228  wSqs = wSquares;
229  bSqs = bSquares;
230  } else {
231  color = (pos->GetToMove() == WHITE) ? 1 : 0;
232  flip = 1;
233  wSqs = bSquares;
234  bSqs = wSquares;
235  iTb = - iTb;
236  }
237 
238  // macro that returns true if corresponding TB was found during initializing
239  if (! FRegistered (iTb, color)) { return ERROR_NotFound; }
240 
241  // Now we know the tablebase is registered. Fill in the array of
242  // square values for each piece:
243 
244  uint * firstSq[16];
245  firstSq[EMPTY] = NULL;
246  firstSq[WK] = &(wSquares [C_PIECES * (x_pieceKing - 1) ]);
247  firstSq[BK] = &(bSquares [C_PIECES * (x_pieceKing - 1) ]);
248  firstSq[WQ] = &(wSquares [C_PIECES * (x_pieceQueen - 1) ]);
249  firstSq[BQ] = &(bSquares [C_PIECES * (x_pieceQueen - 1) ]);
250  firstSq[WR] = &(wSquares [C_PIECES * (x_pieceRook - 1) ]);
251  firstSq[BR] = &(bSquares [C_PIECES * (x_pieceRook - 1) ]);
252  firstSq[WB] = &(wSquares [C_PIECES * (x_pieceBishop - 1) ]);
253  firstSq[BB] = &(bSquares [C_PIECES * (x_pieceBishop - 1) ]);
254  firstSq[WN] = &(wSquares [C_PIECES * (x_pieceKnight - 1) ]);
255  firstSq[BN] = &(bSquares [C_PIECES * (x_pieceKnight - 1) ]);
256  firstSq[WP] = &(wSquares [C_PIECES * (x_piecePawn - 1) ]);
257  firstSq[BP] = &(bSquares [C_PIECES * (x_piecePawn - 1) ]);
258 
259  const pieceT* board = pos->GetBoard();
260 
261  for (squareT sq = A1; sq <= H8; sq++) {
262  pieceT pce = board[sq];
263  if (pce != EMPTY) {
264  *(firstSq[pce]) = (int) sq;
265  firstSq[pce]++;
266  }
267  }
268 
269  // Set En Passant square it should only be a value other than XX if
270  // there is an EP target square, AND there is a possible EP capture.
271  // Specifying a target EP square (since a pawn has just moved two
272  // squares) when there is no enemy pawn actually able to capture
273  // en passant was able to cause the tablebase to give incorrect
274  // results in testing, so that is why we must check here whether an
275  // EP capture is possible.
276 
277  squareT enPassant = pos->GetEPTarget();
278  if (enPassant != NULL_SQUARE) {
279  bool possibleEP = false;
280  if (pos->GetToMove() == BLACK) {
281  // White just made a 2-square pawn move:
282  squareT left = square_Move (enPassant, UP_LEFT);
283  if (left != NULL_SQUARE && board[left] == BP) {
284  possibleEP = true;
285  }
286  squareT right = square_Move (enPassant, UP_RIGHT);
287  if (right != NULL_SQUARE && board[right] == BP) {
288  possibleEP = true;
289  }
290  } else {
291  // BLACK just made a 2-square pawn move:
292  squareT left = square_Move (enPassant, DOWN_LEFT);
293  if (left != NULL_SQUARE && board[left] == WP) {
294  possibleEP = true;
295  }
296  squareT right = square_Move (enPassant, DOWN_RIGHT);
297  if (right != NULL_SQUARE && board[right] == WP) {
298  possibleEP = true;
299  }
300  }
301  if (! possibleEP) { enPassant = NULL_SQUARE; }
302  }
303  int epTarget = (int) enPassant;
304  if (enPassant == NULL_SQUARE) { epTarget = XX; }
305 
306  // Now probe the tablebase:
307 
308  INDEX index = PfnIndCalc(iTb,color) (wSqs, bSqs, epTarget, flip);
309  int tbscore = L_TbtProbeTable (iTb, color, index);
310 
311  if (tbscore == bev_broken) { return ERROR_NotFound; }
312 
313  // Convert the tablebase score to the format we want and return it:
314 
315  int distance = tbscore;
316  if (tbscore > 0) {
317  distance = 32767 - tbscore;
318  } else if (tbscore < 0) {
319  distance = -32767 - tbscore;
320  }
321  *score = distance;
322  return OK;
323 }
324 
325 
326 #else
327 
328 ////////////////////////////////////////////////////////////
329 //
330 // SCID_USE_TB is not defined, so compile empty functions:
331 
332 bool
334  return false;
335 }
336 
337 uint
339 { return 0; }
340 
341 uint
343 { return 0; }
344 
345 void
347 { return; }
348 
349 uint
350 scid_TB_Init (const char *)
351 { return 0; }
352 
353 bool
355 { return false; }
356 
357 errorT
359 { return ERROR_NotFound; }
360 
361 #endif
362 
363 
364 //////////////////////////////////////////////////////////////////////
365 /// END of probe.cpp
366 //////////////////////////////////////////////////////////////////////
367 
const pieceT WK
Definition: common.h:236
unsigned char byte
Definition: common.h:97
const pieceT BB
Definition: common.h:237
const colorT WHITE
Definition: common.h:203
uint GetCount(colorT c)
Definition: position.h:163
const pieceT BK
Definition: common.h:237
sqsqname
Definition: board.tcl:292
const pieceT BN
Definition: common.h:237
uint scid_TB_Init(const char *)
Definition: probe.cpp:350
squareT square_Move(squareT sq, directionT dir)
Definition: sqmove.h:173
const errorT OK
Definition: error.h:23
flipw?newstate?
Definition: board.tcl:1510
const squareT NULL_SQUARE
Definition: common.h:352
bool scid_TB_Available(matSigT)
Definition: probe.cpp:354
const directionT UP_LEFT
Definition: common.h:551
const pieceT BQ
Definition: common.h:237
uint32_t matSigT
Definition: matsig.h:25
const pieceT WQ
Definition: common.h:236
const pieceT BP
Definition: common.h:237
const colorT BLACK
Definition: common.h:204
void scid_TB_SetCacheSize(uint)
Definition: probe.cpp:346
byte PieceCount(pieceT p)
Definition: position.h:150
const squareT A1
Definition: common.h:343
colorpct?col?
Definition: ptracker.tcl:77
const directionT UP_RIGHT
Definition: common.h:552
const pieceT EMPTY
Definition: common.h:234
const pieceT WB
Definition: common.h:236
uint32_t uint
Definition: common.h:99
Definition: board.tcl:276
uint matsig_getCount(matSigT m, pieceT p)
Definition: matsig.h:149
const squareT H8
Definition: common.h:350
unsigned short errorT
Definition: error.h:20
uint scid_TB_MaxPieces(void)
Definition: probe.cpp:338
bool scid_TB_compiled(void)
Definition: probe.cpp:333
const pieceT WP
Definition: common.h:236
uint scid_TB_CacheSize(void)
Definition: probe.cpp:342
const pieceT * GetBoard() const
Definition: position.h:189
errorT scid_TB_Probe(Position *, int *)
Definition: probe.cpp:358
const pieceT BR
Definition: common.h:237
colorT GetToMove()
Definition: position.h:155
const pieceT WN
Definition: common.h:236
const directionT DOWN_RIGHT
Definition: common.h:554
squareT GetEPTarget()
Definition: position.h:153
const errorT ERROR_NotFound
Definition: error.h:50
const directionT DOWN_LEFT
Definition: common.h:553
byte squareT
Definition: common.h:113
byte pieceT
Definition: common.h:111
const pieceT WR
Definition: common.h:236