We have a problem with bishops but also with rooks regarding the MSB of the 64 bit bitboard.
The MSB could be too high that we cannot accumulate on that, as example the a1-h8 diagonal
Code: Select all
abcdefgh
7 00000001
6 00000010
5 00000100
4 0000x000
3 00010000
2 00100000
1 01000000
0 10000000
Piece is in d4 so sq = 36
Here we cannot accumulate on h8 because we go in overflow. A general solution that works also with rooks vertical files too near the H file is the following:
Code: Select all
int count(uint64 b, int sq) {
return ((b & Mask[sq]) * Acc) >> Shift[sq] + (b >> shiftMSB[sq]);
}
Here Mask[36] is a bitboard with ones on the diagonal a1-h8 BUT the h8 square so to clear the MSB bit, we will accumulate on bit 54 (square g6) instead. And of course Shift[36] == 54
The last term of the formula shifts down the MSB bit, in our case shiftMSB[36] == 63, and so count is incremented if the cleared bit was set. Note that we don't need any mask on the last term because the big shift already removes all the bits but the MSB.
Note also that we don't shift anymore the bitboard in first term but we can mask directly "in place". The Acc constant are indipendent from the diagonal position, but depends only on orientation.
The same formula applies for files, diagonals and antidiagonals so that we can unify in a template:
Code: Select all
enum Direction {
A1_A8,
A1_H8,
A8_H1,
A1_H1 // Horizontal
};
template<Direction D>
inline int count(uint64_t b, int sq) {
const uint64_t // evaluated at compile time
Acc = (D == A1_A8 ? 0x0101010101010101ULL :
D == A1_H8 ? 0x8040201008040201ULL : 0x0810204081020481ULL);
return ((b & Mask[D][sq]) * Acc) >> Shift[D][sq] + (b >> shiftMSB[D][sq]);
}
// Template specialization for the case of horizontal line
template<>
inline int count<A1_H1>(uint64_t b, int sq) {
int rk = sq >> 3; // as per square definition in Glaurung
return BitCount8Bit[(b >> rk*8) & 0xFF]; // rk*8 could be further optimized, see the above instruction
}
It is of course trivial the sequence of functions to call to get bitcount for bishops, rooks and even queens.
Code: Select all
// Count rook mobility
int r_mob = count<A1_H1>(b, sq) + count<A1_A8>(b, sq);
// Count bishop mobility
int b_mob = count<A1_H8>(b, sq) + count<A8_H1>(b, sq);