First Rank Attacks
Home * Board Representation * Bitboards * Sliding Piece Attacks * First Rank Attacks
The technique of occupancy lookups is base for Rotated bitboards, Kindergarten bitboards and Magic bitboards. The first rank with an occupancy in the byte range serves as teaser to introduce occupancy lookups.
Contents
Introduction to Occupancy Lookup
One Byte Only
Assume we (temporary) reduce the chess-board to one rank. Occupancy bitboard is one byte with up to 256 states. A rook attack-set from one of the eight squares (file) on this single rank is also only one byte. Thus we can construct an array of bytes[256][8], indexed by all 256 occupancies and 8 files, to lookup the pre-calculated rank-attack bytes.
1 | ♘ ♖ ♔ | 1 |
abcdefgh |
Occupancy of the first rank = 01001010B, Rank-attacks ::= f (e-file, Occupancy) = 01110110B
BYTE arrFirstRankAttacks256x8[256][8]; // 2048 Bytes = 2KByte firstRankAttack = arrFirstRankAttacks256x8[rankOccupancy][squareOnRank];
Overdetermined?
In fact both indices seem somehow overdetermined, since the rook is already member of occupancy. But rather than to make the redundant rook-bit disappear to use only the remaining seven occupancy bits, with half table size - which is not that cheap and simple either - we better decide to uncouple this items to eventually pass (virtual) rook squares, not actually member of occupancy. We better rely on another property to reduce the table fourfold.
The Outer Squares
If we think about the occupancy lookup, we may recognize that the outer squares don't matter. There are no more squares behind. The outer squares are either attacked or not - independent from their occupancy state. We can use the six inner bits only as lookup-index with two additional cheap instructions.
BYTE arrFirstRankAttacks64x8[64][8]; // 512 Bytes = 1/2KByte firstRankAttack = arrFirstRankAttacks64x8[(rankOccupancy >> 1) & 63][squareOnRank];
Attacks on all Ranks
Since it is simple to shift ranks up and down, the general rank attack getter is already handy.
BYTE arrFirstRankAttacks64x8[64*8]; // 512 Bytes = 1/2KByte U64 rankAttacks(U64 occ, enumSquare sq) { unsigned int file = sq & 7; unsigned int rkx8 = sq & 56; // rank * 8 unsigned int rankOccX2 = (occ >> rkx8) & 2*63; // 2 times the inner six bit rank occupancy used as index U64 attacks = arrFirstRankAttacks64x8[4*rankOccX2 + file]; // 8 * rank occupancy + file return attacks << rkx8; }
The array is defined one-dimensional, and has to indexed by 8*occ + file. The reason was playing the optimization game and to safe the right shift one, but to scale by 4 instead of 8, which is done by the address calculation unit anyway. This routine may complete the Hyperbola Quintessence.
See also
- Occupancy of any Line
- Hyperbola Quintessence
- Kindergarten Bitboards
- Magic Bitboards
- Rotated Bitboards
Forum Posts
- Understanding first rank attack state generation by Kalyankumar Ramaseshan, CCC, July 18, 2019 » Hyperbola Quintessence