/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "endgame.h"
#include "movegen.h"
+namespace Stockfish {
+
namespace {
// Used to drive the king towards the edge of the board
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
- Square strongKing = relative_square(strongSide, pos.square<KING>(strongSide));
- Square weakKing = relative_square(strongSide, pos.square<KING>(weakSide));
- Square strongRook = relative_square(strongSide, pos.square<ROOK>(strongSide));
- Square weakPawn = relative_square(strongSide, pos.square<PAWN>(weakSide));
- Square queeningSquare = make_square(file_of(weakPawn), RANK_1);
+ Square strongKing = pos.square<KING>(strongSide);
+ Square weakKing = pos.square<KING>(weakSide);
+ Square strongRook = pos.square<ROOK>(strongSide);
+ Square weakPawn = pos.square<PAWN>(weakSide);
+ Square queeningSquare = make_square(file_of(weakPawn), relative_rank(weakSide, RANK_8));
Value result;
// If the stronger side's king is in front of the pawn, it's a win
- if (forward_file_bb(WHITE, strongKing) & weakPawn)
+ if (forward_file_bb(strongSide, strongKing) & weakPawn)
result = RookValueEg - distance(strongKing, weakPawn);
// If the weaker side's king is too far from the pawn and the rook,
// If the pawn is far advanced and supported by the defending king,
// the position is drawish
- else if ( rank_of(weakKing) <= RANK_3
+ else if ( relative_rank(strongSide, weakKing) <= RANK_3
&& distance(weakKing, weakPawn) == 1
- && rank_of(strongKing) >= RANK_4
+ && relative_rank(strongSide, strongKing) >= RANK_4
&& distance(strongKing, weakPawn) > 2 + (pos.side_to_move() == strongSide))
result = Value(80) - 8 * distance(strongKing, weakPawn);
else
- result = Value(200) - 8 * ( distance(strongKing, weakPawn + SOUTH)
- - distance(weakKing, weakPawn + SOUTH)
+ result = Value(200) - 8 * ( distance(strongKing, weakPawn + pawn_push(weakSide))
+ - distance(weakKing, weakPawn + pawn_push(weakSide))
- distance(weakPawn, queeningSquare));
return strongSide == pos.side_to_move() ? result : -result;
}
-/// KQ vs KR. This is almost identical to KX vs K: We give the attacking
+/// KQ vs KR. This is almost identical to KX vs K: we give the attacking
/// king a bonus for having the kings close together, and for forcing the
/// defending king towards the edge. If we also take care to avoid null move for
/// the defending side in the search, this is usually sufficient to win KQ vs KR.
/// KNN vs KP. Very drawish, but there are some mate opportunities if we can
-// press the weakSide King to a corner before the pawn advances too much.
+/// press the weakSide King to a corner before the pawn advances too much.
template<>
Value Endgame<KNNKP>::operator()(const Position& pos) const {
Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN));
// 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
+ // the bishop cannot attack it or they only have one pawn left.
if ( relative_rank(strongSide, weakPawn) == RANK_7
&& (strongPawns & (weakPawn + pawn_push(weakSide)))
&& (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns)))
// closer. (I think this rule only fails in practically
// unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
// and positions where qsearch will immediately correct the
- // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w)
+ // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w).
if ( relative_rank(strongSide, weakKing) >= RANK_7
&& weakKingDist <= 2
&& weakKingDist <= strongKingDist)
assert(verify_material(pos, strongSide, RookValueMg, 2));
assert(verify_material(pos, weakSide, RookValueMg, 1));
- Square strongPawn1 = pos.squares<PAWN>(strongSide)[0];
- Square strongPawn2 = pos.squares<PAWN>(strongSide)[1];
+ Square strongPawn1 = lsb(pos.pieces(strongSide, PAWN));
+ Square strongPawn2 = msb(pos.pieces(strongSide, PAWN));
Square weakKing = pos.square<KING>(weakSide);
// Does the stronger side have a passed pawn?
}
-/// K and two or more pawns vs K. There is just a single rule here: If all pawns
+/// K and two or more pawns vs K. 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>::operator()(const Position& pos) const {
Bitboard strongPawns = pos.pieces(strongSide, PAWN);
// If all pawns are ahead of the king on a single rook file, it's a draw.
- if (!((strongPawns & ~FileABB) || (strongPawns & ~FileHBB)) &&
- !(strongPawns & ~passed_pawn_span(weakSide, weakKing)))
+ if ( !(strongPawns & ~(FileABB | FileHBB))
+ && !(strongPawns & ~passed_pawn_span(weakSide, weakKing)))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
return SCALE_FACTOR_NONE;
Square weakKing = pos.square<KING>(weakSide);
- Square strongPawn1 = pos.squares<PAWN>(strongSide)[0];
- Square strongPawn2 = pos.squares<PAWN>(strongSide)[1];
+ Square strongPawn1 = lsb(pos.pieces(strongSide, PAWN));
+ Square strongPawn2 = msb(pos.pieces(strongSide, PAWN));
Square blockSq1, blockSq2;
if (relative_rank(strongSide, strongPawn1) > relative_rank(strongSide, strongPawn2))
}
-/// KBP vs KN. There is a single rule: If the defending king is somewhere along
+/// KBP vs KN. There is a single rule: 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.
template<>
/// 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
+/// 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
/// side's pawn is far 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).
// it's probably at least a draw even with the pawn.
return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
}
+
+} // namespace Stockfish