Improve endgame KBN vs K (#1877)
authorprotonspring <mike@whiteley.org>
Mon, 17 Dec 2018 17:25:25 +0000 (10:25 -0700)
committerStéphane Nicolet <cassio@free.fr>
Mon, 24 Dec 2018 09:44:38 +0000 (10:44 +0100)
Even when playing without endgame table bases, this particular endgame should
be a win 100% of the time when Stockfish is given a KRBK position, assuming
there are enough moves remaining in the FEN to finish the game without hitting
the 50 move rule.

PROBLEM: The issue with master here is that the PushClose difference per square
is 20, however, the difference in squares for the PushToCorners array is usually
less. Thus, the engine prefers to move the kings closer together rather than pushing
the weak king to the correct corner.

What happens is if the weak king is in a safe corner, SF still prefers pushing the
kings together. Occasionally, the strong king traps the weak king in the safe corner.
It takes a while for SF to figure it out, but often draws the game by the 50 move rule
(on shorter time controls).

This patch increases the PushToCorners values to correct this problem. We also added
an assert to catch any overflow problem if anybody would want to increase the array
values again in the future.

It was tested in a couple of matches starting with random KRBK positions and showed
increased winning rates, see https://github.com/official-stockfish/Stockfish/pull/1877

No functional change

src/endgame.cpp

index 2ad1117b41efe3e061a3a8eb9f63524fbbc27933..66ee54d846044c90d03ec4dcaf9699e07aae13ee 100644 (file)
@@ -45,14 +45,14 @@ namespace {
   // Table used to drive the king towards a corner square of the
   // right color in KBN vs K endgames.
   constexpr int PushToCorners[SQUARE_NB] = {
-    200, 190, 180, 170, 160, 150, 140, 130,
-    190, 180, 170, 160, 150, 140, 130, 140,
-    180, 170, 155, 140, 140, 125, 140, 150,
-    170, 160, 140, 120, 110, 140, 150, 160,
-    160, 150, 140, 110, 120, 140, 160, 170,
-    150, 140, 125, 140, 140, 155, 170, 180,
-    140, 130, 140, 150, 160, 170, 180, 190,
-    130, 140, 150, 160, 170, 180, 190, 200
+     6400, 6080, 5760, 5440, 5120, 4800, 4480, 4160,
+     6080, 5760, 5440, 5120, 4800, 4480, 4160, 4480,
+     5760, 5440, 4960, 4480, 4480, 4000, 4480, 4800,
+     5440, 5120, 4480, 3840, 3520, 4480, 4800, 5120,
+     5120, 4800, 4480, 3520, 3840, 4480, 5120, 5440,
+     4800, 4480, 4000, 4480, 4480, 4960, 5440, 5760,
+     4480, 4160, 4480, 4800, 5120, 5440, 5760, 6080,
+     4160, 4480, 4800, 5120, 5440, 5760, 6080, 6400
   };
 
   // Tables used to drive a piece towards or away from another piece
@@ -138,6 +138,7 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
                 + PushClose[distance(winnerKSq, loserKSq)]
                 + PushToCorners[opposite_colors(bishopSq, SQ_A1) ? ~loserKSq : loserKSq];
 
+  assert(abs(result) < VALUE_MATE_IN_MAX_PLY);
   return strongSide == pos.side_to_move() ? result : -result;
 }