};
// Evaluation grain size, must be a power of 2
- const int GrainSize = 8;
+ const int GrainSize = 4;
// Evaluation weights, initialized from UCI options
- enum { Mobility, PassedPawns, Space, KingDangerUs, KingDangerThem };
+ enum { Mobility, PawnStructure, PassedPawns, Space, KingDangerUs, KingDangerThem };
Score Weights[6];
typedef Value V;
//
// Values modified by Joona Kiiski
const Score WeightsInternal[] = {
- S(289, 344), S(221, 273), S(46, 0), S(271, 0), S(307, 0)
+ S(289, 344), S(233, 201), S(221, 273), S(46, 0), S(271, 0), S(307, 0)
};
// MobilityBonus[PieceType][attacked] contains mobility bonuses for middle and
// by friendly pieces.
const Score MobilityBonus[][32] = {
{}, {},
- { S(-38,-33), S(-25,-23), S(-12,-13), S( 0, -3), S(12, 7), S(25, 17), // Knights
- S( 31, 22), S( 38, 27), S( 38, 27) },
- { S(-25,-30), S(-11,-16), S( 3, -2), S(17, 12), S(31, 26), S(45, 40), // Bishops
- S( 57, 52), S( 65, 60), S( 71, 65), S(74, 69), S(76, 71), S(78, 73),
- S( 79, 74), S( 80, 75), S( 81, 76), S(81, 76) },
- { S(-20,-36), S(-14,-19), S( -8, -3), S(-2, 13), S( 4, 29), S(10, 46), // Rooks
- S( 14, 62), S( 19, 79), S( 23, 95), S(26,106), S(27,111), S(28,114),
- S( 29,116), S( 30,117), S( 31,118), S(32,118) },
- { S(-10,-18), S( -8,-13), S( -6, -7), S(-3, -2), S(-1, 3), S( 1, 8), // Queens
- S( 3, 13), S( 5, 19), S( 8, 23), S(10, 27), S(12, 32), S(15, 34),
- S( 16, 35), S( 17, 35), S( 18, 35), S(20, 35), S(20, 35), S(20, 35),
- S( 20, 35), S( 20, 35), S( 20, 35), S(20, 35), S(20, 35), S(20, 35),
- S( 20, 35), S( 20, 35), S( 20, 35), S(20, 35), S(20, 35), S(20, 35),
- S( 20, 35), S( 20, 35) }
+ { S(-35,-30), S(-22,-20), S(-9,-10), S( 3, 0), S(15, 10), S(27, 20), // Knights
+ S( 37, 28), S( 42, 31), S(44, 33) },
+ { S(-22,-27), S( -8,-13), S( 6, 1), S(20, 15), S(34, 29), S(48, 43), // Bishops
+ S( 60, 55), S( 68, 63), S(74, 68), S(77, 72), S(80, 75), S(82, 77),
+ S( 84, 79), S( 86, 81), S(87, 82), S(87, 82) },
+ { S(-17,-33), S(-11,-16), S(-5, 0), S( 1, 16), S( 7, 32), S(13, 48), // Rooks
+ S( 18, 64), S( 22, 80), S(26, 96), S(29,109), S(31,115), S(33,119),
+ S( 35,122), S( 36,123), S(37,124), S(38,124) },
+ { S(-12,-20), S( -8,-13), S(-5, -7), S(-2, -1), S( 1, 5), S( 4, 11), // Queens
+ S( 7, 17), S( 10, 23), S(13, 29), S(16, 34), S(18, 38), S(20, 40),
+ S( 22, 41), S( 23, 41), S(24, 41), S(25, 41), S(25, 41), S(25, 41),
+ S( 25, 41), S( 25, 41), S(25, 41), S(25, 41), S(25, 41), S(25, 41),
+ S( 25, 41), S( 25, 41), S(25, 41), S(25, 41), S(25, 41), S(25, 41),
+ S( 25, 41), S( 25, 41) }
};
// OutpostBonus[PieceType][Square] contains outpost bonuses of knights and
template<Color Us, bool Trace>
Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]);
- template<Color Us>
+ template<Color Us, bool Trace>
Score evaluate_threats(const Position& pos, EvalInfo& ei);
- template<Color Us>
- int evaluate_space(const Position& pos, EvalInfo& ei);
+ template<Color Us, bool Trace>
+ Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei);
template<Color Us>
- Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei);
+ int evaluate_space(const Position& pos, EvalInfo& ei);
Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei);
Value interpolate(const Score& v, Phase ph, ScaleFactor sf);
+ Score apply_weight(Score v, Score w);
Score weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight);
double to_cp(Value v);
void trace_add(int idx, Score term_w, Score term_b = SCORE_ZERO);
void init() {
- Weights[Mobility] = weight_option("Mobility (Middle Game)", "Mobility (Endgame)", WeightsInternal[Mobility]);
- Weights[PassedPawns] = weight_option("Passed Pawns (Middle Game)", "Passed Pawns (Endgame)", WeightsInternal[PassedPawns]);
+ Weights[Mobility] = weight_option("Mobility (Midgame)", "Mobility (Endgame)", WeightsInternal[Mobility]);
+ Weights[PawnStructure] = weight_option("Pawn Structure (Midgame)", "Pawn Structure (Endgame)", WeightsInternal[PawnStructure]);
+ Weights[PassedPawns] = weight_option("Passed Pawns (Midgame)", "Passed Pawns (Endgame)", WeightsInternal[PassedPawns]);
Weights[Space] = weight_option("Space", "Space", WeightsInternal[Space]);
Weights[KingDangerUs] = weight_option("Cowardice", "Cowardice", WeightsInternal[KingDangerUs]);
Weights[KingDangerThem] = weight_option("Aggressiveness", "Aggressiveness", WeightsInternal[KingDangerThem]);
// Probe the pawn hash table
ei.pi = Pawns::probe(pos, th->pawnsTable);
- score += ei.pi->pawns_value();
+ score += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
// Initialize attack and king safety bitboards
init_eval_info<WHITE>(pos, ei);
- evaluate_king<BLACK, Trace>(pos, ei, margins);
// Evaluate tactical threats, we need full attack information including king
- score += evaluate_threats<WHITE>(pos, ei)
- - evaluate_threats<BLACK>(pos, ei);
+ 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>(pos, ei)
- - evaluate_passed_pawns<BLACK>(pos, ei);
+ score += evaluate_passed_pawns<WHITE, Trace>(pos, ei)
+ - evaluate_passed_pawns<BLACK, Trace>(pos, ei);
// If one side has only a king, check whether exists any unstoppable passed pawn
if (!pos.non_pawn_material(WHITE) || !pos.non_pawn_material(BLACK))
trace_add(PST, pos.psq_score());
trace_add(IMBALANCE, ei.mi->material_value());
trace_add(PAWN, ei.pi->pawns_value());
- trace_add(MOBILITY, apply_weight(mobilityWhite, Weights[Mobility]), apply_weight(mobilityBlack, Weights[Mobility]));
- trace_add(THREAT, evaluate_threats<WHITE>(pos, ei), evaluate_threats<BLACK>(pos, ei));
- trace_add(PASSED, evaluate_passed_pawns<WHITE>(pos, ei), evaluate_passed_pawns<BLACK>(pos, ei));
trace_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);
// evaluate_threats<>() assigns bonuses according to the type of attacking piece
// and the type of attacked one.
- template<Color Us>
+ template<Color Us, bool Trace>
Score evaluate_threats(const Position& pos, EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
& ~ei.attackedBy[Them][PAWN]
& ei.attackedBy[Us][ALL_PIECES];
- if (!weakEnemies)
- return score;
-
// Add bonus according to type of attacked enemy piece and to the
// type of attacking piece, from knights to queens. Kings are not
// considered because are already handled in king evaluation.
- for (PieceType pt1 = KNIGHT; pt1 < KING; pt1++)
- {
- b = ei.attackedBy[Us][pt1] & weakEnemies;
- if (b)
- for (PieceType pt2 = PAWN; pt2 < KING; pt2++)
- if (b & pos.pieces(pt2))
- score += ThreatBonus[pt1][pt2];
- }
+ if (weakEnemies)
+ for (PieceType pt1 = KNIGHT; pt1 < KING; pt1++)
+ {
+ b = ei.attackedBy[Us][pt1] & weakEnemies;
+ if (b)
+ for (PieceType pt2 = PAWN; pt2 < KING; pt2++)
+ if (b & pos.pieces(pt2))
+ score += ThreatBonus[pt1][pt2];
+ }
+
+ if (Trace)
+ TracedScores[Us][THREAT] = score;
+
return score;
}
ei.attackedBy[Us][ALL_PIECES] = ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT]
| ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK]
| ei.attackedBy[Us][QUEEN] | ei.attackedBy[Us][KING];
+ if (Trace)
+ TracedScores[Us][MOBILITY] = apply_weight(mobility, Weights[Mobility]);
+
return score;
}
// evaluate_passed_pawns<>() evaluates the passed pawns of the given color
- template<Color Us>
+ template<Color Us, bool Trace>
Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
b = ei.pi->passed_pawns(Us);
- if (!b)
- return SCORE_ZERO;
-
- do {
+ while (b)
+ {
Square s = pop_lsb(&b);
assert(pos.pawn_is_passed(Us, s));
}
score += make_score(mbonus, ebonus);
- } while (b);
+ }
+
+ if (Trace)
+ TracedScores[Us][PASSED] = apply_weight(score, Weights[PassedPawns]);
// Add the scores to the middle game and endgame eval
return apply_weight(score, Weights[PassedPawns]);
return Value((result + GrainSize / 2) & ~(GrainSize - 1));
}
+ // apply_weight() weights score v by score w trying to prevent overflow
+ Score apply_weight(Score v, Score w) {
+ return make_score((int(mg_value(v)) * mg_value(w)) / 0x100,
+ (int(eg_value(v)) * eg_value(w)) / 0x100);
+ }
// weight_option() computes the value of an evaluation weight, by combining
// two UCI-configurable weights (midgame and endgame) with an internal weight.