Unreliable mate scores

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
hgm
Posts: 28387
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Unreliable mate scores

Post by hgm »

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.
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Re: Unreliable mate scores

Post by Desperado »

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.
Hello HG,

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).
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Unreliable mate scores

Post by Sven »

Desperado wrote:if i change the statements when retrieving from

FULLPLY(rdp) < rdp

into

FULLPLY(rdp) <= rdp
I was just about to propose that change ...
Desperado wrote:uhps, second bug found in valueFrTTB (ubound+maxdepth ???)
A good one, hidden in the last three lines of your long code fragment. Nice to read that you managed to find it.

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);
    }
}
Translate it to your own coding style, of course.

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;
    }
}
I think that has the same semantics as your code, hasn't it?

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
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Re: Unreliable mate scores

Post by Desperado »

@ 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
User avatar
hgm
Posts: 28387
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Unreliable mate scores

Post by hgm »

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.

Image