]> git.sesse.net Git - stockfish/blobdiff - src/evaluate.cpp
Group common evaluate code
[stockfish] / src / evaluate.cpp
index bf02fc81f319025c3905da95f44d2266920c83be..6f4de561fd42aa68156a4df42e25ec54f1b7790a 100644 (file)
@@ -6,12 +6,12 @@
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
-  
+
   Glaurung is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
-  
+
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -105,7 +105,7 @@ namespace {
   //    8       9     10     11     12     13     14     15
     V( 24), V( 27), V(28), V(29), V(30), V(31), V(32), V(33)
   };
-  
+
   const Value EndgameRookMobilityBonus[] = {
   //    0       1      2      3      4      5      6      7
     V(-30), V(-18), V(-6),  V(6), V(18), V(30), V(42), V(54),
@@ -200,7 +200,7 @@ namespace {
     ((1ULL << SQ_A1) | (1ULL << SQ_H1)),
     ((1ULL << SQ_A8) | (1ULL << SQ_H8))
   };
-  
+
   /// King safety constants and variables.  The king safety scores are taken
   /// from the array SafetyTable[].  Various little "meta-bonuses" measuring
   /// the strength of the attack are added up into an integer, which is used
@@ -212,7 +212,7 @@ namespace {
   const int BishopAttackWeight = 2;
   const int KnightAttackWeight = 2;
 
-  // Bonuses for safe checks for each piece type.  
+  // Bonuses for safe checks for each piece type.
   int QueenContactCheckBonus = 4;
   int RookContactCheckBonus  = 2;
   int QueenCheckBonus        = 2;
@@ -268,7 +268,7 @@ namespace {
   void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us,
                                     EvalInfo &ei);
 
-  Value apply_weight(Value v, int w);
+  inline Value apply_weight(Value v, int w);
   Value scale_by_game_phase(Value mv, Value ev, Phase ph, ScaleFactor sf[]);
 
   int count_1s_8bit(Bitboard b);
@@ -352,7 +352,7 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
       s = pos.knight_list(c, i);
       evaluate_knight(pos, s, c, ei);
     }
-    
+
     // Bishops
     for(int i = 0; i < pos.bishop_count(c); i++) {
       s = pos.bishop_list(c, i);
@@ -390,8 +390,8 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
     }
 
     ei.attackedBy[c][0] =
-      ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT] 
-      | ei.attackedBy[c][BISHOP] | ei.attackedBy[c][ROOK] 
+      ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT]
+      | ei.attackedBy[c][BISHOP] | ei.attackedBy[c][ROOK]
       | ei.attackedBy[c][QUEEN] | ei.attackedBy[c][KING];
   }
 
@@ -420,7 +420,7 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
         ei.pi->kingside_storm_value(BLACK);
     else if(square_file(pos.king_square(WHITE)) <= FILE_D &&
             square_file(pos.king_square(BLACK)) >= FILE_E)
-      ei.mgValue += 
+      ei.mgValue +=
         ei.pi->kingside_storm_value(WHITE) -
         ei.pi->queenside_storm_value(BLACK);
   }
@@ -483,7 +483,7 @@ Value quick_evaluate(const Position &pos) {
   Value mgValue, egValue;
   ScaleFactor factor[2] = {SCALE_FACTOR_NORMAL, SCALE_FACTOR_NORMAL};
   Phase phase;
-  
+
   assert(pos.is_ok());
 
   stm = pos.side_to_move();
@@ -496,32 +496,32 @@ Value quick_evaluate(const Position &pos) {
 
   return Sign[stm] * value;
 }
-  
+
 
 /// init_eval() initializes various tables used by the evaluation function.
 
 void init_eval(int threads) {
+
   assert(threads <= THREAD_MAX);
-  
-  for(int i = 0; i < threads; i++) {
-    if(PawnTable[i] == NULL)
-      PawnTable[i] = new PawnInfoTable(PawnTableSize);
-    if(MaterialTable[i] == NULL)
-      MaterialTable[i] = new MaterialInfoTable(MaterialTableSize);
-  }
-  for(int i = threads; i < THREAD_MAX; i++) {
-    if(PawnTable[i] != NULL) {
-      delete PawnTable[i];
-      PawnTable[i] = NULL;
-    }
-    if(MaterialTable[i] != NULL) {
-      delete MaterialTable[i];
-      MaterialTable[i] = NULL;
+
+  for (int i = 0; i < THREAD_MAX; i++)
+  {
+    if (i >= threads)
+    {
+        delete PawnTable[i];
+        delete MaterialTable[i];
+        PawnTable[i] = NULL;
+        MaterialTable[i] = NULL;
+        continue;
     }
+    if (!PawnTable[i])
+        PawnTable[i] = new PawnInfoTable(PawnTableSize);
+    if (!MaterialTable[i])
+        MaterialTable[i] = new MaterialInfoTable(MaterialTableSize);
   }
 
-  for(Bitboard b = 0ULL; b < 256ULL; b++)
-    BitCount8Bit[b] = count_1s(b);
+  for (Bitboard b = 0ULL; b < 256ULL; b++)
+      BitCount8Bit[b] = count_1s(b);
 }
 
 
@@ -571,32 +571,46 @@ void read_weights(Color sideToMove) {
 
 namespace {
 
-  // evaluate_knight() assigns bonuses and penalties to a knight of a given
-  // color on a given square.
-  
-  void evaluate_knight(const Position &p, Square s, Color us, EvalInfo &ei) {
+  // evaluate_common() computes terms common to all pieces attack
+
+  int evaluate_common(const Position&p, const Bitboard& b, Color us, EvalInfo& ei,
+                       int AttackWeight, const Value* mgBonus, const Value* egBonus) {
 
     Color them = opposite_color(us);
-    Bitboard b = p.knight_attacks(s);
-    ei.attackedBy[us][KNIGHT] |= b;
 
     // King attack
     if(b & ei.attackZone[us]) {
       ei.attackCount[us]++;
-      ei.attackWeight[us] += KnightAttackWeight;
+      ei.attackWeight[us] += AttackWeight;
       Bitboard bb = (b & ei.attackedBy[them][KING]);
       if(bb) ei.attacked[us] += count_1s_max_15(bb);
     }
-        
+
     // Mobility
     int mob = count_1s_max_15(b & ~p.pieces_of_color(us));
-    ei.mgMobility += Sign[us] * MidgameKnightMobilityBonus[mob];
-    ei.egMobility += Sign[us] * EndgameKnightMobilityBonus[mob];
+    ei.mgMobility += Sign[us] * mgBonus[mob];
+    ei.egMobility += Sign[us] * egBonus[mob];
+
+    return mob;
+  }
+
+  // evaluate_knight() assigns bonuses and penalties to a knight of a given
+  // color on a given square.
+
+  void evaluate_knight(const Position &p, Square s, Color us, EvalInfo &ei) {
+
+    Color them = opposite_color(us);
+    Bitboard b = p.knight_attacks(s);
+    ei.attackedBy[us][KNIGHT] |= b;
+
+    // King attack and mobility
+    evaluate_common(p, b, us, ei, KnightAttackWeight,
+                    MidgameKnightMobilityBonus, EndgameKnightMobilityBonus);
 
     // Knight outposts:
     if(p.square_is_weak(s, them)) {
       Value v, bonus;
-      
+
       // Initial bonus based on square:
       v = bonus = KnightOutpostBonus[relative_square(us, s)];
 
@@ -619,32 +633,23 @@ namespace {
 
   // evaluate_bishop() assigns bonuses and penalties to a bishop of a given
   // color on a given square.
-  
+
   void evaluate_bishop(const Position &p, Square s, Color us, EvalInfo &ei) {
 
     Color them = opposite_color(us);
     Bitboard b =
       bishop_attacks_bb(s, p.occupied_squares() & ~p.queens(us));
-                                   
-    ei.attackedBy[us][BISHOP] |= b;
 
-    // King attack
-    if(b & ei.attackZone[us]) {
-      ei.attackCount[us]++;
-      ei.attackWeight[us] += BishopAttackWeight;
-      Bitboard bb = (b & ei.attackedBy[them][KING]);
-      if(bb) ei.attacked[us] += count_1s_max_15(bb);
-    }
+    ei.attackedBy[us][BISHOP] |= b;
 
-    // Mobility:
-    int mob = count_1s_max_15(b & ~p.pieces_of_color(us));
-    ei.mgMobility += Sign[us] * MidgameBishopMobilityBonus[mob];
-    ei.egMobility += Sign[us] * EndgameBishopMobilityBonus[mob];
+    // King attack and mobility
+    evaluate_common(p, b, us, ei, BishopAttackWeight,
+                    MidgameBishopMobilityBonus, EndgameBishopMobilityBonus);
 
     // Bishop outposts:
     if(p.square_is_weak(s, them)) {
       Value v, bonus;
-      
+
       // Initial bonus based on square:
       v = bonus = BishopOutpostBonus[relative_square(us, s)];
 
@@ -661,17 +666,17 @@ namespace {
 
       ei.mgValue += Sign[us] * bonus;
       ei.egValue += Sign[us] * bonus;
-    }    
+    }
   }
-  
+
 
   // evaluate_rook() assigns bonuses and penalties to a rook of a given
   // color on a given square.
-  
+
   void evaluate_rook(const Position &p, Square s, Color us, EvalInfo &ei) {
 
     Color them = opposite_color(us);
-    
+
     // Open and half-open files:
     File f = square_file(s);
     if(ei.pi->file_is_half_open(us, f)) {
@@ -697,18 +702,9 @@ namespace {
       rook_attacks_bb(s, p.occupied_squares() & ~p.rooks_and_queens(us));
     ei.attackedBy[us][ROOK] |= b;
 
-    // King attack
-    if(b & ei.attackZone[us]) {
-      ei.attackCount[us]++;
-      ei.attackWeight[us] += RookAttackWeight;
-      Bitboard bb = (b & ei.attackedBy[them][KING]);
-      if(bb) ei.attacked[us] += count_1s_max_15(bb);
-    }
-
-    // Mobility
-    int mob = count_1s_max_15(b & ~p.pieces_of_color(us));
-    ei.mgMobility += Sign[us] * MidgameRookMobilityBonus[mob];
-    ei.egMobility += Sign[us] * EndgameRookMobilityBonus[mob];
+    // King attack and mobility
+    int mob = evaluate_common(p, b, us, ei, RookAttackWeight,
+                              MidgameRookMobilityBonus, EndgameRookMobilityBonus);
 
     // Penalize rooks which are trapped inside a king which has lost the
     // right to castle:
@@ -741,7 +737,7 @@ namespace {
 
   // evaluate_queen() assigns bonuses and penalties to a queen of a given
   // color on a given square.
-  
+
   void evaluate_queen(const Position &p, Square s, Color us, EvalInfo &ei) {
 
     Color them = opposite_color(us);
@@ -756,26 +752,17 @@ namespace {
     Bitboard b = p.queen_attacks(s);
     ei.attackedBy[us][QUEEN] |= b;
 
-    // King attack
-    if(b & ei.attackZone[us]) {
-      ei.attackCount[us]++;
-      ei.attackWeight[us] += QueenAttackWeight;
-      Bitboard bb = (b & ei.attackedBy[them][KING]);
-      if(bb) ei.attacked[us] += count_1s_max_15(bb);
-    }
-    
-    // Mobility
-    int mob = count_1s(b & ~p.pieces_of_color(us));
-    ei.mgMobility += Sign[us] * MidgameQueenMobilityBonus[mob];
-    ei.egMobility += Sign[us] * EndgameQueenMobilityBonus[mob];
+    // King attack and mobility
+    evaluate_common(p, b, us, ei, QueenAttackWeight,
+                    MidgameQueenMobilityBonus, EndgameQueenMobilityBonus);
   }
 
 
   // evaluate_king() assigns bonuses and penalties to a king of a given
   // color on a given square.
-  
+
   void evaluate_king(const Position &p, Square s, Color us, EvalInfo &ei) {
-    
+
     int shelter = 0, sign = Sign[us];
 
     // King shelter.
@@ -788,7 +775,7 @@ namespace {
     }
 
     // King safety.  This is quite complicated, and is almost certainly far
-    // from optimally tuned.  
+    // from optimally tuned.
     Color them = opposite_color(us);
     if(p.queen_count(them) >= 1 && ei.attackCount[them] >= 2
        && p.non_pawn_material(them) >= QueenValueMidgame + RookValueMidgame
@@ -796,7 +783,7 @@ namespace {
 
       // Is it the attackers turn to move?
       bool sente = (them == p.side_to_move());
-      
+
       // Find the attacked squares around the king which has no defenders
       // apart from the king itself:
       Bitboard undefended =
@@ -869,7 +856,7 @@ namespace {
           }
         }
       }
-      
+
       // Analyse safe distance checks:
       if(QueenCheckBonus > 0 || RookCheckBonus > 0) {
         b = p.rook_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
@@ -1079,7 +1066,7 @@ namespace {
   // evaluate_trapped_bishop_a7h7() determines whether a bishop on a7/h7
   // (a2/h2 for black) is trapped by enemy pawns, and assigns a penalty
   // if it is.
-  
+
   void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us,
                                     EvalInfo &ei) {
     Piece pawn = pawn_of_color(opposite_color(us));
@@ -1109,7 +1096,7 @@ namespace {
   // (a8/h8 for black) is trapped by a friendly pawn on b2/g2 (b7/g7 for
   // black), and assigns a penalty if it is.  This pattern can obviously
   // only occur in Chess960 games.
-  
+
   void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us,
                                     EvalInfo &ei) {
     Piece pawn = pawn_of_color(us);
@@ -1139,7 +1126,7 @@ namespace {
         penalty = TrappedBishopA1H1Penalty;
       else
         penalty = TrappedBishopA1H1Penalty / 2;
-      
+
       ei.mgValue -= Sign[us] * penalty;
       ei.egValue -= Sign[us] * penalty;
     }
@@ -1157,7 +1144,7 @@ namespace {
   // scale_by_game_phase interpolates between a middle game and an endgame
   // score, based on game phase.  It also scales the return value by a
   // ScaleFactor array.
-  
+
   Value scale_by_game_phase(Value mv, Value ev, Phase ph, ScaleFactor sf[]) {
     assert(mv > -VALUE_INFINITE && mv < VALUE_INFINITE);
     assert(ev > -VALUE_INFINITE && ev < VALUE_INFINITE);
@@ -1181,7 +1168,7 @@ namespace {
   // count_1s_8bit() counts the number of nonzero bits in the 8 least
   // significant bits of a Bitboard. This function is used by the king
   // shield evaluation.
-  
+
   int count_1s_8bit(Bitboard b) {
     return int(BitCount8Bit[b & 0xFF]);
   }
@@ -1194,15 +1181,15 @@ namespace {
     uciWeight = (uciWeight * 0x100) / 100;
     return (uciWeight * internalWeight) / 0x100;
   }
-  
+
 
   // init_safety() initizes the king safety evaluation, based on UCI
   // parameters.  It is called from read_weights().
-  
+
   void init_safety() {
     double a, b;
     int maxSlope, peak, i, j;
-    
+
     QueenContactCheckBonus = get_option_value_int("Queen Contact Check Bonus");
     RookContactCheckBonus = get_option_value_int("Rook Contact Check Bonus");
     QueenCheckBonus = get_option_value_int("Queen Check Bonus");
@@ -1216,7 +1203,7 @@ namespace {
     b = get_option_value_int("King Safety X Intercept") * 1.0;
     maxSlope = get_option_value_int("King Safety Max Slope");
     peak = (get_option_value_int("King Safety Max Value") * 256) / 100;
-    
+
     for(i = 0; i < 100; i++) {
       if(i < b) SafetyTable[i] = Value(0);
       else if(get_option_value_string("King Safety Curve") == "Quadratic")
@@ -1234,5 +1221,5 @@ namespace {
       if(SafetyTable[i]  > Value(peak))
         SafetyTable[i] = Value(peak);
   }
-  
+
 }