Browse files

Add draw detection for KBPPKNP endgames

  • Loading branch information...
1 parent dbe5e28 commit c91bfb1349803a27252fa636d2137c689230fd37 @glinscott committed Mar 26, 2012
Showing with 55 additions and 8 deletions.
  1. +54 −8 src/endgame.cpp
  2. +1 −0 src/endgame.h
View
62 src/endgame.cpp
@@ -103,6 +103,7 @@ Endgames::Endgames() {
add<KRPKR>("KRPKR");
add<KBPKB>("KBPKB");
add<KBPKN>("KBPKN");
+ add<KBPPKNP>("KBPPKNP");
add<KBPPKB>("KBPPKB");
add<KRPPKRP>("KRPPKRP");
}
@@ -799,8 +800,20 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
}
}
+bool KingDefendsInBNEndgame(const Position &pos, const Color strongerSide, const Color weakerSide, const Square pawnSq) {
+ Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP)[0];
+ Square weakerKingSq = pos.king_square(weakerSide);
+
+ if ( file_of(weakerKingSq) == file_of(pawnSq)
+ && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
+ && ( opposite_colors(weakerKingSq, strongerBishopSq)
+ || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
+ return true;
+
+ return false;
+}
-/// K, bisop and a pawn vs K and knight. There is a single rule: If the defending
+/// K, bishop and a pawn vs K and knight. There is a single rule: If the defending
/// king is somewhere along the path of the pawn, and the square of the king is
/// not of the same color as the stronger side's bishop, it's a draw.
template<>
@@ -814,19 +827,52 @@ ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
assert(pos.piece_count(weakerSide, PAWN) == 0);
Square pawnSq = pos.piece_list(strongerSide, PAWN)[0];
+
+ return KingDefendsInBNEndgame(pos, strongerSide, weakerSide, pawnSq) ? SCALE_FACTOR_DRAW
+ : SCALE_FACTOR_NONE;
+}
+
+// K, bishop and two pawns vs K, knight and pawn. Uses the same rule as KBPKN if the extra
+// pawns are on the same file, and the enemy pawn is not on the same color square as the
+// bishop.
+template<>
+ScaleFactor Endgame<KBPPKNP>::operator()(const Position& pos) const {
+
+ assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
+ assert(pos.piece_count(strongerSide, BISHOP) == 1);
+ assert(pos.piece_count(strongerSide, PAWN) == 2);
+ assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
+ assert(pos.piece_count(weakerSide, KNIGHT) == 1);
+ assert(pos.piece_count(weakerSide, PAWN) == 1);
+
+ Square weakPawnSq = pos.piece_list(weakerSide, PAWN)[0];
+ Square psq1 = pos.piece_list(strongerSide, PAWN)[0];
+ Square psq2 = pos.piece_list(strongerSide, PAWN)[1];
Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP)[0];
- Square weakerKingSq = pos.king_square(weakerSide);
+ Square passedSq, notPassedSq;
+ int passedCount = 0;
- if ( file_of(weakerKingSq) == file_of(pawnSq)
- && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
- && ( opposite_colors(weakerKingSq, strongerBishopSq)
- || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
- return SCALE_FACTOR_DRAW;
+ if (pos.pawn_is_passed(strongerSide, psq1)) {
+ passedCount++;
+ passedSq = psq1;
+ notPassedSq = psq2;
+ }
+ if (pos.pawn_is_passed(strongerSide, psq2)) {
+ passedCount++;
+ passedSq = psq2;
+ notPassedSq = psq1;
+ }
+ if (passedCount != 1)
+ return SCALE_FACTOR_NONE;
+ if ( file_of(notPassedSq) == file_of(weakPawnSq)
+ && opposite_colors(strongerBishopSq, weakPawnSq)
+ && KingDefendsInBNEndgame(pos, strongerSide, weakerSide, passedSq))
+ return ScaleFactor(16);
+
return SCALE_FACTOR_NONE;
}
-
/// K, knight and a pawn vs K. There is a single rule: If the pawn is a rook pawn
/// on the 7th rank and the defending king prevents the pawn from advancing, the
/// position is drawn.
View
1 src/endgame.h
@@ -56,6 +56,7 @@ enum EndgameType {
KBPKB, // KBP vs KB
KBPPKB, // KBPP vs KB
KBPKN, // KBP vs KN
+ KBPPKNP, // KBPP vs KNP
KNPK, // KNP vs K
KPKP // KP vs KP
};

0 comments on commit c91bfb1

Please sign in to comment.