]> git.sesse.net Git - stockfish/blobdiff - src/movepick.cpp
Rename stages
[stockfish] / src / movepick.cpp
index 3b636b935d431ac1af263b6e1ede2fc882fb3e23..94ceedbfd4cf4a37cca4e4db6104a982ce60576f 100644 (file)
 namespace {
 
   enum Stages {
-    MAIN_SEARCH, CAPTURES_S1, KILLERS_S1, QUIETS_1_S1, QUIETS_2_S1, BAD_CAPTURES_S1,
-    EVASION,     EVASIONS_S2,
-    QSEARCH_0,   CAPTURES_S3, QUIET_CHECKS_S3,
-    QSEARCH_1,   CAPTURES_S4,
-    PROBCUT,     CAPTURES_S5,
-    RECAPTURE,   CAPTURES_S6,
+    MAIN_SEARCH, GOOD_CAPTURES, KILLERS, GOOD_QUIETS, BAD_QUIETS, BAD_CAPTURES,
+    EVASION, ALL_EVASIONS,
+    QSEARCH_WITH_CHECKS, QCAPTURES_1, CHECKS,
+    QSEARCH_WITHOUT_CHECKS, QCAPTURES_2,
+    PROBCUT, PROBCUT_CAPTURES,
+    RECAPTURE, RECAPTURES,
     STOP
   };
 
@@ -52,7 +52,7 @@ namespace {
   // pick_best() finds the best move in the range (begin, end) and moves it to
   // the front. It's faster than sorting all the moves in advance when there
   // are few moves e.g. the possible captures.
-  inline Move pick_best(ExtMove* begin, ExtMove* end)
+  Move pick_best(ExtMove* begin, ExtMove* end)
   {
       std::swap(*begin, *std::max_element(begin, end));
       return *begin;
@@ -67,14 +67,13 @@ namespace {
 /// search captures, promotions and some checks) and how important good move
 /// ordering is at the current node.
 
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
-                       Move* cm, Move* fm, Search::Stack* s) : pos(p), history(h), depth(d) {
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h, const CounterMovesHistoryStats& cmh,
+                       Move cm, Search::Stack* s) : pos(p), history(h), counterMovesHistory(cmh), depth(d) {
 
   assert(d > DEPTH_ZERO);
 
   endBadCaptures = moves + MAX_MOVES - 1;
-  countermoves = cm;
-  followupmoves = fm;
+  countermove = cm;
   ss = s;
 
   if (pos.checkers())
@@ -87,8 +86,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
   endMoves += (ttMove != MOVE_NONE);
 }
 
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
-                       Square s) : pos(p), history(h) {
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h, const CounterMovesHistoryStats& cmh,
+                       Square s) : pos(p), history(h), counterMovesHistory(cmh) {
 
   assert(d <= DEPTH_ZERO);
 
@@ -96,10 +95,10 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
       stage = EVASION;
 
   else if (d > DEPTH_QS_NO_CHECKS)
-      stage = QSEARCH_0;
+      stage = QSEARCH_WITH_CHECKS;
 
   else if (d > DEPTH_QS_RECAPTURES)
-      stage = QSEARCH_1;
+      stage = QSEARCH_WITHOUT_CHECKS;
 
   else
   {
@@ -112,8 +111,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
   endMoves += (ttMove != MOVE_NONE);
 }
 
-MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, PieceType pt)
-                       : pos(p), history(h) {
+MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, const CounterMovesHistoryStats& cmh, PieceType pt)
+                       : pos(p), history(h), counterMovesHistory(cmh) {
 
   assert(!pos.checkers());
 
@@ -135,10 +134,10 @@ MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Piece
 /// highest values will be picked first.
 template<>
 void MovePicker::score<CAPTURES>() {
-  // Winning and equal captures in the main search are ordered by MVV/LVA.
+  // Winning and equal captures in the main search are ordered by MVV.
   // Suprisingly, this appears to perform slightly better than SEE based
   // move ordering. The reason is probably that in a position with a winning
-  // capture, capturing a more valuable (but sufficiently defended) piece
+  // capture, capturing a valuable (but sufficiently defended) piece
   // first usually doesn't hurt. The opponent will have to recapture, and
   // the hanging piece will still be hanging (except in the unusual cases
   // where it is possible to recapture with the hanging piece). Exchanging
@@ -149,21 +148,19 @@ void MovePicker::score<CAPTURES>() {
   // has been picked up in pick_move_from_list(). This way we save some SEE
   // calls in case we get a cutoff.
   for (auto& m : *this)
-      if (type_of(m) == ENPASSANT)
-          m.value = PieceValue[MG][PAWN] - Value(PAWN);
-
-      else if (type_of(m) == PROMOTION)
-          m.value =  PieceValue[MG][pos.piece_on(to_sq(m))] - Value(PAWN)
-                   + PieceValue[MG][promotion_type(m)] - PieceValue[MG][PAWN];
-      else
-          m.value =  PieceValue[MG][pos.piece_on(to_sq(m))]
-                   - Value(type_of(pos.moved_piece(m)));
+      m.value =  PieceValue[MG][pos.piece_on(to_sq(m))]
+               - 200 * relative_rank(pos.side_to_move(), to_sq(m));
 }
 
 template<>
 void MovePicker::score<QUIETS>() {
+
+  Square prevSq = to_sq((ss-1)->currentMove);
+  const HistoryStats& cmh = counterMovesHistory[pos.piece_on(prevSq)][prevSq];
+
   for (auto& m : *this)
-      m.value = history[pos.moved_piece(m)][to_sq(m)];
+      m.value =  history[pos.moved_piece(m)][to_sq(m)]
+               + cmh[pos.moved_piece(m)][to_sq(m)] * 3;
 }
 
 template<>
@@ -194,53 +191,58 @@ void MovePicker::generate_next_stage() {
 
   switch (++stage) {
 
-  case CAPTURES_S1: case CAPTURES_S3: case CAPTURES_S4: case CAPTURES_S5: case CAPTURES_S6:
+  case GOOD_CAPTURES: case QCAPTURES_1: case QCAPTURES_2:
+  case PROBCUT_CAPTURES: case RECAPTURES:
       endMoves = generate<CAPTURES>(pos, moves);
       score<CAPTURES>();
       break;
 
-  case KILLERS_S1:
+  case KILLERS:
       cur = killers;
-      endMoves = cur + 6;
+      endMoves = cur + 2;
+
       killers[0] = ss->killers[0];
       killers[1] = ss->killers[1];
-      killers[2] = countermoves[0];
-      killers[3] = countermoves[1];
-      killers[4] = followupmoves[0];
-      killers[5] = followupmoves[1];
+      killers[2].move = MOVE_NONE;
+
+      // Be sure countermoves are different from killers
+      if (   countermove != killers[0]
+          && countermove != killers[1])
+          *endMoves++ = countermove;
       break;
 
-  case QUIETS_1_S1:
+  case GOOD_QUIETS:
       endQuiets = endMoves = generate<QUIETS>(pos, moves);
       score<QUIETS>();
       endMoves = std::partition(cur, endMoves, [](const ExtMove& m) { return m.value > VALUE_ZERO; });
       insertion_sort(cur, endMoves);
       break;
 
-  case QUIETS_2_S1:
+  case BAD_QUIETS:
       cur = endMoves;
       endMoves = endQuiets;
       if (depth >= 3 * ONE_PLY)
           insertion_sort(cur, endMoves);
       break;
 
-  case BAD_CAPTURES_S1:
+  case BAD_CAPTURES:
       // Just pick them in reverse order to get MVV/LVA ordering
       cur = moves + MAX_MOVES - 1;
       endMoves = endBadCaptures;
       break;
 
-  case EVASIONS_S2:
+  case ALL_EVASIONS:
       endMoves = generate<EVASIONS>(pos, moves);
       if (endMoves - moves > 1)
           score<EVASIONS>();
       break;
 
-  case QUIET_CHECKS_S3:
+  case CHECKS:
       endMoves = generate<QUIET_CHECKS>(pos, moves);
       break;
 
-  case EVASION: case QSEARCH_0: case QSEARCH_1: case PROBCUT: case RECAPTURE:
+  case EVASION: case QSEARCH_WITH_CHECKS: case QSEARCH_WITHOUT_CHECKS:
+  case PROBCUT: case RECAPTURE:
       stage = STOP;
       /* Fall through */
 
@@ -270,11 +272,12 @@ Move MovePicker::next_move<false>() {
 
       switch (stage) {
 
-      case MAIN_SEARCH: case EVASION: case QSEARCH_0: case QSEARCH_1: case PROBCUT:
+      case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS:
+      case QSEARCH_WITHOUT_CHECKS: case PROBCUT:
           ++cur;
           return ttMove;
 
-      case CAPTURES_S1:
+      case GOOD_CAPTURES:
           move = pick_best(cur++, endMoves);
           if (move != ttMove)
           {
@@ -286,55 +289,46 @@ Move MovePicker::next_move<false>() {
           }
           break;
 
-      case KILLERS_S1:
+      case KILLERS:
           move = *cur++;
           if (    move != MOVE_NONE
               &&  move != ttMove
               &&  pos.pseudo_legal(move)
               && !pos.capture(move))
-          {
-              for (int i = 0; i < cur - 1 - killers; i++) // Skip duplicated
-                  if (move == killers[i])
-                      goto skip;
               return move;
-          }
-      skip:
           break;
 
-      case QUIETS_1_S1: case QUIETS_2_S1:
+      case GOOD_QUIETS: case BAD_QUIETS:
           move = *cur++;
           if (   move != ttMove
               && move != killers[0]
               && move != killers[1]
-              && move != killers[2]
-              && move != killers[3]
-              && move != killers[4]
-              && move != killers[5])
+              && move != killers[2])
               return move;
           break;
 
-      case BAD_CAPTURES_S1:
+      case BAD_CAPTURES:
           return *cur--;
 
-      case EVASIONS_S2: case CAPTURES_S3: case CAPTURES_S4:
+      case ALL_EVASIONS: case QCAPTURES_1: case QCAPTURES_2:
           move = pick_best(cur++, endMoves);
           if (move != ttMove)
               return move;
           break;
 
-      case CAPTURES_S5:
+      case PROBCUT_CAPTURES:
            move = pick_best(cur++, endMoves);
            if (move != ttMove && pos.see(move) > captureThreshold)
                return move;
            break;
 
-      case CAPTURES_S6:
+      case RECAPTURES:
           move = pick_best(cur++, endMoves);
           if (to_sq(move) == recaptureSquare)
               return move;
           break;
 
-      case QUIET_CHECKS_S3:
+      case CHECKS:
           move = *cur++;
           if (move != ttMove)
               return move;