Semi-piece-list nastiness

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

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

Semi-piece-list nastiness

Post by hgm »

KingSlayer uses a 'semi-piece-list', indexed by piece type rather than a unique piece number. This is not very useful, but the intended use was to keep track of the King location, (for the purpose of check testing). Testing whether the moved piece is a King is more expensive than just always updating location[pieceType].

So far so good. But when I wanted to put in some end-game knowledge, the location[] array was useful to quickly find other pieces in the case you have only one of each type left. E.g. when the material counters say you are down to KPK, you can easily peek where the single Pawn is, (in addition to the King), and determine the outcome from that. This worked fine, and I also put in a KBPK evaluator. But I saw it lose a KBPKPP end-game that should have been a dead draw, so apparently it was not working. In a simple test position with a black Pawn on h2 and the King defending on h1/g2 it was seeing a draw up to depth six, but from then on it thought it was badly lost. WTF!?! Never noticed that in the original testing of the KBPK code.

Turns out that the code was broken when I let KingSlayer also consider under-promotion, in particular to Bishop. This brings a second Bishop on the board, and at the moment it appears it is of course the last-moved Bishop, and usurps the Bishop slot in location[]. Taking the move back 'restores' the location by location[piece] = fromSqr, but 'piece' is just a Pawn. The phantom Bishop stays on the promotion square (as far as the piece list is concerned, on the board it is of course gone). Since it is on the promotion square, the KBPK evaluator doesn't think it is a draw anymore. Any move with the real Bishop would of course make the latter visible again to the KBPK code, but as the side that can move it is pretty happy with the winning score, he just glues that Bishop to its current location.

The recognizer was not entirely naive; it knows the location[] is unreliable, and can still point to a piece that is in fact captured. So it checks if the piece is indeed there, and aborts if it isn't. But then it cannot recognize the draw. Just assuming that a phantom Bishop means the real one is on the other shade (after all, I don't really want to know where the Bishop is, just its shade) would work after capture, but not after promotion (which could very well be on the same shade).

Fortunately there is a fix. During MakeMove I have variables 'piece' and 'promoted', (the piece types before and after the move), which normally are the same. If in the conditional code section that makes 'promoted' different from 'piece' I add oldLoc = location[promoted], and in UnMake do

location[promoted] = oldLoc; location[piece] = fromSqr;

the first statement is a no-op on any non-promotion, as it is immediately overwritten by the second. When they are different (i.e. on a promotion move), then the location of the piece type you promoted to is restored to its original value (in this case the Bishop of the wrong shade), and the KBPK evaluator keeps working on reliable data.
lauriet
Posts: 199
Joined: Sun Nov 03, 2013 9:32 am

Re: Semi-piece-list nastiness

Post by lauriet »

I too have had plenty of time up my sleeve lately to work on my program and have found a few glaring errors that, once fixed, have led to better play.
I find it fascinating that with chess programming, errors don't crash the program, but simply result in worse play. This I find makes it difficult to detect all the bugs.
A lot of the more experienced/wiser contributors here have stressed making the program bug free before you worry about speed/optimisation.
I can only say that If I write another one, I would be fanatical about testing every small segment of code. I would avoid cut/paste as some errors I found where a result of code that was meant for black was pasted for white and not changed.
I have so often written a section and thought "yep, that's obviously working" and of course missed the 5% where it doesn't.
Still its fun when you can put on your detective hat, and sit down to chase a juicy bug.

Laurie (LTchess)
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Semi-piece-list nastiness

Post by mvanthoor »

Bugs in chess programs can crash the program by indexing arrays or vectors out of bounds for example.

On the other hand, there are indeed many bugs that just cause the program to play worse. One is for example a wrong zobrist hash calculation, which would either make it fail to detect third repetition reliably, or the hash table would function suboptimally. You could be making moves that 'seem' to be good, but actually aren't. That sort of thing.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
JohnWoe
Posts: 491
Joined: Sat Mar 02, 2013 11:31 pm

Re: Semi-piece-list nastiness

Post by JohnWoe »

lauriet wrote: Thu Apr 30, 2020 3:21 am I too have had plenty of time up my sleeve lately to work on my program and have found a few glaring errors that, once fixed, have led to better play.
I find it fascinating that with chess programming, errors don't crash the program, but simply result in worse play. This I find makes it difficult to detect all the bugs.
A lot of the more experienced/wiser contributors here have stressed making the program bug free before you worry about speed/optimisation.
I can only say that If I write another one, I would be fanatical about testing every small segment of code. I would avoid cut/paste as some errors I found where a result of code that was meant for black was pasted for white and not changed.
I have so often written a section and thought "yep, that's obviously working" and of course missed the 5% where it doesn't.
Still its fun when you can put on your detective hat, and sit down to chase a juicy bug.

Laurie (LTchess)
Make it work. Then make it better. Results less bugs and more developer hair.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Semi-piece-list nastiness

Post by Henk »

JohnWoe wrote: Thu Apr 30, 2020 4:43 pm
lauriet wrote: Thu Apr 30, 2020 3:21 am I too have had plenty of time up my sleeve lately to work on my program and have found a few glaring errors that, once fixed, have led to better play.
I find it fascinating that with chess programming, errors don't crash the program, but simply result in worse play. This I find makes it difficult to detect all the bugs.
A lot of the more experienced/wiser contributors here have stressed making the program bug free before you worry about speed/optimisation.
I can only say that If I write another one, I would be fanatical about testing every small segment of code. I would avoid cut/paste as some errors I found where a result of code that was meant for black was pasted for white and not changed.
I have so often written a section and thought "yep, that's obviously working" and of course missed the 5% where it doesn't.
Still its fun when you can put on your detective hat, and sit down to chase a juicy bug.

Laurie (LTchess)
Make it work. Then make it better. Results less bugs and more developer hair.
Yes 12 or 13 years ago I worked for a boss telling me "First time right". I remember he didn't have much hair. O wait he was a CEO not a developer.