Changes

Jump to: navigation, search

SISSY Bitboards

1,195 bytes added, 09:57, 14 February 2021
no edit summary
a new and interesting approach to determine sliding piece attacks devised by [[Michael Sherwin]], introduced and discussed in [[CCC]] in February 2020 <ref>[http://www.talkchess.com/forum3/viewtopic.php?f=7&t=73083 Split Index Super Set Yielding (SISSY) Bitboards] by [[Michael Sherwin]], [[CCC]], February 13, 2020</ref> as an improvement of his [[Sherwin Bitboards]].
SISSY bitboards apply the occupancy lookup [[Ranks|rank]] by rank to [[General Setwise Operations#Intersection|intersect]] supersets of the attack bitboards from the same square considering blocking pieces on that particular rank only.
While using eight lookups to intersect sounds expensive on the first glance, SISSY Bitboards yields up to eight [[Direction#RayDirections|ray-directions]] of a queen in one run with cheap instructions and high [https://en.wikipedia.org/wiki/Instructions_per_cycle IPC] potential, and thus may be an alternative for [[Magic Bitboards|magic bitboards]] on architectures with slow 64-bit multiplication, in particular for the queen.
{{MappingHint}}
=Queen Attacks=
The general SISSY attack getter requires a 3-dimensional 1MByte lookup table, with pre-initialized attack bitboards indexed by 3-bit rank index, 6-bit square, 8-bit rank occupancy and 3-bit rank index.
<pre>
U64 qss[8][64][256][8];
U64 queenAttacks(U64 occ, enumSquare sq) {
return
qss[0][sq][ occ & 255][0] & qss[1][sq][(occ >> 8) & 255][1] & qss[2][sq][(occ >> 16) & 255][2] & qss[3][sq][(occ >> 24) & 255][3] & qss[4][sq][(occ >> 32) & 255][4] & qss[5][sq][(occ >> 40) & 255][5] & qss[6][sq][(occ >> 48) & 255][6] & qss[7][sq][(occ >> 56) & 255][7] ; }
</pre>
The following sample demonstrates how to determine queen attacks. The intersection of the eight split index addressed attack bitboards yields the desired queen attack bitboard (red squares attacked by queen, blue reset due to blocker):
occ = 0x8041A20428054A00
<pre>
[7][d4][0x80] [76] [d4][0x41] [65] [d4][0xA2] [54] [d4][0x04][4]
. . . 1 . . . 1* . . . 1 . . . 0 . . . 1 . . . 0 . . . 1 . . . 1
1 . . 1 . . 1 . * 1 . . 1 . . 1 .* 0 . . 1 . . 0 . 0 . . 1 . . 1 .
. 1 . 1 . 1 . . . 1 . 1 . 1 . . . 1 . 1 . 1 . .* . 0 . 1 . 1 . .
. . 1 1 1 . . . & . . 1 1 1 . . . & . . 1 1 1 . . . & . . 1 1 1 . . .*
1 . . 1 . . 1 . 1 . . 1 . . 1 . 1 . . 1 . . 1 . 1 . . 1 . . 1 .
[3][d4][0x28] [32] [d4][0x05] [21] [d4][0x4a] [10] [d4][0x00][0]
. . . 1 . . . 1 . . . 1 . . . 1 . . . 1 . . . 1 . . . 1 . . . 1
1 . . 1 . . 1 . 1 . . 1 . . 1 . 1 . . 1 . . 1 . 1 . . 1 . . 1 .
=Union Bitboard=
Rather then using shift/and instructions to get the ranrank-wise occupancies, and similar to [[Sherwin Bitboards]], one may use a [[C#Union|union]] of a bitboard and a struct or array of eight [[Byte|bytes]] (Portability concerning [[Endianness|endianness]] is an issue), to appear the code looking simpler.
<pre>
typedef unsigned char U08;
union bbu {U64 b64; bb8 b08;};
U64 qss[8][64][256][8]; // 1M
U64 queenAttacks(U64 occ, enumSquare sq) {
bbu o; o.b64 = occ;
return
qss[0][sq][o.b08.r1][0] & qss[1][sq][o.b08.r2][1] & qss[2][sq][o.b08.r3][2] & qss[3][sq][o.b08.r4][3] & qss[4][sq][o.b08.r5][4] & qss[5][sq][o.b08.r6][5] & qss[6][sq][o.b08.r7][6] & qss[7][sq][o.b08.r8][7];};
</pre>
Targeting [[X86-64]], the generated [[Assembly|assembly]] is likely similar to the above shift/and255 code <ref>[https://godbolt.org/ Compiler Explorer] with x86-64 clang (experimental - Wlifetime), -O3</ref>.
<pre>
queenAttacks(unsigned long long, int): # @queenAttacks(unsigned long long, int) mov rdx, rdi
mov rcx, rdi
shr rcx, 50 and ecx, -6456 movsxd rdxrsi, esi movzx esiedi, dildl shl rsi, 611 shl rdx, 14 mov rax, rdi shr rax, 2 and movzx eax, 16320dh mov rax, qword ptr [rdx rsi + 8*rax + qss+8131072] and rax, qword ptr [rdx rsi + rsi 8*rdi + qss] mov rsirdi, rdirdx shr rsirdi, 1013 and esiedi, 163202040 and rax, qword ptr [rdx rsi + rsi rdi + qss+16262144] mov rsirdi, rdirdx shr rsirdi, 1821 and esiedi, 163202040 and rax, qword ptr [rdx rsi + rsi rdi + qss+24393216] mov rsirdi, rdirdx shr rsirdi, 2629 and esiedi, 163202040 and rax, qword ptr [rdx rsi + rsi rdi + qss+32524288] mov rsirdi, rdirdx shr rsirdi, 3437 and esiedi, 163202040 and rax, qword ptr [rdx rsi + rsi rdi + qss+40655360] shr rdirdx, 4245 and ediedx, 163202040 and rax, qword ptr [rsi + rdx + rdi + qss+48786432] and rax, qword ptr [rdx rsi + 8*rcx + qss+56917504]
ret
</pre>
Taking advantage of the [[First Rank Attacks#TheOuterSquares|inner six bits]] optimization for SISSY bishop attacks, but still much memory and computation compared to other techniques:
<pre>
U64 bss[646][64][664]; // 192 K
U64 bishopAttacks(U64 occ, enumSquare sq) {
return
rss bss[0][sq][(occ >> 9) & 63][0] & // 2nd rank rss bss[1][sq][(occ >> 17) & 63][1] & rss bss[2][sq][(occ >> 25) & 63][2] & rss bss[3][sq][(occ >> 33) & 63][3] & rss bss[4][sq][(occ >> 41) & 63][4] & rss bss[5][sq][(occ >> 49) & 63][5] ; // 7th rank}
</pre>
One may There is a more recent attempt to half the table size number of lookups by [[Martin Sedlak]] but using much larger tables <ref>[http://www.talkchess.com/forum3/viewtopic.php?f=7&t=73083&start=55 Re: Split Index Super Set Yielding (SISSY) Bitboards] by combining occupancy indices of two consecutive ranks, since their relevant bits on [[Diagonals|diagonalMartin Sedlak]] and , [[Anti-Diagonals|anti-diagonalCCC]] are always disjoint, February 14, 2021</ref>.
=Rook Attacks=
If combined with the [[First Rank Attacks#AttacksOnAllRanks|rank lookup]] to for SISSY fileAttacks only, one can dense the occupy index range to 2, considering only blockers on the same file, SISSY file attack generation looks not that competitive compared to other techniques as well, see for instance [[Kindergarten Bitboards#File-Attacks|Kindergarten file attacks]] or [[Hyperbola Quintessence]].
<pre>
U64 rss[6][64][2][6]; // 6K
U64 fileAttacks(U64 occ, enumSquare sq) {
occ >>= (sq & 7); // shift occupancy to A file
return
rss[0][sq][(occ >> 8) & 1][0] & // 2nd rank rss[1][sq][(occ >> 16) & 1][1] & rss[2][sq][(occ >> 24) & 1][2] & rss[3][sq][(occ >> 32) & 1][3] & rss[4][sq][(occ >> 40) & 1][4] & rss[5][sq][(occ >> 48) & 1][5] ; // 7th rank}
</pre>
One may try some more index trickery for instance considering 3 ranks each, for an upper and lower half,
<pre>
U64 rss[2][64][8]; // 8K
U64 fileAttacks(U64 occ, enumSquare sq) {
occ >>= (sq & 7); // shift occupancy to A file
return
rss[0][sq][((occ>>22)&4) | ((occ>>15)&2) | ((occ>> 8)&1)] & // rank 4,3,2
rss[1][sq][((occ>>46)&4) | ((occ>>39)&2) | ((occ>>32)&1)]; // rank 7,6,5
}
</pre>
One step further, to combine the occupancy to one six-bit index is already quite similar to [[Kindergarten Bitboards#FileAttacks|Kindergarten File Attacks]], in particular [[Zach Wegner|Zach Wegner's]] [[Kindergarten Bitboards#32-bit Versions|32-bit Version]] <ref>[http://www.open-aurec.com/wbforum/viewtopic.php?topic_view=threads&p=26851&t=4523 Zach's tricky 32-bit approach] by [[Zach Wegner]], [[Computer Chess Forums|Winboard Forum]], August 22, 2006</ref>
=Forum Posts=
* [http://www.talkchess.com/forum3/viewtopic.php?f=7&t=73063 New RookAttacks() - possibly] by [[Michael Sherwin]], [[CCC]], February 12, 2020
* [http://www.talkchess.com/forum3/viewtopic.php?f=7&t=73083 Split Index Super Set Yielding (SISSY) Bitboards] by [[Michael Sherwin]], [[CCC]], February 13, 2020
: [http://www.talkchess.com/forum3/viewtopic.php?f=7&t=73083&start=46 Re: Split Index Super Set Yielding (SISSY) Bitboards] by [[Michael Sherwin]], [[CCC]], February 13, 2021
: [http://www.talkchess.com/forum3/viewtopic.php?f=7&t=73083&start=55 Re: Split Index Super Set Yielding (SISSY) Bitboards] by [[Martin Sedlak]], [[CCC]], February 14, 2021
=References=

Navigation menu