X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fendgame.cpp;h=c0d317b779234f4ae5cca323c221ffb5be8c4c93;hp=20d175bab916fe150172bb63f2cabd724499b597;hb=55df3fa2d7631ed67e46f9433aa7f3a71c18e5e7;hpb=4b7dbb3922a0c563d74be4474b0cbdc1b00b4595 diff --git a/src/endgame.cpp b/src/endgame.cpp index 20d175ba..c0d317b7 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -31,7 +31,7 @@ namespace { // Table used to drive the defending king towards the edge of the board // in KX vs K and KQ vs KR endgames. - const int MateTable[64] = { + const int MateTable[SQUARE_NB] = { 100, 90, 80, 70, 70, 80, 90, 100, 90, 70, 60, 50, 50, 60, 70, 90, 80, 60, 40, 30, 30, 40, 60, 80, @@ -44,7 +44,7 @@ namespace { // Table used to drive the defending king towards a corner square of the // right color in KBN vs K endgames. - const int KBNKMateTable[64] = { + const int KBNKMateTable[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, @@ -95,6 +95,7 @@ Endgames::Endgames() { add("KRKP"); add("KRKB"); add("KRKN"); + add("KQKP"); add("KQKR"); add("KBBKN"); @@ -169,12 +170,12 @@ Value Endgame::operator()(const Position& pos) const { Square winnerKSq = pos.king_square(strongerSide); Square loserKSq = pos.king_square(weakerSide); - Square bishopSquare = pos.piece_list(strongerSide, BISHOP)[0]; + Square bishopSq = pos.piece_list(strongerSide, BISHOP)[0]; // kbnk_mate_table() tries to drive toward corners A1 or H8, // if we have a bishop that cannot reach the above squares we // mirror the kings so to drive enemy toward corners A8 or H1. - if (opposite_colors(bishopSquare, SQ_A1)) + if (opposite_colors(bishopSq, SQ_A1)) { winnerKSq = mirror(winnerKSq); loserKSq = mirror(loserKSq); @@ -326,6 +327,37 @@ Value Endgame::operator()(const Position& pos) const { } +/// KQ vs KP. In general, a win for the stronger side, however, there are a few +/// important exceptions. Pawn on 7th rank, A,C,F or H file, with king next can +/// be a draw, so we scale down to distance between kings only. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(pos.non_pawn_material(strongerSide) == QueenValueMg); + assert(pos.piece_count(strongerSide, PAWN) == 0); + assert(pos.non_pawn_material(weakerSide) == 0); + assert(pos.piece_count(weakerSide, PAWN) == 1); + + Square winnerKSq = pos.king_square(strongerSide); + Square loserKSq = pos.king_square(weakerSide); + Square pawnSq = pos.piece_list(weakerSide, PAWN)[0]; + + Value result = QueenValueEg + - PawnValueEg + + DistanceBonus[square_distance(winnerKSq, loserKSq)]; + + if ( square_distance(loserKSq, pawnSq) == 1 + && relative_rank(weakerSide, pawnSq) == RANK_7) + { + File f = file_of(pawnSq); + + if (f == FILE_A || f == FILE_C || f == FILE_F || f == FILE_H) + result = Value(DistanceBonus[square_distance(winnerKSq, loserKSq)]); + } + return strongerSide == pos.side_to_move() ? result : -result; +} + + /// KQ vs KR. This is almost identical to KX vs K: We give the attacking /// king a bonus for having the kings close together, and for forcing the /// defending king towards the edge. If we also take care to avoid null move