First+Rank+Attacks

toc
 * Home * Board Representation * Bitboards * Sliding Piece Attacks * First Rank Attacks**

The technique of occupancy lookups is base for rotated- and kindergarten -bitboards.

=Introduction to Occupancy Lookup= The first rank is the ideal line to introduce occupancy lookups.

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.


 * [[image:firstRank.JPG]] ||
 * Occupancy of the first rank = 01001010B ||
 * [[image:firstRankA.JPG]] ||
 * Rank-attacks ::= f (e-file, Occupancy) = 01110110B ||

code format="cpp" BYTE arrFirstRankAttacks256x8[256][8]; // 2048 Bytes = 2KByte

firstRankAttack = arrFirstRankAttacks256x8[rankOccupancy][squareOnRank]; code

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 to 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. code format="cpp" BYTE arrFirstRankAttacks64x8[64][8]; // 512 Bytes = 1/2KByte

firstRankAttack = arrFirstRankAttacks64x8[(rankOccupancy >> 1)& 63][squareOnRank]; code  =Attacks on all Ranks= Since it is simple to shift ranks up and down, the general rank attack getter is already handy. code format="cpp" 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 occ = (occ >> rkx8) & 2*63; U64 attacks = arrFirstRankAttacks64x8[4*occ + file]; return attacks << rkx8; } code 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.

=What links here?= include page="First Rank Attacks" component="backlinks" limit="40"
 * Up one Level**