-/// KBPKBScalingFunction scales KBP vs KB endgames. 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.
-
-ScaleFactor KBPKBScalingFunction::apply(const Position &pos) {
- assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
- assert(pos.bishop_count(strongerSide) == 1);
- assert(pos.pawn_count(strongerSide) == 1);
- assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
- assert(pos.bishop_count(weakerSide) == 1);
- assert(pos.pawn_count(weakerSide) == 0);
-
- Square pawnSq = pos.pawn_list(strongerSide, 0);
- Square strongerBishopSq = pos.bishop_list(strongerSide, 0);
- Square weakerBishopSq = pos.bishop_list(weakerSide, 0);
- Square weakerKingSq = pos.king_square(weakerSide);
-
- // Case 1: Defending king blocks the pawn, and cannot be driven away.
- if(square_file(weakerKingSq) == square_file(pawnSq)
- && pawn_rank(strongerSide, pawnSq) < pawn_rank(strongerSide, weakerKingSq)
- && (square_color(weakerKingSq) != square_color(strongerBishopSq)
- || pawn_rank(strongerSide, weakerKingSq) <= RANK_6))
- return ScaleFactor(0);
-
- // Case 2: Opposite colored bishops.
- if(square_color(strongerBishopSq) != square_color(weakerBishopSq)) {
-
- // We assume that the position is drawn in the following three situations:
- //
- // a. The pawn is on rank 5 or further back.
- // b. The defending king is somewhere in the pawn's path.
- // c. The defending bishop attacks some square along the pawn's path,
- // and is at least three squares away from the pawn.
- //
- // These rules are probably not perfect, but in practice they work
- // reasonably well.
-
- if(pawn_rank(strongerSide, pawnSq) <= RANK_5)
- return ScaleFactor(0);
- else {
- Bitboard ray =
- ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S);
- if(ray & pos.kings(weakerSide))
- return ScaleFactor(0);
- if((pos.bishop_attacks(weakerBishopSq) & ray)
- && square_distance(weakerBishopSq, pawnSq) >= 3)
- return ScaleFactor(0);
- }
- }