From 848fae6c1630f6833696f4e4fbb6a7dc047196b7 Mon Sep 17 00:00:00 2001 From: John Doknjas <32089502+johndoknjas@users.noreply.github.com> Date: Sun, 14 Sep 2025 08:14:22 -0700 Subject: [PATCH] Fix antichess K vs N endgame evaluation (#909) --- src/endgame.cpp | 30 ++++++++++++++++++++---------- 1 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/endgame.cpp b/src/endgame.cpp index 6da7d67..6a8247d 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -1033,7 +1033,7 @@ Value Endgame::operator()(const Position& pos) const { } -/// K vs N. The king usally wins, but there are a few exceptions. +/// K vs N. The king usually wins, but there are a few exceptions. template<> Value Endgame::operator()(const Position& pos) const { @@ -1041,16 +1041,26 @@ Value Endgame::operator()(const Position& pos) const { Square KSq = pos.square(strongSide); Square NSq = pos.square(weakSide); + Bitboard kingAttacks = attacks_bb(KSq) & pos.board_bb(); + Bitboard knightAttacks = attacks_bb(NSq) & pos.board_bb(); + bool strongSideToMove = pos.side_to_move() == strongSide; + + // Loss in 1 play + if (strongSideToMove ? kingAttacks & NSq : knightAttacks & KSq) + return VALUE_TB_LOSS_IN_MAX_PLY + 1; + // Win in 2 ply + if (kingAttacks & knightAttacks) + return VALUE_TB_WIN_IN_MAX_PLY - 2; + // Loss in 3 ply + if (strongSideToMove ? knightAttacks & KSq : kingAttacks & NSq) + return VALUE_TB_LOSS_IN_MAX_PLY + 3; + + Value result = Value(push_to_edge(NSq, pos)) - push_to_edge(KSq, pos); + // The king usually wins, but scenarios with king on the edge are more complicated + if (!(KSq & (FileABB | FileHBB | Rank1BB | Rank8BB))) + result += VALUE_KNOWN_WIN; - // wins for knight - if (pos.side_to_move() == strongSide && (attacks_bb(NSq) & KSq)) - return -VALUE_KNOWN_WIN; - if (pos.side_to_move() == weakSide && (attacks_bb(NSq) & attacks_bb(KSq))) - return VALUE_KNOWN_WIN; - - Value result = VALUE_KNOWN_WIN + push_to_edge(NSq, pos) - push_to_edge(KSq, pos); - - return strongSide == pos.side_to_move() ? result : -result; + return strongSideToMove ? result : -result; } /// N vs N. The side to move always wins/loses if the knights are on -- 1.7.0.4