S(112,125), S(113,127), S(117,137), S(122,143) }
};
+ // Mask of allowed outpost squares indexed by color
+ const Bitboard OutpostMask[COLOR_NB] = {
+ Rank4BB | Rank5BB | Rank6BB, Rank5BB | Rank4BB | Rank3BB
+ };
+
// Outpost[knight/bishop][supported by pawn] contains bonuses for knights and
// bishops outposts, bigger if outpost piece is supported by a pawn.
const Score Outpost[][2] = {
{ S(18, 5), S(27, 8) } // Bishops
};
+ // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for knights and
+ // bishops which can reach a outpost square in one move, bigger if outpost square is supported by a pawn.
+ const Score ReachableOutpost[][2] = {
+ { S(21, 5), S(31, 8) }, // Knights
+ { S( 8, 2), S(13, 4) } // Bishops
+ };
+
// Threat[minor/rook][attacked PieceType] contains
// bonuses according to which piece type attacks which one.
// Attacks on lesser pieces which are pawn defended are not considered.
template<PieceType Pt, Color Us, bool DoTrace>
Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility, const Bitboard* mobilityArea) {
- Bitboard b;
+ Bitboard b, bb;
Square s;
Score score = SCORE_ZERO;
{
ei.kingAttackersCount[Us]++;
ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
- Bitboard bb = b & ei.attackedBy[Them][KING];
+ bb = b & ei.attackedBy[Them][KING];
if (bb)
ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
}
if (Pt == BISHOP || Pt == KNIGHT)
{
- // Bonus for outpost square
- if ( relative_rank(Us, s) >= RANK_4
- && relative_rank(Us, s) <= RANK_6
- && !(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
+ // Bonus for outpost squares
+ bb = OutpostMask[Us] & ~ei.pi->pawn_attacks_span(Them);
+ if (bb & s)
score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)];
+ else
+ {
+ bb &= b & ~pos.pieces(Us);
+ if (bb)
+ score += ReachableOutpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
+ }
// Bonus when behind a pawn
if ( relative_rank(Us, s) < RANK_5