Bitboards and pinned pieces
Posted: 12 Dec 2006, 18:47
As I mentioned in another thread, I wrote a little magic number generator yesterday. Because it would be a waste to produce these numbers without using them for anything, I've now modified the bitboard version of my program (which used classical rotated bitboards) to use magic-based attack generation instead.
Most of the work was very easy, but I had a few small problems. A problem I still haven't been able to solve cleanly is to find a bitboard of all pinned pieces for a given side. My old rotated bitboard code looks like this:
My current magic bitboard version is a lot messier:
This is fast enough and has the advantage of avoiding the dreaded bitscanning, but looks awfully ugly and complicated. There has to be a better way to do this. Because magic bitboards generate attacks in several directions at once, I would expect a good magic bitboard solution to be shorter and simpler than the rotated bitboard solution.
Any ideas about how to improve this code?
Tord
Most of the work was very easy, but I had a few small problems. A problem I still haven't been able to solve cleanly is to find a bitboard of all pinned pieces for a given side. My old rotated bitboard code looks like this:
- Code: Select all
Bitboard Position::pinned_pieces(Color c) const {
Bitboard pinned = EmptyBoardBB, b1, b2;
Square ksq = this->king_square(c), s;
Color them = opposite_color(c);
for(Direction d = DIR_E; d <= DIR_NW; d++) {
b1 = this->sliders_of_color(them, d);
b2 = this->sliding_attacks(ksq, d) & this->pieces_of_color(c);
while(b2) {
s = pop_1st_bit(&b2);
if(this->sliding_attacks(s, d) & b1) set_bit(&pinned, s);
}
}
return pinned;
}
My current magic bitboard version is a lot messier:
- Code: Select all
Bitboard Position::pinned_pieces(Color c) const {
Bitboard b1, b2, b3, pinned, sliders;
Square ksq = this->king_square(c);
Color them = opposite_color(c);
pinned = EmptyBoardBB;
b1 = this->occupied_squares();
sliders = this->rooks_and_queens_of_color(them);
if(sliders) {
b2 = this->rook_attacks(ksq) & this->pieces_of_color(c);
while(b2) {
b3 = b2 & -b2;
b2 ^= b3;
if(rook_attacks_bb(ksq, b1 ^ b3) & sliders) pinned |= b3;
}
}
sliders = this->bishops_and_queens_of_color(them);
if(sliders) {
b2 = this->bishop_attacks(ksq) & this->pieces_of_color(c);
while(b2) {
b3 = b2 & -b2;
b2 ^= b3;
if(bishop_attacks_bb(ksq, b1 ^ b3) & sliders) pinned |= b3;
}
}
return pinned;
}
This is fast enough and has the advantage of avoiding the dreaded bitscanning, but looks awfully ugly and complicated. There has to be a better way to do this. Because magic bitboards generate attacks in several directions at once, I would expect a good magic bitboard solution to be shorter and simpler than the rotated bitboard solution.
Any ideas about how to improve this code?
Tord