Split killer moves from non-captures
authorMarco Costalba <mcostalba@gmail.com>
Mon, 25 May 2009 06:49:50 +0000 (07:49 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 25 May 2009 06:49:50 +0000 (07:49 +0100)
In MovePicker consider killer moves as a separate
phase from non-capture picking.

Note that this change guarantees that killer1 is always
tried before killer2. Until now, because scoring difference
of the two moves was just 1 point, if psqt tables of killer1
gave a lower value then killer2, the latter was tried as first.

After 999 games at 1+0 we have
Mod vs Orig: +245 =527 -227 +6 ELO

Not a lot but patch is anyhow something worth to have.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/movegen.cpp
src/movepick.cpp
src/movepick.h

index a783a62..3845cd9 100644 (file)
@@ -392,7 +392,6 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
   assert(pinned == pos.pinned_pieces(pos.side_to_move()));
 
   Color us = pos.side_to_move();
-  Color them = opposite_color(us);
   Square from = move_from(m);
   Piece pc = pos.piece_on(from);
 
@@ -401,6 +400,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
   if (color_of_piece(pc) != us)
       return false;
 
+  Color them = opposite_color(us);
   Square to = move_to(m);
 
   // En passant moves
index 3897f4c..60fcbaa 100644 (file)
@@ -74,6 +74,7 @@ MovePicker::MovePicker(const Position& p, bool pv, Move ttm,
   movesPicked = 0;
   numOfMoves = 0;
   numOfBadCaptures = 0;
+  checkKillers = checkLegal = false;
 
   if (p.is_check())
       phaseIndex = EvasionsPhaseIndex;
@@ -139,18 +140,30 @@ Move MovePicker::get_next_move() {
         score_captures();
         std::sort(moves, moves + numOfMoves);
         movesPicked = 0;
+        checkLegal = true;
         break;
 
-    case PH_BAD_CAPTURES:
-        // It's probably a good idea to use SEE move ordering here. FIXME
-        movesPicked = 0;
+    case PH_KILLERS:
+        movesPicked = numOfMoves = 0;
+        checkLegal = false;
+        if (killer1 != MOVE_NONE && move_is_legal(pos, killer1, pinned) && !pos.move_is_capture(killer1))
+            moves[numOfMoves++].move = killer1;
+        if (killer2 != MOVE_NONE && move_is_legal(pos, killer2, pinned) && !pos.move_is_capture(killer2) )
+            moves[numOfMoves++].move = killer2;
         break;
 
     case PH_NONCAPTURES:
+        checkKillers = (numOfMoves != 0); // previous phase is PH_KILLERS
         numOfMoves = generate_noncaptures(pos, moves);
         score_noncaptures();
         std::sort(moves, moves + numOfMoves);
         movesPicked = 0;
+        checkLegal = true;
+        break;
+
+    case PH_BAD_CAPTURES:
+        // It's probably a good idea to use SEE move ordering here. FIXME
+        movesPicked = 0;
         break;
 
     case PH_EVASIONS:
@@ -258,13 +271,7 @@ void MovePicker::score_noncaptures() {
   for (int i = 0; i < numOfMoves; i++)
   {
       m = moves[i].move;
-
-      if (m == killer1)
-          hs = HistoryMax + 2;
-      else if (m == killer2)
-          hs = HistoryMax + 1;
-      else
-          hs = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
+      hs = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
 
       // Ensure history is always preferred to pst
       if (hs > 0)
@@ -320,13 +327,15 @@ Move MovePicker::pick_move_from_list() {
   switch (PhaseTable[phaseIndex]) {
 
   case PH_GOOD_CAPTURES:
+  case PH_KILLERS:
   case PH_NONCAPTURES:
       while (movesPicked < numOfMoves)
       {
           Move move = moves[movesPicked++].move;
           if (   move != ttMove
               && move != mateKiller
-              && pos.pl_move_is_legal(move, pinned))
+              && (!checkKillers || (move != killer1 && move != killer2))
+              && (!checkLegal || pos.pl_move_is_legal(move, pinned)))
               return move;
       }
       break;
@@ -381,9 +390,7 @@ void MovePicker::init_phase_table() {
   PhaseTable[i++] = PH_TT_MOVE;
   PhaseTable[i++] = PH_MATE_KILLER;
   PhaseTable[i++] = PH_GOOD_CAPTURES;
-  // PH_KILLER_1 and PH_KILLER_2 are not yet used.
-  // PhaseTable[i++] = PH_KILLER_1;
-  // PhaseTable[i++] = PH_KILLER_2;
+  PhaseTable[i++] = PH_KILLERS;
   PhaseTable[i++] = PH_NONCAPTURES;
   PhaseTable[i++] = PH_BAD_CAPTURES;
   PhaseTable[i++] = PH_STOP;
index 500ed8b..3d87b9c 100644 (file)
@@ -57,10 +57,9 @@ public:
     PH_TT_MOVE,        // Transposition table move
     PH_MATE_KILLER,    // Mate killer from the current ply
     PH_GOOD_CAPTURES,  // Queen promotions and captures with SEE values >= 0
-    PH_BAD_CAPTURES,   // Queen promotions and captures with SEE values < 0
-    PH_KILLER_1,       // Killer move 1 from the current ply (not used yet).
-    PH_KILLER_2,       // Killer move 2 from the current ply (not used yet).
+    PH_KILLERS,        // Killer moves from the current ply
     PH_NONCAPTURES,    // Non-captures and underpromotions
+    PH_BAD_CAPTURES,   // Queen promotions and captures with SEE values < 0
     PH_EVASIONS,       // Check evasions
     PH_QCAPTURES,      // Captures in quiescence search
     PH_QCHECKS,        // Non-capture checks in quiescence search
@@ -91,6 +90,7 @@ private:
   int phaseIndex;
   int numOfMoves, numOfBadCaptures;
   int movesPicked;
+  bool checkKillers, checkLegal;
   bool finished;
 };