Fix cycle detection in presence of repetitions
authorSergei Ivanov <srg.ivanov@gmail.com>
Sun, 14 Apr 2019 12:50:37 +0000 (15:50 +0300)
committerStéphane Nicolet <cassio@free.fr>
Thu, 9 May 2019 13:39:57 +0000 (15:39 +0200)
In master search() may incorrectly return a draw score in the following
corner case: there was a 2-fold repetition during the game, and the
current position can be reached by a move from a repeated one. This case
is treated as an upcoming 3-fold repetition, which it is not.

Here is a testcase demonstrating the issue (note that the moves
after FEN are required). The input:

  position fen 8/8/8/8/8/8/p7/2k4K b - - 0 1 moves c1b1 h1g1 b1c1 g1h1 c1b1 h1g1 b1a1 g1h1
  go movetime 1000

produces the output:

  [...]
  info depth 127 seldepth 2 multipv 1 score cp 0 [...]
  bestmove a1b1

saying that the game will be drawn by repetion. However the other possible
move for black, Kb2, avoids repetitions and wins. The patch fixes this behavior.
In particular it finds mate in 10 in the above position.

STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 10604 W: 2390 L: 2247 D: 5967
http://tests.stockfishchess.org/tests/view/5cb373e00ebc5925cf0167bf

LTC:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 19620 W: 3308 L: 3185 D: 13127
http://tests.stockfishchess.org/tests/view/5cb3822f0ebc5925cf016b2d

Bench is not changed since it does not test positions with history of moves.

Bench: 3184182

src/position.cpp

index 8c6dc8023af52997b2dac142c5fcb454a07ed314..a86d77ad7707bcfc6337f293cfa7180af31c6635 100644 (file)
@@ -1206,6 +1206,11 @@ bool Position::has_game_cycle(int ply) const {
               if (ply > i)
                   return true;
 
+              // For nodes before or at the root, check that the move is a repetition one
+              // rather than a move to the current position
+              if (color_of(piece_on(empty(s1) ? s2 : s1)) != side_to_move())
+                  continue;
+
               // For repetitions before or at the root, require one more
               StateInfo* next_stp = stp;
               for (int k = i + 2; k <= end; k += 2)