import typing def int_to_hexstr(bm: int) -> str: if bm > 0xFFFF_FFFF_FFFF_FFFF: return False return '0x' + '_'.join(f'{bm:016X}'[i : i + 4] for i in range(0, 16, 4)) def fill_bm(bm: int, bits: int) -> int: filled_bm = 0 for idx in range(64): if bm & 1 << idx: if bits & 1: filled_bm |= 1 << idx bits >>= 1 return filled_bm def count_ones(bm: int) -> int: ctr = 0 for idx in range(64): ctr += bm >> idx & 1 return ctr def all_bit_combs(bm: int): for bit_comb in range(2**count_ones(bm)): yield fill_bm(bm, bit_comb) def n_mvs_mask(idx: int) -> int: bm = 0 for dir in (-6, -10, -17, -15, 6, 10, 17, 15): new_idx = idx + dir if abs(new_idx%8 - idx%8) < 3 and new_idx in range(64): bm |= 1 << new_idx return bm def k_mvs_mask(idx: int) -> int: bm = 0 for dir in (1, -1, -7, -8, -9, 7, 8, 9): new_idx = idx + dir if abs(new_idx%8 - idx%8) < 2 and new_idx in range(64): bm |= 1 << new_idx return bm def wp_double_push_mask(idx: int) -> int: if idx // 8 == 6: return 1 << (idx - 16) return 0 def wp_push_mask(idx: int) -> int: if not idx // 8 == 0: return 1 << (idx - 8) return 0 def wp_left_take_mask(idx: int) -> int: if not idx // 8 == 0 and not idx % 8 == 0: return 1 << (idx - 9) return 0 def wp_right_take_mask(idx: int) -> int: if not idx // 8 == 0 and not idx % 8 == 7: return 1 << (idx - 7) return 0 def bp_double_push_mask(idx: int) -> int: if idx // 8 == 1: return 1 << (idx + 16) return 0 def bp_push_mask(idx: int) -> int: if not idx // 8 == 7: return 1 << (idx + 8) return 0 def bp_left_take_mask(idx: int) -> int: if not idx // 8 == 7 and not idx % 8 == 0: return 1 << (idx + 7) return 0 def bp_right_take_mask(idx: int) -> int: if not idx // 8 == 7 and not idx % 8 == 7: return 1 << (idx + 9) return 0 def l_border_slide(idx: int) -> int: slide_bm = 0 if idx % 8 == 7: return slide_bm while True: idx += 1 slide_bm |= 1 << idx if idx % 8 == 7: return slide_bm def l_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx % 8 == 7: return slide_bm while True: idx += 1 slide_bm |= 1 << idx if idx % 8 == 7 or bm & 1 << idx: return slide_bm def r_border_slide(idx: int) -> int: slide_bm = 0 if idx % 8 == 0: return slide_bm while True: idx -= 1 slide_bm |= 1 << idx if idx % 8 == 0: return slide_bm def r_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx % 8 == 0: return slide_bm while True: idx -= 1 slide_bm |= 1 << idx if idx % 8 == 0 or bm & 1 << idx: return slide_bm def u_border_slide(idx: int) -> int: slide_bm = 0 if idx // 8 == 7: return slide_bm while True: idx += 8 slide_bm |= 1 << idx if idx // 8 == 7: return slide_bm def u_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx // 8 == 7: return slide_bm while True: idx += 8 slide_bm |= 1 << idx if idx // 8 == 7 or bm & 1 << idx: return slide_bm def d_border_slide(idx: int) -> int: slide_bm = 0 if idx // 8 == 0: return slide_bm while True: idx -= 8 slide_bm |= 1 << idx if idx // 8 == 0: return slide_bm def d_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx // 8 == 0: return slide_bm while True: idx -= 8 slide_bm |= 1 << idx if idx // 8 == 0 or bm & 1 << idx: return slide_bm def lu_border_slide(idx: int) -> int: slide_bm = 0 if idx % 8 == 7 or idx // 8 == 7: return slide_bm while True: idx += 9 slide_bm |= 1 << idx if idx % 8 == 7 or idx // 8 == 7: return slide_bm def lu_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx % 8 == 7 or idx // 8 == 7: return slide_bm while True: idx += 9 slide_bm |= 1 << idx if idx % 8 == 7 or idx // 8 == 7 or bm & 1 << idx: return slide_bm def ld_border_slide(idx: int) -> int: slide_bm = 0 if idx % 8 == 7 or idx // 8 == 0: return slide_bm while True: idx -= 7 slide_bm |= 1 << idx if idx % 8 == 7 or idx // 8 == 0: return slide_bm def ld_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx % 8 == 7 or idx // 8 == 0: return slide_bm while True: idx -= 7 slide_bm |= 1 << idx if idx % 8 == 7 or idx // 8 == 0 or bm & 1 << idx: return slide_bm def ru_border_slide(idx: int) -> int: slide_bm = 0 if idx % 8 == 0 or idx // 8 == 7: return slide_bm while True: idx += 7 slide_bm |= 1 << idx if idx % 8 == 0 or idx // 8 == 7: return slide_bm def ru_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx % 8 == 0 or idx // 8 == 7: return slide_bm while True: idx += 7 slide_bm |= 1 << idx if idx % 8 == 0 or idx // 8 == 7 or bm & 1 << idx: return slide_bm def rd_border_slide(idx: int) -> int: slide_bm = 0 if idx % 8 == 0 or idx // 8 == 0: return slide_bm while True: idx -= 9 slide_bm |= 1 << idx if idx % 8 == 0 or idx // 8 == 0: return slide_bm def rd_slide(bm: int, idx: int) -> int: slide_bm = 0 if idx % 8 == 0 or idx // 8 == 0: return slide_bm while True: idx -= 9 slide_bm |= 1 << idx if idx % 8 == 0 or idx // 8 == 0 or bm & 1 << idx: return slide_bm direction_sliding_func = { 'L': l_slide, 'R': r_slide, 'U': u_slide, 'D': d_slide, 'LU': lu_slide, 'LD': ld_slide, 'RU': ru_slide, 'RD': rd_slide, } direction_border_sliding_func = { 'L': l_border_slide, 'R': r_border_slide, 'U': u_border_slide, 'D': d_border_slide, 'LU': lu_border_slide, 'LD': ld_border_slide, 'RU': ru_border_slide, 'RD': rd_border_slide, } def write_8x8_table(function: typing.Callable[[int], int], file_name: str = '8x8_table.py', tuple_name: str = 'TABLE', overwrite: bool = False) -> None: f = open(file_name, 'w' if overwrite else 'a') f.write(tuple_name + ' = (') for idx in range(64): if idx % 8 == 0: f.write('\n ') f.write(int_to_hexstr(function(idx)) + ', ') f.write('\n)\n') def write_comb_dict(border_func: int, sliding_func: typing.Callable[[int, int], int], file_name: str = 'blocker_comb_table.py', tuple_name: str = 'BLOCKER_COMBS', overwrite: bool = False) -> None: f = open(file_name, 'w' if overwrite else 'a') f.write(tuple_name + ' = (') for idx in range(64): f.write('\n {') for ctr, bit_comb in enumerate(all_bit_combs(border_func(idx))): if ctr % 4 == 0: f.write('\n ') f.write(int_to_hexstr(bit_comb) + ': ' + int_to_hexstr(sliding_func(bit_comb, idx)) + ', ') f.write('\n }, ') f.write('\n)\n') def write_piece_move_tables(file_name: str = 'piece_move_tables.py', overwrite: bool = True) -> None: if overwrite: open(file_name, 'w') func_dict = {'N': n_mvs_mask, 'K': k_mvs_mask, 'WP_DOUBLE_PUSH': wp_double_push_mask, 'WP_PUSH': wp_push_mask, 'WP_LEFT_TAKE': wp_left_take_mask, 'WP_RIGHT_TAKE': wp_right_take_mask, 'BP_DOUBLE_PUSH': bp_double_push_mask, 'BP_PUSH': bp_push_mask, 'BP_LEFT_TAKE': bp_left_take_mask, 'BP_RIGHT_TAKE': bp_right_take_mask} for piece, func in func_dict.items(): write_8x8_table(func, file_name, piece + '_MASK') for direction in ('L', 'R', 'U', 'D', 'LU', 'LD', 'RU', 'RD'): write_8x8_table(direction_border_sliding_func[direction], file_name, direction + '_BORDER_MASK') for direction in ('L', 'R', 'U', 'D', 'LU', 'LD', 'RU', 'RD'): write_comb_dict(direction_border_sliding_func[direction], direction_sliding_func[direction], file_name, direction + '_MASK') if __name__ == '__main__': write_piece_move_tables()