Lots of bugs
Posted: Thu Feb 04, 2016 1:58 am
Sorry for what might all sound like a blatant defeatist moan, but I don't mean for it to be -- rather just looking for tips from more experienced developers who may have had similar problems when they began. I have just got my engine working with xboard, and being able to play against other engines without having to babysit has brought to light a number of problems, which I have only partially resolved.
It did bring to light a problem with my futility pruning. It was running faster without it, but I managed to solve that particular issue, although my poor old brain can't get around why it would slow it down. I'm happy that's ok now however.
Secondly, when Eva is white, and the opening goes:
e4, e5
d4, e5xd4
she seems to willingly give up the pawn. She doesn't recapture with the queen, but just attacks it again with the king's knight and spends the next few moves hopelessly trying to win it back. I'm hoping this may just be an evaluation tuning issue, but disabling bits of my evaluation function corrects it, only to find that changing a line of code in my search function makes it do it again. And I found this with my previous attempt at writing an engine (which shares much of the same design as Eva) so it seems just like that is what it naturally wants to do, like it's at some kind of minimum point and any deviation from that point will result in it just falling back into the minimum. But whatever the reason, even as an average chess player, it is wrong!
Also, my PV arbitrarily cuts off. I have partially managed to solve this -- it was much worse with each depth iteration only being 2 or 3 moves long. Now, it can be at depth 9 with a pv 9 moves long say, and at depth 10 there might only be 1 move in the pv. The replacement scheme for my hashtable goes thus (probably easier to just give the code than try to explain it in words):
At each call to my search function, I check the hashtable, and if it's a pv node I just return the score. If it's a cut node, I return the TT score if it's greater than the current beta and the depth is greater. If it's an all node I return the score if it's lower than the current alpha and the depth is greater. I refresh the stale flag if a node turns out to still be useful. Also, after the first move, my PV (as printed to the screen) is extended. I think that's just because I extract the PV from the TT table, and it's picking up old entries, but I don't understand why.
Finally, and I think this is related to the previous problem, is that as the game goes on, my program slows down massively. I would obviously expect it to as the game gets more complicated, but on the positions that it is particularly slow on (~half an hour), I write them down and set it going from scratch from that position and it takes only 5 minutes say to depth 15. With my extensions set as they are, it gets to a maximum depth of the low 20s, not including quiescence. My theory is that the hash table is getting filled up with entries, and never getting replaced, but I'm not sure why. At present my hashtable's size is 10^8 entries, which takes up like 6 gigabytes, which I am sure is quite unnecessary. Previously I thought it may be due to search explosion, so I really cut down my search extensions to fractions of a ply, and never more than 1 in total, but it's still slowing down. I clear the killer tables and the history tables at the beginning of each search.
It did bring to light a problem with my futility pruning. It was running faster without it, but I managed to solve that particular issue, although my poor old brain can't get around why it would slow it down. I'm happy that's ok now however.
Secondly, when Eva is white, and the opening goes:
e4, e5
d4, e5xd4
she seems to willingly give up the pawn. She doesn't recapture with the queen, but just attacks it again with the king's knight and spends the next few moves hopelessly trying to win it back. I'm hoping this may just be an evaluation tuning issue, but disabling bits of my evaluation function corrects it, only to find that changing a line of code in my search function makes it do it again. And I found this with my previous attempt at writing an engine (which shares much of the same design as Eva) so it seems just like that is what it naturally wants to do, like it's at some kind of minimum point and any deviation from that point will result in it just falling back into the minimum. But whatever the reason, even as an average chess player, it is wrong!
Also, my PV arbitrarily cuts off. I have partially managed to solve this -- it was much worse with each depth iteration only being 2 or 3 moves long. Now, it can be at depth 9 with a pv 9 moves long say, and at depth 10 there might only be 1 move in the pv. The replacement scheme for my hashtable goes thus (probably easier to just give the code than try to explain it in words):
Code: Select all
if (TT[g%Nh].stale()) TT[g%Nh]=x;
else if (x.node()==pv) TT[g%Nh]=x;
else if (g==TT[g%Nh].key() && TT[g%Nh].depth()<x.depth() && TT[g%Nh].node()!=pv) TT[g%Nh]=x;
Finally, and I think this is related to the previous problem, is that as the game goes on, my program slows down massively. I would obviously expect it to as the game gets more complicated, but on the positions that it is particularly slow on (~half an hour), I write them down and set it going from scratch from that position and it takes only 5 minutes say to depth 15. With my extensions set as they are, it gets to a maximum depth of the low 20s, not including quiescence. My theory is that the hash table is getting filled up with entries, and never getting replaced, but I'm not sure why. At present my hashtable's size is 10^8 entries, which takes up like 6 gigabytes, which I am sure is quite unnecessary. Previously I thought it may be due to search explosion, so I really cut down my search extensions to fractions of a ply, and never more than 1 in total, but it's still slowing down. I clear the killer tables and the history tables at the beginning of each search.