# How do I complete this implementation of magic bitboards?

I'm currently coding a chess engine in C++, and have run into a bit of trouble with my magic bitboard implementation.

So far, I have a function that calculates blockerBoards (all the possible pieces that can block the rook or the bishop).

From there, I have the following code to take these blockerBoards and convert them into attack tables:

``````bitset<M> mBishopAttacks; // 256 K
bitset<M> mRookAttacks; // 2048K

bitset<M> bishopAttacks(bitset<M> blockerBoard, int sq) {
unsigned long long index = blockerBoard.to_ullong();
index *= bishopMagics[sq];
index >>= 64-9
return mBishopAttacks[sq][index]; //outputs corresponding attack board
}
``````

Note that I got the array of magic numbers, bishopMagics, from somewhere on the web.

How do I initialize these attack tables, mBishopAttacks and mRookAttacks? Currently, they are empty. Do I simply have to calculate the attack tables for each possible permutation of blockers?

• I assume you know this wiki? Mar 12, 2021 at 18:26

It is probably most efficient if I paste my code from my chess move generator on GitHub.

``````int ROOK_ATTACK_SHIFTS;
Bitboard ROOK_ATTACKS;

void initialise_rook_attacks() {
Bitboard edges, subset, index;

for (Square sq = a1; sq <= h8; ++sq) {

subset = 0;
do {
index = subset;
index = index * ROOK_MAGICS[sq];
index = index >> ROOK_ATTACK_SHIFTS[sq];
ROOK_ATTACKS[sq][index] = get_rook_attacks_for_init(sq, subset);
} while (subset);
}
}
``````

• For each square, the bitboard stored in the attacks table is determined by a complicated cycling algorithm. You start with an empty bitboard `subset`, then manipulate it using the magics and the masks generated previously. This gives you an index. You then initialise the attacks table at `ROOK_ATTACKS[sq][index]` as the bitboard of slider moves from that square, using the initial value of `subset` as the occupation bitboard. `subset` is then updated using the masks, and the loop continues. The nature of the magic numbers is that, starting with `subset=0`, you will cycle through all 4096 indices (not in order), and `subset` will turn into the correct "representative" occupation bitboard for all 4096 of these.
• The value of "9" while bitshifting to calculate the index should not be hardcoded. Instead, it should depend on whether the piece is in the centre, on an edge or in a corner, which is what `ROOK_ATTACK_MASKS` and `ROOK_ATTACK_SHIFTS` are for. I believe excluding these is a little-known bug
• I am confused about this `subset = (subset - ROOK_ATTACK_MASKS[sq]) & ROOK_ATTACK_MASKS[sq];` line. How exactly is it supposed to work, because it doesn't for me? Dec 20, 2021 at 17:44
• I am using C++. You claim that `subset` should turn into all possible permutations of the attack mask, but it does not when I try to replicate your example. The attack mask generation is definitely working correctly, I don't see where I could have made a mistake. No matter what square I am indexing, `subset` always turns to `1` and then to `0`. Any ideas? Dec 30, 2021 at 17:23