diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 01a99b41..13cb9961 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1210,20 +1210,23 @@ int probe_dtz_table(const Position& pos, WDLScore wdl, ProbeState* result) // All of this means that during probing, the engine must look at captures and probe // their results and must probe the position itself. The "best" result of these // probes is the correct result for the position. -template +// DTZ table don't store values when a following move is a zeroing winning move +// (winning capture or winning pawn move). Also DTZ store wrong values for positions +// where the best move is an ep-move (even if losing). So in all these cases set +// the state to ZEROING_MOVE. +template WDLScore search(Position& pos, WDLScore alpha, WDLScore beta, ProbeState* result) { WDLScore value, epValue = WDLScoreNone; StateInfo st; CheckInfo ci(pos); - Move bestMove = MOVE_NONE; auto moveList = MoveList(pos); size_t moveCount = moveList.size(); for (const Move& move : moveList) { if ( !pos.capture(move) - && (!CheckPawnMoves || type_of(pos.moved_piece(move)) != PAWN)) + && (!CheckZeroingMoves || type_of(pos.moved_piece(move)) != PAWN)) continue; pos.do_move(move, st, pos.gives_check(move, ci)); @@ -1242,15 +1245,12 @@ WDLScore search(Position& pos, WDLScore alpha, WDLScore beta, ProbeState* result if (value >= beta) { - *result = (!CheckPawnMoves || pos.capture(move)) ? WIN_CAPTURE : WIN_PAWN_MOVE; + *result = ZEROING_MOVE; // Winning DTZ-zeroing move return value; } if (value > alpha) - { alpha = value; - bestMove = move; - } } value = probe_wdl_table(pos, result); @@ -1267,13 +1267,9 @@ WDLScore search(Position& pos, WDLScore alpha, WDLScore beta, ProbeState* result // Here alpha stores the best value out of the previous search if (value > alpha) - return *result = (value == epValue && value > WDLDraw ? WIN_CAPTURE : OK), value; - - if (bestMove && alpha > WDLDraw) - *result = (!CheckPawnMoves || pos.capture(bestMove)) ? WIN_CAPTURE : WIN_PAWN_MOVE; - else - *result = OK; + return *result = (value == epValue ? ZEROING_MOVE : OK), value; + *result = alpha > WDLDraw ? ZEROING_MOVE : OK; return alpha; } @@ -1461,9 +1457,13 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) if (wdl == WDLDraw) // DTZ tables don't store draws return 0; - if ( *result == WIN_CAPTURE // DTZ tables store a 'don't care' value in this case - || *result == WIN_PAWN_MOVE) - return wdl == WDLWin ? 1 : 101; // DTZ scores for immediate win or cursed win + // DTZ table stores a 'don't care' value in this case, or even a plain wrong + // one as in case the best move is a losing ep, so it cannot be probed. + if (*result == ZEROING_MOVE) + return wdl == WDLWin ? 1 : + wdl == WDLCursedWin ? 101 : + wdl == WDLCursedLoss ? -101 : + wdl == WDLLoss ? -1 : 0; int dtz = probe_dtz_table(pos, wdl, result); // Probe the table! diff --git a/src/syzygy/tbprobe.h b/src/syzygy/tbprobe.h index 4a1f7fde..27da52da 100644 --- a/src/syzygy/tbprobe.h +++ b/src/syzygy/tbprobe.h @@ -38,11 +38,10 @@ enum WDLScore { // Possible states after a probing operation enum ProbeState { - FAIL = 0, // Probe failed (missing file table) - OK = 1, // Probe succesful - CHANGE_STM = -1, // WDL probe succesful but DTZ should check the other side - WIN_CAPTURE = 2, // WDL probe succesful but position's DTZ value is invalid - WIN_PAWN_MOVE = 3 // WDL probe succesful but position's DTZ value is invalid + FAIL = 0, // Probe failed (missing file table) + OK = 1, // Probe succesful + CHANGE_STM = -1, // DTZ should check the other side + ZEROING_MOVE = 2 // Best move zeroes DTZ (capture or pawn move) }; extern size_t MaxCardinality; @@ -69,8 +68,7 @@ inline std::ostream& operator<<(std::ostream& os, const ProbeState v) { os << (v == FAIL ? "Failed" : v == OK ? "Success" : v == CHANGE_STM ? "Probed opponent side" : - v == WIN_CAPTURE ? "Found a winning capture" : - v == WIN_PAWN_MOVE ? "Found a winning pawn move" : "None"); + v == ZEROING_MOVE ? "Missing DTZ value" : "None"); return os; }