from __future__ import annotations import os import random import sys import chess from search import Searcher ENGINE_NAME = "ChessMamba" ENGINE_AUTHOR = "CatGirlHtfi" DEFAULT_CKPT = os.environ.get( "CHESSMAMBA_CKPT", os.path.join(os.path.dirname(__file__), "ckpt", "model.pt") ) POLICY_ONLY = os.environ.get("CHESSMAMBA_POLICY_ONLY", "") == "1" def send(msg: str) -> None: sys.stdout.write(msg + "\n") sys.stdout.flush() def main() -> None: board = chess.Board() searcher = Searcher(checkpoint_path=DEFAULT_CKPT, policy_only=POLICY_ONLY) for line in sys.stdin: line = line.strip() if not line: continue tokens = line.split() cmd = tokens[0] if cmd == "uci": send(f"id name {ENGINE_NAME}") send(f"id author {ENGINE_AUTHOR}") send("uciok") elif cmd == "isready": send("readyok") elif cmd == "ucinewgame": board = chess.Board() searcher.reset() elif cmd == "position": _handle_position(board, tokens) searcher.sync(board) elif cmd == "go": move = searcher.choose_move(board, tokens) if move is None: legal = list(board.legal_moves) move = random.choice(legal) if legal else None if move is not None: send(f"bestmove {move.uci()}") else: send("bestmove 0000") elif cmd == "quit": break elif cmd == "stop": pass def _handle_position(board: chess.Board, tokens: list[str]) -> None: if "startpos" in tokens: board.reset() idx = tokens.index("startpos") + 1 elif "fen" in tokens: fen_idx = tokens.index("fen") moves_idx = tokens.index("moves") if "moves" in tokens else len(tokens) fen = " ".join(tokens[fen_idx + 1 : moves_idx]) board.set_fen(fen) idx = moves_idx else: return if idx < len(tokens) and tokens[idx] == "moves": for uci_move in tokens[idx + 1 :]: board.push_uci(uci_move) if __name__ == "__main__": main()