I just ran a 30 min test, 15 different positions. 10 of them had not castled yet, 5 already had. I did it my current way (if-test) and using a simple table which dumps the branch. Could measure no speed difference whatsoever. The castle branch is probably predicted 99.99999% of the time in positions where you start off not yet castled, and is predicted 100% of the time when you start out with no castle rights at all. In real games, the latter is far more common, thanks to book lines...wgarvin wrote:Better if it can be done without if-tests though. Using a table indexed by source square and destination square, to mask off the appropriate rights, is branchless, but it uses a couple L1 cache lines. For bitboard programs, the "bitboard of squares that don't have their castling right" is also branchless and extremely lightweight. When generating the castling moves, you just have to test one byte of the bitboard with a mask containing the two bits (one for a rook, one for a king) and if either of them is set you know the move is not legal anymore. So its cheap in makemove and in the move generation.bob wrote:Not quite. I don't use anything but the square for this.hgm wrote:That is exactly what he does, but with the quirk that the masks deciding which bits to clear are coming from the piece codes themselves, rather than from a separate table.
I have a separate piece of code for moving pawns, knights, etc...
in the rook move code:
if square == a1 castle&=0x0d;
if square == h1 castle&=0x0e;
in king move code:
castle &= 0xc0;
Of course the three AND masks are different for black and white. And square is the "from" square assuming white is moving, or "to" for black, since capturing either white rook ends castling to that side from here on...
In a typical program, make/unmake is < 10% of total time, so worrying about saving 0.1% of less than 10% is not exactly productively spent time.
I tend to do what is simplest in these kinds of cases...