X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fendgame.cpp;h=c0d317b779234f4ae5cca323c221ffb5be8c4c93;hp=dbf10582ac8964fdf3f047d6d93c54b202274c5d;hb=cee6336515d5772370d061aa54cf3ec9f9a0d3c2;hpb=b84af67f4c88f3e3f7b61bf2035475f79fb3e62e diff --git a/src/endgame.cpp b/src/endgame.cpp index dbf10582..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 @@ -648,7 +680,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1 || ( file_of(ksq) == FILE_A - && !in_front_bb(strongerSide, ksq) & pawns)) + && !(in_front_bb(strongerSide, ksq) & pawns))) return SCALE_FACTOR_DRAW; } // Are all pawns on the 'h' file? @@ -657,7 +689,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1 || ( file_of(ksq) == FILE_H - && !in_front_bb(strongerSide, ksq) & pawns)) + && !(in_front_bb(strongerSide, ksq) & pawns))) return SCALE_FACTOR_DRAW; } return SCALE_FACTOR_NONE;