Assuming you count a single repetition as a draw in the search...which you should.

Moderator: Ras
It might have something to do with me only storing the first mate found and not necessarily the best/fastest mate? By deviation I don't mean "deviate from a forced checkmate" but more "deviate from the initial found mate line". My engine might find a "mate in 14", so it plays that move. But then the opponent doesn't play a move in that line, so it searches again and finds a "mate in 9". And so on. And then, what I think sometimes happens, is that it gets to a position already stored from one of those previous mate lines and goes "hey, this move leads to a mate in X!" and selects it, even though it already tried that position and might lead to a repetition because it's not a forced mate line. I'm not sure why the repetition draw isn't considering since I check for that and normally it does work.hgm wrote: ↑Tue Feb 07, 2023 8:22 pmThis should not be possible in a properly working search. If you find a forced mate, it means that every possible deviation of the PV has been searched, and proven to result in a mate that is at least as fast. So it does not matter whether the opponent deviates from your PV; the move stored in the TT should result in the fastest mate. No side branch should ever go through a repetition if you have a winning score.KhepriChess wrote: ↑Tue Feb 07, 2023 12:45 am 1. search finds a forced mate at some depth
2. opponent doesn't play exact same moves, so engine deviates from the above line
3. at some point, position gets back to a position that has the best move already found/stored from step 1, so that move is played even if that will result in a 3-fold draw.
I don't think so? I've seen a number of other engines do it this same way.
Oh I see, your mate scores are based on .Inf and .Checkmate is a value always < the minimum mate score. Ah well...KhepriChess wrote: ↑Wed Feb 08, 2023 6:37 pmI don't think so? I've seen a number of other engines do it this same way.
.Inf is greater than .Checkmate, so a checkmate score in the TT will be .Inf and always larger than the .Checkmate value (which is what the condition checks). If I returned the Checkmate value in the negamax (and subsequently stored that in the TT), the TT comparison wouldn't work (because the entry.score value wouldn't be larger than the .Checkmate value).
Code: Select all
this.PositionHistory[this.PositionHistory.length] = this.Position.Hash;
For the depth extension, my understanding is sort of based of hgm's comment here: https://www.talkchess.com/forum3/viewto ... 31#p758059Ronald wrote: ↑Thu Feb 09, 2023 9:13 am Hi,
I browsed through your code and I noticed 2 things. Don't know if they help you with your problem, but I thought I'd share them anyway.
First thing is that in negamax you increase depth by 1 when inCheck. That might be a good thing to do, but maybe not in the beginning of negamax, before your move loop, because hashprobing and all kinds of pruning you do before the move loop rely on the depth parameter, while the depth at time should not be tempered with. I guess you could move it inside your move loop, and increase depth + 1 when you're incheck after you made that move. not sure if this creates your current behavior, but it surely influences the hash usage, which you only use when enough "depth".
Second thing I noticed is in your repetition detection you use PositionHistory for checking, you update it when you make the move withbut I can't find the place where you increase the PositionHistory.length. Now I'm not really familiar with javascript, so I might not understand it correctly and it might happen elsewhere or automatically, but maybe every position is stored in [0] every time.Code: Select all
this.PositionHistory[this.PositionHistory.length] = this.Position.Hash;
Hope this helps
Code: Select all
this.PositionHistory[this.PositionHistory.length] = this.Position.Hash;