- // Probe the pawn hash table
- ei.pi = Threads[pos.thread()].pawnTable.get_pawn_info(pos);
- score += ei.pi->pawns_value();
-
- // Initialize attack and king safety bitboards
- init_eval_info<WHITE, HasPopCnt>(pos, ei);
- init_eval_info<BLACK, HasPopCnt>(pos, ei);
-
- // Evaluate pieces and mobility
- score += evaluate_pieces_of_color<WHITE, HasPopCnt, Trace>(pos, ei, mobilityWhite)
- - evaluate_pieces_of_color<BLACK, HasPopCnt, Trace>(pos, ei, mobilityBlack);
-
- score += apply_weight(mobilityWhite - mobilityBlack, Weights[Mobility]);
-
- // Evaluate kings after all other pieces because we need complete attack
- // information when computing the king safety evaluation.
- score += 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
- score += evaluate_threats<WHITE>(pos, ei)
- - evaluate_threats<BLACK>(pos, ei);
-
- // Evaluate passed pawns, we need full attack information including king
- score += 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))
- score += evaluate_unstoppable_pawns<HasPopCnt>(pos, ei);
-
- // Evaluate space for both sides, only in middle-game.
- if (ei.mi->space_weight())
- {
- int s = evaluate_space<WHITE, HasPopCnt>(pos, ei) - evaluate_space<BLACK, HasPopCnt>(pos, ei);
- score += apply_weight(make_score(s * ei.mi->space_weight(), 0), Weights[Space]);
- }
-
- // Scale winning side if position is more drawish that what it appears
- ScaleFactor sf = eg_value(score) > VALUE_DRAW ? ei.mi->scale_factor(pos, WHITE)
- : ei.mi->scale_factor(pos, BLACK);
-
- // If we don't already have an unusual scale factor, check for opposite
- // colored bishop endgames, and use a lower scale for those.
- if ( ei.mi->game_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(score, ei.mi->game_phase(), sf);
-
- // In case of tracing add all single evaluation contributions for both white and black
- if (Trace)
- {
- trace_add(PST, pos.value());
- trace_add(IMBALANCE, ei.mi->material_value());
- trace_add(PAWN, ei.pi->pawns_value());
- 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(UNSTOPPABLE, evaluate_unstoppable_pawns<false>(pos, ei));
- Score w = make_score(ei.mi->space_weight() * evaluate_space<WHITE, false>(pos, ei), 0);
- Score b = make_score(ei.mi->space_weight() * evaluate_space<BLACK, false>(pos, ei), 0);
- trace_add(SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
- trace_add(TOTAL, score);
- TraceStream << "\nUncertainty margin: White: " << to_cp(margins[WHITE])
- << ", Black: " << to_cp(margins[BLACK])
- << "\nScaling: " << std::noshowpos
- << std::setw(6) << 100.0 * ei.mi->game_phase() / 128.0 << "% MG, "
- << std::setw(6) << 100.0 * (1.0 - ei.mi->game_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
-
-
-/// read_weights() reads evaluation weights from the corresponding UCI parameters
-
-void read_evaluation_uci_options(Color us) {
-
- // King safety is asymmetrical. Our king danger level is weighted by
- // "Cowardice" UCI parameter, instead the opponent one by "Aggressiveness".
- const int kingDangerUs = (us == WHITE ? KingDangerUs : KingDangerThem);
- const int kingDangerThem = (us == WHITE ? KingDangerThem : KingDangerUs);
-
- Weights[Mobility] = weight_option("Mobility (Middle Game)", "Mobility (Endgame)", WeightsInternal[Mobility]);
- Weights[PassedPawns] = weight_option("Passed Pawns (Middle Game)", "Passed Pawns (Endgame)", WeightsInternal[PassedPawns]);
- Weights[Space] = weight_option("Space", "Space", WeightsInternal[Space]);
- Weights[kingDangerUs] = weight_option("Cowardice", "Cowardice", WeightsInternal[KingDangerUs]);
- Weights[kingDangerThem] = weight_option("Aggressiveness", "Aggressiveness", WeightsInternal[KingDangerThem]);
-
- // If running in analysis mode, make sure we use symmetrical king safety. We do this
- // by replacing both Weights[kingDangerUs] and Weights[kingDangerThem] by their average.
- if (Options["UCI_AnalyseMode"].value<bool>())
- Weights[kingDangerUs] = Weights[kingDangerThem] = (Weights[kingDangerUs] + Weights[kingDangerThem]) / 2;
-
- init_safety();
-}
-
-
-namespace {