Magic Bitboards explained using fileAttacks() from Gerd's 9.5 KB compromise
- Code: Select all
u64 diagonalMask[64];
// diagonal bits for each square that are a1/h8 orientated
u64 antidiagMask[64];
// diagonal bits for each square that are h1/a8 orientated
u64 fillUpAttacks[64][8];
// For every combination of blockers ([64]) there is
// a bitboard of diagonal and antidiagonal attack sets for every square on a file
// this is a data compression technique
u64 aFileAttacks[64][8];
// For every combination of blockers ([64]) there is
// a bitboard of file attack sets for every rank
// this is a data compression technique
u8 firstRankAttacks[64][8];
// For every combination of blockers ([64]) there is
// a bitrank of rank attack sets for every file
// this is a data compression technique
u64 rankAttacks(u64 occ, u32 sq) {
u32 f = sq & 7;
// isolate the file
u32 r = sq & ~7; // rank * 8
// the number of bits to shift based on the rank
u32 o = (u32) (occ >> (r+1)) & 63;
// For the occupied set, shift the selected rank to rank one
// sence the first bit is always empty, nudge all bits down one
// and make sure that only valid bits remain (index for [64])
return (u64) firstRankAttacks[o][f] << r;
// retrieve and return the attackset after shifting it back to the correct rank
}
u64 fileAttacks(u64 occ, u32 sq) {
u32 f = sq & 7;
// isolate the file
occ = 0x0101010101010101 & (occ >> f); // a-file
// using an a-file mask select the file bits after haveing shifted them to the a-file
u32 o = ( 0x0080402010080400 * occ ) >> 58;
// using a 'magic number' multiply it by the a-file bits to propogate them to the a8 rank
// then shift them down to the a1 rank
// this is an easy magic to demonstrate:
// note: that rows containing all zeros have been omitted and
// that two hex digits have been translated to binary
// magic 0 0 8 0 4 0 2 0 1 0 0 8 0 4 0 0
// * blockers (occ) 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 rook on a1 with all blockers
// ____________________________________________________________
// + 0000 0000 8 0 4 0 2 0 1 0 0 8 0 4 0 0
// + 0 0 1000 0000 4 0 2 0 1 0 0 8 0 4 0 0
// + 0 0 8 0 0100 0000 2 0 1 0 0 8 0 4 0 0
// + 0 0 8 0 4 0 0010 0000 1 0 0 8 0 4 0 0
// + 0 0 8 0 4 0 2 0 0001 0000 0 8 0 4 0 0
// + 0 0 8 0 4 0 2 0 1 0 0000 1000 0 4 0 0
// + 0 0 8 0 4 0 2 0 1 0 0 8 0000 0010 0 0
// + 0 0 8 0 4 0 2 0 1 0 0 8 0 4 0000 0000
// _____________________________________________________________
// = 0 0 8 0 c 0 e 0 f 0 f 8 f c 1111 1100 f c 7 c 3 c 1 c 1 c 0 4 0 0
// here are the relevant bits _______ that are to be shifted into the low byte
// (>> 58) here is the 58 bit _
// these bits drop off and are lost ______________________________
// in the set of blockers only the middle 6 bits count, so, if any of them are 0 then its bit from
// the stack of relevant bits will be missing as that row will be all zeros.
edited: this explaination works for bits on a file or a diagonal as they are widely spaced and do not invade the index area
**********************************************************************************************************
*// 'magics' work by using multipication to make parallel shifts of bits in a pattern to a mapped bit
*// in a result. therefore, you can hand create magics by deciding where in the result that you would
*// like a pattern bit to land' and then place a bit in the magic that when shifted in its turn is
*// placed into the correct slot.
*
*// example: 0100000001000000 are the possible bits of a pattern
*// this pattern will be shifted into bits 25 && 26 then shifted back to bits 1 && 2
*// this bit 0000000001000000 if it exist in the pattern is to be shifted to slot 25, and will be in the
*// 7th shift, therefore, moveing the bit 6 places to the right from 25 gives this partial magic 1000000000000000000
*// this bit 0100000000000000 if it exist in the pattern is to be shifted to slot 26, and will be in the
*// 15th shift, therefore, moveing the bit 14 places from 26 to the right gives this partial magic 100000000000
*// adding the partial magics together will form the complete magic
10000001000000000000
100000001000000
________________________
1000000010000000000000000
1000000010000000000000000000000000
__________________________________
1000000011000000010000000000000000
|| >> 24
I have no idea how to create an index from a pattern of closely spaced bits as they might be along a rank for rook blockers
[b]Anyone?[/b]
edit2: maybe just get the rank blockers similar to the way Gerd does it and then place them in the first 6 bits and shift the file bits magic index down to bit 7? I need to study pradu's magic for clues!
end edit2
**********************************************************************************************************
end edit
// extreme compression of data can be achived for indexs of 9 to 16 bits if they are split in half
// and each used to retrieve a possible attack set that when anded together yeilds the true attack set.
// or the indexs are used to retrieve two patial indexs that when combined point to a much smaller table.
// the idea is that half of the attack set is represented many times in the big table with the other half
// being different, so, just lookup each half seperatly in much smaller tables!
return ( aFileAttacks[o][sq>>3] ) << f;
}
Given the explanations for the rank and files I leave it to the 'student' to understand the diagonals.
correction welcomed
Mike
P.S. You gota be inorder to do this stuff! [/b]