*/
#include <cassert>
+#include <algorithm>
#include "bitcount.h"
#include "endgame.h"
/// attacking side a bonus for driving the defending king towards the edge
/// of the board, and for keeping the distance between the two kings small.
template<>
-Value Endgame<KXK>::apply(const Position& pos) const {
+Value Endgame<KXK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
/// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
/// defending king towards a corner square of the right color.
template<>
-Value Endgame<KBNK>::apply(const Position& pos) const {
+Value Endgame<KBNK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
// kbnk_mate_table() tries to drive toward corners A1 or H8,
// if we have a bishop that cannot reach the above squares we
// mirror the kings so to drive enemy toward corners A8 or H1.
- if (opposite_color_squares(bishopSquare, SQ_A1))
+ if (opposite_colors(bishopSquare, SQ_A1))
{
winnerKSq = mirror(winnerKSq);
loserKSq = mirror(loserKSq);
/// KP vs K. This endgame is evaluated with the help of a bitbase.
template<>
-Value Endgame<KPK>::apply(const Position& pos) const {
+Value Endgame<KPK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
/// far advanced with support of the king, while the attacking king is far
/// away.
template<>
-Value Endgame<KRKP>::apply(const Position& pos) const {
+Value Endgame<KRKP>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.piece_count(strongerSide, PAWN) == 0);
/// KR vs KB. This is very simple, and always returns drawish scores. The
/// score is slightly bigger when the defending king is close to the edge.
template<>
-Value Endgame<KRKB>::apply(const Position& pos) const {
+Value Endgame<KRKB>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.piece_count(strongerSide, PAWN) == 0);
/// KR vs KN. The attacking side has slightly better winning chances than
/// in KR vs KB, particularly if the king and the knight are far apart.
template<>
-Value Endgame<KRKN>::apply(const Position& pos) const {
+Value Endgame<KRKN>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.piece_count(strongerSide, PAWN) == 0);
/// for the defending side in the search, this is usually sufficient to be
/// able to win KQ vs KR.
template<>
-Value Endgame<KQKR>::apply(const Position& pos) const {
+Value Endgame<KQKR>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
assert(pos.piece_count(strongerSide, PAWN) == 0);
}
template<>
-Value Endgame<KBBKN>::apply(const Position& pos) const {
+Value Endgame<KBBKN>::operator()(const Position& pos) const {
assert(pos.piece_count(strongerSide, BISHOP) == 2);
assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame);
assert(pos.piece_count(weakerSide, KNIGHT) == 1);
assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
- assert(pos.pieces(PAWN) == EmptyBoardBB);
+ assert(!pos.pieces(PAWN));
Value result = BishopValueEndgame;
Square wksq = pos.king_square(strongerSide);
/// 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>::apply(const Position&) const {
+Value Endgame<KmmKm>::operator()(const Position&) const {
return VALUE_DRAW;
}
template<>
-Value Endgame<KNNK>::apply(const Position&) const {
+Value Endgame<KNNK>::operator()(const Position&) const {
return VALUE_DRAW;
}
/// returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
/// will be used.
template<>
-ScaleFactor Endgame<KBPsK>::apply(const Position& pos) const {
+ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.piece_count(strongerSide, BISHOP) == 1);
// All pawns are on a single rook file ?
if ( (pawnFile == FILE_A || pawnFile == FILE_H)
- && (pawns & ~file_bb(pawnFile)) == EmptyBoardBB)
+ && !(pawns & ~file_bb(pawnFile)))
{
Square bishopSq = pos.piece_list(strongerSide, BISHOP)[0];
Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8));
Square kingSq = pos.king_square(weakerSide);
- if ( opposite_color_squares(queeningSq, bishopSq)
+ if ( opposite_colors(queeningSq, bishopSq)
&& abs(file_of(kingSq) - pawnFile) <= 1)
{
// The bishop has the wrong color, and the defending king is on the
Rank rank;
if (strongerSide == WHITE)
{
- for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {}
+ 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) == EmptyBoardBB; rank++) {}
+ 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);
}
/// It tests for fortress draws with a rook on the third rank defended by
/// a pawn.
template<>
-ScaleFactor Endgame<KQKRPs>::apply(const Position& pos) const {
+ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
assert(pos.piece_count(strongerSide, QUEEN) == 1);
/// It would also be nice to rewrite the actual code for this function,
/// which is mostly copied from Glaurung 1.x, and not very pretty.
template<>
-ScaleFactor Endgame<KRPKR>::apply(const Position& pos) const {
+ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.piece_count(strongerSide, PAWN) == 1);
/// single pattern: If the stronger side has no pawns and the defending king
/// is actively placed, the position is drawish.
template<>
-ScaleFactor Endgame<KRPPKRP>::apply(const Position& pos) const {
+ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.piece_count(strongerSide, PAWN) == 2);
|| pos.pawn_is_passed(strongerSide, wpsq2))
return SCALE_FACTOR_NONE;
- Rank r = Max(relative_rank(strongerSide, wpsq1), relative_rank(strongerSide, wpsq2));
+ Rank r = std::max(relative_rank(strongerSide, wpsq1), relative_rank(strongerSide, wpsq2));
if ( file_distance(bksq, wpsq1) <= 1
&& file_distance(bksq, wpsq2) <= 1
/// against king. There is just a single rule here: If all pawns are on
/// the same rook file and are blocked by the defending king, it's a draw.
template<>
-ScaleFactor Endgame<KPsK>::apply(const Position& pos) const {
+ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
assert(pos.piece_count(strongerSide, PAWN) >= 2);
Bitboard pawns = pos.pieces(PAWN, strongerSide);
// Are all pawns on the 'a' file?
- if ((pawns & ~FileABB) == EmptyBoardBB)
+ if (!(pawns & ~FileABB))
{
// Does the defending king block the pawns?
if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1
|| ( file_of(ksq) == FILE_A
- && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB))
+ && !in_front_bb(strongerSide, ksq) & pawns))
return SCALE_FACTOR_ZERO;
}
// Are all pawns on the 'h' file?
- else if ((pawns & ~FileHBB) == EmptyBoardBB)
+ else if (!(pawns & ~FileHBB))
{
// Does the defending king block the pawns?
if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1
|| ( file_of(ksq) == FILE_H
- && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB))
+ && !in_front_bb(strongerSide, ksq) & pawns))
return SCALE_FACTOR_ZERO;
}
return SCALE_FACTOR_NONE;
/// it's a draw. If the two bishops have opposite color, it's almost always
/// a draw.
template<>
-ScaleFactor Endgame<KBPKB>::apply(const Position& pos) const {
+ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.piece_count(strongerSide, BISHOP) == 1);
// Case 1: Defending king blocks the pawn, and cannot be driven away
if ( file_of(weakerKingSq) == file_of(pawnSq)
&& relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
- && ( opposite_color_squares(weakerKingSq, strongerBishopSq)
+ && ( opposite_colors(weakerKingSq, strongerBishopSq)
|| relative_rank(strongerSide, weakerKingSq) <= RANK_6))
return SCALE_FACTOR_ZERO;
// Case 2: Opposite colored bishops
- if (opposite_color_squares(strongerBishopSq, weakerBishopSq))
+ if (opposite_colors(strongerBishopSq, weakerBishopSq))
{
// We assume that the position is drawn in the following three situations:
//
/// KBPPKBScalingFunction scales KBPP vs KB endgames. It detects a few basic
/// draws with opposite-colored bishops.
template<>
-ScaleFactor Endgame<KBPPKB>::apply(const Position& pos) const {
+ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.piece_count(strongerSide, BISHOP) == 1);
Square wbsq = pos.piece_list(strongerSide, BISHOP)[0];
Square bbsq = pos.piece_list(weakerSide, BISHOP)[0];
- if (!opposite_color_squares(wbsq, bbsq))
+ if (!opposite_colors(wbsq, bbsq))
return SCALE_FACTOR_NONE;
Square ksq = pos.king_square(weakerSide);
// some square in the frontmost pawn's path.
if ( file_of(ksq) == file_of(blockSq1)
&& relative_rank(strongerSide, ksq) >= relative_rank(strongerSide, blockSq1)
- && opposite_color_squares(ksq, wbsq))
+ && opposite_colors(ksq, wbsq))
return SCALE_FACTOR_ZERO;
else
return SCALE_FACTOR_NONE;
// in front of the frontmost pawn's path, and the square diagonally behind
// this square on the file of the other pawn.
if ( ksq == blockSq1
- && opposite_color_squares(ksq, wbsq)
+ && opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq2
|| (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(BISHOP, weakerSide))
|| abs(r1 - r2) >= 2))
return SCALE_FACTOR_ZERO;
else if ( ksq == blockSq2
- && opposite_color_squares(ksq, wbsq)
+ && opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq1
|| (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(BISHOP, weakerSide))))
return SCALE_FACTOR_ZERO;
/// square of the king is not of the same color as the stronger side's bishop,
/// it's a draw.
template<>
-ScaleFactor Endgame<KBPKN>::apply(const Position& pos) const {
+ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.piece_count(strongerSide, BISHOP) == 1);
if ( file_of(weakerKingSq) == file_of(pawnSq)
&& relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
- && ( opposite_color_squares(weakerKingSq, strongerBishopSq)
+ && ( opposite_colors(weakerKingSq, strongerBishopSq)
|| relative_rank(strongerSide, weakerKingSq) <= RANK_6))
return SCALE_FACTOR_ZERO;
/// 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>::apply(const Position& pos) const {
+ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame);
assert(pos.piece_count(strongerSide, KNIGHT) == 1);
/// advanced and not on a rook file; in this case it is often possible to win
/// (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
template<>
-ScaleFactor Endgame<KPKP>::apply(const Position& pos) const {
+ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);