Sounds that I have to work hard with this bughgm wrote:It is best to test the TT on a simple position with very many transpositions. Like the KPK ending or Fine #70. If it doesn't work perfectly, it would almost certainly show up there. E.g. can you find the promotion in
[d]4k3/8/8/8/8/8/4P3/4K3 w
If not, let it print the relevant part of the tree and look where it goes wrong. I always put infra-structure in my engines to print debug info along a selected path, labeled with ply, depth (and possibly IID iteration depth), so that you know which node is printing. Most useful is to print move, score, bestScore immediately after UnMake, and the hash key at the point where you take a hash cutoff. Then you can see which move has the wrong score, add that to the print path, and zoom in on the error. This never fails, although it sometimes is tedious.
BTW, why 32 bits for flags? What flags can you possibly have? I never used more than 3: upper bound, lower bound and in check.
flag will be uint8, it will just store the bound
Sven Schüle wrote: @Tony:
The problem is in at least two places in the hash table code.
1) tt_init():This calculation is wrong. Simply remove the "<< 20" part.Code: Select all
uint32_t t = 2; for (; t <= size; t *= 2) ; // Cast to uint64_t because gives = 0 uint64_t ttsize = (((uint64_t)t / 2) << 20);
2) index calculation by using bitwise AND (at 3 places):After correcting issue 1) above this will work "somehow" but it drops the lowest two bits from the index due to the statementCode: Select all
uint64_t index = key & hash->size;
in tt_init() which seems to increase the probability of hash collisions if I understood it right. Why is that necessary? Why not "hash->size = ttsize - 1" ?Code: Select all
hash->size = ttsize - 4;
EDIT: 3) Please check the value of MAX_MATE_EVAL. It is used for transforming mate scores from/to TT but then its value should be the biggest possible value that can be returned by the evaluation function (the name MAX_MATE_EVAL could be understood different, though). This would not cause the big problems you were describing but could be another small source of trouble.
The TT it's calculate with MB, so if size = 32, will be 32MB TT, basically I stole the code from Sungorus, I think it's -4 because it uses 4 slots to save the move into the TT, I don't use slots(for now) so I will let -1
I have discovered bugs and I re-activated an old bug that gives the wrong pv move, in the UCI pv string shows the right move but moves a blunder one
In the search:
Code: Select all
if (score > alpha) {
if (score >= beta) {
#ifdef USE_HASHTABLE
tt_save(board->key, board->ply, hash, beta, move, depth, HASH_BETA, 0);
#endif
return beta;
}
alpha = score;
bestMove = move;
//UpdatePv(pv, new_pv, move); // <<-- Here is the problem
}
Code: Select all
if (!board->ply)
pv[0] = bestMove;
Kinda hard to choose the correct value for mate, I was tesing these new values:
Code: Select all
#define INF (32767)
#define MATE_EVAL (32000)
#define MIN_MATE_EVAL (MATE_EVAL + MAX_DEPTH)
#define MAX_MATE_EVAL (MIN_MATE_EVAL - MAX_DEPTH)
#define MAX_EVAL (29999)
Code: Select all
if (score >= +MAX_MATE_EVAL) {
score += ply;
ASSERT(Abs(score) <= MIN_MATE_EVAL && Abs(score) >= MAX_MATE_EVAL);
} else if (score <= -MAX_MATE_EVAL) {
score -= ply;
ASSERT(Abs(score) <= MIN_MATE_EVAL && Abs(score) >= MAX_MATE_EVAL);
}
Thanks everyone and Sven for spotting the mate value bug, new headache