- // Initialize attack and king safety bitboards
- init_eval_info<WHITE, HasPopCnt>(pos, ei);
- init_eval_info<BLACK, HasPopCnt>(pos, ei);
-
- // Evaluate pieces and mobility
- bonus += evaluate_pieces_of_color<WHITE, HasPopCnt, Trace>(pos, ei, mobilityWhite)
- - evaluate_pieces_of_color<BLACK, HasPopCnt, Trace>(pos, ei, mobilityBlack);
-
- bonus += apply_weight(mobilityWhite - mobilityBlack, Weights[Mobility]);
-
- // Evaluate kings after all other pieces because we need complete attack
- // information when computing the king safety evaluation.
- bonus += evaluate_king<WHITE, HasPopCnt, Trace>(pos, ei, margins)
- - evaluate_king<BLACK, HasPopCnt, Trace>(pos, ei, margins);
-
- // Evaluate tactical threats, we need full attack information including king
- bonus += evaluate_threats<WHITE>(pos, ei)
- - evaluate_threats<BLACK>(pos, ei);
-
- // Evaluate passed pawns, we need full attack information including king
- bonus += evaluate_passed_pawns<WHITE>(pos, ei)
- - evaluate_passed_pawns<BLACK>(pos, ei);
-
- // If one side has only a king, check whether exists any unstoppable passed pawn
- if (!pos.non_pawn_material(WHITE) || !pos.non_pawn_material(BLACK))
- {
- bonus += evaluate_unstoppable_pawns<HasPopCnt>(pos, ei);
-
- if (Trace)
- trace_add(UNSTOPPABLE, evaluate_unstoppable_pawns<HasPopCnt>(pos, ei));
- }
-
- // Evaluate space for both sides, only in middle-game.
- if (mi->space_weight())
- {
- int s_w = evaluate_space<WHITE, HasPopCnt>(pos, ei);
- int s_b = evaluate_space<BLACK, HasPopCnt>(pos, ei);
- bonus += apply_weight(make_score((s_w - s_b) * mi->space_weight(), 0), Weights[Space]);
-
- if (Trace)
- trace_add(SPACE, apply_weight(make_score(s_w * mi->space_weight(), make_score(0, 0)), Weights[Space]),
- apply_weight(make_score(s_b * mi->space_weight(), make_score(0, 0)), Weights[Space]));
- }
-
- // Scale winning side if position is more drawish that what it appears
- ScaleFactor sf = eg_value(bonus) > VALUE_DRAW ? mi->scale_factor(pos, WHITE)
- : mi->scale_factor(pos, BLACK);
- Phase phase = mi->game_phase();
-
- // If we don't already have an unusual scale factor, check for opposite
- // colored bishop endgames, and use a lower scale for those.
- if ( phase < PHASE_MIDGAME
- && pos.opposite_colored_bishops()
- && sf == SCALE_FACTOR_NORMAL)
- {
- // Only the two bishops ?
- if ( pos.non_pawn_material(WHITE) == BishopValueMidgame
- && pos.non_pawn_material(BLACK) == BishopValueMidgame)
- {
- // Check for KBP vs KB with only a single pawn that is almost
- // certainly a draw or at least two pawns.
- bool one_pawn = (pos.piece_count(WHITE, PAWN) + pos.piece_count(BLACK, PAWN) == 1);
- sf = one_pawn ? ScaleFactor(8) : ScaleFactor(32);
- }
- else
- // Endgame with opposite-colored bishops, but also other pieces. Still
- // a bit drawish, but not as drawish as with only the two bishops.
- sf = ScaleFactor(50);
- }
-
- // Interpolate between the middle game and the endgame score
- margin = margins[pos.side_to_move()];
- Value v = scale_by_game_phase(bonus, phase, sf);
-
- if (Trace)
- {
- trace_add(PST, pos.value());
- trace_add(IMBALANCE, mi->material_value());
- trace_add(PAWN, apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]));
- trace_add(MOBILITY, apply_weight(mobilityWhite, Weights[Mobility]), apply_weight(mobilityBlack, Weights[Mobility]));
- trace_add(THREAT, evaluate_threats<WHITE>(pos, ei), evaluate_threats<BLACK>(pos, ei));
- trace_add(PASSED, evaluate_passed_pawns<WHITE>(pos, ei), evaluate_passed_pawns<BLACK>(pos, ei));
- trace_add(TOTAL, bonus);
- TraceStream << "\nUncertainty margin: White: " << to_cp(margins[WHITE])
- << ", Black: " << to_cp(margins[BLACK])
- << "\nScaling: " << std::noshowpos
- << std::setw(6) << 100.0 * phase/128.0 << "% MG, "
- << std::setw(6) << 100.0 * (1.0 - phase/128.0) << "% * "
- << std::setw(6) << (100.0 * sf) / SCALE_FACTOR_NORMAL << "% EG.\n"
- << "Total evaluation: " << to_cp(v);
- }
-
- return pos.side_to_move() == WHITE ? v : -v;
-}
-
-} // namespace
-
-
-/// init_eval() initializes various tables used by the evaluation function
-
-void init_eval(int threads) {