Unreliable mate scores
Moderator: Ras
-
- Posts: 28387
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Unreliable mate scores
This has nothing to do with mate scores being unreliable. It simpy means the engine is badly broken. Perhaps undo is not implemented correctly, or some Zobrist keys are zero.
-
- Posts: 879
- Joined: Mon Dec 15, 2008 11:45 am
Re: Unreliable mate scores
Hello HG,hgm wrote:This has nothing to do with mate scores being unreliable. It simpy means the engine is badly broken. Perhaps undo is not implemented correctly, or some Zobrist keys are zero.
you are right, simple bugs caused the problem. (2 in all, mentioned
above). Was just to blind to see them (and didnt thought of doing
something wrong, which i already did a 100 times before).
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: Unreliable mate scores
I was just about to propose that change ...Desperado wrote:if i change the statements when retrieving from
FULLPLY(rdp) < rdp
into
FULLPLY(rdp) <= rdp
A good one, hidden in the last three lines of your long code fragment. Nice to read that you managed to find it.Desperado wrote:uhps, second bug found in valueFrTTB (ubound+maxdepth ???)
Nevertheless here is one "non-functional" proposal, just to shorten your code a little bit.
Code: Select all
void writeTTSlot(
TRANSDAT_T * tdat,
TRANSTABLE_T * ttb,
BOARD_T * brd,
MVE_T mve,
VAL_T score,
PLY_T rdp,
int type)
{
tdat->lock = lockTTB(brd->key);
tdat->mve = mve;
tdat->score= score;
tdat->rdp = rdp;
tdat->type = type;
tdat->age = ttb->age;
}
void writeTTB(
TRANSTABLE_T * ttb,
BOARD_T * brd,
MVE_T mve,
VAL_T score,
PLY_T rdp,
int type)
{
TRANSDAT_T *tdat = connectTTB(ttb,brd->key);
//empty slot
if (tdat->type == 0) {
writeTTSlot(tdat, ttb, brd, mve, score, rdp, type);
}
//overwrite aged slot
else if (tdat->age != ttb->age) {
writeTTSlot(tdat, ttb, brd, mve, score, rdp, type);
}
//position already in
else if (tdat->lock == lockTTB(brd->key)) {
if (rdp >= tdat->rdp) {
writeTTSlot(tdat, ttb, brd, mve, score, rdp, type);
}
}
//always replace
else {
writeTTSlot(tdat, ttb, brd, mve, score, rdp, type);
}
}
Having written this, another "cosmetical" point pops up for me. In writeTTB() you only keep a TT entry intact (i.e., do not overwrite it) under the following conditions:
1. non-empty slot (type != 0), and
2. same age, and
3. position already in (same lock), and
4. entry has remaining depth greater than current remaining depth.
If this is really what you intend (it looks plausible at least) then you can write it even much shorter, dropping again the additional function I introduced above:
Code: Select all
void writeTTB(
TRANSTABLE_T * ttb,
BOARD_T * brd,
MVE_T mve,
VAL_T score,
PLY_T rdp,
int type)
{
TRANSDAT_T *tdat = connectTTB(ttb,brd->key);
if (tdat->type == 0 // empty slot
|| tdat->age != ttb->age // aged slot
|| tdat->lock != lockTTB(brd->key) // non-matching key
|| rdp >= tdat->rdp // remaining depth of slot too low
) {
tdat->lock = lockTTB(brd->key);
tdat->mve = mve;
tdat->score= score;
tdat->rdp = rdp;
tdat->type = type;
tdat->age = ttb->age;
}
}
Even though cosmetics like this are often regarded as unimportant I think it is sometimes better to express an algorithm in a clear and simple way instead of keeping it complex, just because any later changes will make the complex code even more complex.
Sven
-
- Posts: 879
- Joined: Mon Dec 15, 2008 11:45 am
Re: Unreliable mate scores
@ sven
of course my _quick_trial_(dirty) code was just to have sth. to play
with. yesterday in the evening. At the end it might more look
like you proposal (depending, what i will change).
Anyway i am very suprised that such a "basic" implementation
is such effectiv compared to clustered approaches. (like fruit,glaurung...),
with special replacement schemes.
since i coded my first ttb, i started automatically implementing such clustered ttbs. Now i was curious how this basic approach would perform.
The first impression is, that i cannot see some significant differences.
(but i will examine more closely of course).
So, thx for your interest and help.
cheers Michael
of course my _quick_trial_(dirty) code was just to have sth. to play
with. yesterday in the evening. At the end it might more look
like you proposal (depending, what i will change).
Anyway i am very suprised that such a "basic" implementation
is such effectiv compared to clustered approaches. (like fruit,glaurung...),
with special replacement schemes.
since i coded my first ttb, i started automatically implementing such clustered ttbs. Now i was curious how this basic approach would perform.
The first impression is, that i cannot see some significant differences.
(but i will examine more closely of course).
So, thx for your interest and help.
cheers Michael
-
- Posts: 28387
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Unreliable mate scores
How did you concude it is effective? Did you really try searches where the tree was 10 or 100 times larger than the TT size?
Always-replace, which is basically what you use, is a viable scheme, and micro-Max uses it too. Your replacement condition is a bit illogical. Testing for emptinesss in the end will only waste time, as the entire table will be 99+% filled for most of the game, and even when it is not empty, you eventually write it anyway. Testing for the age seems to serve no purpose for the same reason. It only decides if you are going to apply the depth criterion in case of a hit. and why would you want to do that? If hat position occurs in your tree, why would it matter how long ago it was searched. Seems to me that a better depth of large age is equally vlue as a better depth found recently. Finally, keeping an entry that could not be used (or you would not have re-searched it!) because it has higher depth is likely to be very counter-productive in PVS: apparently its bound makes it useless compared to the current window, and it will likely remain useless, as the entire tree in PVS will keep using that same null window.
At high overloading, more advanced replacement schemes can make quite some difference, though.

Always-replace, which is basically what you use, is a viable scheme, and micro-Max uses it too. Your replacement condition is a bit illogical. Testing for emptinesss in the end will only waste time, as the entire table will be 99+% filled for most of the game, and even when it is not empty, you eventually write it anyway. Testing for the age seems to serve no purpose for the same reason. It only decides if you are going to apply the depth criterion in case of a hit. and why would you want to do that? If hat position occurs in your tree, why would it matter how long ago it was searched. Seems to me that a better depth of large age is equally vlue as a better depth found recently. Finally, keeping an entry that could not be used (or you would not have re-searched it!) because it has higher depth is likely to be very counter-productive in PVS: apparently its bound makes it useless compared to the current window, and it will likely remain useless, as the entire tree in PVS will keep using that same null window.
At high overloading, more advanced replacement schemes can make quite some difference, though.
