So ladies(?) and gentlemen, I present to you SBAMG: Subtraction based Attack Mask Generation. Here's the C code for it:
Code: Select all
uint64_t rank_attacks(int sq, uint64_t occ)
{
static const uint64_t OuterSquares[64] = {
0x0000000000000081ULL, 0x0000000000000081ULL, 0x0000000000000081ULL,
0x0000000000000081ULL, 0x0000000000000081ULL, 0x0000000000000081ULL,
0x0000000000000081ULL, 0x0000000000000001ULL, 0x0000000000008000ULL,
0x0000000000008100ULL, 0x0000000000008100ULL, 0x0000000000008100ULL,
0x0000000000008100ULL, 0x0000000000008100ULL, 0x0000000000008100ULL,
0x0000000000000100ULL, 0x0000000000800000ULL, 0x0000000000810000ULL,
0x0000000000810000ULL, 0x0000000000810000ULL, 0x0000000000810000ULL,
0x0000000000810000ULL, 0x0000000000810000ULL, 0x0000000000010000ULL,
0x0000000080000000ULL, 0x0000000081000000ULL, 0x0000000081000000ULL,
0x0000000081000000ULL, 0x0000000081000000ULL, 0x0000000081000000ULL,
0x0000000081000000ULL, 0x0000000001000000ULL, 0x0000008000000000ULL,
0x0000008100000000ULL, 0x0000008100000000ULL, 0x0000008100000000ULL,
0x0000008100000000ULL, 0x0000008100000000ULL, 0x0000008100000000ULL,
0x0000000100000000ULL, 0x0000800000000000ULL, 0x0000810000000000ULL,
0x0000810000000000ULL, 0x0000810000000000ULL, 0x0000810000000000ULL,
0x0000810000000000ULL, 0x0000810000000000ULL, 0x0000010000000000ULL,
0x0080000000000000ULL, 0x0081000000000000ULL, 0x0081000000000000ULL,
0x0081000000000000ULL, 0x0081000000000000ULL, 0x0081000000000000ULL,
0x0081000000000000ULL, 0x0001000000000000ULL, 0x8000000000000000ULL,
0x8100000000000000ULL, 0x8100000000000000ULL, 0x8100000000000000ULL,
0x8100000000000000ULL, 0x8100000000000000ULL, 0x8100000000000000ULL,
0x0100000000000000ULL
};
occ = (occ & RankMaskEx[sq]) | OuterSquares[sq];
return ((occ - ThisAndNextSq[msb(occ & PrevSquares[sq])]) ^ occ)
& RankMaskEx[sq];
}
uint64_t file_attacks(int sq, uint64_t occ)
{
static const uint64_t OuterSquares[64] = {
0x0100000000000000ULL, 0x0200000000000000ULL, 0x0400000000000000ULL,
0x0800000000000000ULL, 0x1000000000000000ULL, 0x2000000000000000ULL,
0x4000000000000000ULL, 0x8000000000000000ULL, 0x0100000000000001ULL,
0x0200000000000002ULL, 0x0400000000000004ULL, 0x0800000000000008ULL,
0x1000000000000010ULL, 0x2000000000000020ULL, 0x4000000000000040ULL,
0x8000000000000080ULL, 0x0100000000000001ULL, 0x0200000000000002ULL,
0x0400000000000004ULL, 0x0800000000000008ULL, 0x1000000000000010ULL,
0x2000000000000020ULL, 0x4000000000000040ULL, 0x8000000000000080ULL,
0x0100000000000001ULL, 0x0200000000000002ULL, 0x0400000000000004ULL,
0x0800000000000008ULL, 0x1000000000000010ULL, 0x2000000000000020ULL,
0x4000000000000040ULL, 0x8000000000000080ULL, 0x0100000000000001ULL,
0x0200000000000002ULL, 0x0400000000000004ULL, 0x0800000000000008ULL,
0x1000000000000010ULL, 0x2000000000000020ULL, 0x4000000000000040ULL,
0x8000000000000080ULL, 0x0100000000000001ULL, 0x0200000000000002ULL,
0x0400000000000004ULL, 0x0800000000000008ULL, 0x1000000000000010ULL,
0x2000000000000020ULL, 0x4000000000000040ULL, 0x8000000000000080ULL,
0x0100000000000001ULL, 0x0200000000000002ULL, 0x0400000000000004ULL,
0x0800000000000008ULL, 0x1000000000000010ULL, 0x2000000000000020ULL,
0x4000000000000040ULL, 0x8000000000000080ULL, 0x0000000000000001ULL,
0x0000000000000002ULL, 0x0000000000000004ULL, 0x0000000000000008ULL,
0x0000000000000010ULL, 0x0000000000000020ULL, 0x0000000000000040ULL,
0x0000000000000080ULL
};
occ = (occ & FileMaskEx[sq]) | OuterSquares[sq];
return ((occ - ThisAndNextSq[msb(occ & PrevSquares[sq])]) ^ occ)
& FileMaskEx[sq];
}
My benchmarks show that this method is at least as fast as HQ, and since it is fully calculation based it'd serve as a good method to complete HQ for completely calculated slider attack mask generation. If you get the idea, then you can easily apply this method to diagonals as well, so it'd work independently of HQ. I have struggled to describe this idea, and the smart ones would understand it anyway.