]> git.sesse.net Git - stockfish/blobdiff - src/evaluate.cpp
Sync with master
[stockfish] / src / evaluate.cpp
index e03dfb94fb7fa28dcd18f43710f10b7c5ac98ed1..30e4c59a040ea1761ebbfa9d6526f5e7f4ee94bc 100644 (file)
 
 namespace {
 
+  namespace Tracing {
+
+    enum Term { // First 8 entries are for PieceType
+      MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, TOTAL, TERM_NB
+    };
+
+    Score scores[COLOR_NB][TERM_NB];
+
+    std::ostream& operator<<(std::ostream& os, Term idx);
+
+    double to_cp(Value v);
+    void write(int idx, Color c, Score s);
+    void write(int idx, Score w, Score b = SCORE_ZERO);
+    std::string do_trace(const Position& pos);
+  }
+
+
   // Struct EvalInfo contains various information computed and collected
   // by the evaluation functions.
   struct EvalInfo {
@@ -61,38 +78,29 @@ namespace {
     // KingAttackWeights array.
     int kingAttackersWeight[COLOR_NB];
 
-    // kingAdjacentZoneAttacksCount[color] is the number of attacks to squares
-    // directly adjacent to the king of the given color. Pieces which attack
-    // more than one square are counted multiple times. For instance, if black's
-    // king is on g8 and there's a white knight on g5, this knight adds
-    // 2 to kingAdjacentZoneAttacksCount[BLACK].
+    // kingAdjacentZoneAttacksCount[color] is the number of attacks by the given
+    // color to squares directly adjacent to the enemy king. Pieces which attack
+    // more than one square are counted multiple times. For instance, if there is
+    // a white knight on g5 and black's king is on g8, this white knight adds 2
+    // to kingAdjacentZoneAttacksCount[WHITE].
     int kingAdjacentZoneAttacksCount[COLOR_NB];
 
     Bitboard pinnedPieces[COLOR_NB];
   };
 
-  namespace Tracing {
-
-    enum Term { // First 8 entries are for PieceType
-      MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, TOTAL, TERMS_NB
-    };
-
-    Score scores[COLOR_NB][TERMS_NB];
-
-    std::ostream& operator<<(std::ostream& os, Term idx);
-
-    double to_cp(Value v);
-    void write(int idx, Color c, Score s);
-    void write(int idx, Score w, Score b = SCORE_ZERO);
-    std::string do_trace(const Position& pos);
-  }
 
-  // Evaluation weights, indexed by evaluation term
+  // Evaluation weights, indexed by the corresponding evaluation term
   enum { Mobility, PawnStructure, PassedPawns, Space, KingSafety };
+
   const struct Weight { int mg, eg; } Weights[] = {
     {289, 344}, {233, 201}, {221, 273}, {46, 0}, {322, 0}
   };
 
+  Score operator*(Score s, const Weight& w) {
+    return make_score(mg_value(s) * w.mg / 256, eg_value(s) * w.eg / 256);
+  }
+
+
   #define V(v) Value(v)
   #define S(mg, eg) make_score(mg, eg)
 
@@ -147,7 +155,7 @@ namespace {
   // ThreatenedByPawn[PieceType] contains a penalty according to which piece
   // type is attacked by an enemy pawn.
   const Score ThreatenedByPawn[PIECE_TYPE_NB] = {
-    S(0, 0), S(0, 0), S(87, 118), S(84, 122), S(114, 203), S(121, 217)
+    S(0, 0), S(0, 0), S(107, 138), S(84, 122), S(114, 203), S(121, 217)
   };
 
   // Assorted bonuses and penalties used by evaluation
@@ -162,6 +170,7 @@ namespace {
   const Score Unstoppable        = S( 0, 20);
   const Score Hanging            = S(31, 26);
   const Score PawnAttackThreat   = S(20, 20);
+  const Score PawnSafePush       = S( 5,  5);
 
   // Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
   // a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
@@ -184,11 +193,12 @@ namespace {
   // in KingDanger[]. Various little "meta-bonuses" measuring the strength
   // of the enemy attack are added up into an integer, which is used as an
   // index to KingDanger[].
-  //
+  Score KingDanger[512];
+
   // KingAttackWeights[PieceType] contains king attack weights by piece type
   const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 7, 5, 4, 1 };
 
-  // Bonuses for enemy's safe checks
+  // Penalties for enemy's safe checks
   const int QueenContactCheck = 89;
   const int RookContactCheck  = 71;
   const int QueenCheck        = 50;
@@ -196,15 +206,6 @@ namespace {
   const int BishopCheck       = 6;
   const int KnightCheck       = 14;
 
-  // KingDanger[attackUnits] contains the actual king danger weighted
-  // scores, indexed by a calculated integer number.
-  Score KingDanger[512];
-
-  // apply_weight() weighs score 's' by weight 'w' trying to prevent overflow
-  Score apply_weight(Score s, const Weight& w) {
-    return make_score(mg_value(s) * w.mg / 256, eg_value(s) * w.eg / 256);
-  }
-
 
   // init_eval_info() initializes king bitboards for given color adding
   // pawn attacks. To be done at the beginning of the evaluation.
@@ -300,8 +301,7 @@ namespace {
                    | ei.attackedBy[Them][BISHOP]
                    | ei.attackedBy[Them][ROOK]);
 
-        int mob = Pt != QUEEN ? popcount<Max15>(b & mobilityArea[Us])
-                              : popcount<Full >(b & mobilityArea[Us]);
+        int mob = popcount<Pt == QUEEN ? Full : Max15>(b & mobilityArea[Us]);
 
         mobility[Us] += MobilityBonus[Pt][mob];
 
@@ -411,10 +411,10 @@ namespace {
         // attacked and undefended squares around our king and the quality of
         // the pawn shelter (current 'score' value).
         attackUnits =  std::min(74, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
-                     + 8 * ei.kingAdjacentZoneAttacksCount[Them]
+                     +  8 * ei.kingAdjacentZoneAttacksCount[Them]
                      + 25 * popcount<Max15>(undefended)
-                     +  11 * (ei.pinnedPieces[Us] != 0)
-                     - mg_value(score) * 31 / 256
+                     + 11 * (ei.pinnedPieces[Us] != 0)
+                     - mg_value(score) / 8
                      - !pos.count<QUEEN>(Them) * 60;
 
         // Analyse the enemy's safe queen contact checks. Firstly, find the
@@ -505,8 +505,7 @@ namespace {
     Score score = SCORE_ZERO;
 
     // Non-pawn enemies defended by a pawn
-    defended =  (pos.pieces(Them) ^ pos.pieces(Them, PAWN))
-              &  ei.attackedBy[Them][PAWN];
+    defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Them][PAWN];
 
     // Add a bonus according to the kind of attacking pieces
     if (defended)
@@ -545,14 +544,18 @@ namespace {
             score += more_than_one(b) ? KingOnMany : KingOnOne;
     }
 
-    // Add bonus for safe pawn pushes which attacks an enemy piece
+    // Add a small bonus for safe pawn pushes
     b = pos.pieces(Us, PAWN) & ~TRank7BB;
     b = shift_bb<Up>(b | (shift_bb<Up>(b & TRank2BB) & ~pos.pieces()));
 
     b &=  ~pos.pieces()
         & ~ei.attackedBy[Them][PAWN]
-        & (ei.attackedBy[Us][PAWN] | ~ei.attackedBy[Them][ALL_PIECES]);
+        & (ei.attackedBy[Us][ALL_PIECES] | ~ei.attackedBy[Them][ALL_PIECES]);
+
+    if (b)
+        score += popcount<Full>(b) * PawnSafePush;
 
+    // Add another bonus if the pawn push attacks an enemy piece
     b =  (shift_bb<Left>(b) | shift_bb<Right>(b))
        &  pos.pieces(Them)
        & ~ei.attackedBy[Us][PAWN];
@@ -644,10 +647,10 @@ namespace {
     }
 
     if (Trace)
-        Tracing::write(Tracing::PASSED, Us, apply_weight(score, Weights[PassedPawns]));
+        Tracing::write(Tracing::PASSED, Us, score * Weights[PassedPawns]);
 
     // Add the scores to the middlegame and endgame eval
-    return apply_weight(score, Weights[PassedPawns]);
+    return score * Weights[PassedPawns];
   }
 
 
@@ -713,7 +716,7 @@ namespace {
 
     // Probe the pawn hash table
     ei.pi = Pawns::probe(pos);
-    score += apply_weight(ei.pi->pawns_score(), Weights[PawnStructure]);
+    score += ei.pi->pawns_score() * Weights[PawnStructure];
 
     // Initialize attack and king safety bitboards
     init_eval_info<WHITE>(pos, ei);
@@ -728,7 +731,7 @@ namespace {
 
     // Evaluate pieces and mobility
     score += evaluate_pieces<KNIGHT, WHITE, Trace>(pos, ei, mobility, mobilityArea);
-    score += apply_weight(mobility[WHITE] - mobility[BLACK], Weights[Mobility]);
+    score += (mobility[WHITE] - mobility[BLACK]) * Weights[Mobility];
 
     // Evaluate kings after all other pieces because we need complete attack
     // information when computing the king safety evaluation.
@@ -755,11 +758,8 @@ namespace {
     }
 
     // Evaluate space for both sides, only during opening
-    if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 2 * QueenValueMg + 4 * RookValueMg + 2 * KnightValueMg)
-    {
-        Score s = evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei);
-        score += apply_weight(s, Weights[Space]);
-    }
+    if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 11756)
+        score += (evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei)) * Weights[Space];
 
     // Scale winning side if position is more drawish than it appears
     Color strongSide = eg_value(score) > VALUE_DRAW ? WHITE : BLACK;
@@ -803,14 +803,14 @@ namespace {
         Tracing::write(Tracing::MATERIAL, pos.psq_score());
         Tracing::write(Tracing::IMBALANCE, ei.mi->imbalance());
         Tracing::write(PAWN, ei.pi->pawns_score());
-        Tracing::write(Tracing::MOBILITY, apply_weight(mobility[WHITE], Weights[Mobility])
-                                        , apply_weight(mobility[BLACK], Weights[Mobility]));
-        Tracing::write(Tracing::SPACE, apply_weight(evaluate_space<WHITE>(pos, ei), Weights[Space])
-                                     , apply_weight(evaluate_space<BLACK>(pos, ei), Weights[Space]));
+        Tracing::write(Tracing::MOBILITY, mobility[WHITE] * Weights[Mobility]
+                                        , mobility[BLACK] * Weights[Mobility]);
+        Tracing::write(Tracing::SPACE, evaluate_space<WHITE>(pos, ei) * Weights[Space]
+                                     , evaluate_space<BLACK>(pos, ei) * Weights[Space]);
         Tracing::write(Tracing::TOTAL, score);
     }
 
-    return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo;
+    return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo; // Side to move point of view
   }
 
 
@@ -899,14 +899,14 @@ namespace Eval {
 
   void init() {
 
-    const double MaxSlope = 8.7;
-    const double Peak = 1280;
-    double t = 0.0;
+    const int MaxSlope = 8700;
+    const int Peak = 1280000;
+    int t = 0;
 
-    for (int i = 1; i < 400; ++i)
+    for (int i = 0; i < 400; ++i)
     {
-        t = std::min(Peak, std::min(0.027 * i * i, t + MaxSlope));
-        KingDanger[i] = apply_weight(make_score(int(t), 0), Weights[KingSafety]);
+        t = std::min(Peak, std::min(i * i * 27, t + MaxSlope));
+        KingDanger[i] = make_score(t / 1000, 0) * Weights[KingSafety];
     }
   }