The nodes per second limit feature (-n) was meant to dumb-down the engine by slowing it down. It gives us an engine reminiscent of the 1980s 8-bit computers that were able to search in hundreds of NPS. At the same time, it takes only as much CPU time as needed, which is almost nothing in the current machines. Just like the easy levels (-e), it's still CPU-independent, as long as your CPU can make it to the NPS requested.
Now I find it useful in debugging and tuning the engine as well. Using the NPS limit, I've just found a bug in the lazy evaluation code that would otherwise be hidden by the deep search. It can be reproduced, here is the position from a blitz game, where the 200 NPS engine was checkmated by an easy level one:
It doesn't see the checkmate with the zero-width window, then it does see it at re-search, where it is spotted as expected, as Phalanx searches checks in the first ply of the quiescence search. This is not caused by the lazy eval only, there is also a bug in it. ... If i remove lazy eval (or just extend the margin enough), it's fixed:
This is now definitely the number one item on my to do list... The fix should be easy, but i might also reconsider the lazy eval code and remove it completely.
-- Edit -- I have found the real reason of the problem above. The lazy eval code is pretty ok as it is, the real issue was down in the search, where the check in the quiescence search was generated only if the static eval function found that the king is in danger. With lazy eval, the flag was whatever was found at the most recent full static eval, which is not always correct. That condition should be removed.
Last edit: Dušan Dobeš 2014-05-05
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The nodes per second limit feature (-n) was meant to dumb-down the engine by slowing it down. It gives us an engine reminiscent of the 1980s 8-bit computers that were able to search in hundreds of NPS. At the same time, it takes only as much CPU time as needed, which is almost nothing in the current machines. Just like the easy levels (-e), it's still CPU-independent, as long as your CPU can make it to the NPS requested.
Now I find it useful in debugging and tuning the engine as well. Using the NPS limit, I've just found a bug in the lazy evaluation code that would otherwise be hidden by the deep search. It can be reproduced, here is the position from a blitz game, where the 200 NPS engine was checkmated by an easy level one:
5r1k/p1p1R1pp/4Q3/3p4/4b3/1N3P2/P3q1PP/6K1 w - - 3 27
1 -168 401 805 Nb3-d2 Qe2xd2 Pf3xe4
1 -167 411 824 Ph2-h3 !
1 -196 411 825 Ph2-h3
1 -195 481 948 Qe6-g4 !
1 -29998 481 956 Qe6-g4 Qe2-e1
1 -> 0:05.01 992 2 turns
-> forced checkmate -> easy move (2)
Depth=1, Value=-29998, Time=5.01, Last turn=4.81, Nodes=992, N/s=198
PV = Qe6-g4 Qe2-e1
It doesn't see the checkmate with the zero-width window, then it does see it at re-search, where it is spotted as expected, as Phalanx searches checks in the first ply of the quiescence search. This is not caused by the lazy eval only, there is also a bug in it. ... If i remove lazy eval (or just extend the margin enough), it's fixed:
5r1k/p1p1R1pp/4Q3/3p4/4b3/1N3P2/P3q1PP/6K1 w - - 3 27
1 -168 380 759 Nb3-d2 Qe2xd2 Pf3xe4
1 -> 0:04.40 880 0 turns
2 -168 500 991 Nb3-d2 Qe2xd2 Pf3xe4
2 -167 590 1185 Ph2-h3 !
2 -105 650 1305 Ph2-h3 Qe2-e1 Kg1-h2
2 -> 0:07.10 1443 1 turn
3 -81 1750 3499 Ph2-h3 Qe2-d1 Kg1-h2 Be4-f5 Qe6-e3
3 -> 0:19.50 3972 0 turns
Depth=3, Value=-81, Time=19.50, Last turn=5.90, Nodes=3972, N/s=203
PV = Ph2-h3 Qe2-d1 Kg1-h2 Be4-f5 Qe6-e3
This is now definitely the number one item on my to do list... The fix should be easy, but i might also reconsider the lazy eval code and remove it completely.
-- Edit -- I have found the real reason of the problem above. The lazy eval code is pretty ok as it is, the real issue was down in the search, where the check in the quiescence search was generated only if the static eval function found that the king is in danger. With lazy eval, the flag was whatever was found at the most recent full static eval, which is not always correct. That condition should be removed.
Last edit: Dušan Dobeš 2014-05-05