Material::Entry* me;
Pawns::Entry* pe;
- Bitboard pinnedPieces[COLOR_NB];
Bitboard mobilityArea[COLOR_NB];
// attackedBy[color][piece type] is a bitboard representing all squares
const int KnightCheck = 924;
// Threshold for lazy evaluation
- const Value LazyEval = Value(1500);
+ const Value LazyThreshold = Value(1500);
// eval_init() initializes king and attack bitboards for a given color
// adding pawn attacks. To be done at the beginning of the evaluation.
const Square Down = (Us == WHITE ? SOUTH : NORTH);
const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
- ei.pinnedPieces[Us] = pos.pinned_pieces(Us);
-
// Find our pawns on the first two ranks, and those which are blocked
Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
: Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN))
: pos.attacks_from<Pt>(s);
- if (ei.pinnedPieces[Us] & s)
+ if (pos.pinned_pieces(Us) & s)
b &= LineBB[pos.square<KING>(Us)][s];
ei.attackedBy2[Us] |= ei.attackedBy[Us][ALL_PIECES] & b;
kingDanger = std::min(807, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
+ 101 * ei.kingAdjacentZoneAttacksCount[Them]
+ 235 * popcount(undefended)
- + 134 * (popcount(b) + !!ei.pinnedPieces[Us])
+ + 134 * (popcount(b) + !!pos.pinned_pieces(Us))
- 717 * !pos.count<QUEEN>(Them)
- 7 * mg_value(score) / 5 - 5;
}
- // evaluate_passed_pawns() evaluates the passed pawns of the given color
+ // evaluate_passer_pawns() evaluates the passed pawns and candidate passed
+ // pawns of the given color.
template<Color Us, bool DoTrace>
- Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) {
+ Score evaluate_passer_pawns(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
{
Square s = pop_lsb(&b);
- assert(pos.pawn_passed(Us, s));
assert(!(pos.pieces(PAWN) & forward_bb(Us, s)));
bb = forward_bb(Us, s) & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
if (!pos.non_pawn_material(Them))
ebonus += 20;
+ // Scale down bonus for candidate passers which need more than one pawn
+ // push to become passed.
+ if (!pos.pawn_passed(Us, s + pawn_push(Us)))
+ mbonus /= 2, ebonus /= 2;
+
score += make_score(mbonus, ebonus) + PassedFile[file_of(s)];
}
return sf;
}
-
- Value lazy_eval(Value mg, Value eg) {
-
- if (mg > LazyEval && eg > LazyEval)
- return LazyEval + ((mg + eg) / 2 - LazyEval) / 4;
-
- else if (mg < -LazyEval && eg < -LazyEval)
- return -LazyEval + ((mg + eg) / 2 + LazyEval) / 4;
-
- return VALUE_ZERO;
- }
-
} // namespace
assert(!pos.checkers());
Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
+ Value v;
EvalInfo ei;
// Probe the material hash table
ei.pe = Pawns::probe(pos);
score += ei.pe->pawns_score();
- // We have taken into account all cheap evaluation terms.
- // If score exceeds a threshold return a lazy evaluation.
- Value lazy = lazy_eval(mg_value(score), eg_value(score));
- if (lazy)
- return pos.side_to_move() == WHITE ? lazy : -lazy;
+ // Early exit if score is high
+ v = (mg_value(score) + eg_value(score)) / 2;
+ if (abs(v) > LazyThreshold)
+ return pos.side_to_move() == WHITE ? v : -v;
// Initialize attack and king safety bitboards
eval_init<WHITE>(pos, ei);
- evaluate_threats<BLACK, DoTrace>(pos, ei);
// Evaluate passed pawns, we need full attack information including king
- score += evaluate_passed_pawns<WHITE, DoTrace>(pos, ei)
- - evaluate_passed_pawns<BLACK, DoTrace>(pos, ei);
+ score += evaluate_passer_pawns<WHITE, DoTrace>(pos, ei)
+ - evaluate_passer_pawns<BLACK, DoTrace>(pos, ei);
// Evaluate space for both sides, only during opening
if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222)
ScaleFactor sf = evaluate_scale_factor(pos, ei, eg_value(score));
// Interpolate between a middlegame and a (scaled by 'sf') endgame score
- Value v = mg_value(score) * int(ei.me->game_phase())
- + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
+ v = mg_value(score) * int(ei.me->game_phase())
+ + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
v /= int(PHASE_MIDGAME);