summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-07 15:01:59 -0700
committerScott Gasch <[email protected]>2026-10-07 15:01:59 -0700
commit73b4afb12abf7cc442831dea42b41b63a2ce07be (patch)
tree4200cf56ad007484ce3d5734f91e4ebf9055a947
parente5d20411a389fbabca6d9ec36262c1a1f72ad2cb (diff)
Play EGTB move at root even when 'cursed'.
-rw-r--r--src/probe.c39
-rw-r--r--src/root.c6
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);
}
}
diff --git a/src/root.c b/src/root.c
index 8fcace7..e9e82d4 100644
--- a/src/root.c
+++ b/src/root.c
@@ -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;