Spaces:
Sleeping
Sleeping
| # ====================================================== | |
| # ChessPositionSolverTool | |
| # • Uses chessvision.ai’s open-source detector to turn a board image into FEN | |
| # • Feeds that FEN to Stockfish (via python-chess) and returns best move in | |
| # short algebraic notation (e.g. “Qh5#”) | |
| # • Requires: | |
| # pip install chessvision python-chess opencv-python | |
| # and Stockfish binary in PATH (adjust `STOCKFISH_PATH` if needed) | |
| # ====================================================== | |
| import requests, cv2, numpy as np, os, subprocess, json, tempfile | |
| from pydantic import BaseModel, Field | |
| from langchain_core.tools import tool | |
| import chess, chess.engine | |
| from chesscog import Chesscog # <- pip install chesscog | |
| STOCKFISH_PATH = os.getenv("STOCKFISH_PATH", "stockfish") # apt-get install stockfish | |
| class ChessInput(BaseModel): | |
| image_url: str = Field(..., description="PNG/JPG of the chess position") | |
| stockfish_depth: int = Field(18, ge=10, le=30, | |
| description="Search depth for Stockfish") | |
| def chess_position_solver(image_url: str, stockfish_depth: int = 18) -> str: | |
| """ | |
| Converts a chessboard image to FEN with chesscog, sends it to Stockfish, | |
| and returns the best move in algebraic notation (e.g. 'Rxf2+'). | |
| """ | |
| try: | |
| # 1 - download image | |
| img_bytes = requests.get(image_url, timeout=30).content | |
| img = cv2.imdecode(np.frombuffer(img_bytes, np.uint8), cv2.IMREAD_COLOR) | |
| # 2 - infer FEN with chesscog | |
| detector = Chesscog(device="cpu") # auto-downloads model weights | |
| fen = detector.get_fen(img) | |
| if fen is None: | |
| return "chess_position_solver failed: board not recognised." | |
| board = chess.Board(fen) | |
| # 3 - Stockfish | |
| engine = chess.engine.SimpleEngine.popen_uci(STOCKFISH_PATH) | |
| result = engine.play(board, chess.engine.Limit(depth=stockfish_depth)) | |
| engine.quit() | |
| best_move_san = board.san(result.move) # algebraic, e.g. 'Qh5#' | |
| return best_move_san | |
| except Exception as e: | |
| return f"chess_position_solver failed: {e}" |