#include "endgame.h"
#include "movegen.h"
-using std::string;
-
namespace {
// Used to drive the king towards the edge of the board
add<KQKR>("KQKR");
add<KNNKP>("KNNKP");
- add<KNPK>("KNPK");
- add<KNPKB>("KNPKB");
add<KRPKR>("KRPKR");
add<KRPKB>("KRPKB");
add<KBPKB>("KBPKB");
// No assertions about the material of weakSide, because we want draws to
// be detected even when the weaker side has some pawns.
- Bitboard strongpawns = pos.pieces(strongSide, PAWN);
- Bitboard allpawns = pos.pieces(PAWN);
+ Bitboard strongPawns = pos.pieces(strongSide, PAWN);
+ Bitboard allPawns = pos.pieces(PAWN);
// All strongSide pawns are on a single rook file?
- if (!(strongpawns & ~FileABB) || !(strongpawns & ~FileHBB))
+ if (!(strongPawns & ~FileABB) || !(strongPawns & ~FileHBB))
{
Square bishopSq = pos.square<BISHOP>(strongSide);
- Square queeningSq = relative_square(strongSide, make_square(file_of(lsb(strongpawns)), RANK_8));
- Square weakkingSq = pos.square<KING>(weakSide);
+ Square queeningSq = relative_square(strongSide, make_square(file_of(lsb(strongPawns)), RANK_8));
+ Square weakKingSq = pos.square<KING>(weakSide);
if ( opposite_colors(queeningSq, bishopSq)
- && distance(queeningSq, weakkingSq) <= 1)
+ && distance(queeningSq, weakKingSq) <= 1)
return SCALE_FACTOR_DRAW;
}
// If all the pawns are on the same B or G file, then it's potentially a draw
- if ((!(allpawns & ~FileBBB) || !(allpawns & ~FileGBB))
+ if ((!(allPawns & ~FileBBB) || !(allPawns & ~FileGBB))
&& pos.non_pawn_material(weakSide) == 0
&& pos.count<PAWN>(weakSide) >= 1)
{
// There's potential for a draw if our pawn is blocked on the 7th rank,
// the bishop cannot attack it or they only have one pawn left
if ( relative_rank(strongSide, weakPawnSq) == RANK_7
- && (strongpawns & (weakPawnSq + pawn_push(weakSide)))
- && (opposite_colors(bishopSq, weakPawnSq) || !more_than_one(strongpawns)))
+ && (strongPawns & (weakPawnSq + pawn_push(weakSide)))
+ && (opposite_colors(bishopSq, weakPawnSq) || !more_than_one(strongPawns)))
{
int strongKingDist = distance(weakPawnSq, strongKingSq);
int weakKingDist = distance(weakPawnSq, weakKingSq);
Square ksq = pos.square<KING>(weakSide);
Bitboard pawns = pos.pieces(strongSide, PAWN);
- // 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)
+ // If all pawns are ahead of the king on a single rook file, it's a draw.
+ if (!((pawns & ~FileABB) || (pawns & ~FileHBB)) &&
+ !(pawns & ~passed_pawn_span(weakSide, ksq)))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
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)
+ if ( (forward_file_bb(strongSide, pawnSq) & weakKingSq)
&& ( opposite_colors(weakKingSq, strongBishopSq)
|| relative_rank(strongSide, weakKingSq) <= RANK_6))
return SCALE_FACTOR_DRAW;
}
-/// KNP 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.
-template<>
-ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
-
- assert(verify_material(pos, strongSide, KnightValueMg, 1));
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
-
- // Assume strongSide is white and the pawn is on files A-D
- Square pawnSq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
- Square weakKingSq = normalize(pos, strongSide, pos.square<KING>(weakSide));
-
- if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
- return SCALE_FACTOR_DRAW;
-
- return SCALE_FACTOR_NONE;
-}
-
-
-/// KNP vs KB. If knight can block bishop from taking pawn, it's a win.
-/// Otherwise the position is drawn.
-template<>
-ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {
-
- assert(verify_material(pos, strongSide, KnightValueMg, 1));
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
-
- Square pawnSq = pos.square<PAWN>(strongSide);
- Square bishopSq = pos.square<BISHOP>(weakSide);
- Square weakKingSq = pos.square<KING>(weakSide);
-
- // King needs to get close to promoting pawn to prevent knight from blocking.
- // Rules for this are very tricky, so just approximate.
- if (forward_file_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
- return ScaleFactor(distance(weakKingSq, pawnSq));
-
- return SCALE_FACTOR_NONE;
-}
-
-
/// KP vs KP. 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, it probably
/// has at least a draw with the pawn as well. The exception is when the stronger