S(118,174), S(119,177), S(123,191), S(128,199) }
};
- // Outpost[knight/bishop][supported by pawn] contains bonuses for knights and
- // bishops outposts, bigger if outpost piece is supported by a pawn.
+ // Outpost[knight/bishop][supported by pawn] contains bonuses for minor
+ // pieces if they can reach an outpost square, bigger if that square is
+ // supported by a pawn. If the minor piece occupies an outpost square
+ // then score is doubled.
const Score Outpost[][2] = {
- { S(43,11), S(65,20) }, // Knights
- { S(20, 3), S(29, 8) } // Bishops
- };
-
- // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for
- // knights and bishops which can reach an outpost square in one move, bigger
- // if outpost square is supported by a pawn.
- const Score ReachableOutpost[][2] = {
- { S(21, 5), S(35, 8) }, // Knights
- { S( 8, 0), S(14, 4) } // Bishops
+ { S(22, 6), S(33, 9) }, // Knight
+ { S( 9, 2), S(14, 4) } // Bishop
};
// RookOnFile[semiopen/open] contains bonuses for each rook when there is no
const int KnightCheck = 924;
// Threshold for lazy evaluation
- const Value LazyEval = Value(1500);
+ const Value LazyThreshold = Value(1500);
// eval_init() initializes king and attack bitboards for a given color
// adding pawn attacks. To be done at the beginning of the evaluation.
// Bonus for outpost squares
bb = OutpostRanks & ~ei.pe->pawn_attacks_span(Them);
if (bb & s)
- score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)];
+ score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)] * 2;
else
{
bb &= b & ~pos.pieces(Us);
if (bb)
- score += ReachableOutpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
+ score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
}
// Bonus when behind a pawn
return sf;
}
-
- Value lazy_eval(Value mg, Value eg) {
-
- if (mg > LazyEval && eg > LazyEval)
- return LazyEval + ((mg + eg) / 2 - LazyEval) / 4;
-
- else if (mg < -LazyEval && eg < -LazyEval)
- return -LazyEval + ((mg + eg) / 2 + LazyEval) / 4;
-
- return VALUE_ZERO;
- }
-
} // namespace
assert(!pos.checkers());
Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
+ Value v;
EvalInfo ei;
// Probe the material hash table
ei.pe = Pawns::probe(pos);
score += ei.pe->pawns_score();
- // We have taken into account all cheap evaluation terms.
- // If score exceeds a threshold return a lazy evaluation.
- Value lazy = lazy_eval(mg_value(score), eg_value(score));
- if (lazy)
- return pos.side_to_move() == WHITE ? lazy : -lazy;
+ // Early exit if score is high
+ v = (mg_value(score) + eg_value(score)) / 2;
+ if (abs(v) > LazyThreshold)
+ return pos.side_to_move() == WHITE ? v : -v;
// Initialize attack and king safety bitboards
eval_init<WHITE>(pos, ei);
ScaleFactor sf = evaluate_scale_factor(pos, ei, eg_value(score));
// Interpolate between a middlegame and a (scaled by 'sf') endgame score
- Value v = mg_value(score) * int(ei.me->game_phase())
- + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
+ v = mg_value(score) * int(ei.me->game_phase())
+ + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
v /= int(PHASE_MIDGAME);