diff --git a/src/endgame.cpp b/src/endgame.cpp index 34d9b484..52786cdb 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -100,6 +100,7 @@ Endgames::Endgames() { add("KBBKN"); add("KNPK"); + add("KNPKB"); add("KRPKR"); add("KBPKB"); add("KBPKN"); @@ -904,6 +905,24 @@ ScaleFactor Endgame::operator()(const Position& pos) const { } +/// K, knight and a pawn vs K and bishop. If knight can block bishop from taking +/// pawn, it's a win. Otherwise, drawn. +template<> +ScaleFactor Endgame::operator()(const Position& pos) const { + + Square pawnSq = pos.piece_list(strongerSide, PAWN)[0]; + Square bishopSq = pos.piece_list(weakerSide, BISHOP)[0]; + Square weakerKingSq = pos.king_square(weakerSide); + + // King needs to get close to promoting pawn to prevent knight from blocking. + // Rules for this are very tricky, so just approximate. + if (forward_bb(strongerSide, pawnSq) & pos.attacks_from(bishopSq)) + return ScaleFactor(square_distance(weakerKingSq, pawnSq)); + + return SCALE_FACTOR_NONE; +} + + /// K and a pawn vs K and a pawn. This is done by removing the weakest side's /// pawn and probing the KP vs K bitbase: If the weakest side has a draw without /// the pawn, she probably has at least a draw with the pawn as well. The exception diff --git a/src/endgame.h b/src/endgame.h index c603d267..b560c798 100644 --- a/src/endgame.h +++ b/src/endgame.h @@ -58,6 +58,7 @@ enum EndgameType { KBPPKB, // KBPP vs KB KBPKN, // KBP vs KN KNPK, // KNP vs K + KNPKB, // KNP vs KB KPKP // KP vs KP };