]> git.sesse.net Git - stockfish/blobdiff - src/evaluate.cpp
Group common evaluate code
[stockfish] / src / evaluate.cpp
index 74ee58f412e2e127497be66eb7341039b8e6c3d1..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/>.
 */
@@ -44,123 +44,136 @@ namespace {
   const int GrainSize = 4;
 
   // Evaluation weights
-  int WeightMobilityMidgame = 0x100;
-  int WeightMobilityEndgame = 0x100;
+  int WeightMobilityMidgame      = 0x100;
+  int WeightMobilityEndgame      = 0x100;
   int WeightPawnStructureMidgame = 0x100;
   int WeightPawnStructureEndgame = 0x100;
-  int WeightPassedPawnsMidgame = 0x100;
-  int WeightPassedPawnsEndgame = 0x100;
+  int WeightPassedPawnsMidgame   = 0x100;
+  int WeightPassedPawnsEndgame   = 0x100;
   int WeightKingSafety[2] = { 0x100, 0x100 };
 
   // 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.
-  const int WeightMobilityMidgameInternal = 0x100;
-  const int WeightMobilityEndgameInternal = 0x100;
+  const int WeightMobilityMidgameInternal      = 0x100;
+  const int WeightMobilityEndgameInternal      = 0x100;
   const int WeightPawnStructureMidgameInternal = 0x100;
   const int WeightPawnStructureEndgameInternal = 0x100;
-  const int WeightPassedPawnsMidgameInternal = 0x100;
-  const int WeightPassedPawnsEndgameInternal = 0x100;
-  const int WeightKingSafetyInternal = 0x100;
+  const int WeightPassedPawnsMidgameInternal   = 0x100;
+  const int WeightPassedPawnsEndgameInternal   = 0x100;
+  const int WeightKingSafetyInternal           = 0x100;
+
+  // Visually better to define tables constants
+  typedef Value V;
 
   // Knight mobility bonus in middle game and endgame, indexed by the number
   // of attacked squares not occupied by friendly piecess.
   const Value MidgameKnightMobilityBonus[] = {
-    Value(-30), Value(-20), Value(-10), Value(0), Value(10),
-    Value(20), Value(25), Value(30), Value(30)
+  //    0       1      2     3      4      5      6      7      8
+    V(-30), V(-20),V(-10), V(0), V(10), V(20), V(25), V(30), V(30)
   };
 
   const Value EndgameKnightMobilityBonus[] = {
-    Value(-30), Value(-20), Value(-10), Value(0), Value(10),
-    Value(20), Value(25), Value(30), Value(30)
+  //    0       1      2     3      4      5      6      7      8
+    V(-30), V(-20),V(-10), V(0), V(10), V(20), V(25), V(30), V(30)
   };
 
   // Bishop mobility bonus in middle game and endgame, indexed by the number
   // of attacked squares not occupied by friendly pieces.  X-ray attacks through
   // queens are also included.
   const Value MidgameBishopMobilityBonus[] = {
-    Value(-30), Value(-15), Value(0), Value(15), Value(30), Value(45),
-    Value(58), Value(66), Value(72), Value(76), Value(78), Value(80),
-    Value(81), Value(82), Value(83), Value(83)
+  //    0       1      2      3      4      5      6      7
+    V(-30), V(-15),  V(0), V(15), V(30), V(45), V(58), V(66),
+  //    8       9     10     11     12     13     14     15
+    V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83)
   };
 
   const Value EndgameBishopMobilityBonus[] = {
-    Value(-30), Value(-15), Value(0), Value(15), Value(30), Value(45),
-    Value(58), Value(66), Value(72), Value(76), Value(78), Value(80),
-    Value(81), Value(82), Value(83), Value(83)
+  //    0       1      2      3      4      5      6      7
+    V(-30), V(-15),  V(0), V(15), V(30), V(45), V(58), V(66),
+  //    8       9     10     11     12     13     14     15
+    V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83)
   };
 
   // Rook mobility bonus in middle game and endgame, indexed by the number
   // of attacked squares not occupied by friendly pieces.  X-ray attacks through
   // queens and rooks are also included.
   const Value MidgameRookMobilityBonus[] = {
-    Value(-18), Value(-12), Value(-6), Value(0), Value(6), Value(12),
-    Value(16), Value(21), Value(24), Value(27), Value(28), Value(29),
-    Value(30), Value(31), Value(32), Value(33)
+  //    0       1      2      3      4      5      6      7
+    V(-18), V(-12), V(-6),  V(0),  V(6), V(12), V(16), V(21),
+  //    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[] = {
-    Value(-30), Value(-18), Value(-6), Value(6), Value(18), Value(30),
-    Value(42), Value(54), Value(66), Value(74), Value(78), Value(80),
-    Value(81), Value(82), Value(83), Value(83)
+  //    0       1      2      3      4      5      6      7
+    V(-30), V(-18), V(-6),  V(6), V(18), V(30), V(42), V(54),
+  //    8       9     10     11     12     13     14     15
+    V( 66), V( 74), V(78), V(80), V(81), V(82), V(83), V(83)
   };
 
   // Queen mobility bonus in middle game and endgame, indexed by the number
   // of attacked squares not occupied by friendly pieces.
   const Value MidgameQueenMobilityBonus[] = {
-    Value(-10), Value(-8), Value(-6), Value(-4), Value(-2), Value(0), Value(2),
-    Value(4), Value(6), Value(8), Value(10), Value(12), Value(13), Value(14),
-    Value(15), Value(16), Value(16), Value(16), Value(16), Value(16),
-    Value(16), Value(16), Value(16), Value(16), Value(16), Value(16),
-    Value(16), Value(16), Value(16), Value(16), Value(16), Value(16)
+  //    0      1      2      3      4      5      6      7
+    V(-10), V(-8), V(-6), V(-4), V(-2), V( 0), V( 2), V( 4),
+  //    8      9     10     11     12     13     14     15
+    V(  6), V( 8), V(10), V(12), V(13), V(14), V(15), V(16),
+  //   16     17     18     19     20     21     22     23
+    V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16),
+  //   24     25     26     27     28     29     30     31
+    V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16)
   };
 
   const Value EndgameQueenMobilityBonus[] = {
-    Value(-20), Value(-15), Value(-10), Value(-5), Value(0), Value(5),
-    Value(10), Value(15), Value(19), Value(23), Value(27), Value(29),
-    Value(30), Value(30), Value(30), Value(30), Value(30), Value(30),
-    Value(30), Value(30), Value(30), Value(30), Value(30), Value(30),
-    Value(30), Value(30), Value(30), Value(30), Value(30), Value(30),
-    Value(30), Value(30)
+  //    0      1      2      3      4      5      6      7
+    V(-20),V(-15),V(-10), V(-5), V( 0), V( 5), V(10), V(15),
+  //    8      9     10     11     12     13     14     15
+    V( 19), V(23), V(27), V(29), V(30), V(30), V(30), V(30),
+  //   16     17     18     19     20     21     22     23
+    V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30),
+  //   24     25     26     27     28     29     30     31
+    V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30)
   };
 
-
   // Outpost bonuses for knights and bishops, indexed by square (from white's
   // point of view).
   const Value KnightOutpostBonus[64] = {
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
-    Value(0),Value(0),Value(5),Value(10),Value(10),Value(5),Value(0),Value(0),
-    Value(0),Value(5),Value(20),Value(30),Value(30),Value(20),Value(5),Value(0),
-    Value(0),Value(10),Value(30),Value(40),Value(40),Value(30),Value(10),Value(0),
-    Value(0),Value(5),Value(20),Value(20),Value(20),Value(20),Value(5),Value(0),
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0)
+  //  A     B     C     D     E     F     G     H
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 1
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 2
+    V(0), V(0), V(5),V(10),V(10), V(5), V(0), V(0), // 3
+    V(0), V(5),V(20),V(30),V(30),V(20), V(5), V(0), // 4
+    V(0),V(10),V(30),V(40),V(40),V(30),V(10), V(0), // 5
+    V(0), V(5),V(20),V(20),V(20),V(20), V(5), V(0), // 6
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 7
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0)  // 8
   };
 
   const Value BishopOutpostBonus[64] = {
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
-    Value(0),Value(0),Value(5),Value(5),Value(5),Value(5),Value(0),Value(0),
-    Value(0),Value(5),Value(10),Value(10),Value(10),Value(10),Value(5),Value(0),
-    Value(0),Value(10),Value(20),Value(20),Value(20),Value(20),Value(10),Value(0),
-    Value(0),Value(5),Value(8),Value(8),Value(8),Value(8),Value(5),Value(0),
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
-    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0)
+  //  A     B     C     D     E     F     G     H
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 1
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 2
+    V(0), V(0), V(5), V(5), V(5), V(5), V(0), V(0), // 3
+    V(0), V(5),V(10),V(10),V(10),V(10), V(5), V(0), // 4
+    V(0),V(10),V(20),V(20),V(20),V(20),V(10), V(0), // 5
+    V(0), V(5), V(8), V(8), V(8), V(8), V(5), V(0), // 6
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 7
+    V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0)  // 8
   };
 
   // Bonus for unstoppable passed pawns:
   const Value UnstoppablePawnValue = Value(0x500);
 
   // Rooks and queens on the 7th rank:
-  const Value MidgameRookOn7thBonus = Value(50);
-  const Value EndgameRookOn7thBonus = Value(100);
+  const Value MidgameRookOn7thBonus  = Value(50);
+  const Value EndgameRookOn7thBonus  = Value(100);
   const Value MidgameQueenOn7thBonus = Value(25);
   const Value EndgameQueenOn7thBonus = Value(50);
 
   // Rooks on open files:
-  const Value RookOpenFileBonus = Value(40);
+  const Value RookOpenFileBonus     = Value(40);
   const Value RookHalfOpenFileBonus = Value(20);
 
   // Penalty for rooks trapped inside a friendly king which has lost the
@@ -188,26 +201,25 @@ namespace {
     ((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
   /// as an index to SafetyTable[].
 
   // Attack weights for each piece type.
-  const int QueenAttackWeight = 5;
-  const int RookAttackWeight = 3;
+  const int QueenAttackWeight  = 5;
+  const int RookAttackWeight   = 3;
   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;
-  int RookCheckBonus = 1;
-  int BishopCheckBonus = 1;
-  int KnightCheckBonus = 1;
-  int DiscoveredCheckBonus = 3;
+  int RookContactCheckBonus  = 2;
+  int QueenCheckBonus        = 2;
+  int RookCheckBonus         = 1;
+  int BishopCheckBonus       = 1;
+  int KnightCheckBonus       = 1;
+  int DiscoveredCheckBonus   = 3;
 
   // Scan for queen contact mates?
   const bool QueenContactMates = true;
@@ -218,20 +230,20 @@ namespace {
   // InitKingDanger[] contains bonuses based on the position of the defending
   // king.
   const int InitKingDanger[64] = {
-    2, 0, 2, 5, 5, 2, 0, 2,
-    2, 2, 4, 8, 8, 4, 2, 2,
-    7, 10, 12, 12, 12, 12, 10, 7,
+     2,  0,  2,  5,  5,  2,  0,  2,
+     2,  2,  4,  8,  8,  4,  2,  2,
+     7, 10, 12, 12, 12, 12, 10,  7,
     15, 15, 15, 15, 15, 15, 15, 15,
     15, 15, 15, 15, 15, 15, 15, 15,
     15, 15, 15, 15, 15, 15, 15, 15,
     15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15
   };
 
   // SafetyTable[] contains the actual king safety scores.  It is initialized
   // in init_safety().
   Value SafetyTable[100];
 
-
   // Pawn and material hash tables, indexed by the current thread id:
   PawnInfoTable *PawnTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
   MaterialInfoTable *MaterialTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
@@ -256,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);
@@ -340,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);
@@ -378,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];
   }
 
@@ -408,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);
   }
@@ -471,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();
@@ -484,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);
 }
 
 
@@ -559,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)];
 
@@ -607,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)];
 
@@ -649,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)) {
@@ -685,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:
@@ -729,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);
@@ -744,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.
@@ -776,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
@@ -784,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 =
@@ -857,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);
@@ -1067,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));
@@ -1097,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);
@@ -1127,7 +1126,7 @@ namespace {
         penalty = TrappedBishopA1H1Penalty;
       else
         penalty = TrappedBishopA1H1Penalty / 2;
-      
+
       ei.mgValue -= Sign[us] * penalty;
       ei.egValue -= Sign[us] * penalty;
     }
@@ -1145,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);
@@ -1169,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]);
   }
@@ -1182,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");
@@ -1204,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")
@@ -1222,5 +1221,5 @@ namespace {
       if(SafetyTable[i]  > Value(peak))
         SafetyTable[i] = Value(peak);
   }
-  
+
 }