"""Bitboard utilities (square index: a1=0, h8=63).""" from __future__ import annotations RANK_1 = 0x00000000000000FF RANK_2 = 0x000000000000FF00 RANK_3 = 0x0000000000FF0000 RANK_4 = 0x00000000FF000000 RANK_5 = 0x000000FF00000000 RANK_6 = 0x0000FF0000000000 RANK_7 = 0x00FF000000000000 RANK_8 = 0xFF00000000000000 FILE_A = 0x0101010101010101 FILE_B = 0x0202020202020202 FILE_C = 0x0404040404040404 FILE_D = 0x0808080808080808 FILE_E = 0x1010101010101010 FILE_F = 0x2020202020202020 FILE_G = 0x4040404040404040 FILE_H = 0x8080808080808080 WHITE_SQUARES = 0x55AA55AA55AA55AA BLACK_SQUARES = 0xAA55AA55AA55AA55 LONG_DIAGONALS = 0x8142241818244281 CENTER_SQUARES = 0x0000001818000000 CENTER_BIG = 0x00003C3C3C3C0000 LEFT_FLANK = FILE_A | FILE_B | FILE_C | FILE_D RIGHT_FLANK = FILE_E | FILE_F | FILE_G | FILE_H FILES = [FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H] RANKS = [RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8] MIRROR_FILE = (0, 1, 2, 3, 3, 2, 1, 0) def file_of(sq: int) -> int: return sq % 8 def rank_of(sq: int) -> int: return sq // 8 def square(rank: int, file: int) -> int: return rank * 8 + file def relative_rank_of(colour: int, sq: int) -> int: return rank_of(sq) if colour == 0 else 7 - rank_of(sq) def relative_square(colour: int, sq: int) -> int: return square(relative_rank_of(colour, sq), file_of(sq)) def relative_square32(colour: int, sq: int) -> int: return 4 * relative_rank_of(colour, sq) + MIRROR_FILE[file_of(sq)] def squares_of_matching_colour(sq: int) -> int: return WHITE_SQUARES if (WHITE_SQUARES >> sq) & 1 else BLACK_SQUARES def popcount(bb: int) -> int: return bb.bit_count() def getlsb(bb: int) -> int: return (bb & -bb).bit_length() - 1 def getmsb(bb: int) -> int: return bb.bit_length() - 1 def poplsb(bb: int) -> tuple[int, int]: sq = getlsb(bb) return sq, bb & (bb - 1) def several(bb: int) -> bool: return bb & (bb - 1) != 0 def only_one(bb: int) -> bool: return bb != 0 and not several(bb) def test_bit(bb: int, sq: int) -> bool: return (bb >> sq) & 1 != 0 def set_bit(bb: int, sq: int) -> int: return bb | (1 << sq) def backmost(colour: int, bb: int) -> int: return getlsb(bb) if colour == 0 else getmsb(bb) def frontmost(colour: int, bb: int) -> int: return getmsb(bb) if colour == 0 else getlsb(bb)