-/// evaluate() is the main evaluation function. It always computes two
-/// values, an endgame score and a middle game score, and interpolates
-/// between them based on the remaining material.
-Value evaluate(const Position& pos, Value& margin) {
-
- return CpuHasPOPCNT ? do_evaluate<true, false>(pos, margin)
- : do_evaluate<false, false>(pos, margin);
-}
-
-namespace {
-
-double to_cp(Value v) { return double(v) / double(PawnValueMidgame); }
-
-void trace_add(int idx, Score term_w, Score term_b = Score(0)) {
-
- TracedTerms[WHITE][idx] = term_w;
- TracedTerms[BLACK][idx] = term_b;
-}
-
-template<bool HasPopCnt, bool Trace>
-Value do_evaluate(const Position& pos, Value& margin) {
-
- EvalInfo ei;
- Value margins[2];
- Score mobilityWhite, mobilityBlack;
-
- assert(pos.is_ok());
- assert(pos.thread() >= 0 && pos.thread() < MAX_THREADS);
- assert(!pos.in_check());
-
- // Initialize value by reading the incrementally updated scores included
- // in the position object (material + piece square tables).
- Score bonus = pos.value();
-
- // margins[] store the uncertainty estimation of position's evaluation
- // that typically is used by the search for pruning decisions.
- margins[WHITE] = margins[BLACK] = VALUE_ZERO;
-
- // Probe the material hash table
- MaterialInfo* mi = Threads[pos.thread()].materialTable.get_material_info(pos);
- bonus += mi->material_value();
-
- // If we have a specialized evaluation function for the current material
- // configuration, call it and return.
- if (mi->specialized_eval_exists())
- {
- margin = VALUE_ZERO;
- return mi->evaluate(pos);
- }
-
- // Probe the pawn hash table
- ei.pi = Threads[pos.thread()].pawnTable.get_pawn_info(pos);
- bonus += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
-
- // 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);
-
- // 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]));