const Score RookOpenFile = make_score(43, 21);
const Score RookSemiopenFile = make_score(19, 10);
const Score BishopPawns = make_score( 8, 12);
+ const Score MinorBehindPawn = make_score(16, 0);
const Score UndefendedMinor = make_score(25, 10);
const Score TrappedRook = make_score(90, 0);
Score evaluate_pieces_of_color(const Position& pos, EvalInfo& ei, Score& mobility);
template<Color Us, bool Trace>
- Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]);
+ Score evaluate_king(const Position& pos, const EvalInfo& ei, Value margins[]);
template<Color Us, bool Trace>
- Score evaluate_threats(const Position& pos, EvalInfo& ei);
+ Score evaluate_threats(const Position& pos, const EvalInfo& ei);
template<Color Us, bool Trace>
- Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei);
+ Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei);
template<Color Us>
- int evaluate_space(const Position& pos, EvalInfo& ei);
+ int evaluate_space(const Position& pos, const EvalInfo& ei);
- Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei);
+ Score evaluate_unstoppable_pawns(const Position& pos, const EvalInfo& ei);
Value interpolate(const Score& v, Phase ph, ScaleFactor sf);
Score apply_weight(Score v, Score w);
if (ei.mi->space_weight())
{
int s = evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei);
- score += apply_weight(make_score(s * ei.mi->space_weight(), 0), Weights[Space]);
+ score += apply_weight(s * ei.mi->space_weight(), Weights[Space]);
}
// Scale winning side if position is more drawish that what it appears
Tracing::add(IMBALANCE, ei.mi->material_value());
Tracing::add(PAWN, ei.pi->pawns_value());
Tracing::add(UNSTOPPABLE, evaluate_unstoppable_pawns(pos, ei));
- Score w = make_score(ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei), 0);
- Score b = make_score(ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei), 0);
+ Score w = ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei);
+ Score b = ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei);
Tracing::add(SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
Tracing::add(TOTAL, score);
Tracing::stream << "\nUncertainty margin: White: " << to_cp(margins[WHITE])
if (bonus && (ei.attackedBy[Us][PAWN] & s))
{
if ( !pos.pieces(Them, KNIGHT)
- && !(same_color_squares(s) & pos.pieces(Them, BISHOP)))
+ && !(squares_of_color(s) & pos.pieces(Them, BISHOP)))
bonus += bonus + bonus / 2;
else
bonus += bonus / 2;
if (Piece == BISHOP)
score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s);
- // Bishop and knight outposts squares
- if ( (Piece == BISHOP || Piece == KNIGHT)
- && !(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
- score += evaluate_outposts<Piece, Us>(pos, ei, s);
+ if (Piece == BISHOP || Piece == KNIGHT)
+ {
+ // Bishop and knight outposts squares
+ if (!(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
+ score += evaluate_outposts<Piece, Us>(pos, ei, s);
+
+ // Bishop or knight behind a pawn
+ if ( relative_rank(Us, s) < RANK_5
+ && (pos.pieces(PAWN) & (s + pawn_push(Us))))
+ score += MinorBehindPawn;
+ }
if ( (Piece == ROOK || Piece == QUEEN)
&& relative_rank(Us, s) >= RANK_5)
// and the type of attacked one.
template<Color Us, bool Trace>
- Score evaluate_threats(const Position& pos, EvalInfo& ei) {
+ Score evaluate_threats(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
// evaluate_king<>() assigns bonuses and penalties to a king of a given color
template<Color Us, bool Trace>
- Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]) {
+ Score evaluate_king(const Position& pos, const EvalInfo& ei, Value margins[]) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
// be very big, and so capturing a single attacking piece can therefore
// result in a score change far bigger than the value of the captured piece.
score -= KingDanger[Us == Search::RootColor][attackUnits];
- margins[Us] += mg_value(KingDanger[Us == Search::RootColor][attackUnits]) / 2;
+ margins[Us] += mg_value(KingDanger[Us == Search::RootColor][attackUnits]);
}
if (Trace)
// evaluate_passed_pawns<>() evaluates the passed pawns of the given color
template<Color Us, bool Trace>
- Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei) {
+ Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
if (pos.is_empty(blockSq))
{
squaresToQueen = forward_bb(Us, s);
- defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
// If there is an enemy rook or queen attacking the pawn from behind,
// add all X-ray attacks by the rook or queen. Otherwise consider only
else
unsafeSquares = squaresToQueen & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
+ if ( unlikely(forward_bb(Them, s) & pos.pieces(Us, ROOK, QUEEN))
+ && (forward_bb(Them, s) & pos.pieces(Us, ROOK, QUEEN) & pos.attacks_from<ROOK>(s)))
+ defendedSquares = squaresToQueen;
+ else
+ defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
+
// If there aren't enemy attacks huge bonus, a bit smaller if at
// least block square is not attacked, otherwise smallest bonus.
int k = !unsafeSquares ? 15 : !(unsafeSquares & blockSq) ? 9 : 3;
// evaluate_unstoppable_pawns() evaluates the unstoppable passed pawns for both sides, this is quite
// conservative and returns a winning score only when we are very sure that the pawn is winning.
- Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei) {
+ Score evaluate_unstoppable_pawns(const Position& pos, const EvalInfo& ei) {
Bitboard b, b2, blockers, supporters, queeningPath, candidates;
Square s, blockSq, queeningSquare;
// twice. Finally, the space bonus is scaled by a weight taken from the
// material hash table. The aim is to improve play on game opening.
template<Color Us>
- int evaluate_space(const Position& pos, EvalInfo& ei) {
+ int evaluate_space(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
assert(eg_value(v) > -VALUE_INFINITE && eg_value(v) < VALUE_INFINITE);
assert(ph >= PHASE_ENDGAME && ph <= PHASE_MIDGAME);
- int ev = (eg_value(v) * int(sf)) / SCALE_FACTOR_NORMAL;
- int result = (mg_value(v) * int(ph) + ev * int(128 - ph)) / 128;
- return Value((result + GrainSize / 2) & ~(GrainSize - 1));
+ int e = (eg_value(v) * int(sf)) / SCALE_FACTOR_NORMAL;
+ int r = (mg_value(v) * int(ph) + e * int(PHASE_MIDGAME - ph)) / PHASE_MIDGAME;
+ return Value((r / GrainSize) * GrainSize); // Sign independent
}
// apply_weight() weights score v by score w trying to prevent overflow
std::string Tracing::do_trace(const Position& pos) {
- Search::RootColor = pos.side_to_move();
-
stream.str("");
stream << std::showpoint << std::showpos << std::fixed << std::setprecision(2);
std::memset(scores, 0, 2 * (TOTAL + 1) * sizeof(Score));