- // Initialize score by reading the incrementally updated scores included
- // in the position object (material + piece square tables) and adding a
- // Tempo bonus. Score is computed from the point of view of white.
- score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo);
-
- // Probe the material hash table
- ei.mi = Material::probe(pos, thisThread->materialTable, thisThread->endgames);
- score += ei.mi->material_value();
-
- // If we have a specialized evaluation function for the current material
- // configuration, call it and return.
- if (ei.mi->specialized_eval_exists())
- return ei.mi->evaluate(pos);
-
- // Probe the pawn hash table
- ei.pi = Pawns::probe(pos, thisThread->pawnsTable);
- score += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
-
- // Initialize attack and king safety bitboards
- init_eval_info<WHITE>(pos, ei);
- init_eval_info<BLACK>(pos, ei);
-
- // Evaluate pieces and mobility
- score += evaluate_pieces<WHITE, Trace>(pos, ei, mobility)
- - evaluate_pieces<BLACK, Trace>(pos, ei, mobility);
-
- score += apply_weight(mobility[WHITE] - mobility[BLACK], Weights[Mobility]);
-
- // Evaluate kings after all other pieces because we need complete attack
- // information when computing the king safety evaluation.
- score += evaluate_king<WHITE, Trace>(pos, ei)
- - evaluate_king<BLACK, Trace>(pos, ei);
-
- // Evaluate tactical threats, we need full attack information including king
- score += evaluate_threats<WHITE, Trace>(pos, ei)
- - evaluate_threats<BLACK, Trace>(pos, ei);
-
- // Evaluate passed pawns, we need full attack information including king
- score += evaluate_passed_pawns<WHITE, Trace>(pos, ei)
- - evaluate_passed_pawns<BLACK, Trace>(pos, ei);
-
- // If one side has only a king, score for potential unstoppable pawns
- if (!pos.non_pawn_material(WHITE) || !pos.non_pawn_material(BLACK))
- score += evaluate_unstoppable_pawns(pos, WHITE, ei)
- - evaluate_unstoppable_pawns(pos, BLACK, ei);
-
- // Evaluate space for both sides, only in middlegame
- if (ei.mi->space_weight())
- {
- int s = evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei);
- score += apply_weight(s * ei.mi->space_weight(), Weights[Space]);
- }
-
- // Scale winning side if position is more drawish than it appears
- ScaleFactor sf = eg_value(score) > VALUE_DRAW ? ei.mi->scale_factor(pos, WHITE)
- : ei.mi->scale_factor(pos, BLACK);