]> git.sesse.net Git - stockfish/blobdiff - src/evaluate.cpp
Introduce new Threats weights = {350, 256}
[stockfish] / src / evaluate.cpp
index 897fc778a467ded318fbbba61f0dc047af32845a..406d07459df577af3c617b40b91d2257a1774d32 100644 (file)
@@ -107,10 +107,10 @@ namespace {
 
 
   // Evaluation weights, indexed by the corresponding evaluation term
-  enum { Mobility, PawnStructure, PassedPawns, Space, KingSafety };
+  enum { Mobility, PawnStructure, PassedPawns, Space, KingSafety, Threats };
 
   const struct Weight { int mg, eg; } Weights[] = {
-    {289, 344}, {233, 201}, {221, 273}, {46, 0}, {322, 0}
+    {289, 344}, {233, 201}, {221, 273}, {46, 0}, {322, 0}, {350, 256}
   };
 
   Score operator*(Score s, const Weight& w) {
@@ -141,6 +141,11 @@ namespace {
       S(112,125), S(113,127), S(117,137), S(122,143) }
   };
 
+  // Mask of allowed outpost squares indexed by color
+  const Bitboard OutpostMask[COLOR_NB] = {
+    Rank4BB | Rank5BB | Rank6BB, Rank5BB | Rank4BB | Rank3BB
+  };
+
   // Outpost[knight/bishop][supported by pawn] contains bonuses for knights and
   // bishops outposts, bigger if outpost piece is supported by a pawn.
   const Score Outpost[][2] = {
@@ -148,6 +153,13 @@ namespace {
     { S(18, 5), S(27, 8) }  // Bishops
   };
 
+  // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for knights and
+  // bishops which can reach a outpost square in one move, bigger if outpost square is supported by a pawn.
+  const Score ReachableOutpost[][2] = {
+    { S(21, 5), S(31, 8) }, // Knights
+    { S( 8, 2), S(13, 4) }  // Bishops
+  };
+
   // Threat[minor/rook][attacked PieceType] contains
   // bonuses according to which piece type attacks which one.
   // Attacks on lesser pieces which are pawn defended are not considered.
@@ -171,8 +183,8 @@ namespace {
 
   // PassedFile[File] contains a bonus according to the file of a passed pawn.
   const Score PassedFile[] = {
-    S( 12,  10), S( 3,  10), S( 1, -8), S(-27, -12),
-    S(-27, -12), S( 1, -8),  S( 3, 10), S( 12,  10)
+    S( 12,  10), S( 3, 10), S( 1, -8), S(-27, -12),
+    S(-27, -12), S( 1, -8), S( 3, 10), S( 12,  10)
   };
 
   const Score ThreatenedByHangingPawn = S(40, 60);
@@ -257,7 +269,7 @@ namespace {
   template<PieceType Pt, Color Us, bool DoTrace>
   Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility, const Bitboard* mobilityArea) {
 
-    Bitboard b;
+    Bitboard b, bb;
     Square s;
     Score score = SCORE_ZERO;
 
@@ -283,7 +295,7 @@ namespace {
         {
             ei.kingAttackersCount[Us]++;
             ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
-            Bitboard bb = b & ei.attackedBy[Them][KING];
+            bb = b & ei.attackedBy[Them][KING];
             if (bb)
                 ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
         }
@@ -299,11 +311,16 @@ namespace {
 
         if (Pt == BISHOP || Pt == KNIGHT)
         {
-            // Bonus for outpost square
-            if (   relative_rank(Us, s) >= RANK_4
-                && relative_rank(Us, s) <= RANK_6
-                && !(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
+            // Bonus for outpost squares
+            bb = OutpostMask[Us] & ~ei.pi->pawn_attacks_span(Them);
+            if (bb & s)
                 score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)];
+            else
+            {
+                bb &= b & ~pos.pieces(Us);
+                if (bb)
+                   score += ReachableOutpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
+            }
 
             // Bonus when behind a pawn
             if (    relative_rank(Us, s) < RANK_5
@@ -549,9 +566,9 @@ namespace {
         score += popcount<Max15>(b) * PawnAttackThreat;
 
     if (DoTrace)
-        Trace::add(THREAT, Us, score);
+        Trace::add(THREAT, Us, score * Weights[Threats]);
 
-    return score;
+    return score * Weights[Threats];
   }
 
 
@@ -677,20 +694,18 @@ namespace {
   // evaluate_initiative() computes the initiative correction value for the
   // position, i.e. second order bonus/malus based on the known attacking/defending
   // status of the players.
-  Score evaluate_initiative(const Position& pos, const EvalInfo& ei, const Score positional_score) {
+  Score evaluate_initiative(const Position& pos, int asymmetry, Value eg) {
 
-    int king_separation = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
-    int pawns           = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
-    int asymmetry       = ei.pi->pawn_asymmetry();
+    int kingDistance = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
+    int pawns = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
 
     // Compute the initiative bonus for the attacking side
-    int attacker_bonus = 8 * (pawns + asymmetry + king_separation) - 120;
+    int initiative = 8 * (pawns + asymmetry + kingDistance - 15);
 
-    // Now apply the bonus: note that we find the attacking side by extracting the sign
-    // of the endgame value of "positional_score", and that we carefully cap the bonus so
-    // that the endgame score with the correction will never be divided by more than two.
-    int eg = eg_value(positional_score);
-    int value = ((eg > 0) - (eg < 0)) * std::max(attacker_bonus, -abs(eg / 2));
+    // Now apply the bonus: note that we find the attacking side by extracting
+    // the sign of the endgame value, and that we carefully cap the bonus so
+    // that the endgame score will never be divided by more than two.
+    int value = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg / 2));
 
     return make_score(0, value);
   }
@@ -777,8 +792,8 @@ Value Eval::evaluate(const Position& pos) {
   if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222)
       score += (evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei)) * Weights[Space];
 
-  // Evaluate initiative
-  score += evaluate_initiative(pos, ei, score);
+  // Evaluate position potential for the winning side
+  score += evaluate_initiative(pos, ei.pi->pawn_asymmetry(), eg_value(score));
 
   // Scale winning side if position is more drawish than it appears
   Color strongSide = eg_value(score) > VALUE_DRAW ? WHITE : BLACK;