};
// PassedDanger[Rank] contains a term to weight the passed score
- constexpr int PassedDanger[RANK_NB] = { 0, 0, 0, 3, 6, 12, 21 };
+ constexpr int PassedDanger[RANK_NB] = { 0, 0, 0, 2, 7, 12, 19 };
- // KingProtector[PieceType-2] contains a penalty according to distance from king
- constexpr Score KingProtector[PIECE_TYPE_NB - 2] = { S(3, 5), S(4, 3), S(3, 0), S(1, -1), S(2, 2) };
++ // KingProximity contains a penalty according to distance from king
++ constexpr Score KingProximity = S(2, 2);
++
+ // KingProtector[knight/bishop] contains a penalty according to distance from king
+ constexpr Score KingProtector[] = { S(4, 6), S(6, 3) };
// Assorted bonuses and penalties
constexpr Score BishopPawns = S( 3, 5);
int mob = popcount(b & mobilityArea[Us]);
- mobility[Us] += MobilityBonus[Pt - 2][mob];
+ if (Pt <= QUEEN)
+ mobility[Us] += MobilityBonus[Pt - 2][mob];
+ else
+ mobility[Us] += MaxMobility * (mob - 1) / (8 + mob);
+
+ // Piece promotion bonus
+ if (pos.promoted_piece_type(Pt) != NO_PIECE_TYPE)
+ {
+ if (promotion_zone_bb(Us, pos.promotion_rank(), pos.max_rank()) & (b | s))
+ score += make_score(PieceValue[MG][pos.promoted_piece_type(Pt)] - PieceValue[MG][Pt],
+ PieceValue[EG][pos.promoted_piece_type(Pt)] - PieceValue[EG][Pt]) / 10;
+ }
+ else if (pos.captures_to_hand() && pos.unpromoted_piece_on(s))
+ score += make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
+ PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 8;
+
- // Penalty if the piece is far from the king
- if (pos.count<KING>(Us))
- {
- int dist = distance(s, pos.square<KING>(Us));
- if (pos.captures_to_hand() && pos.count<KING>(Them))
- dist *= distance(s, pos.square<KING>(Them));
- score -= KingProtector[std::min(Pt - 2, QUEEN - 1)] * dist;
- }
++ // Penalty if the piece is far from the kings in drop variants
++ if (pos.captures_to_hand() && pos.count<KING>(Them) && pos.count<KING>(Us))
++ score -= KingProximity * distance(s, pos.square<KING>(Us)) * distance(s, pos.square<KING>(Them));
if (Pt == BISHOP || Pt == KNIGHT)
{
unsafeChecks &= mobilityArea[Them];
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
- + 102 * kingAttacksCount[Them] * (1 + 2 * !!pos.max_check_count())
- + 191 * popcount(kingRing[Us] & weak) * (1 + pos.captures_to_hand() + !!pos.max_check_count())
- + 143 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
- - 848 * !(pos.count<QUEEN>(Them) || pos.captures_to_hand()) / (1 + !!pos.max_check_count())
- - 9 * mg_value(score) / 8
- + 40;
- + 64 * kingAttacksCount[Them]
- + 183 * popcount(kingRing[Us] & weak)
++ + 64 * kingAttacksCount[Them] * (1 + 2 * !!pos.max_check_count())
++ + 183 * popcount(kingRing[Us] & weak) * (1 + pos.captures_to_hand() + !!pos.max_check_count())
+ + 122 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
- - 860 * !pos.count<QUEEN>(Them)
++ - 860 * !(pos.count<QUEEN>(Them) || pos.captures_to_hand()) / (1 + !!pos.max_check_count())
+ - 7 * mg_value(score) / 8
- + 17 ;
++ + 17;
// Transform the kingDanger units into a Score, and subtract it from the evaluation
if (kingDanger > 0)
assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up)));
- bb = forward_file_bb(Us, s) & (attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
+ bb = forward_file_bb(Us, s) & pos.pieces(Them);
score -= HinderPassedPawn * popcount(bb);
- int r = relative_rank(Us, s);
+ int r = relative_rank(Us, s, pos.max_rank());
int w = PassedDanger[r];
Score bonus = PassedRank[r];
int sf = me->scale_factor(pos, strongSide);
// If scale is not already specific, scale down the endgame via general heuristics
- if (sf == SCALE_FACTOR_NORMAL)
+ if (sf == SCALE_FACTOR_NORMAL && !pos.captures_to_hand())
{
- if (pos.opposite_bishops())
- {
- // Endgame with opposite-colored bishops and no other pieces is almost a draw
- if ( pos.non_pawn_material(WHITE) == BishopValueMg
- && pos.non_pawn_material(BLACK) == BishopValueMg)
- sf = 31;
-
- // Endgame with opposite-colored bishops, but also other pieces. Still
- // a bit drawish, but not as drawish as with only the two bishops.
- else
- sf = 46;
- }
+ if ( pos.opposite_bishops()
+ && pos.non_pawn_material(WHITE) == BishopValueMg
+ && pos.non_pawn_material(BLACK) == BishopValueMg)
+ sf = 31;
else
- sf = std::min(40 + 7 * pos.count<PAWN>(strongSide), sf);
+ sf = std::min(40 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide), sf);
}
return ScaleFactor(sf);