+ EvalInfo ei;
+ Score score, mobility[2] = { SCORE_ZERO, SCORE_ZERO };
+ Thread* thisThread = pos.this_thread();
+
+ // 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);
+
+ ei.attackedBy[WHITE][ALL_PIECES] |= ei.attackedBy[WHITE][KING];
+ ei.attackedBy[BLACK][ALL_PIECES] |= ei.attackedBy[BLACK][KING];
+
+ // Do not include in mobility squares protected by enemy pawns or occupied by our pawns or king
+ Bitboard mobilityArea[] = { ~(ei.attackedBy[BLACK][PAWN] | pos.pieces(WHITE, PAWN, KING)),
+ ~(ei.attackedBy[WHITE][PAWN] | pos.pieces(BLACK, PAWN, KING)) };
+
+ // Evaluate pieces and mobility
+ score += evaluate_pieces<KNIGHT, WHITE, Trace>(pos, ei, mobility, mobilityArea);
+ 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]);
+ }