+ // Since SpaceMask[Us] is fully on our half of the board
+ assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0);
+
+ // Count safe + (behind & safe) with a single popcount
+ return popcount<Full>((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
+ }
+
+
+ // 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 };
+ Thread* thisThread = pos.this_thread();
+
+ // 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, 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) + Eval::Tempo;
+
+ // 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 both sides have only pawns, score for potential unstoppable pawns
+ if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK))
+ score += evaluate_unstoppable_pawns(WHITE, ei)
+ - evaluate_unstoppable_pawns(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
+ 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;
+
+ v /= int(PHASE_MIDGAME);
+
+ // In case of tracing add all single evaluation contributions for both white and black
+ if (Trace)
+ {
+ Tracing::write(Tracing::MATERIAL, pos.psq_score());
+ Tracing::write(Tracing::IMBALANCE, ei.mi->material_value());
+ Tracing::write(PAWN, ei.pi->pawns_value());
+ Tracing::write(Tracing::MOBILITY, apply_weight(mobility[WHITE], Weights[Mobility])
+ , apply_weight(mobility[BLACK], Weights[Mobility]));
+ Score w = ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei);
+ Score b = ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei);
+ Tracing::write(Tracing::SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
+ Tracing::write(Tracing::TOTAL, score);
+ Tracing::ei = ei;
+ Tracing::sf = sf;
+ }
+
+ return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo;