BTW, I am still not convinced that marking attacked squares on a board-size table would be any more difficult than keeping a bitmap of attacked squares in the King neighborhood only (so that it can be byte size).
Code: Select all
unsigned char neighborhood[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,128, 2, 64, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 32, 1, 16, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
int attacked;
// for marking attacked squares:
attacked |= neighborhood[toSqr - kingSqr + (7*16+7)]; // instead of attacks[toSqr] = nodeCount;
// when later generating King moves
if((neighborhood[step + (7*16+7)] & attacked) == 0) { // steps to safe square
int toSqr = kingSqr + step;
GenerateOneMove(kingSqr, toSqr);
}
This method can be more easily combined with checking for contact attacks, because you can indicate all squares attacked by a single leaper in one quantity, rather than spreading them out over different squares of a board array. E.g.:
Code: Select all
int contact_hits[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0x80, 0x02, 0xC0, 0x02, 0x40, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0x80, 0x00800A, 0x80000240, 0x0200C00C, 0x40000280, 0x004006, 0x40, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0x08, 0x80000820, 0x0A000005, 0xC0000C30, 0x06000009, 0x40000410, 0x04, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0xA0, 0x08802003, 0xA0020150, 0, 0x500201A0, 0x04401003, 0x50, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0x08, 0x20080080, 0x09000006, 0x300C00C0, 0x0500000A, 0x10040040, 0x04, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0x20, 0x200009, 0x20010010, 0x0130000C, 0x10010020, 0x100005, 0x10, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0x20, 0x01, 0x30, 0x01, 0x10, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
int contact_mask[NPIECES];
Init()
{
contact_mask[WP] = 0xFF00;
contact_mask[BP] = 0xFF0000;
contact_mask[N] = 0xFF;
contact_mask[B] = 0x00FFFF00;
contact_mask[R] = 0xFF000000;
contact_mask[Q] = 0xFFFFFF00;
contact_mask[K] = 0xFFFFFF00;
}
// while running through piece list
attacked |= contact_hits[vector + (7*16+7)] & contact_mask[piece];
// when generating King moves:
if((neighborhood[step + (7*16+7)]*0x01010101 & attacked) == 0) {
...
The extra multiplication by 0x01010101 is needed to test the biits for all different move types simultaneously, as the attacked squares are split out by move type in 'attacked'.