maksimKorzh wrote: ↑Thu Oct 29, 2020 2:36 am
I will now ask a dumb question, but it would point to the exact issue I had with repetitions.
Do you update history ply (repetition half move) in UCI when GUI sends position startpos moves e2e4 e7e5 ...?
The PLY is changing only from root of the search, so during search ply can be 6, 7 ... etc and when the search ends PLY is 0 again because every time we are making the move we say PLY++ evaery time we are taking move back we are saying PLY--.
In some of my engines I keep the game history in the same array as the current search branch, at negative index. So ply == 0 still is the root, and its repKey is in gameHist[0]. But gameHist[-1] is the key of the forelast posiiton of the game, etc. Every time a move is made in the game I insert ithe key of the new position at 0, shifting the old game history one down.
As I am often dealing with variants where all moves are reversible (because captured pieces can be dropped back in play), and it is a pain to have to loop through the entire game in every node, I often use entirely different methods for detecting repettions. One method uses two small hash tables (one for wtm, one for btm) large enough to hold a maximum-length game. MakeMove puts the key of the new position into the table; if the entry to which it maps is occupied, it just steps sequentially through the table until it finds an empty one. If in that process (which commonly finds an empty entry on the first try) it finds an entry that already contais the key you want to store, you have a repetition. On UnMake, I mark the entry that held the key again as empty.
In principle you can clear the entire table on an irreversible move at game level. If you want to exclude null-move-spanning repeat loops, you can store the ply level together with the key, and remember the ply of the latest null move, to see how it compares.
Another method is the one I already described of micro-Max: just alter the score of the TT entry for the root position into a draw, and put its depth at max, so it will satisfy any hash probe. (The root already has an 'exact' bound type.) If you use a depth-preferred scheme for replacement, this automatically guarantees these entries will never be overwritten. So any attempt to repeat them in search will result in a hash hit with a draw score. You cannot exclude null-move-spanning repeats with this method, though.