]> git.sesse.net Git - stockfish/commitdiff
Use std library to sort moves
authorMarco Costalba <mcostalba@gmail.com>
Thu, 14 Jul 2011 11:12:49 +0000 (12:12 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Thu, 14 Jul 2011 11:43:13 +0000 (12:43 +0100)
Functional change due to the fact that now pick_best() is
stable, but should be no change in strenght.

Example code and ideas by Rein Halbersma.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/bitboard.h
src/move.h
src/movepick.cpp
src/position.cpp
src/search.cpp

index 0177df8cdb02c7345e991c3de6046ff412a7b03a..55f40eee2e8e2414c2af55c4e1c5c949670fd982 100644 (file)
@@ -245,7 +245,7 @@ inline Bitboard attack_span_mask(Color c, Square s) {
 
 inline bool squares_aligned(Square s1, Square s2, Square s3) {
   return  (BetweenBB[s1][s2] | BetweenBB[s1][s3] | BetweenBB[s2][s3])
-        & ((1ULL << s1) | (1ULL << s2) | (1ULL << s3));
+        & (    SetMaskBB[s1] |     SetMaskBB[s2] |     SetMaskBB[s3]);
 }
 
 
index d014dc7775bae101542f12cc0080d50c49240bc6..3d97799741667d73c2009a65265f93fe503e9fd2 100644 (file)
@@ -55,7 +55,7 @@ inline bool operator<(const MoveStack& f, const MoveStack& s) { return f.score <
 
 // An helper insertion sort implementation, works with pointers and iterators
 template<typename T, typename K>
-inline void insertion_sort(K firstMove, K lastMove)
+inline void sort(K firstMove, K lastMove)
 {
     T value;
     K cur, p, d;
@@ -74,61 +74,6 @@ inline void insertion_sort(K firstMove, K lastMove)
         }
 }
 
-// Our dedicated sort in range [firstMove, lastMove), first splits
-// positive scores from ramining then order seaprately the two sets.
-template<typename T>
-inline void sort_moves(T* firstMove, T* lastMove, T** lastPositive)
-{
-    T tmp;
-    T *p, *d;
-
-    d = lastMove;
-    p = firstMove - 1;
-
-    d->score = -1; // right guard
-
-    // Split positives vs non-positives
-    do {
-        while ((++p)->score > 0) {}
-
-        if (p != d)
-        {
-            while (--d != p && d->score <= 0) {}
-
-            tmp = *p;
-            *p = *d;
-            *d = tmp;
-        }
-
-    } while (p != d);
-
-    // Sort just positive scored moves, remaining only when we get there
-    insertion_sort<T, T*>(firstMove, p);
-    *lastPositive = p;
-}
-
-// Picks up the best move in range [curMove, lastMove), one per cycle.
-// It is faster then sorting all the moves in advance when moves are few,
-// as normally are the possible captures. Note that is not a stable alghoritm.
-template<typename T>
-inline T pick_best(T* curMove, T* lastMove)
-{
-    T bestMove, tmp;
-
-    bestMove = *curMove;
-    while (++curMove != lastMove)
-    {
-        if (bestMove < *curMove)
-        {
-            tmp = *curMove;
-            *curMove = bestMove;
-            bestMove = tmp;
-        }
-    }
-    return bestMove;
-}
-
-
 inline Square move_from(Move m) {
   return Square((m >> 6) & 0x3F);
 }
index 07e8ef9d97290b68db0bb17076dfd11fd00b1374..b9594ba1cf998689596a139300ffc473688a9285 100644 (file)
@@ -18,6 +18,7 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <algorithm>
 #include <cassert>
 
 #include "movegen.h"
@@ -49,6 +50,19 @@ namespace {
   const uint8_t QsearchWithoutChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_STOP };
   const uint8_t QsearchRecapturesTable[] = { PH_TT_MOVE, PH_QRECAPTURES, PH_STOP };
   const uint8_t ProbCutTable[] = { PH_TT_MOVE, PH_GOOD_PROBCUT, PH_STOP };
+
+  // Unary predicate used by std::partition to split positive scores from ramining
+  // ones so to sort separately the two sets, and with the second sort delayed.
+  inline bool has_positive_score(const MoveStack& move) { return move.score > 0; }
+
+  // Picks and pushes to the front the best move in range [firstMove, lastMove),
+  // it is faster then sorting all the moves in advance when moves are few, as
+  // normally are the possible captures.
+  inline MoveStack* pick_best(MoveStack* firstMove, MoveStack* lastMove)
+  {
+      std::swap(*firstMove, *std::max_element(firstMove, lastMove));
+      return firstMove;
+  }
 }
 
 /// Constructors for the MovePicker class. As arguments we pass information
@@ -164,14 +178,15 @@ void MovePicker::go_next_phase() {
   case PH_NONCAPTURES_1:
       lastNonCapture = lastMove = generate<MV_NON_CAPTURE>(pos, moves);
       score_noncaptures();
-      sort_moves(moves, lastNonCapture, &lastMove);
+      lastMove = std::partition(curMove, lastMove, has_positive_score);
+      sort<MoveStack>(curMove, lastMove);
       return;
 
   case PH_NONCAPTURES_2:
       curMove = lastMove;
       lastMove = lastNonCapture;
       if (depth >= 3 * ONE_PLY)
-          insertion_sort<MoveStack>(curMove, lastMove);
+          sort<MoveStack>(curMove, lastMove);
       return;
 
   case PH_BAD_CAPTURES:
@@ -306,7 +321,7 @@ Move MovePicker::get_next_move() {
           break;
 
       case PH_GOOD_CAPTURES:
-          move = pick_best(curMove++, lastMove).move;
+          move = pick_best(curMove++, lastMove)->move;
           if (move != ttMove)
           {
               assert(captureThreshold <= 0); // Otherwise we must use see instead of see_sign
@@ -324,7 +339,7 @@ Move MovePicker::get_next_move() {
           break;
 
      case PH_GOOD_PROBCUT:
-          move = pick_best(curMove++, lastMove).move;
+          move = pick_best(curMove++, lastMove)->move;
           if (   move != ttMove
               && pos.see(move) > captureThreshold)
               return move;
@@ -349,12 +364,12 @@ Move MovePicker::get_next_move() {
           break;
 
       case PH_BAD_CAPTURES:
-          move = pick_best(curMove++, lastMove).move;
+          move = pick_best(curMove++, lastMove)->move;
           return move;
 
       case PH_EVASIONS:
       case PH_QCAPTURES:
-          move = pick_best(curMove++, lastMove).move;
+          move = pick_best(curMove++, lastMove)->move;
           if (move != ttMove)
               return move;
           break;
index 281109b19a34a8ba6d3f6602115d7b61d4cbb43a..cb5370d5b581412af7b800a6ffc891abcca75739 100644 (file)
@@ -513,14 +513,14 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   assert(piece_color(piece_on(from)) == us);
   assert(piece_on(king_square(us)) == make_piece(us, KING));
 
-  // En passant captures are a tricky special case. Because they are
-  // rather uncommon, we do it simply by testing whether the king is attacked
-  // after the move is made
+  // En passant captures are a tricky special case. Because they are rather
+  // uncommon, we do it simply by testing whether the king is attacked after
+  // the move is made.
   if (move_is_ep(m))
   {
       Color them = opposite_color(us);
       Square to = move_to(m);
-      Square capsq = make_square(square_file(to), square_rank(from));
+      Square capsq = to + Square(us == WHITE ? -8 : 8);
       Square ksq = king_square(us);
       Bitboard b = occupied_squares();
 
index 41992efbc55b5625649ecfe380e81775af703356..829e1bbef9bb3155048e72d65e424b8ba7c2eb87 100644 (file)
@@ -79,16 +79,9 @@ namespace {
     Move pv[PLY_MAX_PLUS_2];
   };
 
-  // RootMoveList struct is just a vector of RootMove objects,
-  // with an handful of methods above the standard ones.
+  // RootMoveList struct is mainly a std::vector of RootMove objects
   struct RootMoveList : public std::vector<RootMove> {
-
-    typedef std::vector<RootMove> Base;
-
     void init(Position& pos, Move searchMoves[]);
-    void sort() { insertion_sort<RootMove, Base::iterator>(begin(), end()); }
-    void sort_first(int n) { insertion_sort<RootMove, Base::iterator>(begin(), begin() + n); }
-
     int bestMoveChanges;
   };
 
@@ -1219,7 +1212,7 @@ split_point_start: // At split points actual search starts from here
               // because all the values but the first are usually set to
               // -VALUE_INFINITE and we want to keep the same order for all
               // the moves but the new PV that goes to head.
-              Rml.sort_first(moveCount);
+              sort<RootMove>(Rml.begin(), Rml.begin() + moveCount);
 
               // Update alpha. In multi-pv we don't use aspiration window, so set
               // alpha equal to minimum score among the PV lines searched so far.
@@ -1555,7 +1548,7 @@ split_point_start: // At split points actual search starts from here
   bool connected_moves(const Position& pos, Move m1, Move m2) {
 
     Square f1, t1, f2, t2;
-    Piece p;
+    Piece p1, p2;
 
     assert(m1 && move_is_ok(m1));
     assert(m2 && move_is_ok(m2));
@@ -1573,17 +1566,18 @@ split_point_start: // At split points actual search starts from here
         return true;
 
     // Case 3: Moving through the vacated square
-    if (   piece_is_slider(pos.piece_on(f2))
+    p2 = pos.piece_on(f2);
+    if (   piece_is_slider(p2)
         && bit_is_set(squares_between(f2, t2), f1))
       return true;
 
     // Case 4: The destination square for m2 is defended by the moving piece in m1
-    p = pos.piece_on(t1);
-    if (bit_is_set(pos.attacks_from(p, t1), t2))
+    p1 = pos.piece_on(t1);
+    if (bit_is_set(pos.attacks_from(p1, t1), t2))
         return true;
 
     // Case 5: Discovered check, checking piece is the piece moved in m1
-    if (    piece_is_slider(p)
+    if (    piece_is_slider(p1)
         &&  bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), f2)
         && !bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), t2))
     {
@@ -2093,7 +2087,7 @@ split_point_start: // At split points actual search starts from here
                 break;
             }
 
-    Rml.sort();
+    sort<RootMove>(Rml.begin(), Rml.end());
   }
 
 } // namespace