summaryrefslogtreecommitdiff
path: root/src/probe.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-08-23 13:12:04 -0700
committerScott Gasch <[email protected]>2026-08-23 13:12:04 -0700
commitf83f1592659a0e06182e3017aafbd84ba83935fb (patch)
tree57eb77a2ec1a137666b39b961e0bcf08444a6eef /src/probe.c
parentdf8facc22815f9eca0897e27ccce30701ba95322 (diff)
Integrate new syzygy egtb code, lose the old Nalimov code.
Diffstat (limited to 'src/probe.c')
-rw-r--r--src/probe.c629
1 files changed, 330 insertions, 299 deletions
diff --git a/src/probe.c b/src/probe.c
index 2d8c43d..242612c 100644
--- a/src/probe.c
+++ b/src/probe.c
@@ -8,12 +8,21 @@ Module Name:
Abstract:
- Routines for probing endgame tablebases; much of this code is
- "borrowed" from crafty.
+ Routines for probing endgame tablebases. This uses Ronald de
+ Man's Syzygy tablebase format via Jon Dart's "Fathom" probing
+ library (see fathom/) instead of Eugene Nalimov's original
+ tablebases. Syzygy tables store WDL (win/draw/loss) + DTZ
+ (distance to zeroing move) rather than Nalimov's DTM (distance
+ to mate); they are dramatically smaller on disk and the probing
+ code is far simpler as a result. We lose literal mate-distance
+ information from interior-node probes, so a probed win/loss is
+ reported as a large-but-not-mate-range score rather than a
+ precise mate score.
Author:
Scott Gasch ([email protected]) 02 Jul 2004
+ Converted to Syzygy/Fathom 23 Aug 2026
Revision History:
@@ -22,105 +31,34 @@ Revision History:
**/
#include "chess.h"
-
-#define XX (127) // sq not on the board
-#define C_PIECES (3) // max num pieces of one color
+#include "fathom/tbprobe.h"
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;
-
+// A probed tablebase win/loss doesn't carry a real distance-to-mate
+// (Syzygy WDL doesn't encode one), so we report a large decisive
+// score that stays safely below NMATE. This keeps it from being
+// mistaken for (and ply-adjusted as) a literal forced mate elsewhere
+// in the engine while still dominating ordinary evaluation scores.
//
-// Globals
-//
-static int EGTBMenCount = 0;
-void *egtb_cache = NULL;
-#define EGTB_CACHE_SIZE (8*1024*1024)
+#define EGTB_WIN_SCORE (NMATE - VALUE_QUEEN)
+#define EGTB_LOSS_SCORE (-EGTB_WIN_SCORE)
+static FLAG g_fEgtbInitialized = FALSE;
-void
+void
InitializeEGTB(void)
/**
Routine description:
- [Re]Initialize the Nalimov EGTB system. Called during system
+ [Re]Initialize the Syzygy EGTB system. Called during system
startup and when the user uses "set" to change the EGTB path.
Parameters:
- void (uses g_OPtionz.szEGTBPath)
+ void (uses g_Options.szEGTBPath)
Return value:
@@ -130,33 +68,33 @@ Return value:
{
CHAR *szPath = g_Options.szEGTBPath;
- if ((szPath != NULL) && strlen(szPath) > 0) {
- // TB_CRC_CHECK = 1;
- EGTBMenCount = IInitializeTb(szPath);
- if (0 != EGTBMenCount)
+ if (TRUE == g_fEgtbInitialized)
+ {
+ tb_free();
+ g_fEgtbInitialized = FALSE;
+ }
+
+ if ((szPath != NULL) && strlen(szPath) > 0)
+ {
+ if (TRUE == tb_init(szPath))
{
- Trace("Found %d-men endgame tablebases.\n\n", EGTBMenCount);
- if (NULL != egtb_cache)
+ g_fEgtbInitialized = TRUE;
+ if (TB_LARGEST > 0)
{
- SystemFreeMemory(egtb_cache);
- egtb_cache = NULL;
- }
- egtb_cache = SystemAllocateMemory(EGTB_CACHE_SIZE);
- if (NULL != egtb_cache)
- {
- FTbSetCacheSize(egtb_cache, EGTB_CACHE_SIZE);
+ Trace("Found Syzygy endgame tablebases (up to %u men).\n\n",
+ TB_LARGEST);
}
}
}
}
-void
+void
CleanupEGTB(void)
/**
Routine description:
- Cleanup the Nalimov EGTB system.
+ Cleanup the Syzygy EGTB system.
Parameters:
@@ -168,22 +106,108 @@ Return value:
**/
{
- if (NULL != egtb_cache)
+ if (TRUE == g_fEgtbInitialized)
{
- SystemFreeMemory(egtb_cache);
- egtb_cache = NULL;
+ tb_free();
+ g_fEgtbInitialized = FALSE;
}
}
-FLAG
+static void
+_BuildFathomBitboards(IN POSITION *pos,
+ OUT UINT64 *pu64White,
+ OUT UINT64 *pu64Black,
+ OUT UINT64 *pu64Kings,
+ OUT UINT64 *pu64Queens,
+ OUT UINT64 *pu64Rooks,
+ OUT UINT64 *pu64Bishops,
+ OUT UINT64 *pu64Knights,
+ OUT UINT64 *pu64Pawns)
+/**
+
+Routine description:
+
+ Build the set of bitboards Fathom's tb_probe_wdl wants out of our
+ POSITION. Fathom expects the standard tablebase square numbering
+ (a1 == bit 0 ... h8 == bit 63), which is exactly what our TO64()
+ macro produces -- note this is *not* the same square numbering as
+ our engine's own internal BBSQUARE/COOR_TO_BB bitboards, so we
+ must not use those macros here.
+
+Parameters:
+
+ POSITION *pos,
+ UINT64 *pu64White ... pu64Pawns
+
+Return value:
+
+ static void
+
+**/
+{
+ ULONG uColor;
+ ULONG u;
+ COOR c;
+ PIECE p;
+ UINT64 bb;
+
+ *pu64White = *pu64Black = 0ULL;
+ *pu64Kings = *pu64Queens = *pu64Rooks = 0ULL;
+ *pu64Bishops = *pu64Knights = *pu64Pawns = 0ULL;
+
+ for (uColor = BLACK; uColor <= WHITE; uColor++)
+ {
+ UINT64 *pu64Side = (uColor == WHITE) ? pu64White : pu64Black;
+
+ for (u = 0; u < pos->uPawnCount[uColor]; u++)
+ {
+ c = pos->cPawns[uColor][u];
+ ASSERT(IS_ON_BOARD(c));
+ bb = (1ULL << (TO64(c)));
+ *pu64Side |= bb;
+ *pu64Pawns |= bb;
+ }
+
+ for (u = 0; u < pos->uNonPawnCount[uColor][0]; u++)
+ {
+ c = pos->cNonPawns[uColor][u];
+ ASSERT(IS_ON_BOARD(c));
+ bb = (1ULL << (TO64(c)));
+ *pu64Side |= bb;
+
+ if (0 == u)
+ {
+ ASSERT(IS_KING(pos->rgSquare[c].pPiece));
+ *pu64Kings |= bb;
+ continue;
+ }
+
+ p = pos->rgSquare[c].pPiece;
+ ASSERT(p && !IS_PAWN(p) && !IS_KING(p));
+ if (IS_KNIGHT(p)) *pu64Knights |= bb;
+ else if (IS_BISHOP(p)) *pu64Bishops |= bb;
+ else if (IS_ROOK(p)) *pu64Rooks |= bb;
+ else
+ {
+ ASSERT(IS_QUEEN(p));
+ *pu64Queens |= bb;
+ }
+ }
+ }
+}
+
+
+FLAG
ProbeEGTB(SEARCHER_THREAD_CONTEXT *ctx,
SCORE *piScore)
/**
Routine description:
- Search for a board position in the EGTB files on disk.
+ Search for a board position in the Syzygy EGTB files on disk via
+ Fathom. This only returns a WDL (win/draw/loss) result, not a
+ literal mate distance -- see EGTB_WIN_SCORE / EGTB_LOSS_SCORE.
Parameters:
@@ -197,236 +221,243 @@ Return value:
**/
{
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;
+ UINT64 u64White, u64Black, u64Kings, u64Queens;
+ UINT64 u64Rooks, u64Bishops, u64Knights, u64Pawns;
+ unsigned uEp;
+ unsigned uWdl;
+ ULONG wcount, bcount;
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))
+ if (FALSE == g_fEgtbInitialized || 0 == TB_LARGEST)
{
return(FALSE);
}
- INC(ctx->sCounters.egtb.uProbes);
- memset(pcCount, 0, sizeof(pcCount));
- for (x = 0;
- x < pos->uPawnCount[WHITE];
- x++)
+ //
+ // Syzygy WDL probing requires no castling rights on the board and
+ // a zero halfmove (fifty move rule) clock; the WDL tables don't
+ // encode either.
+ //
+ if ((0 != pos->bvCastleInfo) || (0 != pos->uFifty))
{
- 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]++;
+ return(FALSE);
}
- for (x = 1;
- x < pos->uNonPawnCount[WHITE][0];
- x++)
+ wcount = pos->uNonPawnCount[WHITE][0] + pos->uPawnCount[WHITE];
+ bcount = pos->uNonPawnCount[BLACK][0] + pos->uPawnCount[BLACK];
+ if ((wcount + bcount) > TB_LARGEST)
{
- 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]++;
+ return(FALSE);
}
+ INC(ctx->sCounters.egtb.uProbes);
- 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]++;
- }
+ _BuildFathomBitboards(pos, &u64White, &u64Black, &u64Kings, &u64Queens,
+ &u64Rooks, &u64Bishops, &u64Knights, &u64Pawns);
- for (x = 1;
- x < pos->uNonPawnCount[BLACK][0];
- x++)
+ uEp = 0;
+ if (IS_ON_BOARD(pos->cEpSquare))
{
- 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]++;
+ uEp = TO64(pos->cEpSquare);
}
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);
+ uWdl = tb_probe_wdl(u64White, u64Black, u64Kings, u64Queens, u64Rooks,
+ u64Bishops, u64Knights, u64Pawns,
+ /* rule50 */ 0, /* castling */ 0, uEp,
+ (pos->uToMove == WHITE));
+ ReleaseSpinLock(&g_uEgtbLock);
- if (iTB > 0)
+ if (TB_RESULT_FAILED == uWdl)
{
- 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;
+ return(FALSE);
}
-
- if (!FRegisteredFun(iTB, uColor))
+
+ switch (uWdl)
{
- fResult = FALSE;
- goto end;
+ case TB_WIN:
+ *piScore = EGTB_WIN_SCORE;
+ break;
+ case TB_LOSS:
+ *piScore = EGTB_LOSS_SCORE;
+ break;
+ case TB_CURSED_WIN:
+ case TB_BLESSED_LOSS:
+ case TB_DRAW:
+ default:
+ *piScore = 0; // g_iDrawValue[pos->uToMove];
+ break;
}
- ep = XX;
- if (IS_ON_BOARD(pos->cEpSquare))
+ fResult = TRUE;
+
+#ifdef PERF_COUNTERS
+ INC(ctx->sCounters.egtb.uHits);
+#endif
+ return(fResult);
+}
+
+
+//
+// Convert a Fathom tablebase square index (a1==0 ... h8==63) back into
+// our own COOR encoding. Inverse of TO64().
+//
+#define FROM64(s) \
+ ((((7 - ((s) >> 3)) << 4)) | ((s) & 0x7))
+
+
+static PIECE
+_TbPromotesToPiece(IN unsigned uPromotes)
+/**
+
+Routine description:
+
+ Map a TB_PROMOTES_* value from a Fathom root probe result to our
+ own PIECE constant.
+
+Parameters:
+
+ unsigned uPromotes
+
+Return value:
+
+ static PIECE
+
+**/
+{
+ switch (uPromotes)
{
- 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);
+ case TB_PROMOTES_QUEEN: return(QUEEN);
+ case TB_PROMOTES_ROOK: return(ROOK);
+ case TB_PROMOTES_BISHOP: return(BISHOP);
+ case TB_PROMOTES_KNIGHT: return(KNIGHT);
+ default: return(0);
}
-
-#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++)
+}
+
+
+FLAG
+ProbeEGTBRoot(SEARCHER_THREAD_CONTEXT *ctx,
+ MOVE *pmv,
+ SCORE *piScore)
+/**
+
+Routine description:
+
+ Probe the Syzygy DTZ tables for the best move at the root. Unlike
+ ProbeEGTB (WDL-only, used at interior nodes), this uses DTZ to
+ pick a move that actually makes progress towards mate / the
+ fifty-move-rule reset -- Syzygy WDL alone has no notion of "closer
+ to mate" so relying on it exclusively could shuffle forever inside
+ a won position. This is expected to be called once at the root,
+ before the normal iterative search, when <= TB_LARGEST pieces
+ remain on the board.
+
+ We ask Fathom for its suggested (from, to, promotion) and then
+ find the matching move in our own already-generated root move
+ list, rather than reconstructing a MOVE by hand, so we inherit our
+ engine's own move flags (capture, en passant, special, etc).
+
+Parameters:
+
+ SEARCHER_THREAD_CONTEXT *ctx,
+ MOVE *pmv,
+ SCORE *piScore
+
+Return value:
+
+ FLAG : TRUE if a move was found and *pmv / *piScore were set.
+
+**/
+{
+ POSITION *pos = &(ctx->sPosition);
+ UINT64 u64White, u64Black, u64Kings, u64Queens;
+ UINT64 u64Rooks, u64Bishops, u64Knights, u64Pawns;
+ unsigned uEp;
+ unsigned uResult;
+ unsigned uWdl;
+ COOR cFrom, cTo;
+ PIECE pPromotes;
+ ULONG wcount, bcount;
+ ULONG u;
+
+ if (FALSE == g_fEgtbInitialized || 0 == TB_LARGEST)
{
- Trace("%u\t\t\t%u\n", wSquares[x], bSquares[x]);
+ return(FALSE);
}
-#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)
+
+ wcount = pos->uNonPawnCount[WHITE][0] + pos->uPawnCount[WHITE];
+ bcount = pos->uNonPawnCount[BLACK][0] + pos->uPawnCount[BLACK];
+ if ((wcount + bcount) > TB_LARGEST)
{
- fResult = FALSE;
- goto end;
+ return(FALSE);
}
- if (value > 0)
+ _BuildFathomBitboards(pos, &u64White, &u64Black, &u64Kings, &u64Queens,
+ &u64Rooks, &u64Bishops, &u64Knights, &u64Pawns);
+
+ uEp = 0;
+ if (IS_ON_BOARD(pos->cEpSquare))
{
- *piScore = INFINITY + (2*(-bev_mi1+value)) - 1;
+ uEp = TO64(pos->cEpSquare);
}
- else if (value < 0)
+
+ AcquireSpinLock(&g_uEgtbLock);
+ uResult = tb_probe_root(u64White, u64Black, u64Kings, u64Queens, u64Rooks,
+ u64Bishops, u64Knights, u64Pawns,
+ pos->uFifty, pos->bvCastleInfo, uEp,
+ (pos->uToMove == WHITE), NULL);
+ ReleaseSpinLock(&g_uEgtbLock);
+
+ if ((TB_RESULT_FAILED == uResult) ||
+ (TB_RESULT_CHECKMATE == uResult) ||
+ (TB_RESULT_STALEMATE == uResult))
{
- *piScore = -INFINITY + (2*(bev_mi1+value));
+ //
+ // No usable move (either failed, or the earlier terminal-state
+ // check already handles checkmate/stalemate).
+ //
+ return(FALSE);
}
- else
+
+ //
+ // A blessed win / cursed loss / plain draw at the root: don't
+ // steer the search away from its own move choice, since these
+ // are all draws under the fifty move rule and normal search
+ // handles that correctly already. Only override the root move
+ // when this is a clear win or a position we must play carefully
+ // to avoid losing (both cases: follow the DTZ suggestion).
+ //
+ uWdl = TB_GET_WDL(uResult);
+ if ((TB_DRAW == uWdl) ||
+ (TB_CURSED_WIN == uWdl) ||
+ (TB_BLESSED_LOSS == uWdl))
{
- *piScore = 0; // g_iDrawValue[pos->uToMove];
+ return(FALSE);
}
- fResult = TRUE;
- end:
- ReleaseSpinLock(&g_uEgtbLock);
-#ifdef PERF_COUNTERS
- if (fResult == TRUE)
+ cFrom = FROM64(TB_GET_FROM(uResult));
+ cTo = FROM64(TB_GET_TO(uResult));
+ pPromotes = _TbPromotesToPiece(TB_GET_PROMOTES(uResult));
+
+ for (u = ctx->sMoveStack.uBegin[ctx->uPly];
+ u < ctx->sMoveStack.uEnd[ctx->uPly];
+ u++)
{
- INC(ctx->sCounters.egtb.uHits);
+ MOVE mv = ctx->sMoveStack.mvf[u].mv;
+ if ((mv.cFrom == cFrom) &&
+ (mv.cTo == cTo) &&
+ (mv.pPromoted == pPromotes))
+ {
+ *pmv = mv;
+ *piScore = (TB_WIN == uWdl) ? EGTB_WIN_SCORE : EGTB_LOSS_SCORE;
+ return(TRUE);
+ }
}
-#endif
- return(fResult);
+
+ //
+ // Fathom suggested a move we couldn't find in our own move list;
+ // this shouldn't happen for a legally-generated root, but don't
+ // trust it if it does.
+ //
+ ASSERT(FALSE);
+ return(FALSE);
}