From 8cc6bc200c9b690b46facdb687a6e8a8cd59a3eb Mon Sep 17 00:00:00 2001 From: Adarsh Das Date: Wed, 3 Jun 2026 21:10:00 +0530 Subject: [PATCH] Fix forgotten mate and aborted loss score bug A later iteration could overwrite a better mate score found previously, either due to TT collisions or an aborted search. Restore the previous iteration's score in both cases, and move the UCI print after the restore to print the updated score. Bench: 3634130 Co-authored-by: Shahin M. Shahin --- src/search.rs | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/search.rs b/src/search.rs index ee9c63d20..26f6eca76 100644 --- a/src/search.rs +++ b/src/search.rs @@ -178,15 +178,6 @@ pub fn start(td: &mut ThreadData, report: Report, thread_count: usize) { td.completed_depth = depth; } - if report == Report::Full - && !(is_loss(td.root_moves[0].display_score) && td.shared.status.get() == Status::STOPPED) - && (td.shared.status.get() == Status::STOPPED - || td.pv_index + 1 == td.multi_pv - || td.shared.nodes.aggregate() > 10_000_000) - { - td.print_uci_info(depth); - } - if (td.root_moves[0].score - average[0]).abs() < 12 { eval_stability += 1; } else { @@ -199,18 +190,42 @@ pub fn start(td: &mut ThreadData, report: Report, thread_count: usize) { pv_stability = 0; } - if td.root_moves[0].score != -Score::INFINITE + let last_score = last_best_rootmove.score; + + let is_forgotten_mate = last_score != -Score::INFINITE + && is_decisive(last_score) + && (td.root_moves[0].score.abs() < last_score.abs() + || td.root_moves[0].upperbound + || td.root_moves[0].lowerbound); + + let is_aborted_loss = td.shared.status.get() == Status::STOPPED + && td.root_moves[0].score != -Score::INFINITE && is_loss(td.root_moves[0].score) - && td.shared.status.get() == Status::STOPPED - { + && !td.root_moves[0].upperbound + && !td.root_moves[0].lowerbound; + + if is_aborted_loss || is_forgotten_mate { if let Some(pos) = td.root_moves.iter().position(|rm| rm.mv == last_best_rootmove.mv) { td.root_moves.remove(pos); td.root_moves.insert(0, last_best_rootmove.clone()); + td.root_moves[0].upperbound = false; + td.root_moves[0].lowerbound = false; + } else if is_aborted_loss { + td.root_moves[0].lowerbound = true; } - } else { + } else if td.shared.status.get() != Status::STOPPED { last_best_rootmove = td.root_moves[0].clone(); } + if report == Report::Full + && !(is_loss(td.root_moves[0].display_score) && td.shared.status.get() == Status::STOPPED) + && (td.shared.status.get() == Status::STOPPED + || td.pv_index + 1 == td.multi_pv + || td.shared.nodes.aggregate() > 10_000_000) + { + td.print_uci_info(depth); + } + if td.shared.status.get() == Status::STOPPED { break; }