diff options
Diffstat (limited to 'src/probe.c')
| -rw-r--r-- | src/probe.c | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/src/probe.c b/src/probe.c new file mode 100644 index 0000000..2d8c43d --- /dev/null +++ b/src/probe.c @@ -0,0 +1,432 @@ +/** + +Copyright (c) Scott Gasch + +Module Name: + + probe.c + +Abstract: + + Routines for probing endgame tablebases; much of this code is + "borrowed" from crafty. + +Author: + + Scott Gasch ([email protected]) 02 Jul 2004 + +Revision History: + + $Id: probe.c 355 2008-07-01 15:46:43Z scott $ + +**/ + +#include "chess.h" + +#define XX (127) // sq not on the board +#define C_PIECES (3) // max num pieces of one color + +ULONG g_uEgtbLock = 0; + +// +// define INDEX type +// +#define T_INDEX64 // use 64 bit indexes +#if defined (T_INDEX64) && defined (_MSC_VER) +typedef unsigned __int64 INDEX; +#elif defined (T_INDEX64) +typedef unsigned long long INDEX; +#else +typedef unsigned long INDEX; +#endif + +// +// define square type and tb type +// +typedef unsigned int squaret; +typedef signed char tb_t; + +// +// define color +// +typedef int color; +#define x_colorWhite 0 +#define x_colorBlack 1 +#define x_colorNeutral 2 +#define COLOR_DECLARED + +// +// define pieces +// +typedef int piece; +#define x_pieceNone 0 +#define x_piecePawn 1 +#define x_pieceKnight 2 +#define x_pieceBishop 3 +#define x_pieceRook 4 +#define x_pieceQueen 5 +#define x_pieceKing 6 +#define PIECES_DECLARED + +// +// scores returned from egtb.cpp +// +#define pageL 65536 +#define tbbe_ssL ((pageL-4)/2) +#define bev_broken (tbbe_ssL+1) /* illegal or busted */ +#define bev_mi1 tbbe_ssL /* mate in 1 move */ +#define bev_mimin 1 /* mate in max moves */ +#define bev_draw 0 /* draw */ +#define bev_limax (-1) /* mated in max moves */ +#define bev_li0 (-tbbe_ssL) /* mated in 0 moves */ + +// +// define PfnCalcIndex +// +typedef INDEX(TB_FASTCALL * PfnCalcIndex)(squaret *, + squaret *, + squaret, + int fInverse); + +// +// prototypes for functions in egtb.cpp +// +extern int IDescFindFromCounters(int *); +extern int FRegisteredFun(int, color); +extern PfnCalcIndex PfnIndCalcFun(int, color); +extern int TB_FASTCALL L_TbtProbeTable(int, color, INDEX); +#define PfnIndCalc PfnIndCalcFun +#define FRegistered FRegisteredFun +extern int IInitializeTb(char *); +extern int FTbSetCacheSize(void *buffer, unsigned long size); +extern int TB_CRC_CHECK; + +// +// Globals +// +static int EGTBMenCount = 0; +void *egtb_cache = NULL; +#define EGTB_CACHE_SIZE (8*1024*1024) + + +void +InitializeEGTB(void) +/** + +Routine description: + + [Re]Initialize the Nalimov EGTB system. Called during system + startup and when the user uses "set" to change the EGTB path. + +Parameters: + + void (uses g_OPtionz.szEGTBPath) + +Return value: + + void + +**/ +{ + CHAR *szPath = g_Options.szEGTBPath; + + if ((szPath != NULL) && strlen(szPath) > 0) { + // TB_CRC_CHECK = 1; + EGTBMenCount = IInitializeTb(szPath); + if (0 != EGTBMenCount) + { + Trace("Found %d-men endgame tablebases.\n\n", EGTBMenCount); + if (NULL != egtb_cache) + { + SystemFreeMemory(egtb_cache); + egtb_cache = NULL; + } + egtb_cache = SystemAllocateMemory(EGTB_CACHE_SIZE); + if (NULL != egtb_cache) + { + FTbSetCacheSize(egtb_cache, EGTB_CACHE_SIZE); + } + } + } +} + +void +CleanupEGTB(void) +/** + +Routine description: + + Cleanup the Nalimov EGTB system. + +Parameters: + + void + +Return value: + + void + +**/ +{ + if (NULL != egtb_cache) + { + SystemFreeMemory(egtb_cache); + egtb_cache = NULL; + } +} + + +FLAG +ProbeEGTB(SEARCHER_THREAD_CONTEXT *ctx, + SCORE *piScore) +/** + +Routine description: + + Search for a board position in the EGTB files on disk. + +Parameters: + + SEARCHER_THREAD_CONTEXT *ctx, + SCORE *piScore + +Return value: + + FLAG + +**/ +{ + POSITION *pos = &(ctx->sPosition); + int pcCount[10]; + int wSquares[C_PIECES*5+1], bSquares[C_PIECES*5+1]; + int iTB; + ULONG uColor; + int invert; + int *wp, *bp; + int ep; + INDEX index; + int value; + FLAG fResult; + ULONG x; + int y; + COOR c; + PIECE p; + PfnCalcIndex fp; + + // + // EGTB initialized? + // + ULONG wcount = (pos->uNonPawnCount[WHITE][0] + + pos->uPawnCount[WHITE]); + ULONG bcount = (pos->uNonPawnCount[BLACK][0] + + pos->uPawnCount[BLACK]); + if ((wcount + bcount > (ULONG)EGTBMenCount) || + (wcount > 3) || + (bcount > 3)) + { + return(FALSE); + } + INC(ctx->sCounters.egtb.uProbes); + memset(pcCount, 0, sizeof(pcCount)); + + for (x = 0; + x < pos->uPawnCount[WHITE]; + x++) + { + c = pos->cPawns[WHITE][x]; + ASSERT (IS_ON_BOARD(c)); + ASSERT(pos->rgSquare[c].pPiece && IS_PAWN(pos->rgSquare[c].pPiece)); + + c = TO64(c); + ASSERT((c >= 0) && (c <= 64)); + + y = pcCount[0]; + ASSERT(y >= 0); + ASSERT(y < (C_PIECES * 5 + 1)); + wSquares[y] = c; + pcCount[0]++; + } + + for (x = 1; + x < pos->uNonPawnCount[WHITE][0]; + x++) + { + c = pos->cNonPawns[WHITE][x]; + ASSERT (IS_ON_BOARD(c)); + + p = pos->rgSquare[c].pPiece; + ASSERT(p && !IS_PAWN(p) && !IS_KING(p)); + + // + // convert: into: + // XXX_PAWN 0 + // XXX_KNIGHT 1 + // XXX_BISHOP 2 + // XXX_ROOK 3 + // XXX_QUEEN 4 + // + p = ((p >> 1) & 0x7) - 1; + ASSERT(p > 0); + ASSERT(p < 5); + + c = TO64(c); + ASSERT((c >= 0) && (c <= 64)); + + y = p * C_PIECES + pcCount[p]; + ASSERT(y >= 0); + ASSERT(y < (C_PIECES * 5 + 1)); + wSquares[y] = c; + pcCount[p]++; + } + + for (x = 0; + x < pos->uPawnCount[BLACK]; + x++) + { + c = pos->cPawns[BLACK][x]; + ASSERT(IS_ON_BOARD(c)); + ASSERT(pos->rgSquare[c].pPiece && IS_PAWN(pos->rgSquare[c].pPiece)); + + c = TO64(c); + ASSERT(c >= 0); + ASSERT(c <= 64); + + y = pcCount[5]; + ASSERT(y >= 0); + ASSERT(y < (C_PIECES * 5 + 1)); + bSquares[y] = c; + pcCount[5]++; + } + + for (x = 1; + x < pos->uNonPawnCount[BLACK][0]; + x++) + { + c = pos->cNonPawns[BLACK][x]; + ASSERT(IS_ON_BOARD(c)); + + p = pos->rgSquare[c].pPiece; + ASSERT(p && !IS_PAWN(p) && !IS_KING(p)); + + // + // convert: into: + // XXX_PAWN 0 + // XXX_KNIGHT 1 + // XXX_BISHOP 2 + // XXX_ROOK 3 + // XXX_QUEEN 4 + // + p = ((p >> 1) & 0x7) - 1; + ASSERT(p > 0); + ASSERT(p < 5); + + c = TO64(c); + ASSERT(c >= 0); + ASSERT(c <= 64); + + y = p * C_PIECES + pcCount[5 + p]; + ASSERT(y >= 0); + ASSERT(y < (C_PIECES * 5 + 1)); + bSquares[y] = c; + pcCount[5 + p]++; + } + + AcquireSpinLock(&g_uEgtbLock); + iTB = IDescFindFromCounters(pcCount); + if (iTB == 0) + { + fResult = FALSE; + goto end; + } + + // + // Add the kings to the piece lists + // + ASSERT(pos->rgSquare[pos->cNonPawns[WHITE][0]].pPiece == WHITE_KING); + wSquares[C_PIECES * 5] = TO64(pos->cNonPawns[WHITE][0]); + ASSERT(wSquares[C_PIECES * 5] >= 0); + ASSERT(wSquares[C_PIECES * 5] <= 64); + + ASSERT(pos->rgSquare[pos->cNonPawns[BLACK][0]].pPiece == BLACK_KING); + bSquares[C_PIECES * 5] = TO64(pos->cNonPawns[BLACK][0]); + ASSERT(bSquares[C_PIECES * 5] >= 0); + ASSERT(bSquares[C_PIECES * 5] <= 64); + + if (iTB > 0) + { + uColor = (pos->uToMove == WHITE) ? 0 : 1; + invert = 0; + wp = wSquares; + bp = bSquares; + } + else + { + uColor = (pos->uToMove == WHITE) ? 1 : 0; + invert = 1; + wp = bSquares; + bp = wSquares; + iTB = -iTB; + } + + if (!FRegisteredFun(iTB, uColor)) + { + fResult = FALSE; + goto end; + } + ep = XX; + if (IS_ON_BOARD(pos->cEpSquare)) + { + ASSERT((IS_ON_BOARD(pos->cEpSquare + 1) && + IS_PAWN(pos->rgSquare[pos->cEpSquare + 1].pPiece)) || + (IS_ON_BOARD(pos->cEpSquare - 1) && + IS_PAWN(pos->rgSquare[pos->cEpSquare - 1].pPiece))); + ep = TO64(pos->cEpSquare); + } + +#if 0 + DumpPosition(pos); + Trace("iTB = %d, uColor = %u, ep = %u, invert = %u\n", + iTB, uColor, ep, invert); + Trace("wp =\t\t\tbp =\n"); + for(x = 0; x < 16; x++) + { + Trace("%u\t\t\t%u\n", wSquares[x], bSquares[x]); + } +#endif + ASSERT(IS_VALID_COLOR(uColor)); + fp = PfnIndCalcFun(iTB, uColor); + index = fp((squaret *)wp, + (squaret *)bp, + (squaret)ep, + invert); + value = L_TbtProbeTable(iTB, uColor, index); + if (value == bev_broken) + { + fResult = FALSE; + goto end; + } + + if (value > 0) + { + *piScore = INFINITY + (2*(-bev_mi1+value)) - 1; + } + else if (value < 0) + { + *piScore = -INFINITY + (2*(bev_mi1+value)); + } + else + { + *piScore = 0; // g_iDrawValue[pos->uToMove]; + } + fResult = TRUE; + + end: + ReleaseSpinLock(&g_uEgtbLock); +#ifdef PERF_COUNTERS + if (fResult == TRUE) + { + INC(ctx->sCounters.egtb.uHits); + } +#endif + return(fResult); +} |
