X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fendgame.cpp;h=efc41a98844799be346293c83e103da236b32a48;hp=55a4caba593a43c77bf3d3d2343f239f8b9a0301;hb=82ad9ce9cfb0eff33f1d781f329f7c5dc0b277eb;hpb=cf5d683408a2ef8a1c80be9bf7d6790a38b16277 diff --git a/src/endgame.cpp b/src/endgame.cpp index 55a4caba..efc41a98 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -18,7 +18,6 @@ along with this program. If not, see . */ -#include #include #include "bitboard.h" @@ -45,14 +44,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 @@ -77,10 +76,7 @@ namespace { if (file_of(pos.square(strongSide)) >= FILE_E) sq = Square(sq ^ 7); // Mirror SQ_H1 -> SQ_A1 - if (strongSide == BLACK) - sq = ~sq; - - return sq; + return strongSide == WHITE ? sq : ~sq; } } // namespace @@ -120,7 +116,7 @@ Value Endgame::operator()(const Position& pos) const { /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the -/// defending king towards a corner square of the right color. +/// defending king towards a corner square that our bishop attacks. template<> Value Endgame::operator()(const Position& pos) const { @@ -131,19 +127,14 @@ Value Endgame::operator()(const Position& pos) const { Square loserKSq = pos.square(weakSide); Square bishopSq = pos.square(strongSide); - // kbnk_mate_table() tries to drive toward corners A1 or H8. If we have a - // bishop that cannot reach the above squares, we flip the kings in order - // to drive the enemy toward corners A8 or H1. - if (opposite_colors(bishopSq, SQ_A1)) - { - winnerKSq = ~winnerKSq; - loserKSq = ~loserKSq; - } + // If our Bishop does not attack A1/H8, we flip the enemy king square + // to drive to opposite corners (A8/H1). Value result = VALUE_KNOWN_WIN + PushClose[distance(winnerKSq, loserKSq)] - + PushToCorners[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; } @@ -291,6 +282,21 @@ Value Endgame::operator()(const Position& pos) const { } +/// KNN vs KP. Simply push the opposing king to the corner +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, 2 * KnightValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 1)); + + Value result = 2 * KnightValueEg + - PawnValueEg + + PushToEdges[pos.square(weakSide)]; + + return strongSide == pos.side_to_move() ? result : -result; +} + + /// Some cases of trivial draws template<> Value Endgame::operator()(const Position&) const { return VALUE_DRAW; } @@ -729,6 +735,9 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { + assert(verify_material(pos, strongSide, KnightValueMg, 1)); + assert(verify_material(pos, weakSide, BishopValueMg, 0)); + Square pawnSq = pos.square(strongSide); Square bishopSq = pos.square(weakSide); Square weakKingSq = pos.square(weakSide);