diff options
| author | Scott Gasch <[email protected]> | 2026-10-07 15:01:59 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-07 15:01:59 -0700 |
| commit | 73b4afb12abf7cc442831dea42b41b63a2ce07be (patch) | |
| tree | 4200cf56ad007484ce3d5734f91e4ebf9055a947 | |
| parent | e5d20411a389fbabca6d9ec36262c1a1f72ad2cb (diff) | |
Play EGTB move at root even when 'cursed'.
| -rw-r--r-- | src/probe.c | 39 | ||||
| -rw-r--r-- | src/root.c | 6 |
2 files changed, 25 insertions, 20 deletions
diff --git a/src/probe.c b/src/probe.c index d08ef75..a6730d8 100644 --- a/src/probe.c +++ b/src/probe.c @@ -487,20 +487,19 @@ Return value: } // - // 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). + // Always follow Fathom's root DTZ suggestion once the tablebase has + // a verdict, including plain draws and the cursed-win/blessed-loss + // buckets. A cursed win's/blessed loss's DTZ move is still the one + // that makes maximum progress toward actually converting/surviving + // before the fifty-move counter forces a draw -- ordinary search, + // steered only by a heuristic eval with no notion of the tablebase's + // verdict, can and does wander off the single correct try in these + // cases (confirmed live: a blessed-loss position in blunders.pgn + // where unassisted search picked a move that lost outright). Plain + // TB_DRAW has many equally-drawing replies, so this is never worse + // than deferring to search, just occasionally no better. // uWdl = TB_GET_WDL(uResult); - if ((TB_DRAW == uWdl) || - (TB_CURSED_WIN == uWdl) || - (TB_BLESSED_LOSS == uWdl)) - { - return(FALSE); - } cFrom = FROM64(TB_GET_FROM(uResult)); cTo = FROM64(TB_GET_TO(uResult)); @@ -524,12 +523,18 @@ Return value: // towards 100, a reset becomes forced soon even though // mate itself is nowhere near), producing a bogus // "+MATE<n>"/"-MATE<n>" display untethered from reality. - // The draw/cursed-win/blessed-loss cases already returned - // FALSE above, so uWdl here is only ever TB_WIN or - // TB_LOSS -- report the same flat mate-magnitude score - // ProbeEGTB/RecognLookup use at interior nodes instead. + // Report the same flat mate-magnitude score ProbeEGTB/ + // RecognLookup use at interior nodes for a clear win/loss; + // the drawish buckets (plain draw, cursed win, blessed + // loss) get the normal draw score instead, matching + // ProbeEGTB's own WDL->score mapping. *pmv = mv; - *piScore = (TB_WIN == uWdl) ? +NMATE : -NMATE; + switch (uWdl) + { + case TB_WIN: *piScore = +NMATE; break; + case TB_LOSS: *piScore = -NMATE; break; + default: *piScore = g_iDrawScore[pos->uToMove]; break; + } return(TRUE); } } @@ -1411,13 +1411,13 @@ Return value: // See if we are sitting at a checkmate or stalemate position; no // sense searching if so. // - ret = _DetectPreMoveTerminalStates(ctx, - fInCheck, + ret = _DetectPreMoveTerminalStates(ctx, + fInCheck, &mv); if (ret.eResult != RESULT_IN_PROGRESS) { goto end; } - + // Game still in progress but only one legal move available? if (mv.uMove != 0) { ctx->mvRootMove = mv; |
