draw by reps bug : oops I did it again
Moderators: hgm, Rebel, chrisw
-
- Posts: 1871
- Joined: Sat Nov 25, 2017 2:28 pm
- Location: France
draw by reps bug : oops I did it again
In a test game against Dropsgek, Weini fall again in a draw bug (https://lichess.org/o2AqjNAV#119). Still can't find it ...
-
- Posts: 1871
- Joined: Sat Nov 25, 2017 2:28 pm
- Location: France
Re: draw by reps bug : oops I did it again
Here's the full pgn
[pgn] 1. e4 {+0,00/10} e5 2. Nf3 {+0,26/11 0,5} Nf6 3. Nc3 {+0,00/9 0,5} Nc6 4. d4 {+0,19/10 0,3} exd4 {+0,05/12 4} 5. Nxd4 {+0,00/11 0,5} Bd6 {+0,05/11 0,4} 6. Nf5 {+0,97/9 0,3} O-O {-0,73/9 0,5} 7. Nxd6 {+1,78/10 0,3} cxd6 {-0,60/9 0,4} 8. Bd3 {+1,48/9 0,5} Ne5 {-0,75/10 0,4} 9. Be2 {+1,58/9 0,4} Re8 {-0,72/9 0,4} 10. Qxd6 {+1,74/9 0,3} Re6 {-0,72/10 0,4} 11. Qd1 {+1,71/9 0,3} Nc6 {-0,82/11 0,4} 12. f3 {+1,70/9 0,4} Qb6 {-1,05/9 0,4} 13. Nd5 {+1,86/10 0,4} Nxd5 {-0,91/8 0,4} 14. exd5 {+1,88/11 0,4} Rd6 {-0,79/10 0,4} 15. c4 {+2,03/8 0,4} Ne5 {-0,85/9 0,4} 16. Qd2 {+2,03/8 0,4} Rf6 {-1,14/8 0,4} 17. Qc3 {+0,00/12 0,6} Qc7 {-1,37/9 0,4} 18. Bg5 {+0,00/11 0,6} Rf5 {-1,20/8 0,4} 19. Be3 {+2,60/10 0,5} b6 {-1,34/10 0,5} 20. Rd1 {+2,71/8 0,3} Ba6 {-0,83/8 0,4} 21. b3 {+0,00/9 0,6} Re8 {-0,88/8 0,4} 22. f4 {+0,00/8 0,6} Ng6 {-0,41/9 0,4} 23. g3 {+0,00/9 0,6} Ne7 {-0,43/9 0,4} 24. Rc1 {+0,00/9 0,6} Rf6 {-0,41/8 0,4} 25. Kd1 {+1,79/9 0,6} Nf5 {-0,10/8 0,4} 26. Bf2 {+0,00/9 0,6} Nd6 {-0,20/6 0,4} 27. Bd4 {+0,00/11 0,6} Ne4 {-0,49/9 0,4} 28. Qb2 {+0,00/9 0,6} Rg6 {-0,42/8 0,4} 29. Re1 {+2,75/10 0,5} Nc5 {-0,49/7 0,4} 30. b4 {+3,63/10 0,4} Ne4 {-1,38/8 0,4} 31. b5 {+3,83/9 0,4} Bb7 {-2,26/10 0,5} 32. Bf3 {+3,91/11 0,4} Nd6 {-1,28/10 0,4} 33. Rxe8+ {+3,58/9 0,4} Nxe8 {-1,43/9 0,5} 34. c5 {+3,56/10 0,5} bxc5 {-1,50/9 0,5} 35. Bxc5 {+0,00/10 0,7} Qb8 {-1,53/9 0,5} 36. Qd4 {+0,00/10 0,7} a6 {-1,33/10 0,4} 37. b6 {+3,92/9 0,4} Rh6 {-1,45/8 0,5} 38. h4 {+3,77/10 0,4} Rg6 {-1,45/9 0,4} 39. g4 {+0,00/11 1,1} Rf6 {-1,89/9 0,5} 40. Rc4 {+4,78/10 0,8} a5 {-1,89/10 0,4} 41. g5 {+4,68/9 0,3} Rf5 {-1,81/10 0,5} 42. Ra4 {+4,58/9 0,4} Kh8 {-2,23/9 0,5} 43. Qd2 {+0,00/9 0,5} Nd6 {-2,63/8 0,5} 44. Qd3 {+5,19/10 0,3} g6 {-3,61/9 0,5} 45. Be3 {+0,00/10 0,5} Qc8 {-3,07/9 0,5} 46. Rxa5 {+0,00/9 0,5} Qc4 {-3,16/10 0,5} 47. Ke2 {+4,75/10 0,3} Rxf4 {-3,31/10 0,5} 48. Bxf4 {+5,09/12 0,4} Qxf4 {-3,03/10 0,5} 49. Qc3+ {+4,91/11 0,4} Kg8 {-3,05/9 0,5} 50. Qc7 {+4,92/11 0,3} Qe5+ {-2,52/9 0,5} 51. Kd3 {+4,92/10 0,4} Qf5+ {-2,64/9 0,5} 52. Ke2 {+0,00/10 0,5} Qe5+ {+0,10/14 0,5} 53. Kd3 {+4,47/9 0,3} Qf5+ {+0,10/16 0,5} 54. Kd4 {+4,63/10 0,4} Qxf3 {-1,01/11 3} 55. Qxd6 {+4,57/10 0,3} Qd1+ {-0,91/12 2,7} 56. Kc5 {+0,00/10 0,6} Qc2+ {-0,10/13 2,1} 57. Kb4 {+3,00/10 0,3} Qd2+ {-0,10/14 1,5} 58. Kb5 {+2,72/10 0,3} Qd3+ {+0,10/14 1,1} 59. Kb4 {+0,00/11 0,6} Qd2+ {-0,10/14 0,8} 60. Kb5 {+0,00/12 0,6} Bxd5 {+0,10/10 0,1} 61. Ra8+ {+10,30/10 0,4} Bxa8 {-9,84/9 0,6} 62. Qxd2 {+10,95/11 0,6} Bc6+ {-10,41/8 0,1} 63. Ka6 {+11,44/11 0,6} f6 {-10,68/8 0,1} 64. gxf6 {+0,00/11 0,6} Kf7 {-10,40/7 0,1} 65. Qd6 {+1000,04/9 0,1} g5 {-19,96/9 0,4} 66. h5 {+1000,03/5} Kg8 {-11,89/6} 67. Qe7 {+1000,02/4} Bb7+ {-78,31/3} 68. Kxb7 {+1000,01/2} d5 {-78,31/2} 69. Qg7# {+1000,00/1} {Xboard adjudication: Checkmate} 1-0 [/pgn]
[pgn] 1. e4 {+0,00/10} e5 2. Nf3 {+0,26/11 0,5} Nf6 3. Nc3 {+0,00/9 0,5} Nc6 4. d4 {+0,19/10 0,3} exd4 {+0,05/12 4} 5. Nxd4 {+0,00/11 0,5} Bd6 {+0,05/11 0,4} 6. Nf5 {+0,97/9 0,3} O-O {-0,73/9 0,5} 7. Nxd6 {+1,78/10 0,3} cxd6 {-0,60/9 0,4} 8. Bd3 {+1,48/9 0,5} Ne5 {-0,75/10 0,4} 9. Be2 {+1,58/9 0,4} Re8 {-0,72/9 0,4} 10. Qxd6 {+1,74/9 0,3} Re6 {-0,72/10 0,4} 11. Qd1 {+1,71/9 0,3} Nc6 {-0,82/11 0,4} 12. f3 {+1,70/9 0,4} Qb6 {-1,05/9 0,4} 13. Nd5 {+1,86/10 0,4} Nxd5 {-0,91/8 0,4} 14. exd5 {+1,88/11 0,4} Rd6 {-0,79/10 0,4} 15. c4 {+2,03/8 0,4} Ne5 {-0,85/9 0,4} 16. Qd2 {+2,03/8 0,4} Rf6 {-1,14/8 0,4} 17. Qc3 {+0,00/12 0,6} Qc7 {-1,37/9 0,4} 18. Bg5 {+0,00/11 0,6} Rf5 {-1,20/8 0,4} 19. Be3 {+2,60/10 0,5} b6 {-1,34/10 0,5} 20. Rd1 {+2,71/8 0,3} Ba6 {-0,83/8 0,4} 21. b3 {+0,00/9 0,6} Re8 {-0,88/8 0,4} 22. f4 {+0,00/8 0,6} Ng6 {-0,41/9 0,4} 23. g3 {+0,00/9 0,6} Ne7 {-0,43/9 0,4} 24. Rc1 {+0,00/9 0,6} Rf6 {-0,41/8 0,4} 25. Kd1 {+1,79/9 0,6} Nf5 {-0,10/8 0,4} 26. Bf2 {+0,00/9 0,6} Nd6 {-0,20/6 0,4} 27. Bd4 {+0,00/11 0,6} Ne4 {-0,49/9 0,4} 28. Qb2 {+0,00/9 0,6} Rg6 {-0,42/8 0,4} 29. Re1 {+2,75/10 0,5} Nc5 {-0,49/7 0,4} 30. b4 {+3,63/10 0,4} Ne4 {-1,38/8 0,4} 31. b5 {+3,83/9 0,4} Bb7 {-2,26/10 0,5} 32. Bf3 {+3,91/11 0,4} Nd6 {-1,28/10 0,4} 33. Rxe8+ {+3,58/9 0,4} Nxe8 {-1,43/9 0,5} 34. c5 {+3,56/10 0,5} bxc5 {-1,50/9 0,5} 35. Bxc5 {+0,00/10 0,7} Qb8 {-1,53/9 0,5} 36. Qd4 {+0,00/10 0,7} a6 {-1,33/10 0,4} 37. b6 {+3,92/9 0,4} Rh6 {-1,45/8 0,5} 38. h4 {+3,77/10 0,4} Rg6 {-1,45/9 0,4} 39. g4 {+0,00/11 1,1} Rf6 {-1,89/9 0,5} 40. Rc4 {+4,78/10 0,8} a5 {-1,89/10 0,4} 41. g5 {+4,68/9 0,3} Rf5 {-1,81/10 0,5} 42. Ra4 {+4,58/9 0,4} Kh8 {-2,23/9 0,5} 43. Qd2 {+0,00/9 0,5} Nd6 {-2,63/8 0,5} 44. Qd3 {+5,19/10 0,3} g6 {-3,61/9 0,5} 45. Be3 {+0,00/10 0,5} Qc8 {-3,07/9 0,5} 46. Rxa5 {+0,00/9 0,5} Qc4 {-3,16/10 0,5} 47. Ke2 {+4,75/10 0,3} Rxf4 {-3,31/10 0,5} 48. Bxf4 {+5,09/12 0,4} Qxf4 {-3,03/10 0,5} 49. Qc3+ {+4,91/11 0,4} Kg8 {-3,05/9 0,5} 50. Qc7 {+4,92/11 0,3} Qe5+ {-2,52/9 0,5} 51. Kd3 {+4,92/10 0,4} Qf5+ {-2,64/9 0,5} 52. Ke2 {+0,00/10 0,5} Qe5+ {+0,10/14 0,5} 53. Kd3 {+4,47/9 0,3} Qf5+ {+0,10/16 0,5} 54. Kd4 {+4,63/10 0,4} Qxf3 {-1,01/11 3} 55. Qxd6 {+4,57/10 0,3} Qd1+ {-0,91/12 2,7} 56. Kc5 {+0,00/10 0,6} Qc2+ {-0,10/13 2,1} 57. Kb4 {+3,00/10 0,3} Qd2+ {-0,10/14 1,5} 58. Kb5 {+2,72/10 0,3} Qd3+ {+0,10/14 1,1} 59. Kb4 {+0,00/11 0,6} Qd2+ {-0,10/14 0,8} 60. Kb5 {+0,00/12 0,6} Bxd5 {+0,10/10 0,1} 61. Ra8+ {+10,30/10 0,4} Bxa8 {-9,84/9 0,6} 62. Qxd2 {+10,95/11 0,6} Bc6+ {-10,41/8 0,1} 63. Ka6 {+11,44/11 0,6} f6 {-10,68/8 0,1} 64. gxf6 {+0,00/11 0,6} Kf7 {-10,40/7 0,1} 65. Qd6 {+1000,04/9 0,1} g5 {-19,96/9 0,4} 66. h5 {+1000,03/5} Kg8 {-11,89/6} 67. Qe7 {+1000,02/4} Bb7+ {-78,31/3} 68. Kxb7 {+1000,01/2} d5 {-78,31/2} 69. Qg7# {+1000,00/1} {Xboard adjudication: Checkmate} 1-0 [/pgn]
-
- Posts: 1871
- Joined: Sat Nov 25, 2017 2:28 pm
- Location: France
Re: draw by reps bug : oops I did it again
0.1 is contempt. And I see alterning +0.1 -0.1 ... at least there is something bad here ...
-
- Posts: 160
- Joined: Tue Jan 23, 2018 10:18 am
- Location: Rotterdam
- Full name: Ronald Friederich
Re: draw by reps bug : oops I did it again
oops I did it again 2
Are you sure it's a bug in draw by repetition, and not due to not correctly handling stopped search of the current rootmove?
I took another short look at your sourcecode (0.0.23). In searcher::SearchRoot if the score of the current move is higher then alfa you always update bestMove.
If you still do this in 0.0.24 then this will probably cause your problem. If the search of the current rootmove is stopped (stopFlag = true), the score of the move is totally unreliable and can not be used. If I understand correctly you return a high score from negamax in case of a stopFlag so the score of the current rootMove will always be better then alfa and thus will be returned as bestMove....
You can easily test if a stopped search is handled correctly (ie completely ignored) by setting _allowedThinkTime lower then the regular time, so that search for every move in the game is stopped prematurely. If you don't see more blunder moves then normal, then the bug must be somewhere else...
Are you sure it's a bug in draw by repetition, and not due to not correctly handling stopped search of the current rootmove?
I took another short look at your sourcecode (0.0.23). In searcher::SearchRoot if the score of the current move is higher then alfa you always update bestMove.
Code: Select all
// =====================
// update alpha
// =====================
if ( score > alpha){
alpha = score;
bestMove = *it;
You can easily test if a stopped search is handled correctly (ie completely ignored) by setting _allowedThinkTime lower then the regular time, so that search for every move in the game is stopped prematurely. If you don't see more blunder moves then normal, then the bug must be somewhere else...
-
- Posts: 1871
- Joined: Sat Nov 25, 2017 2:28 pm
- Location: France
Re: draw by reps bug : oops I did it again
In fact there I use that
just before that will decide what to return from SearchRoot and there is a similar thing
inside the iterative deepening loop.
Code: Select all
HANDLE_TC_WINDOW
Code: Select all
HANDLE_TC_SEARCH
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: draw by reps bug : oops I did it again
HANDLE_TC_SEARCH seems to ignore the whole result of the last iteration on timeout. Is that what you intended?xr_a_y wrote: ↑Tue Oct 02, 2018 7:04 am In fact there I use that
just before that will decide what to return from SearchRoot and there is a similar thingCode: Select all
HANDLE_TC_WINDOW
inside the iterative deepening loop.Code: Select all
HANDLE_TC_SEARCH
Also your handling of "iteration 0" may lead to trouble in case of a timeout since HANDLE_TC_WINDOW returns the current move which may be "hazardous" as you write in your code comment there. You want to ensure that you play some move at least but then why not take the first move of the move list (after move ordering and possibly TT lookup) as your "default move" to return when time is up very early? Taking the current move instead is more like a random decision.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: draw by reps bug : oops I did it again
I think his code works differently here. The high score (+31000) returned from Negamax() in case of a timeout is negated to -31000 at the parent node so the whole subtree will be ignored. And furthermore the ID loop is left immediately if an iteration (represented by SearchRoot()) detects a timeout, without using the best move returned from there.Ronald wrote: ↑Mon Oct 01, 2018 11:18 pm If the search of the current rootmove is stopped (stopFlag = true), the score of the move is totally unreliable and can not be used. If I understand correctly you return a high score from negamax in case of a stopFlag so the score of the current rootMove will always be better then alfa and thus will be returned as bestMove....
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: draw by reps bug : oops I did it again
Another (maybe minor) problem may occur in very fast games where visiting a few more nodes than needed after detecting timeout may lead to a few losses on time.Sven wrote: ↑Wed Oct 03, 2018 2:12 pmHANDLE_TC_SEARCH seems to ignore the whole result of the last iteration on timeout. Is that what you intended?xr_a_y wrote: ↑Tue Oct 02, 2018 7:04 am In fact there I use that
just before that will decide what to return from SearchRoot and there is a similar thingCode: Select all
HANDLE_TC_WINDOW
inside the iterative deepening loop.Code: Select all
HANDLE_TC_SEARCH
Also your handling of "iteration 0" may lead to trouble in case of a timeout since HANDLE_TC_WINDOW returns the current move which may be "hazardous" as you write in your code comment there. You want to ensure that you play some move at least but then why not take the first move of the move list (after move ordering and possibly TT lookup) as your "default move" to return when time is up very early? Taking the current move instead is more like a random decision.
In Negamax() and NegaQuiesce() you return immediately if stopFlag is set. But within the move loop of both functions you do not check the stopFlag after returning from a subtree, which causes to enter (and immediately leave) all other sibling subtrees at all recursion levels from current level back to root. This is a small additional risk which can be avoided easily, and I would definitely do that at least within Negamax(), I think the additional runtime penalty is negligible compared to the risk of not doing so.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 759
- Joined: Fri Jan 04, 2013 4:55 pm
- Location: Nice
Re: draw by reps bug : oops I did it again
Remember me an error I had in Isa .
Sven , again , pointed that for me
But fixing it , was worth 0 elo lol.
But I think it's interresting to fix it , to avoid some time losses at STC, and avoid choosing some bad moves
Dany
Sven , again , pointed that for me
But fixing it , was worth 0 elo lol.
But I think it's interresting to fix it , to avoid some time losses at STC, and avoid choosing some bad moves
Dany
Isa download :
-
- Posts: 1871
- Joined: Sat Nov 25, 2017 2:28 pm
- Location: France
Re: draw by reps bug : oops I did it again
Thanks for the analysis. This was indeed two bugs that were corrected in 0.0.24 this summer. I should probably release it soon at least because helpful people like you want to read up-to-date code.Sven wrote: ↑Wed Oct 03, 2018 2:24 pmAnother (maybe minor) problem may occur in very fast games where visiting a few more nodes than needed after detecting timeout may lead to a few losses on time.Sven wrote: ↑Wed Oct 03, 2018 2:12 pmHANDLE_TC_SEARCH seems to ignore the whole result of the last iteration on timeout. Is that what you intended?xr_a_y wrote: ↑Tue Oct 02, 2018 7:04 am In fact there I use that
just before that will decide what to return from SearchRoot and there is a similar thingCode: Select all
HANDLE_TC_WINDOW
inside the iterative deepening loop.Code: Select all
HANDLE_TC_SEARCH
Also your handling of "iteration 0" may lead to trouble in case of a timeout since HANDLE_TC_WINDOW returns the current move which may be "hazardous" as you write in your code comment there. You want to ensure that you play some move at least but then why not take the first move of the move list (after move ordering and possibly TT lookup) as your "default move" to return when time is up very early? Taking the current move instead is more like a random decision.
In Negamax() and NegaQuiesce() you return immediately if stopFlag is set. But within the move loop of both functions you do not check the stopFlag after returning from a subtree, which causes to enter (and immediately leave) all other sibling subtrees at all recursion levels from current level back to root. This is a small additional risk which can be avoided easily, and I would definitely do that at least within Negamax(), I think the additional runtime penalty is negligible compared to the risk of not doing so.
0.0.23 a some issue with very short TC mainly because I was too lazy to handle things correctly in SearchRoot() and Search().
As I tried out returning some move even if the full root move loop isn't finished (see another forum thread), I also have to fix a bug that lead me to check if current score is not +/-stopflagscore.
Following HGM advice I was not checking for 3reps but 1rep for a while and I see some engine are testing 3reps in PV and 1rep elsewhere. I am trying that right now ...