+ // do_evaluate() is the evaluation entry point, called directly from evaluate()
+
+ template<bool Trace>
+ Value do_evaluate(const Position& pos) {
+
+ assert(!pos.checkers());
+
+ EvalInfo ei;
+ Score score, mobility[2] = { SCORE_ZERO, SCORE_ZERO };
+
+ // Initialize score by reading the incrementally updated scores included
+ // in the position object (material + piece square tables).
+ // Score is computed from the point of view of white.
+ score = pos.psq_score();
+
+ // Probe the material hash table
+ ei.mi = Material::probe(pos);
+ score += ei.mi->imbalance();
+
+ // 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);
+ score += ei.pi->pawns_score() * 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 += (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 both sides have only pawns, score for potential unstoppable pawns
+ if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK))
+ {
+ Bitboard b;
+ if ((b = ei.pi->passed_pawns(WHITE)) != 0)
+ score += int(relative_rank(WHITE, frontmost_sq(WHITE, b))) * Unstoppable;
+
+ if ((b = ei.pi->passed_pawns(BLACK)) != 0)
+ score -= int(relative_rank(BLACK, frontmost_sq(BLACK, b))) * Unstoppable;
+ }
+
+ // Evaluate space for both sides, only during opening
+ if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 11756)
+ score += (evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei)) * Weights[Space];
+
+ // Scale winning side if position is more drawish than it appears
+ Color strongSide = eg_value(score) > VALUE_DRAW ? WHITE : BLACK;
+ ScaleFactor sf = ei.mi->scale_factor(pos, strongSide);
+
+ // If we don't already have an unusual scale factor, check for certain
+ // types of endgames, and use a lower scale for those.
+ if ( ei.mi->game_phase() < PHASE_MIDGAME
+ && (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
+ {
+ if (pos.opposite_bishops())
+ {
+ // Endgame with opposite-colored bishops and no other pieces (ignoring pawns)
+ // is almost a draw, in case of KBP vs KB is even more a draw.
+ if ( pos.non_pawn_material(WHITE) == BishopValueMg
+ && pos.non_pawn_material(BLACK) == BishopValueMg)
+ sf = more_than_one(pos.pieces(PAWN)) ? ScaleFactor(32) : ScaleFactor(8);
+
+ // Endgame with opposite-colored bishops, but also other pieces. Still
+ // a bit drawish, but not as drawish as with only the two bishops.
+ else
+ sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
+ }
+ // Endings where weaker side can place his king in front of the opponent's
+ // pawns are drawish.
+ else if ( abs(eg_value(score)) <= BishopValueEg
+ && ei.pi->pawn_span(strongSide) <= 1
+ && !pos.pawn_passed(~strongSide, pos.king_square(~strongSide)))
+ sf = ei.pi->pawn_span(strongSide) ? ScaleFactor(56) : ScaleFactor(38);
+ }
+
+ // Interpolate between a middlegame and a (scaled by 'sf') endgame score
+ Value v = mg_value(score) * int(ei.mi->game_phase())
+ + eg_value(score) * int(PHASE_MIDGAME - ei.mi->game_phase()) * sf / SCALE_FACTOR_NORMAL;