]> git.sesse.net Git - stockfish/blobdiff - src/evaluate.cpp
Change evaluation GrainSize from 4 to 8
[stockfish] / src / evaluate.cpp
index 62860b4a850d0ca42ed91a49369265068ced07e8..85665a4344de241382f68210b31041eeee1d01fb 100644 (file)
@@ -43,7 +43,7 @@ namespace {
   const int Sign[2] = { 1, -1 };
 
   // Evaluation grain size, must be a power of 2
-  const int GrainSize = 4;
+  const int GrainSize = 8;
 
   // Evaluation weights, initialized from UCI options
   int WeightMobilityMidgame, WeightMobilityEndgame;
@@ -58,16 +58,18 @@ namespace {
   // parameters at 100, which looks prettier.
   //
   // Values modified by Joona Kiiski
-  const int WeightMobilityMidgameInternal      = 0x0FA;
-  const int WeightMobilityEndgameInternal      = 0x10A;
-  const int WeightPawnStructureMidgameInternal = 0x0EC;
-  const int WeightPawnStructureEndgameInternal = 0x0CD;
-  const int WeightPassedPawnsMidgameInternal   = 0x108;
-  const int WeightPassedPawnsEndgameInternal   = 0x109;
-  const int WeightKingSafetyInternal           = 0x0F7;
-  const int WeightKingOppSafetyInternal        = 0x101;
-  const int WeightSpaceInternal                = 0x02F;
-
+  const int WeightMobilityMidgameInternal      = 248;
+  const int WeightMobilityEndgameInternal      = 271;
+  const int WeightPawnStructureMidgameInternal = 233;
+  const int WeightPawnStructureEndgameInternal = 201;
+  const int WeightPassedPawnsMidgameInternal   = 252;
+  const int WeightPassedPawnsEndgameInternal   = 259;
+  const int WeightKingSafetyInternal           = 247;
+  const int WeightKingOppSafetyInternal        = 259;
+  const int WeightSpaceInternal                = 46;
+
+  // Mobility and outposts bonus modified by Joona Kiiski
+  //
   // Visually better to define tables constants
   typedef Value V;
 
@@ -75,12 +77,12 @@ namespace {
   // of attacked squares not occupied by friendly piecess.
   const Value MidgameKnightMobilityBonus[] = {
   //    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)
+    V(-38), V(-25),V(-12), V(0), V(12), V(25), V(31), V(38), V(38)
   };
 
   const Value EndgameKnightMobilityBonus[] = {
   //    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)
+    V(-33), V(-23),V(-13), V(-3), V(7), V(17), V(22), V(27), V(27)
   };
 
   // Bishop mobility bonus in middle game and endgame, indexed by the number
@@ -88,16 +90,16 @@ namespace {
   // queens are also included.
   const Value MidgameBishopMobilityBonus[] = {
   //    0       1      2      3      4      5      6      7
-    V(-30), V(-15),  V(0), V(15), V(30), V(45), V(58), V(66),
+    V(-25), V(-11),  V(3), V(17), V(31), V(45), V(57), V(65),
   //    8       9     10     11     12     13     14     15
-    V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83)
+    V( 71), V( 74), V(76), V(78), V(79), V(80), V(81), V(81)
   };
 
   const Value EndgameBishopMobilityBonus[] = {
   //    0       1      2      3      4      5      6      7
-    V(-30), V(-15),  V(0), V(15), V(30), V(45), V(58), V(66),
+    V(-30), V(-16), V(-2), V(12), V(26), V(40), V(52), V(60),
   //    8       9     10     11     12     13     14     15
-    V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83)
+    V( 65), V( 69), V(71), V(73), V(74), V(75), V(76), V(76)
   };
 
   // Rook mobility bonus in middle game and endgame, indexed by the number
@@ -105,40 +107,40 @@ namespace {
   // queens and rooks are also included.
   const Value MidgameRookMobilityBonus[] = {
   //    0       1      2      3      4      5      6      7
-    V(-18), V(-12), V(-6),  V(0),  V(6), V(12), V(16), V(21),
+    V(-20), V(-14), V(-8), V(-2),  V(4), V(10), V(14), V(19),
   //    8       9     10     11     12     13     14     15
-    V( 24), V( 27), V(28), V(29), V(30), V(31), V(32), V(33)
+    V( 23), V( 26), V(27), V(28), V(29), V(30), V(31), V(32)
   };
 
   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),
+    V(-36), V(-19), V(-3), V(13), V(29), V(46), V(62), V(79),
   //    8       9     10     11     12     13     14     15
-    V( 66), V( 74), V(78), V(80), V(81), V(82), V(83), V(83)
+    V( 95), V(106),V(111),V(114),V(116),V(117),V(118),V(118)
   };
 
   // Queen mobility bonus in middle game and endgame, indexed by the number
   // of attacked squares not occupied by friendly pieces.
   const Value MidgameQueenMobilityBonus[] = {
   //    0      1      2      3      4      5      6      7
-    V(-10), V(-8), V(-6), V(-4), V(-2), V( 0), V( 2), V( 4),
+    V(-10), V(-8), V(-6), V(-3), V(-1), V( 1), V( 3), V( 5),
   //    8      9     10     11     12     13     14     15
-    V(  6), V( 8), V(10), V(12), V(13), V(14), V(15), V(16),
+    V(  8), V(10), V(12), V(15), V(16), V(17), V(18), V(20),
   //   16     17     18     19     20     21     22     23
-    V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16),
+    V( 20), V(20), V(20), V(20), V(20), V(20), V(20), V(20),
   //   24     25     26     27     28     29     30     31
-    V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16)
+    V( 20), V(20), V(20), V(20), V(20), V(20), V(20), V(20)
   };
 
   const Value EndgameQueenMobilityBonus[] = {
   //    0      1      2      3      4      5      6      7
-    V(-20),V(-15),V(-10), V(-5), V( 0), V( 5), V(10), V(15),
+    V(-18),V(-13), V(-7), V(-2), V( 3), V (8), V(13), V(19),
   //    8      9     10     11     12     13     14     15
-    V( 19), V(23), V(27), V(29), V(30), V(30), V(30), V(30),
+    V( 23), V(27), V(32), V(34), V(35), V(35), V(35), V(35),
   //   16     17     18     19     20     21     22     23
-    V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30),
+    V( 35), V(35), V(35), V(35), V(35), V(35), V(35), V(35),
   //   24     25     26     27     28     29     30     31
-    V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30)
+    V( 35), V(35), V(35), V(35), V(35), V(35), V(35), V(35)
   };
 
   // Outpost bonuses for knights and bishops, indexed by square (from white's
@@ -147,10 +149,10 @@ namespace {
   //  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(4), V(8), V(8), V(4), V(0), V(0), // 3
+    V(0), V(4),V(17),V(26),V(26),V(17), V(4), V(0), // 4
+    V(0), V(8),V(26),V(35),V(35),V(26), V(8), V(0), // 5
+    V(0), V(4),V(17),V(17),V(17),V(17), V(4), 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
   };
@@ -161,7 +163,7 @@ namespace {
     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(10),V(21),V(21),V(21),V(21),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
@@ -170,13 +172,13 @@ namespace {
   // Bonus for unstoppable passed pawns
   const Value UnstoppablePawnValue = Value(0x500);
 
-  // Rooks and queens on the 7th rank
+  // Rooks and queens on the 7th rank (modified by Joona Kiiski)
   const Value MidgameRookOn7thBonus  = Value(47);
   const Value EndgameRookOn7thBonus  = Value(98);
   const Value MidgameQueenOn7thBonus = Value(27);
   const Value EndgameQueenOn7thBonus = Value(54);
 
-  // Rooks on open files
+  // Rooks on open files (modified by Joona Kiiski)
   const Value RookOpenFileBonus = Value(43);
   const Value RookHalfOpenFileBonus = Value(19);
 
@@ -264,9 +266,6 @@ namespace {
   const int PawnTableSize = 16384;
   const int MaterialTableSize = 1024;
 
-  // Array which gives the number of nonzero bits in an 8-bit integer
-  uint8_t BitCount8Bit[256];
-
   // Function prototypes
   template<bool HasPopCnt>
   Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID);
@@ -274,15 +273,15 @@ namespace {
   template<PieceType Piece, bool HasPopCnt>
   void evaluate_pieces(const Position& p, Color us, EvalInfo& ei);
 
-  template<>
-  void evaluate_pieces<KING, false>(const Position& p, Color us, EvalInfo &ei);
+  template<bool HasPopCnt>
+  void evaluate_king(const Position& p, Color us, EvalInfo &ei);
 
   void evaluate_passed_pawns(const Position &pos, EvalInfo &ei);
   void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us,
                                     EvalInfo &ei);
   void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us,
                                     EvalInfo &ei);
-
+  template<bool HasPopCnt>
   void evaluate_space(const Position &p, Color us, EvalInfo &ei);
   inline Value apply_weight(Value v, int w);
   Value scale_by_game_phase(Value mv, Value ev, Phase ph, const ScaleFactor sf[]);
@@ -324,8 +323,8 @@ Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) {
 
   // Probe the material hash table
   ei.mi = MaterialTable[threadID]->get_material_info(pos);
-  ei.mgValue += ei.mi->mg_value();
-  ei.egValue += ei.mi->eg_value();
+  ei.mgValue += ei.mi->material_value();
+  ei.egValue += ei.mi->material_value();
 
   // If we have a specialized evaluation function for the current material
   // configuration, call it and return
@@ -343,16 +342,21 @@ Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) {
   ei.egValue += apply_weight(ei.pi->eg_value(), WeightPawnStructureEndgame);
 
   // Initialize king attack bitboards and king attack zones for both sides
-  ei.attackedBy[WHITE][KING] = pos.piece_attacks<KING>(pos.king_square(WHITE));
-  ei.attackedBy[BLACK][KING] = pos.piece_attacks<KING>(pos.king_square(BLACK));
+  ei.attackedBy[WHITE][KING] = pos.attacks_from<KING>(pos.king_square(WHITE));
+  ei.attackedBy[BLACK][KING] = pos.attacks_from<KING>(pos.king_square(BLACK));
   ei.kingZone[WHITE] = ei.attackedBy[BLACK][KING] | (ei.attackedBy[BLACK][KING] >> 8);
   ei.kingZone[BLACK] = ei.attackedBy[WHITE][KING] | (ei.attackedBy[WHITE][KING] << 8);
 
   // Initialize pawn attack bitboards for both sides
-  ei.attackedBy[WHITE][PAWN] = ((pos.pawns(WHITE) << 9) & ~FileABB) | ((pos.pawns(WHITE) << 7) & ~FileHBB);
-  ei.attackedBy[BLACK][PAWN] = ((pos.pawns(BLACK) >> 7) & ~FileABB) | ((pos.pawns(BLACK) >> 9) & ~FileHBB);
-  ei.kingAttackersCount[WHITE] = count_1s_max_15<HasPopCnt>(ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING])/2;
-  ei.kingAttackersCount[BLACK] = count_1s_max_15<HasPopCnt>(ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING])/2;
+  ei.attackedBy[WHITE][PAWN] = ((pos.pieces(PAWN, WHITE) << 9) & ~FileABB) | ((pos.pieces(PAWN, WHITE) << 7) & ~FileHBB);
+  ei.attackedBy[BLACK][PAWN] = ((pos.pieces(PAWN, BLACK) >> 7) & ~FileABB) | ((pos.pieces(PAWN, BLACK) >> 9) & ~FileHBB);
+  Bitboard b1 = ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING];
+  Bitboard b2 = ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING];
+  if (b1)
+      ei.kingAttackersCount[WHITE] = count_1s_max_15<HasPopCnt>(b1)/2;
+
+  if (b2)
+      ei.kingAttackersCount[BLACK] = count_1s_max_15<HasPopCnt>(b2)/2;
 
   // Evaluate pieces
   for (Color c = WHITE; c <= BLACK; c++)
@@ -368,11 +372,11 @@ Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) {
                             | ei.attackedBy[c][QUEEN]  | ei.attackedBy[c][KING];
   }
 
-  // Kings.  Kings are evaluated after all other pieces for both sides,
+  // Kings. Kings are evaluated after all other pieces for both sides,
   // because we need complete attack information for all pieces when computing
   // the king safety evaluation.
   for (Color c = WHITE; c <= BLACK; c++)
-      evaluate_pieces<KING, false>(pos, c, ei);
+      evaluate_king<HasPopCnt>(pos, c, ei);
 
   // Evaluate passed pawns.  We evaluate passed pawns for both sides at once,
   // because we need to know which side promotes first in positions where
@@ -401,8 +405,8 @@ Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) {
     // Evaluate space for both sides
     if (ei.mi->space_weight() > 0)
     {
-        evaluate_space(pos, WHITE, ei);
-        evaluate_space(pos, BLACK, ei);
+        evaluate_space<HasPopCnt>(pos, WHITE, ei);
+        evaluate_space<HasPopCnt>(pos, BLACK, ei);
     }
   }
 
@@ -491,12 +495,6 @@ void init_eval(int threads) {
     if (!MaterialTable[i])
         MaterialTable[i] = new MaterialInfoTable(MaterialTableSize);
   }
-
-  for (Bitboard b = 0ULL; b < 256ULL; b++)
-  {
-      assert(count_1s(b) == int(uint8_t(count_1s(b))));
-      BitCount8Bit[b] = (uint8_t)count_1s(b);
-  }
 }
 
 
@@ -530,6 +528,14 @@ void read_weights(Color us) {
 
   WeightKingSafety[us]   = weight_option("Cowardice", WeightKingSafetyInternal);
   WeightKingSafety[them] = weight_option("Aggressiveness", WeightKingOppSafetyInternal);
+  // If running in analysis mode, make sure we use symmetrical king safety.
+  // We do this by replacing both WeightKingSafety[us] and 
+  // WeightKingSafety[them] by their average.
+  if (get_option_value_bool("UCI_AnalyseMode")) {
+      WeightKingSafety[us] = (WeightKingSafety[us] + WeightKingSafety[them]) / 2;
+      WeightKingSafety[them] = WeightKingSafety[us];
+  }
+
   WeightSpace = weight_option("Space", WeightSpaceInternal);
 
   init_safety();
@@ -584,10 +590,10 @@ namespace {
 
     // Increase bonus if supported by pawn, especially if the opponent has
     // no minor piece which can exchange the outpost piece
-    if (bonus && (p.pawn_attacks(them, s) & p.pawns(us)))
+    if (bonus && (p.attacks_from<PAWN>(s, them) & p.pieces(PAWN, us)))
     {
-        if (    p.knights(them) == EmptyBoardBB
-            && (SquaresByColorBB[square_color(s)] & p.bishops(them)) == EmptyBoardBB)
+        if (    p.pieces(KNIGHT, them) == EmptyBoardBB
+            && (SquaresByColorBB[square_color(s)] & p.pieces(BISHOP, them)) == EmptyBoardBB)
             bonus += bonus + bonus / 2;
         else
             bonus += bonus / 2;
@@ -614,11 +620,11 @@ namespace {
         s = pos.piece_list(us, Piece, i);
 
         if (Piece == KNIGHT || Piece == QUEEN)
-            b = pos.piece_attacks<Piece>(s);
+            b = pos.attacks_from<Piece>(s);
         else if (Piece == BISHOP)
-            b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.queens(us));
+            b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(QUEEN, us));
         else if (Piece == ROOK)
-            b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.rooks_and_queens(us));
+            b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(ROOK, QUEEN, us));
         else
             assert(false);
 
@@ -699,16 +705,11 @@ namespace {
     }
   }
 
-  inline Bitboard shiftRowsDown(const Bitboard& b, int num) {
 
-    return b >> (num << 3);
-  }
-
-  // evaluate_pieces<KING>() assigns bonuses and penalties to a king of a given
-  // color.
+  // evaluate_king<>() assigns bonuses and penalties to a king of a given color.
 
-  template<>
-  void evaluate_pieces<KING, false>(const Position& p, Color us, EvalInfo& ei) {
+  template<bool HasPopCnt>
+  void evaluate_king(const Position& p, Color us, EvalInfo& ei) {
 
     int shelter = 0, sign = Sign[us];
     Square s = p.king_square(us);
@@ -716,19 +717,7 @@ namespace {
     // King shelter
     if (relative_rank(us, s) <= RANK_4)
     {
-        // Shelter cache lookup
-        shelter = ei.pi->kingShelter(us, s);
-        if (shelter == -1)
-        {
-            shelter = 0;
-            Bitboard pawns = p.pawns(us) & this_and_neighboring_files_bb(s);
-            Rank r = square_rank(s);
-            for (int i = 1; i < 4; i++)
-                shelter += BitCount8Bit[shiftRowsDown(pawns, r+i*sign) & 0xFF] * (128 >> i);
-
-            // Cache shelter value in pawn info
-            ei.pi->setKingShelter(us, s, shelter);
-        }
+        shelter = ei.pi->get_king_shelter(p, us, s);
         ei.mgValue += sign * Value(shelter);
     }
 
@@ -761,7 +750,7 @@ namespace {
       // quality of the pawn shelter.
       int attackUnits =
             Min((ei.kingAttackersCount[them] * ei.kingAttackersWeight[them]) / 2, 25)
-          + (ei.kingAdjacentZoneAttacksCount[them] + count_1s_max_15(undefended)) * 3
+          + (ei.kingAdjacentZoneAttacksCount[them] + count_1s_max_15<HasPopCnt>(undefended)) * 3
           + InitKingDanger[relative_square(us, s)] - (shelter >> 5);
 
       // Analyse safe queen contact checks
@@ -777,14 +766,14 @@ namespace {
         {
           // The bitboard b now contains the squares available for safe queen
           // contact checks.
-          int count = count_1s_max_15(b);
+          int count = count_1s_max_15<HasPopCnt>(b);
           attackUnits += QueenContactCheckBonus * count * (sente ? 2 : 1);
 
           // Is there a mate threat?
           if (QueenContactMates && !p.is_check())
           {
             Bitboard escapeSquares =
-                p.piece_attacks<KING>(s) & ~p.pieces_of_color(us) & ~attackedByOthers;
+                p.attacks_from<KING>(s) & ~p.pieces_of_color(us) & ~attackedByOthers;
 
             while (b)
             {
@@ -796,10 +785,10 @@ namespace {
                     for (int i = 0; i < p.piece_count(them, QUEEN); i++)
                     {
                         from = p.piece_list(them, QUEEN, i);
-                        if (    bit_is_set(p.piece_attacks<QUEEN>(from), to)
+                        if (    bit_is_set(p.attacks_from<QUEEN>(from), to)
                             && !bit_is_set(p.pinned_pieces(them), from)
-                            && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & p.rooks_and_queens(us))
-                            && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & p.bishops_and_queens(us)))
+                            && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(ROOK, QUEEN, us))
+                            && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(BISHOP, QUEEN, us)))
 
                             ei.mateThreat[them] = make_move(from, to);
                     }
@@ -812,49 +801,49 @@ namespace {
       // Analyse safe distance checks
       if (QueenCheckBonus > 0 || RookCheckBonus > 0)
       {
-          b = p.piece_attacks<ROOK>(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
+          b = p.attacks_from<ROOK>(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
 
           // Queen checks
           b2 = b & ei.attacked_by(them, QUEEN);
           if( b2)
-              attackUnits += QueenCheckBonus * count_1s_max_15(b2);
+              attackUnits += QueenCheckBonus * count_1s_max_15<HasPopCnt>(b2);
 
           // Rook checks
           b2 = b & ei.attacked_by(them, ROOK);
           if (b2)
-              attackUnits += RookCheckBonus * count_1s_max_15(b2);
+              attackUnits += RookCheckBonus * count_1s_max_15<HasPopCnt>(b2);
       }
       if (QueenCheckBonus > 0 || BishopCheckBonus > 0)
       {
-          b = p.piece_attacks<BISHOP>(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
+          b = p.attacks_from<BISHOP>(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
 
           // Queen checks
           b2 = b & ei.attacked_by(them, QUEEN);
           if (b2)
-              attackUnits += QueenCheckBonus * count_1s_max_15(b2);
+              attackUnits += QueenCheckBonus * count_1s_max_15<HasPopCnt>(b2);
 
           // Bishop checks
           b2 = b & ei.attacked_by(them, BISHOP);
           if (b2)
-              attackUnits += BishopCheckBonus * count_1s_max_15(b2);
+              attackUnits += BishopCheckBonus * count_1s_max_15<HasPopCnt>(b2);
       }
       if (KnightCheckBonus > 0)
       {
-          b = p.piece_attacks<KNIGHT>(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
+          b = p.attacks_from<KNIGHT>(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
 
           // Knight checks
           b2 = b & ei.attacked_by(them, KNIGHT);
           if (b2)
-              attackUnits += KnightCheckBonus * count_1s_max_15(b2);
+              attackUnits += KnightCheckBonus * count_1s_max_15<HasPopCnt>(b2);
       }
 
       // Analyse discovered checks (only for non-pawns right now, consider
       // adding pawns later).
       if (DiscoveredCheckBonus)
       {
-        b = p.discovered_check_candidates(them) & ~p.pawns();
+        b = p.discovered_check_candidates(them) & ~p.pieces(PAWN);
         if (b)
-          attackUnits += DiscoveredCheckBonus * count_1s_max_15(b) * (sente? 2 : 1);
+          attackUnits += DiscoveredCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente? 2 : 1);
       }
 
       // Has a mate threat been found?  We don't do anything here if the
@@ -900,7 +889,7 @@ namespace {
         Color them = opposite_color(us);
         Square ourKingSq = pos.king_square(us);
         Square theirKingSq = pos.king_square(them);
-        Bitboard b = ei.pi->passed_pawns() & pos.pawns(us), b2, b3, b4;
+        Bitboard b = ei.pi->passed_pawns() & pos.pieces(PAWN, us), b2, b3, b4;
 
         while (b)
         {
@@ -934,14 +923,14 @@ namespace {
                     // If there is an enemy rook or queen attacking the pawn from behind,
                     // add all X-ray attacks by the rook or queen.
                     if (    bit_is_set(ei.attacked_by(them,ROOK) | ei.attacked_by(them,QUEEN),s)
-                        && (squares_behind(us, s) & pos.rooks_and_queens(them)))
+                        && (squares_behind(us, s) & pos.pieces(ROOK, QUEEN, them)))
                         b3 = b2;
 
                     // Squares attacked or occupied by enemy pieces
                     b3 |= (b2 & pos.pieces_of_color(them));
 
                     // There are no enemy pawns in the pawn's path
-                    assert((b2 & pos.pieces_of_color_and_type(them, PAWN)) == EmptyBoardBB);
+                    assert((b2 & pos.pieces(PAWN, them)) == EmptyBoardBB);
 
                     // Are any of the squares in the pawn's path attacked or occupied by the enemy?
                     if (b3 == EmptyBoardBB)
@@ -962,10 +951,10 @@ namespace {
             }
 
             // If the pawn is supported by a friendly pawn, increase bonus
-            b2 = pos.pawns(us) & neighboring_files_bb(s);
+            b2 = pos.pieces(PAWN, us) & neighboring_files_bb(s);
             if (b2 & rank_bb(s))
                 ebonus += Value(r * 20);
-            else if (pos.pawn_attacks(them, s) & b2)
+            else if (pos.attacks_from<PAWN>(s, them) & b2)
                 ebonus += Value(r * 12);
 
             // If the other side has only a king, check whether the pawn is
@@ -1004,7 +993,7 @@ namespace {
                 if (   pos.non_pawn_material(them) <= KnightValueMidgame
                     && pos.piece_count(them, KNIGHT) <= 1)
                     ebonus += ebonus / 4;
-                else if (pos.rooks_and_queens(them))
+                else if (pos.pieces(ROOK, QUEEN, them))
                     ebonus -= ebonus / 4;
             }
 
@@ -1116,7 +1105,7 @@ namespace {
   // squares one, two or three squares behind a friendly pawn are counted
   // twice. Finally, the space bonus is scaled by a weight taken from the
   // material hash table.
-
+  template<bool HasPopCnt>
   void evaluate_space(const Position &pos, Color us, EvalInfo &ei) {
 
     Color them = opposite_color(us);
@@ -1126,13 +1115,13 @@ namespace {
     // pawn, or if it is undefended and attacked by an enemy piece.
 
     Bitboard safeSquares =   SpaceMask[us]
-                          & ~pos.pawns(us)
+                          & ~pos.pieces(PAWN, us)
                           & ~ei.attacked_by(them, PAWN)
                           & ~(~ei.attacked_by(us) & ei.attacked_by(them));
 
     // Find all squares which are at most three squares behind some friendly
     // pawn.
-    Bitboard behindFriendlyPawns = pos.pawns(us);
+    Bitboard behindFriendlyPawns = pos.pieces(PAWN, us);
     if (us == WHITE)
     {
         behindFriendlyPawns |= (behindFriendlyPawns >> 8);
@@ -1144,8 +1133,8 @@ namespace {
         behindFriendlyPawns |= (behindFriendlyPawns << 16);
     }
 
-    int space =  count_1s_max_15(safeSquares)
-               + count_1s_max_15(behindFriendlyPawns & safeSquares);
+    int space =  count_1s_max_15<HasPopCnt>(safeSquares)
+               + count_1s_max_15<HasPopCnt>(behindFriendlyPawns & safeSquares);
 
     ei.mgValue += Sign[us] * apply_weight(Value(space * ei.mi->space_weight()), WeightSpace);
   }