Magic bitboards create an index using the hashing function
Code: Select all
ax>>n
Edit: the attack set for an empty occupancy are what moves a slider would have if it was on that square on an empty board. Superset of all attack sets.
Code: Select all
u64 indexify(u64 occ, u64 mask, u64 magic, u64 shift) {
return ((occ & mask) * magic) >> (64-shift);
}
u64 unindexify(u64 index, u64 magic, u64 full) {
return (index * magic) & full;
}
u64 bishop_attacks(u64 occ, Magics &magics) {
occ &= magics.mask;
occ *= magics.factor;
occ >>= 9;
occ *= magic.post_factor;
occ &= magic.postmask;
return occ;
}
v64x8 bishop_attacks(v64x8 occ, v64x8 masks, v64x8 factors, v64x8 post_factors, v64x8 post_masks) {
occ &= masks;
occ *= factors;
occ >>= 59;
occ *= post_factors;
occ &= post_masks;
return occ;
};
Now the problem is finding the parameters for the magics. Unlike regular lookup tables, instead of having a narrower index range, it would be better to have less used entries (that is, we can use any range we want, but not consume a lot of entries) so when looking for post-magics, it would expontetially increase the chances for a post-magic to be one when we are searched for less entries.
For now, for the bishop square B2, I can find about 10K fixed-shift black magic-numbers which use 16 entries (and cant find 15). If use a variable shifts of 5, I can find black magics which use 14 entries with relative easy (but that's still 2.333x more than it's theoretically possible, because there are only 6 distinct attack sets!).
At first, I had trouble breaking 29 entries, but as I got the hang of it I learned some tricks. The main trick was looking at the pattern, some bits are ALWAYS off, some bits are ALWAYS on. I constructed a simple python scripts to look at patterns from magic numbers, a couple of iterations later, from generating 4 a second you generate 10k. (Maybe genetic algorithm to generate those? But it may get stuck on too many local minimums).
As for finding post magics, I use the following unindexify function:
Code: Select all
u64 unindexify(u64 index, u64 magic, u64 full) {
return ~((index * magic) | ~full);
}
One shortcoming which I think is not a big deal is that many resulting attack bitboards have bits set in their low bits: but if the index is odd, it should have a 1-bit in the lowest bit, so the multiplication thing will figure it out nicely.
I post here because I can't find black magic fixed shift numbers which go below 16 entries, and I can't find black post-magic numbers which are ok for anything after the 7th entry.
Anyways any questions? Ideas? Not possible? Possible? Help me? I am un-understandable?