import ctypes import platform import unittest from pathlib import Path WHITE, BLACK = 0, 1 FILES = {c:i for i,c in enumerate("abcdefgh")} def sq(name: str) -> int: f = FILES[name[0].lower()] r = int(name[1]) - 1 return f + 8 * r def bb_from(*algebraic): m = 0 for s in algebraic: m |= (1 << sq(s)) return m def popcount(x: int) -> int: return x.bit_count() def draw_bb(mask: int, origin: int | None = None) -> str: print("\n") lines = [] for r in range(7, -1, -1): row = [] for f in range(8): sqi = r * 8 + f bit = (mask >> sqi) & 1 if origin is not None and sqi == origin: ch = 'O' elif bit: ch = 'x' else: ch = '.' row.append(ch) lines.append(f"{r+1} " + " ".join(row)) lines.append(" " + " ".join(FILES)) lines = "\n".join(lines) print(lines, "\n") class ChessLibTestBase(unittest.TestCase): @classmethod def setUpClass(cls): root = Path(__file__).resolve().parents[1] libname = "libchess.so" libpath = root / "build" / libname cls.lib = ctypes.CDLL(str(libpath)) attack_cache_functions = [ "create_knight_attack_cache", "create_pawn_attack_cache", "create_king_attack_cache", ] # init functions for fn in attack_cache_functions: getattr(cls.lib, fn).argtypes = [] getattr(cls.lib, fn).restype = None cls.lib.create_knight_attack_cache() cls.lib.create_pawn_attack_cache() cls.lib.create_king_attack_cache() KnightArr = ctypes.c_uint64 * 64 KingArr = ctypes.c_uint64 * 64 PawnRow = ctypes.c_uint64 * 64 PawnArr = PawnRow * 2 cls.KNIGHT_ATTACKS = KnightArr.in_dll(cls.lib, "KNIGHT_ATTACKS") cls.KING_ATTACKS = KingArr.in_dll(cls.lib, "KING_ATTACKS") cls.PAWN_ATTACKS = PawnArr.in_dll(cls.lib, "PAWN_ATTACKS")