Think of the function you are implementing (e.g. rook_attacks or bishop_attacks) as a mathematical function. It takes as input a square Sq and a bitboard Occupancy, and it returns a bitboard Result, i.e. something like
Code: Select all
rook_attacks: (Sq, Occupancy) --> Result
Changing the magic number for a given square Sq does not change the Result that rook_attacks is supposed to return for a given input Occupancy. However, it
does change the result of the magic multiplication, that is, it changes what those top M bits are going to be after the magic multiplication (it changes the value of the index). So the actual table of size 2^M or slightly smaller, which maps those index values to the proper Result bitboard, that table does need to change when you change the magic number multiplier. First you need to find a multiplier which doesn't give any "bad" collisions for any of the 2^N occupancy permutations for that square. Then, you need to build the table using that magic multiplier. Some chess engines contain a pre-computed list of magic numbers for each square, but build their actual lookup tables (which map index to Result) each time they are started up.
About changing the square numbering of the board.. it doesn't usually affect magic bitboard stuff, and I'll try and describe why.
If you have a look at
this wiki page, it talks about the mapping between square labels (e.g. A1, A2...) and numeric indexes (0, 1, ...) which are also the bit numbers of bits in a bitboard.
With magic bitboards, it usually turns out that typical reflections (H, V, D) of a bitboard of occupancy squares are commutative with whatever function the magic lookup is supposed to compute (e.g. rook_attacks or bishop_attacks, etc.) In other words, if you flip the input bitboard (Occupancy) and mirror the square number similarly) before calling rook_attacks, or flip the output bitboard (Result) after calling rook_attacks, you get the same result either way. This is also true for 90-degree rotations of the board. [Edit: this assumes the Occupancy bitboard only has bits from the set of N interesting bits, with the other 64-N bits all being zeroes... without this the magic multiply doesn't work anyway. This is usually accomplished by having a Mask bitboard for each square in the magic table, ANDing it with a bitboard of all occupied squares. Those Mask bitboards are also nice reflections of each other, i.e. square 17's Mask is a reflection of square 22's Mask across whatever axis divides square 3 and 4 in your square numbering system.]
Why is that useful, you might wonder?

Well, imagine that instead of flipping the contents of the board, you flipped instead
the labels of the squares on the board. It would still be commutative, for the same reasons!
I guess what I'm trying to say, is that the symmetry of an 8x8 chess board means that the rook_attacks bitboard for square 10 with a certain occupancy bitboard, should have the same result bitboard, regardless of whether square 10 happens to be C7, or B6, or B3, or C2, or F2, or G3, or G6, or F7 in your square numbering system. As long as you number your squares in a sensible way (either the typical A1, B1, C1... numbering or one of the 7 reflections of it) then the same magic multipliers and lookup tables will work!