- // Are all pawns on the 'a' file?
- if((pawns & ~FileABB) == EmptyBoardBB) {
- // Does the defending king block the pawns?
- Square ksq = pos.king_square(weakerSide);
- if(square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1)
- return ScaleFactor(0);
- else if(square_file(ksq) == FILE_A &&
- (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB)
- return ScaleFactor(0);
- else
- return SCALE_FACTOR_NONE;
- }
- // Are all pawns on the 'h' file?
- else if((pawns & ~FileHBB) == EmptyBoardBB) {
- // Does the defending king block the pawns?
- Square ksq = pos.king_square(weakerSide);
- if(square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1)
- return ScaleFactor(0);
- else if(square_file(ksq) == FILE_H &&
- (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB)
- return ScaleFactor(0);
- else
+ // If all pawns are ahead of the king, on a single rook file and
+ // the king is within one file of the pawns, it's a draw.
+ if ( !(pawns & ~forward_ranks_bb(weakSide, ksq))
+ && !((pawns & ~FileABB) && (pawns & ~FileHBB))
+ && distance<File>(ksq, lsb(pawns)) <= 1)
+ return SCALE_FACTOR_DRAW;
+
+ return SCALE_FACTOR_NONE;
+}
+
+
+/// KBP vs KB. There are two rules: 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. If the two bishops have opposite color,
+/// it's almost always a draw.
+template<>
+ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
+
+ assert(verify_material(pos, strongSide, BishopValueMg, 1));
+ assert(verify_material(pos, weakSide, BishopValueMg, 0));
+
+ Square pawnSq = pos.square<PAWN>(strongSide);
+ Square strongBishopSq = pos.square<BISHOP>(strongSide);
+ Square weakBishopSq = pos.square<BISHOP>(weakSide);
+ Square weakKingSq = pos.square<KING>(weakSide);
+
+ // Case 1: Defending king blocks the pawn, and cannot be driven away
+ if ( file_of(weakKingSq) == file_of(pawnSq)
+ && relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
+ && ( opposite_colors(weakKingSq, strongBishopSq)
+ || relative_rank(strongSide, weakKingSq) <= RANK_6))
+ return SCALE_FACTOR_DRAW;
+
+ // Case 2: Opposite colored bishops
+ if (opposite_colors(strongBishopSq, weakBishopSq))
+ return SCALE_FACTOR_DRAW;
+
+ return SCALE_FACTOR_NONE;
+}
+
+
+/// KBPP vs KB. It detects a few basic draws with opposite-colored bishops
+template<>
+ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
+
+ assert(verify_material(pos, strongSide, BishopValueMg, 2));
+ assert(verify_material(pos, weakSide, BishopValueMg, 0));
+
+ Square wbsq = pos.square<BISHOP>(strongSide);
+ Square bbsq = pos.square<BISHOP>(weakSide);
+
+ if (!opposite_colors(wbsq, bbsq))