constexpr Score PawnlessFlank = S( 17, 95);
constexpr Score RestrictedPiece = S( 7, 7);
constexpr Score RookOnPawn = S( 10, 32);
+ constexpr Score RookOnQueenFile = S( 11, 4);
constexpr Score SliderOnQueen = S( 59, 18);
constexpr Score ThreatByKing = S( 24, 89);
constexpr Score ThreatByPawnPush = S( 48, 39);
template<Color Us> Score passed() const;
template<Color Us> Score space() const;
ScaleFactor scale_factor(Value eg) const;
- Score initiative(Value eg) const;
+ Score initiative(Score score) const;
const Position& pos;
Material::Entry* me;
if (relative_rank(Us, s) >= RANK_5)
score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]);
+ // Bonus for rook on the same file as a queen
+ if (file_bb(s) & pos.pieces(QUEEN))
+ score += RookOnQueenFile;
+
// Bonus for rook on an open or semi-open file
if (pos.is_on_semiopen_file(Us, s))
- score += RookOnFile[bool(pos.is_on_semiopen_file(Them, s))];
+ score += RookOnFile[pos.is_on_semiopen_file(Them, s)];
// Penalty when trapped by the king, even more if the king cannot castle
else if (mob <= 3)
// Enemies not strongly protected and under our attack
weak = pos.pieces(Them) & ~stronglyProtected & attackedBy[Us][ALL_PIECES];
- // Safe or protected squares
- safe = ~attackedBy[Them][ALL_PIECES] | attackedBy[Us][ALL_PIECES];
-
// Bonus according to the kind of attacking pieces
if (defended | weak)
{
score += RestrictedPiece * popcount(b);
+ // Protected or unattacked squares
+ safe = ~attackedBy[Them][ALL_PIECES] | attackedBy[Us][ALL_PIECES];
+
+ // Bonus for attacking enemy pieces with our relatively safe pawns
+ b = pos.pieces(Us, PAWN) & safe;
+ b = pawn_attacks_bb<Us>(b) & nonPawnEnemies;
+ score += ThreatBySafePawn * popcount(b);
+
// Find squares where our pawns can push on the next move
b = shift<Up>(pos.pieces(Us, PAWN)) & ~pos.pieces();
b |= shift<Up>(b & TRank3BB) & ~pos.pieces();
b = pawn_attacks_bb<Us>(b) & nonPawnEnemies;
score += ThreatByPawnPush * popcount(b);
- // Our safe or protected pawns
- b = pos.pieces(Us, PAWN) & safe;
-
- b = pawn_attacks_bb<Us>(b) & nonPawnEnemies;
- score += ThreatBySafePawn * popcount(b);
-
// Bonus for threats on the next moves against enemy queen
if (pos.count<QUEEN>(Them) == 1)
{
|| (pos.pieces(PAWN) & (s + Up)))
bonus = bonus / 2;
- score += bonus - PassedFile * std::min(f, ~f);
+ score += bonus - PassedFile * map_to_queenside(f);
}
if (T)
// known attacking/defending status of the players.
template<Tracing T>
- Score Evaluation<T>::initiative(Value eg) const {
+ Score Evaluation<T>::initiative(Score score) const {
+
+ Value mg = mg_value(score);
+ Value eg = eg_value(score);
int outflanking = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
- distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
bool pawnsOnBothFlanks = (pos.pieces(PAWN) & QueenSide)
&& (pos.pieces(PAWN) & KingSide);
+ bool almostUnwinnable = !pe->passed_count()
+ && outflanking < 0
+ && !pawnsOnBothFlanks;
+
// Compute the initiative bonus for the attacking side
int complexity = 9 * pe->passed_count()
+ 11 * pos.count<PAWN>()
+ 9 * outflanking
+ 18 * pawnsOnBothFlanks
+ 49 * !pos.non_pawn_material()
+ - 36 * almostUnwinnable
-103 ;
- // Now apply the bonus: note that we find the attacking side by extracting
- // the sign of the endgame value, and that we carefully cap the bonus so
- // that the endgame score will never change sign after the bonus.
+ // Now apply the bonus: note that we find the attacking side by extracting the
+ // sign of the midgame or endgame values, and that we carefully cap the bonus
+ // so that the midgame and endgame scores do not change sign after the bonus.
+ int u = ((mg > 0) - (mg < 0)) * std::max(std::min(complexity + 50, 0), -abs(mg));
int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
if (T)
- Trace::add(INITIATIVE, make_score(0, v));
+ Trace::add(INITIATIVE, make_score(u, v));
- return make_score(0, v);
+ return make_score(u, v);
}
&& pos.non_pawn_material() == 2 * BishopValueMg)
sf = 16 + 4 * pe->passed_count();
else
- sf = std::min(40 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide), sf);
+ sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide));
+ sf = std::max(0, sf - (pos.rule50_count() - 12) / 4 );
}
return ScaleFactor(sf);
+ passed< WHITE>() - passed< BLACK>()
+ space< WHITE>() - space< BLACK>();
- score += initiative(eg_value(score));
+ score += initiative(score);
// Interpolate between a middlegame and a (scaled by 'sf') endgame score
ScaleFactor sf = scale_factor(eg_value(score));