Transposition tables are hard...

Discussion of chess software programming and technical issues.

Moderator: Ras

eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Re: Transposition tables are hard...

Post by eligolf »

lithander wrote: Sat Feb 26, 2022 1:39 pm
So you were storing and reading depth-0 positions (which is essentially just qsearch) in the TT? And now you go directly into Qsearch and return that result?

While I'm not aware of any reason why the TT shouldn't work when the depth parameter is 0 what you do now is how the TT is used in Leorik. I never stored results from the qsearch, either.

And looking at the code you posted above I do wonder where is the bestMove variable is set so that when you call WriteTT and store it it's really actually the best move? is it a global variable?

Yes I stored the Qsearch result in TT before, since this is how Bruce's code was shown. Now I still store it, but I try to read the TT after Qsearch. Basically the only difference I made was to switch places of TT lookup if statement and the depth == 0 if statement.

bestMove is set to Empty at beginning and then it is set to a move if we find a better one (score > alpha). Not sure if this is correct, I am a bit confused with the best move variable and how to use it properly. In sort move function later on I only assign it the highest score if it is actually a move and not an empty one.
User avatar
lithander
Posts: 915
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: Transposition tables are hard...

Post by lithander »

eligolf wrote: Sat Feb 26, 2022 1:52 pm Yes I stored the Qsearch result in TT before, since this is how Bruce's code was shown. Now I still store it, but I try to read the TT after Qsearch. Basically the only difference I made was to switch places of TT lookup if statement and the depth == 0 if statement.
But if you read the TT only after qsearch why do you still store the result of qsearched positions? When would they ever produce a table hit?
eligolf wrote: Sat Feb 26, 2022 1:52 pm bestMove is set to Empty at beginning and then it is set to a move if we find a better one (score > alpha). Not sure if this is correct, I am a bit confused with the best move variable and how to use it properly.
The idea is that you may have encountered the position before but you didn't search it deep enough to know the score accurately enough to return it now. But you still remember which was the best move. So now in your upcoming search by playing that move first searching this position will be a lot cheaper.

In the code you posted as far as I could see bestMove was never written to. Not even after score > alpha. That's why I asked.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Re: Transposition tables are hard...

Post by eligolf »

lithander wrote: Sat Feb 26, 2022 2:50 pm
eligolf wrote: Sat Feb 26, 2022 1:52 pm Yes I stored the Qsearch result in TT before, since this is how Bruce's code was shown. Now I still store it, but I try to read the TT after Qsearch. Basically the only difference I made was to switch places of TT lookup if statement and the depth == 0 if statement.
But if you read the TT only after qsearch why do you still store the result of qsearched positions? When would they ever produce a table hit?
eligolf wrote: Sat Feb 26, 2022 1:52 pm bestMove is set to Empty at beginning and then it is set to a move if we find a better one (score > alpha). Not sure if this is correct, I am a bit confused with the best move variable and how to use it properly.
The idea is that you may have encountered the position before but you didn't search it deep enough to know the score accurately enough to return it now. But you still remember which was the best move. So now in your upcoming search by playing that move first searching this position will be a lot cheaper.

In the code you posted as far as I could see bestMove was never written to. Not even after score > alpha. That's why I asked.
I thought I could write it to the table in case I get same position at another search or depth later on, maybe I am thinking wrong though.

Ah yes, the bestMove variable wasn't implemented yet in the code I wrote here. I added it after I got the other things to work :) Good catch! Now it is set to empty move at start of negamax loop and then I set it to current move when score > alpha.
User avatar
lithander
Posts: 915
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: Transposition tables are hard...

Post by lithander »

eligolf wrote: Sat Feb 26, 2022 3:25 pm I thought I could write it to the table in case I get same position at another search or depth later on, maybe I am thinking wrong though.
Sure the position can come up again. But the depth of this entry is zero. Depth is like the "quality" of the stored evaluation of that position and you can only use the TT score when the quality is at least as good as what the search would return. So depth = 0 is really not a great quality. It means "just qsearch on this position" and you just made a change that if depth is 0 you never look into the TT before doing qsearch and returning the score, right? So you eliminated the only case where there could be a table hit with sufficient depth on this position. So these positions will just sit there and if they get found with the remaining depth > 0 the score can't be used because it's too shallow. And the bestmove also can't be used either because you just store empty-move after writing from qsearch.

Does that make sense? At least that's how it looks like based on the code you posted.

Edit: I also just tested writing and reading the TT at depth == 0 and everything is working as expected. Maybe you did make some changes to Leorik's TT? Or the original problem was caused by something else.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
amanjpro
Posts: 883
Joined: Sat Mar 13, 2021 1:47 am
Full name: Amanj Sherwany

Re: Transposition tables are hard...

Post by amanjpro »

lithander wrote: Sat Feb 26, 2022 5:12 pm
eligolf wrote: Sat Feb 26, 2022 3:25 pm I thought I could write it to the table in case I get same position at another search or depth later on, maybe I am thinking wrong though.
Sure the position can come up again. But the depth of this entry is zero. Depth is like the "quality" of the stored evaluation of that position and you can only use the TT score when the quality is at least as good as what the search would return. So depth = 0 is really not a great quality. It means "just qsearch on this position" and you just made a change that if depth is 0 you never look into the TT before doing qsearch and returning the score, right? So you eliminated the only case where there could be a table hit with sufficient depth on this position. So these positions will just sit there and if they get found with the remaining depth > 0 the score can't be used because it's too shallow. And the bestmove also can't be used either because you just store empty-move after writing from qsearch.

Does that make sense? At least that's how it looks like based on the code you posted.

Edit: I also just tested writing and reading the TT at depth == 0 and everything is working as expected. Maybe you did make some changes to Leorik's TT? Or the original problem was caused by something else.

In Zahak I also probe TT after checking is depth == 0, you can always probe TT in QS and save some precious CPU cycles