3 Copyright (c) Scott Gasch
11 Routines for probing endgame tablebases; much of this code is
12 "borrowed" from crafty.
20 $Id: probe.c 355 2008-07-01 15:46:43Z scott $
26 #define XX (127) // sq not on the board
27 #define C_PIECES (3) // max num pieces of one color
29 ULONG g_uEgtbLock = 0;
34 #define T_INDEX64 // use 64 bit indexes
35 #if defined (T_INDEX64) && defined (_MSC_VER)
36 typedef unsigned __int64 INDEX;
37 #elif defined (T_INDEX64)
38 typedef unsigned long long INDEX;
40 typedef unsigned long INDEX;
44 // define square type and tb type
46 typedef unsigned int squaret;
47 typedef signed char tb_t;
53 #define x_colorWhite 0
54 #define x_colorBlack 1
55 #define x_colorNeutral 2
56 #define COLOR_DECLARED
64 #define x_pieceKnight 2
65 #define x_pieceBishop 3
67 #define x_pieceQueen 5
69 #define PIECES_DECLARED
72 // scores returned from egtb.cpp
75 #define tbbe_ssL ((pageL-4)/2)
76 #define bev_broken (tbbe_ssL+1) /* illegal or busted */
77 #define bev_mi1 tbbe_ssL /* mate in 1 move */
78 #define bev_mimin 1 /* mate in max moves */
79 #define bev_draw 0 /* draw */
80 #define bev_limax (-1) /* mated in max moves */
81 #define bev_li0 (-tbbe_ssL) /* mated in 0 moves */
84 // define PfnCalcIndex
86 typedef INDEX(TB_FASTCALL * PfnCalcIndex)(squaret *,
92 // prototypes for functions in egtb.cpp
94 extern int IDescFindFromCounters(int *);
95 extern int FRegisteredFun(int, color);
96 extern PfnCalcIndex PfnIndCalcFun(int, color);
97 extern int TB_FASTCALL L_TbtProbeTable(int, color, INDEX);
98 #define PfnIndCalc PfnIndCalcFun
99 #define FRegistered FRegisteredFun
100 extern int IInitializeTb(char *);
101 extern int FTbSetCacheSize(void *buffer, unsigned long size);
102 extern int TB_CRC_CHECK;
107 static int EGTBMenCount = 0;
108 void *egtb_cache = NULL;
109 #define EGTB_CACHE_SIZE (8*1024*1024)
118 [Re]Initialize the Nalimov EGTB system. Called during system
119 startup and when the user uses "set" to change the EGTB path.
123 void (uses g_OPtionz.szEGTBPath)
131 CHAR *szPath = g_Options.szEGTBPath;
133 if ((szPath != NULL) && strlen(szPath) > 0) {
135 EGTBMenCount = IInitializeTb(szPath);
136 if (0 != EGTBMenCount)
138 Trace("Found %d-men endgame tablebases.\n\n", EGTBMenCount);
139 if (NULL != egtb_cache)
141 SystemFreeMemory(egtb_cache);
144 egtb_cache = SystemAllocateMemory(EGTB_CACHE_SIZE);
145 if (NULL != egtb_cache)
147 FTbSetCacheSize(egtb_cache, EGTB_CACHE_SIZE);
159 Cleanup the Nalimov EGTB system.
171 if (NULL != egtb_cache)
173 SystemFreeMemory(egtb_cache);
180 ProbeEGTB(SEARCHER_THREAD_CONTEXT *ctx,
186 Search for a board position in the EGTB files on disk.
190 SEARCHER_THREAD_CONTEXT *ctx,
199 POSITION *pos = &(ctx->sPosition);
201 int wSquares[C_PIECES*5+1], bSquares[C_PIECES*5+1];
219 ULONG wcount = (pos->uNonPawnCount[WHITE][0] +
220 pos->uPawnCount[WHITE]);
221 ULONG bcount = (pos->uNonPawnCount[BLACK][0] +
222 pos->uPawnCount[BLACK]);
223 if ((wcount + bcount > (ULONG)EGTBMenCount) ||
229 INC(ctx->sCounters.egtb.uProbes);
230 memset(pcCount, 0, sizeof(pcCount));
233 x < pos->uPawnCount[WHITE];
236 c = pos->cPawns[WHITE][x];
237 ASSERT (IS_ON_BOARD(c));
238 ASSERT(pos->rgSquare[c].pPiece && IS_PAWN(pos->rgSquare[c].pPiece));
241 ASSERT((c >= 0) && (c <= 64));
245 ASSERT(y < (C_PIECES * 5 + 1));
251 x < pos->uNonPawnCount[WHITE][0];
254 c = pos->cNonPawns[WHITE][x];
255 ASSERT (IS_ON_BOARD(c));
257 p = pos->rgSquare[c].pPiece;
258 ASSERT(p && !IS_PAWN(p) && !IS_KING(p));
268 p = ((p >> 1) & 0x7) - 1;
273 ASSERT((c >= 0) && (c <= 64));
275 y = p * C_PIECES + pcCount[p];
277 ASSERT(y < (C_PIECES * 5 + 1));
283 x < pos->uPawnCount[BLACK];
286 c = pos->cPawns[BLACK][x];
287 ASSERT(IS_ON_BOARD(c));
288 ASSERT(pos->rgSquare[c].pPiece && IS_PAWN(pos->rgSquare[c].pPiece));
296 ASSERT(y < (C_PIECES * 5 + 1));
302 x < pos->uNonPawnCount[BLACK][0];
305 c = pos->cNonPawns[BLACK][x];
306 ASSERT(IS_ON_BOARD(c));
308 p = pos->rgSquare[c].pPiece;
309 ASSERT(p && !IS_PAWN(p) && !IS_KING(p));
319 p = ((p >> 1) & 0x7) - 1;
327 y = p * C_PIECES + pcCount[5 + p];
329 ASSERT(y < (C_PIECES * 5 + 1));
334 AcquireSpinLock(&g_uEgtbLock);
335 iTB = IDescFindFromCounters(pcCount);
343 // Add the kings to the piece lists
345 ASSERT(pos->rgSquare[pos->cNonPawns[WHITE][0]].pPiece == WHITE_KING);
346 wSquares[C_PIECES * 5] = TO64(pos->cNonPawns[WHITE][0]);
347 ASSERT(wSquares[C_PIECES * 5] >= 0);
348 ASSERT(wSquares[C_PIECES * 5] <= 64);
350 ASSERT(pos->rgSquare[pos->cNonPawns[BLACK][0]].pPiece == BLACK_KING);
351 bSquares[C_PIECES * 5] = TO64(pos->cNonPawns[BLACK][0]);
352 ASSERT(bSquares[C_PIECES * 5] >= 0);
353 ASSERT(bSquares[C_PIECES * 5] <= 64);
357 uColor = (pos->uToMove == WHITE) ? 0 : 1;
364 uColor = (pos->uToMove == WHITE) ? 1 : 0;
371 if (!FRegisteredFun(iTB, uColor))
377 if (IS_ON_BOARD(pos->cEpSquare))
379 ASSERT((IS_ON_BOARD(pos->cEpSquare + 1) &&
380 IS_PAWN(pos->rgSquare[pos->cEpSquare + 1].pPiece)) ||
381 (IS_ON_BOARD(pos->cEpSquare - 1) &&
382 IS_PAWN(pos->rgSquare[pos->cEpSquare - 1].pPiece)));
383 ep = TO64(pos->cEpSquare);
388 Trace("iTB = %d, uColor = %u, ep = %u, invert = %u\n",
389 iTB, uColor, ep, invert);
390 Trace("wp =\t\t\tbp =\n");
391 for(x = 0; x < 16; x++)
393 Trace("%u\t\t\t%u\n", wSquares[x], bSquares[x]);
396 ASSERT(IS_VALID_COLOR(uColor));
397 fp = PfnIndCalcFun(iTB, uColor);
398 index = fp((squaret *)wp,
402 value = L_TbtProbeTable(iTB, uColor, index);
403 if (value == bev_broken)
411 *piScore = INFINITY + (2*(-bev_mi1+value)) - 1;
415 *piScore = -INFINITY + (2*(bev_mi1+value));
419 *piScore = 0; // g_iDrawValue[pos->uToMove];
424 ReleaseSpinLock(&g_uEgtbLock);
428 INC(ctx->sCounters.egtb.uHits);