mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-21 01:27:16 +08:00
Big reshuffle in evaluate.cpp
Reshuffle functions to define them in reverse calling order (C style). This allow us to define templates before they are used. Currently it is not like this, for instance evaluate_pieces is defined after do_evaluate that calls it. This happens to work for some strange reason (two phase lookup?) but we want to avoid code that works 'by magic'. As a nice side-effect we can now remove the function prototypes. No functional change.
This commit is contained in:
378
src/evaluate.cpp
378
src/evaluate.cpp
@@ -206,199 +206,37 @@ namespace {
|
|||||||
// scores, indexed by color and by a calculated integer number.
|
// scores, indexed by color and by a calculated integer number.
|
||||||
Score KingDanger[COLOR_NB][128];
|
Score KingDanger[COLOR_NB][128];
|
||||||
|
|
||||||
// Function prototypes
|
|
||||||
template<bool Trace>
|
|
||||||
Value do_evaluate(const Position& pos);
|
|
||||||
|
|
||||||
template<Color Us>
|
// apply_weight() weights score v by score w trying to prevent overflow
|
||||||
void init_eval_info(const Position& pos, EvalInfo& ei);
|
Score apply_weight(Score v, const Weight& w) {
|
||||||
|
return make_score(mg_value(v) * w.mg / 256, eg_value(v) * w.eg / 256);
|
||||||
template<PieceType Pt, Color Us, bool Trace>
|
|
||||||
Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility, Bitboard* mobilityArea);
|
|
||||||
|
|
||||||
template<Color Us, bool Trace>
|
|
||||||
Score evaluate_king(const Position& pos, const EvalInfo& ei);
|
|
||||||
|
|
||||||
template<Color Us, bool Trace>
|
|
||||||
Score evaluate_threats(const Position& pos, const EvalInfo& ei);
|
|
||||||
|
|
||||||
template<Color Us, bool Trace>
|
|
||||||
Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei);
|
|
||||||
|
|
||||||
template<Color Us>
|
|
||||||
int evaluate_space(const Position& pos, const EvalInfo& ei);
|
|
||||||
|
|
||||||
Score evaluate_unstoppable_pawns(const Position& pos, Color us, const EvalInfo& ei);
|
|
||||||
|
|
||||||
Value interpolate(const Score& v, Phase ph, ScaleFactor sf);
|
|
||||||
Score apply_weight(Score v, const Weight& w);
|
|
||||||
Weight weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace Eval {
|
|
||||||
|
|
||||||
/// evaluate() is the main evaluation function. It always computes two
|
|
||||||
/// values, an endgame score and a middlegame score, and interpolates
|
|
||||||
/// between them based on the remaining material.
|
|
||||||
|
|
||||||
Value evaluate(const Position& pos) {
|
|
||||||
return do_evaluate<false>(pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// trace() is like evaluate(), but instead of returning a value, it returns
|
// weight_option() computes the value of an evaluation weight, by combining
|
||||||
/// a string (suitable for outputting to stdout) that contains the detailed
|
// two UCI-configurable weights (midgame and endgame) with an internal weight.
|
||||||
/// descriptions and values of each evaluation term. It's mainly used for
|
|
||||||
/// debugging.
|
Weight weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight) {
|
||||||
std::string trace(const Position& pos) {
|
|
||||||
return Tracing::do_trace(pos);
|
Weight w = { Options[mgOpt] * mg_value(internalWeight) / 100,
|
||||||
|
Options[egOpt] * eg_value(internalWeight) / 100 };
|
||||||
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// init() computes evaluation weights from the corresponding UCI parameters
|
// interpolate() interpolates between a middlegame and an endgame score,
|
||||||
/// and setup king tables.
|
// based on game phase. It also scales the return value by a ScaleFactor array.
|
||||||
|
|
||||||
void init() {
|
Value interpolate(const Score& v, Phase ph, ScaleFactor sf) {
|
||||||
|
|
||||||
Weights[Mobility] = weight_option("Mobility (Midgame)", "Mobility (Endgame)", WeightsInternal[Mobility]);
|
assert(-VALUE_INFINITE < mg_value(v) && mg_value(v) < VALUE_INFINITE);
|
||||||
Weights[PawnStructure] = weight_option("Pawn Structure (Midgame)", "Pawn Structure (Endgame)", WeightsInternal[PawnStructure]);
|
assert(-VALUE_INFINITE < eg_value(v) && eg_value(v) < VALUE_INFINITE);
|
||||||
Weights[PassedPawns] = weight_option("Passed Pawns (Midgame)", "Passed Pawns (Endgame)", WeightsInternal[PassedPawns]);
|
assert(PHASE_ENDGAME <= ph && ph <= PHASE_MIDGAME);
|
||||||
Weights[Space] = weight_option("Space", "Space", WeightsInternal[Space]);
|
|
||||||
Weights[KingDangerUs] = weight_option("Cowardice", "Cowardice", WeightsInternal[KingDangerUs]);
|
|
||||||
Weights[KingDangerThem] = weight_option("Aggressiveness", "Aggressiveness", WeightsInternal[KingDangerThem]);
|
|
||||||
|
|
||||||
const int MaxSlope = 30;
|
int eg = (eg_value(v) * int(sf)) / SCALE_FACTOR_NORMAL;
|
||||||
const int Peak = 1280;
|
return Value((mg_value(v) * int(ph) + eg * int(PHASE_MIDGAME - ph)) / PHASE_MIDGAME);
|
||||||
|
|
||||||
for (int t = 0, i = 1; i < 100; ++i)
|
|
||||||
{
|
|
||||||
t = std::min(Peak, std::min(int(0.4 * i * i), t + MaxSlope));
|
|
||||||
|
|
||||||
KingDanger[1][i] = apply_weight(make_score(t, 0), Weights[KingDangerUs]);
|
|
||||||
KingDanger[0][i] = apply_weight(make_score(t, 0), Weights[KingDangerThem]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Eval
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
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) and adding a
|
|
||||||
// Tempo bonus. Score is computed from the point of view of white.
|
|
||||||
score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// 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 pieces
|
|
||||||
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 one side has only a king, score for potential unstoppable pawns
|
|
||||||
if (!pos.non_pawn_material(WHITE) || !pos.non_pawn_material(BLACK))
|
|
||||||
score += evaluate_unstoppable_pawns(pos, WHITE, ei)
|
|
||||||
- evaluate_unstoppable_pawns(pos, 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
|
|
||||||
ScaleFactor sf = eg_value(score) > VALUE_DRAW ? ei.mi->scale_factor(pos, WHITE)
|
|
||||||
: ei.mi->scale_factor(pos, BLACK);
|
|
||||||
|
|
||||||
// If we don't already have an unusual scale factor, check for opposite
|
|
||||||
// colored bishop endgames, and use a lower scale for those.
|
|
||||||
if ( ei.mi->game_phase() < PHASE_MIDGAME
|
|
||||||
&& pos.opposite_bishops()
|
|
||||||
&& (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
|
|
||||||
{
|
|
||||||
// Ignoring any pawns, do both sides only have a single bishop and no
|
|
||||||
// other pieces?
|
|
||||||
if ( pos.non_pawn_material(WHITE) == BishopValueMg
|
|
||||||
&& pos.non_pawn_material(BLACK) == BishopValueMg)
|
|
||||||
{
|
|
||||||
// Check for KBP vs KB with only a single pawn that is almost
|
|
||||||
// certainly a draw or at least two pawns.
|
|
||||||
bool one_pawn = (pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK) == 1);
|
|
||||||
sf = one_pawn ? ScaleFactor(8) : ScaleFactor(32);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// Endgame with opposite-colored bishops, but also other pieces. Still
|
|
||||||
// a bit drawish, but not as drawish as with only the two bishops.
|
|
||||||
sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value v = interpolate(score, ei.mi->game_phase(), sf);
|
|
||||||
|
|
||||||
// In case of tracing add all single evaluation contributions for both white and black
|
|
||||||
if (Trace)
|
|
||||||
{
|
|
||||||
Tracing::add_term(Tracing::PST, pos.psq_score());
|
|
||||||
Tracing::add_term(Tracing::IMBALANCE, ei.mi->material_value());
|
|
||||||
Tracing::add_term(PAWN, ei.pi->pawns_value());
|
|
||||||
Tracing::add_term(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::add_term(Tracing::SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
|
|
||||||
Tracing::add_term(Tracing::TOTAL, score);
|
|
||||||
Tracing::ei = ei;
|
|
||||||
Tracing::sf = sf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos.side_to_move() == WHITE ? v : -v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// init_eval_info() initializes king bitboards for given color adding
|
// init_eval_info() initializes king bitboards for given color adding
|
||||||
// pawn attacks. To be done at the beginning of the evaluation.
|
// pawn attacks. To be done at the beginning of the evaluation.
|
||||||
@@ -463,6 +301,7 @@ Value do_evaluate(const Position& pos) {
|
|||||||
Square s;
|
Square s;
|
||||||
Score score = SCORE_ZERO;
|
Score score = SCORE_ZERO;
|
||||||
|
|
||||||
|
const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1));
|
||||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
const Square* pl = pos.list<Pt>(Us);
|
const Square* pl = pos.list<Pt>(Us);
|
||||||
|
|
||||||
@@ -574,8 +413,6 @@ Value do_evaluate(const Position& pos) {
|
|||||||
if (Trace)
|
if (Trace)
|
||||||
Tracing::terms[Us][Pt] = score;
|
Tracing::terms[Us][Pt] = score;
|
||||||
|
|
||||||
const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1));
|
|
||||||
|
|
||||||
return score - evaluate_pieces<NextPt, Them, Trace>(pos, ei, mobility, mobilityArea);
|
return score - evaluate_pieces<NextPt, Them, Trace>(pos, ei, mobility, mobilityArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,33 +736,120 @@ Value do_evaluate(const Position& pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// interpolate() interpolates between a middlegame and an endgame score,
|
// do_evaluate() is the evaluation entry point, called directly from evaluate()
|
||||||
// based on game phase. It also scales the return value by a ScaleFactor array.
|
|
||||||
|
|
||||||
Value interpolate(const Score& v, Phase ph, ScaleFactor sf) {
|
template<bool Trace>
|
||||||
|
Value do_evaluate(const Position& pos) {
|
||||||
|
|
||||||
assert(-VALUE_INFINITE < mg_value(v) && mg_value(v) < VALUE_INFINITE);
|
assert(!pos.checkers());
|
||||||
assert(-VALUE_INFINITE < eg_value(v) && eg_value(v) < VALUE_INFINITE);
|
|
||||||
assert(PHASE_ENDGAME <= ph && ph <= PHASE_MIDGAME);
|
|
||||||
|
|
||||||
int eg = (eg_value(v) * int(sf)) / SCALE_FACTOR_NORMAL;
|
EvalInfo ei;
|
||||||
return Value((mg_value(v) * int(ph) + eg * int(PHASE_MIDGAME - ph)) / PHASE_MIDGAME);
|
Score score, mobility[2] = { SCORE_ZERO, SCORE_ZERO };
|
||||||
}
|
Thread* thisThread = pos.this_thread();
|
||||||
|
|
||||||
// apply_weight() weights score v by score w trying to prevent overflow
|
// Initialize score by reading the incrementally updated scores included
|
||||||
Score apply_weight(Score v, const Weight& w) {
|
// in the position object (material + piece square tables) and adding a
|
||||||
|
// Tempo bonus. Score is computed from the point of view of white.
|
||||||
|
score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo);
|
||||||
|
|
||||||
return make_score(mg_value(v) * w.mg / 256, eg_value(v) * w.eg / 256);
|
// Probe the material hash table
|
||||||
}
|
ei.mi = Material::probe(pos, thisThread->materialTable, thisThread->endgames);
|
||||||
|
score += ei.mi->material_value();
|
||||||
|
|
||||||
// weight_option() computes the value of an evaluation weight, by combining
|
// If we have a specialized evaluation function for the current material
|
||||||
// two UCI-configurable weights (midgame and endgame) with an internal weight.
|
// configuration, call it and return.
|
||||||
|
if (ei.mi->specialized_eval_exists())
|
||||||
|
return ei.mi->evaluate(pos);
|
||||||
|
|
||||||
Weight weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight) {
|
// Probe the pawn hash table
|
||||||
|
ei.pi = Pawns::probe(pos, thisThread->pawnsTable);
|
||||||
|
score += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
|
||||||
|
|
||||||
Weight w = { Options[mgOpt] * mg_value(internalWeight) / 100,
|
// Initialize attack and king safety bitboards
|
||||||
Options[egOpt] * eg_value(internalWeight) / 100 };
|
init_eval_info<WHITE>(pos, ei);
|
||||||
return w;
|
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 pieces
|
||||||
|
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 one side has only a king, score for potential unstoppable pawns
|
||||||
|
if (!pos.non_pawn_material(WHITE) || !pos.non_pawn_material(BLACK))
|
||||||
|
score += evaluate_unstoppable_pawns(pos, WHITE, ei)
|
||||||
|
- evaluate_unstoppable_pawns(pos, 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
|
||||||
|
ScaleFactor sf = eg_value(score) > VALUE_DRAW ? ei.mi->scale_factor(pos, WHITE)
|
||||||
|
: ei.mi->scale_factor(pos, BLACK);
|
||||||
|
|
||||||
|
// If we don't already have an unusual scale factor, check for opposite
|
||||||
|
// colored bishop endgames, and use a lower scale for those.
|
||||||
|
if ( ei.mi->game_phase() < PHASE_MIDGAME
|
||||||
|
&& pos.opposite_bishops()
|
||||||
|
&& (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
|
||||||
|
{
|
||||||
|
// Ignoring any pawns, do both sides only have a single bishop and no
|
||||||
|
// other pieces?
|
||||||
|
if ( pos.non_pawn_material(WHITE) == BishopValueMg
|
||||||
|
&& pos.non_pawn_material(BLACK) == BishopValueMg)
|
||||||
|
{
|
||||||
|
// Check for KBP vs KB with only a single pawn that is almost
|
||||||
|
// certainly a draw or at least two pawns.
|
||||||
|
bool one_pawn = (pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK) == 1);
|
||||||
|
sf = one_pawn ? ScaleFactor(8) : ScaleFactor(32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Endgame with opposite-colored bishops, but also other pieces. Still
|
||||||
|
// a bit drawish, but not as drawish as with only the two bishops.
|
||||||
|
sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value v = interpolate(score, ei.mi->game_phase(), sf);
|
||||||
|
|
||||||
|
// In case of tracing add all single evaluation contributions for both white and black
|
||||||
|
if (Trace)
|
||||||
|
{
|
||||||
|
Tracing::add_term(Tracing::PST, pos.psq_score());
|
||||||
|
Tracing::add_term(Tracing::IMBALANCE, ei.mi->material_value());
|
||||||
|
Tracing::add_term(PAWN, ei.pi->pawns_value());
|
||||||
|
Tracing::add_term(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::add_term(Tracing::SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
|
||||||
|
Tracing::add_term(Tracing::TOTAL, score);
|
||||||
|
Tracing::ei = ei;
|
||||||
|
Tracing::sf = sf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos.side_to_move() == WHITE ? v : -v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -994,4 +918,52 @@ Value do_evaluate(const Position& pos) {
|
|||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
namespace Eval {
|
||||||
|
|
||||||
|
/// evaluate() is the main evaluation function. It always computes two
|
||||||
|
/// values, an endgame score and a middlegame score, and interpolates
|
||||||
|
/// between them based on the remaining material.
|
||||||
|
|
||||||
|
Value evaluate(const Position& pos) {
|
||||||
|
return do_evaluate<false>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// trace() is like evaluate(), but instead of returning a value, it returns
|
||||||
|
/// a string (suitable for outputting to stdout) that contains the detailed
|
||||||
|
/// descriptions and values of each evaluation term. It's mainly used for
|
||||||
|
/// debugging.
|
||||||
|
std::string trace(const Position& pos) {
|
||||||
|
return Tracing::do_trace(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// init() computes evaluation weights from the corresponding UCI parameters
|
||||||
|
/// and setup king tables.
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
const int MaxSlope = 30;
|
||||||
|
const int Peak = 1280;
|
||||||
|
|
||||||
|
for (int t = 0, i = 1; i < 100; ++i)
|
||||||
|
{
|
||||||
|
t = std::min(Peak, std::min(int(0.4 * i * i), t + MaxSlope));
|
||||||
|
|
||||||
|
KingDanger[1][i] = apply_weight(make_score(t, 0), Weights[KingDangerUs]);
|
||||||
|
KingDanger[0][i] = apply_weight(make_score(t, 0), Weights[KingDangerThem]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Eval
|
||||||
|
|||||||
Reference in New Issue
Block a user