assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
assert(!pos.count<PAWN>(weakerSide));
+ assert(!pos.checkers()); // Eval is never called when in check
// Stalemate detection with lone king
- if ( pos.side_to_move() == weakerSide
- && !pos.checkers()
- && !MoveList<LEGAL>(pos).size()) {
- return VALUE_DRAW;
- }
+ if (pos.side_to_move() == weakerSide && !MoveList<LEGAL>(pos).size())
+ return VALUE_DRAW;
Square winnerKSq = pos.king_square(strongerSide);
Square loserKSq = pos.king_square(weakerSide);
if ( pos.count<QUEEN>(strongerSide)
|| pos.count<ROOK>(strongerSide)
- || pos.bishop_pair(strongerSide)) {
- result += VALUE_KNOWN_WIN;
- }
+ || pos.bishop_pair(strongerSide))
+ result += VALUE_KNOWN_WIN;
return strongerSide == pos.side_to_move() ? result : -result;
}
}
-/// K and two minors vs K and one or two minors or K and two knights against
-/// king alone are always draw.
-template<>
-Value Endgame<KmmKm>::operator()(const Position&) const {
- return VALUE_DRAW;
-}
+/// Some cases of trivial draws
+template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
+template<> Value Endgame<KmmKm>::operator()(const Position&) const { return VALUE_DRAW; }
-template<>
-Value Endgame<KNNK>::operator()(const Position&) const {
- return VALUE_DRAW;
-}
/// K, bishop and one or more pawns vs K. It checks for draws with rook pawns and
/// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
// The bishop has the wrong color, and the defending king is on the
// file of the pawn(s) or the adjacent file. Find the rank of the
// frontmost pawn.
- Rank rank;
- if (strongerSide == WHITE)
- {
- for (rank = RANK_7; !(rank_bb(rank) & pawns); rank--) {}
- assert(rank >= RANK_2 && rank <= RANK_7);
- }
- else
- {
- for (rank = RANK_2; !(rank_bb(rank) & pawns); rank++) {}
- rank = Rank(rank ^ 7); // HACK to get the relative rank
- assert(rank >= RANK_2 && rank <= RANK_7);
- }
+ Square pawnSq = frontmost_sq(strongerSide, pawns);
+
// If the defending king has distance 1 to the promotion square or
// is placed somewhere in front of the pawn, it's a draw.
if ( square_distance(kingSq, queeningSq) <= 1
- || relative_rank(strongerSide, kingSq) >= rank)
+ || relative_rank(weakerSide, kingSq) <= relative_rank(weakerSide, pawnSq))
return SCALE_FACTOR_DRAW;
}
}
&& pos.non_pawn_material(weakerSide) == 0
&& pos.count<PAWN>(weakerSide) >= 1)
{
- // Get weaker pawn closest to opponent's queening square
- Bitboard wkPawns = pos.pieces(weakerSide, PAWN);
- Square weakerPawnSq = strongerSide == WHITE ? msb(wkPawns) : lsb(wkPawns);
+ // Get weakerSide pawn that is closest to home rank
+ Square weakerPawnSq = backmost_sq(weakerSide, pos.pieces(weakerSide, PAWN));
Square strongerKingSq = pos.king_square(strongerSide);
Square weakerKingSq = pos.king_square(weakerSide);