X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fevaluate.cpp;h=bea0e306388ffed3864091372247f003b55af9b9;hb=7f56d2949d4244c9d2e6796adc721582e9d85804;hp=e1a000c6323d081a2458285083c2c38a4b0910b8;hpb=86c20416c85ac93ab982dda404fc268a92636fa6;p=stockfish
diff --git a/src/evaluate.cpp b/src/evaluate.cpp
index e1a000c6..bea0e306 100644
--- a/src/evaluate.cpp
+++ b/src/evaluate.cpp
@@ -17,10 +17,10 @@
along with this program. If not, see .
*/
+#include
#include
#include
#include
-#include
#include "bitcount.h"
#include "evaluate.h"
@@ -89,23 +89,15 @@ namespace {
std::string do_trace(const Position& pos);
}
- // Evaluation weights, initialized from UCI options
- enum { Mobility, PawnStructure, PassedPawns, Space, KingDangerUs, KingDangerThem };
- struct Weight { int mg, eg; } Weights[6];
+ // Evaluation weights, indexed by evaluation term
+ enum { Mobility, PawnStructure, PassedPawns, Space, KingSafety };
+ const struct Weight { int mg, eg; } Weights[] = {
+ {289, 344}, {233, 201}, {221, 273}, {46, 0}, {318, 0}
+ };
typedef Value V;
#define S(mg, eg) make_score(mg, eg)
- // Internal evaluation weights. These are applied on top of the evaluation
- // weights read from UCI parameters. The purpose is to be able to change
- // the evaluation weights while keeping the default values of the UCI
- // parameters at 100, which looks prettier.
- //
- // Values modified by Joona Kiiski
- const Score WeightsInternal[] = {
- S(289, 344), S(233, 201), S(221, 273), S(46, 0), S(271, 0), S(307, 0)
- };
-
// MobilityBonus[PieceType][attacked] contains bonuses for middle and end
// game, indexed by piece type and number of attacked squares not occupied by
// friendly pieces.
@@ -158,15 +150,16 @@ namespace {
S(0, 0), S(0, 0), S(56, 70), S(56, 70), S(76, 99), S(86, 118)
};
+ // Hanging contains a bonus for each enemy hanging piece
+ const Score Hanging = S(23, 20);
+
#undef S
- const Score Tempo = make_score(24, 11);
const Score RookOnPawn = make_score(10, 28);
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);
const Score Unstoppable = make_score( 0, 20);
@@ -200,9 +193,9 @@ namespace {
const int BishopCheck = 2;
const int KnightCheck = 3;
- // KingDanger[Color][attackUnits] contains the actual king danger weighted
- // scores, indexed by color and by a calculated integer number.
- Score KingDanger[COLOR_NB][128];
+ // KingDanger[attackUnits] contains the actual king danger weighted
+ // scores, indexed by a calculated integer number.
+ Score KingDanger[128];
// apply_weight() weighs score 'v' by weight 'w' trying to prevent overflow
@@ -211,31 +204,6 @@ namespace {
}
- // weight_option() computes the value of an evaluation weight, by combining
- // two UCI-configurable weights (midgame and endgame) with an internal weight.
-
- Weight weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight) {
-
- Weight w = { Options[mgOpt] * mg_value(internalWeight) / 100,
- Options[egOpt] * eg_value(internalWeight) / 100 };
- return w;
- }
-
-
- // interpolate() interpolates between a middlegame and an endgame score,
- // based on game phase. It also scales the return value by a ScaleFactor array.
-
- Value interpolate(const Score& v, Phase ph, ScaleFactor sf) {
-
- assert(-VALUE_INFINITE < mg_value(v) && mg_value(v) < VALUE_INFINITE);
- 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;
- return Value((mg_value(v) * int(ph) + eg * int(PHASE_MIDGAME - ph)) / PHASE_MIDGAME);
- }
-
-
// init_eval_info() initializes king bitboards for given color adding
// pawn attacks. To be done at the beginning of the evaluation.
@@ -457,9 +425,7 @@ namespace {
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]);
if (b)
- attackUnits += QueenContactCheck
- * popcount(b)
- * (Them == pos.side_to_move() ? 2 : 1);
+ attackUnits += QueenContactCheck * popcount(b);
}
// Analyse the enemy's safe rook contact checks. Firstly, find the
@@ -477,9 +443,7 @@ namespace {
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]);
if (b)
- attackUnits += RookContactCheck
- * popcount(b)
- * (Them == pos.side_to_move() ? 2 : 1);
+ attackUnits += RookContactCheck * popcount(b);
}
// Analyse the enemy's safe distance checks for sliders and knights
@@ -513,7 +477,7 @@ namespace {
// Finally, extract the king danger score from the KingDanger[]
// array and subtract the score from evaluation.
- score -= KingDanger[Us == Search::RootColor][attackUnits];
+ score -= KingDanger[attackUnits];
}
if (Trace)
@@ -531,17 +495,10 @@ namespace {
const Color Them = (Us == WHITE ? BLACK : WHITE);
- Bitboard b, undefendedMinors, weakEnemies;
+ Bitboard b, weakEnemies;
Score score = SCORE_ZERO;
- // Undefended minors get penalized even if they are not under attack
- undefendedMinors = pos.pieces(Them, BISHOP, KNIGHT)
- & ~ei.attackedBy[Them][ALL_PIECES];
-
- if (undefendedMinors)
- score += UndefendedMinor;
-
- // Enemy pieces not defended by a pawn and under our attack
+ // Enemies not defended by a pawn and under our attack
weakEnemies = pos.pieces(Them)
& ~ei.attackedBy[Them][PAWN]
& ei.attackedBy[Us][ALL_PIECES];
@@ -549,13 +506,17 @@ namespace {
// Add a bonus according if the attacking pieces are minor or major
if (weakEnemies)
{
- b = weakEnemies & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]);
+ b = weakEnemies & (ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]);
if (b)
score += Threat[0][type_of(pos.piece_on(lsb(b)))];
b = weakEnemies & (ei.attackedBy[Us][ROOK] | ei.attackedBy[Us][QUEEN]);
if (b)
score += Threat[1][type_of(pos.piece_on(lsb(b)))];
+
+ b = weakEnemies & ~ei.attackedBy[Them][ALL_PIECES];
+ if (b)
+ score += more_than_one(b) ? Hanging * popcount(b) : Hanging;
}
if (Trace)
@@ -583,8 +544,8 @@ namespace {
assert(pos.pawn_passed(Us, s));
- Rank r = relative_rank(Us, s) - RANK_2;
- Rank rr = r * (r - 1);
+ int r = relative_rank(Us, s) - RANK_2;
+ int rr = r * (r - 1);
// Base bonus based on rank
Value mbonus = Value(17 * rr), ebonus = Value(7 * (rr + r + 1));
@@ -599,7 +560,7 @@ namespace {
// If blockSq is not the queening square then consider also a second push
if (relative_rank(Us, blockSq) != RANK_8)
- ebonus -= rr * square_distance(pos.king_square(Us), blockSq + pawn_push(Us));
+ ebonus -= square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr;
// If the pawn is free to advance, then increase the bonus
if (pos.empty(blockSq))
@@ -710,9 +671,9 @@ namespace {
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);
+ // 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);
@@ -734,7 +695,7 @@ namespace {
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
+ // 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)) };
@@ -793,7 +754,11 @@ namespace {
sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
}
- Value v = interpolate(score, ei.mi->game_phase(), sf);
+ // 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)
@@ -860,7 +825,7 @@ namespace {
<< " | MG EG | MG EG | MG EG \n"
<< "---------------------+-------------+-------------+-------------\n";
- format_row(ss, "Material, PST, Tempo", PST);
+ format_row(ss, "Material, PST", PST);
format_row(ss, "Material imbalance", IMBALANCE);
format_row(ss, "Pawns", PAWN);
format_row(ss, "Knights", KNIGHT);
@@ -890,7 +855,7 @@ namespace Eval {
/// of the position always from the point of view of the side to move.
Value evaluate(const Position& pos) {
- return do_evaluate(pos);
+ return do_evaluate(pos) + Tempo;
}
@@ -908,22 +873,13 @@ namespace Eval {
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 double MaxSlope = 30;
const double Peak = 1280;
for (int t = 0, i = 1; i < 100; ++i)
{
- t = std::min(Peak, std::min(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]);
+ t = int(std::min(Peak, std::min(0.4 * i * i, t + MaxSlope)));
+ KingDanger[i] = apply_weight(make_score(t, 0), Weights[KingSafety]);
}
}