import os os.system("pip install gradio chess cairosvg torch huggingface") import gradio as gr import chess import chess.svg from io import BytesIO import cairosvg import torch from huggingface_hub import hf_hub_download from torch import nn import numpy as np from PIL import Image eval = 0 # Global board state wait_list_ip = [] wait_list_name = [] user_n = 0 board = chess.Board() player_color = chess.WHITE # Default ai_color = chess.BLACK # Default model_path = hf_hub_download("sigmoidneuron123/NeoChess", "chessy_model.pth") device = torch.device("cpu") def board_to_tensor(board): piece_encoding = { 'P': 1, 'N': 2, 'B': 3, 'R': 4, 'Q': 5, 'K': 6, 'p': 7, 'n': 8, 'b': 9, 'r': 10, 'q': 11, 'k': 12 } tensor = torch.zeros(64, dtype=torch.long) for square in chess.SQUARES: piece = board.piece_at(square) if piece: tensor[square] = piece_encoding[piece.symbol()] else: tensor[square] = 0 return tensor.unsqueeze(0) class NN1(nn.Module): def __init__(self): super().__init__() self.embedding = nn.Embedding(13, 64) self.attention = nn.MultiheadAttention(embed_dim=64, num_heads=16) self.neu = 512 self.neurons = nn.Sequential( nn.Linear(4096, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, self.neu), nn.ReLU(), nn.Linear(self.neu, 64), nn.ReLU(), nn.Linear(64, 4) ) def forward(self, x): x = self.embedding(x) x = x.permute(1, 0, 2) attn_output, _ = self.attention(x, x, x) x = attn_output.permute(1, 0, 2).contiguous() x = x.view(x.size(0), -1) x = self.neurons(x) return x model = NN1().to(device) file = torch.load(model_path,map_location=device) model.load_state_dict(file) model.eval() def get_evaluation(board): tensor = board_to_tensor(board).to(device) with torch.no_grad(): evaluation = model(tensor)[0][0].item() if board.turn == chess.WHITE: return evaluation else: return -evaluation def order_moves(board): # Example heuristic: captures first, then others captures = [] non_captures = [] for move in board.legal_moves: if board.is_capture(move): captures.append(move) else: non_captures.append(move) # Put captures first return captures + non_captures def search(board, depth, alpha, beta): """ A negamax search function. """ if depth == 0 or board.is_game_over(): return get_evaluation(board) max_eval = float('-inf') for move in order_moves(board): board.push(move) evali = -search(board, depth - 1, -beta, -alpha) board.pop() max_eval = max(max_eval, evali) alpha = max(alpha, evali) if alpha >= beta: break return max_eval def ai_actor(board): evaling = {} for move in board.legal_moves: board.push(move) evaling[move] = -search(board, depth=2, alpha=float('-inf'), beta=float('inf')) board.pop() keys = list(evaling.keys()) vals = list(evaling.values()) logits = torch.tensor(vals).to(device) probs = torch.softmax(logits,dim=0) idx = torch.argmax(probs) idx = int(idx) return (keys[idx],vals[idx]) # Convert board to image def board_to_image(): svg_data = chess.svg.board(board, orientation=player_color) png_data = BytesIO() cairosvg.svg2png(bytestring=svg_data.encode('utf-8'), write_to=png_data) return np.array(Image.open(BytesIO(png_data.getvalue())).convert("RGB")) # Handle move input def make_move(move_uci,request: gr.Request): global board, eval, wait_list_ip, user_n if wait_list_ip[user_n] == request.client.host: if board.turn == player_color: if not move_uci: return "Please enter a move.", board_to_image(), f'Your Eval: {eval}' if board.is_game_over(): return "Game over!", board_to_image(), f'Your Eval: {eval}' # Player's move try: board.push_uci(move_uci) except: return "Invalid move!", board_to_image(), f'Your Eval: {eval}' # AI's move if not board.is_game_over(): ai_act = ai_actor(board) ai_move = ai_act[0].uci() eval = -ai_act[1] if ai_move: board.push_uci(ai_move) return "Move accepted.", board_to_image(), f'Your Eval: {eval}' else: ai_act = ai_actor(board) ai_move = ai_act[0].uci() eval = -ai_act[1] if ai_move: board.push_uci(ai_move) if not move_uci: return "Please enter a move.", board_to_image(), f'Your Eval: {eval}' if board.is_game_over(): return "Game over!", board_to_image(), f'Your Eval: {eval}' # Player's move try: board.push_uci(move_uci) except: return "Invalid move!", board_to_image(), f'Your Eval: {eval}' return "Move accepted.", board_to_image(), f'Your Eval: {eval}' else: return "Wrong user!", board_to_image(), f'Your Eval: {eval}' def wait(user_name,request: gr.Request): global wait_list_ip, wait_list_name wait_list_ip.append(request.client.host) wait_list_name.append(user_name) return None def next(request: gr.Request): global wait_list_ip, user_n, wait_list_name if wait_list_ip[user_n] == request.client.host: try: user_n += 1 wait_list_ip[user_n] except: pass return f"Current_user: {wait_list_name[user_n]}" # Reset game def reset_game(request: gr.Request): global board, wait_list_ip, user_n if wait_list_ip[user_n] == request.client.host: board = chess.Board() return board_to_image() # Set player color def set_color(color_choice,request: gr.Request): global player_color, ai_color, board, wait_list_ip, user_n if wait_list_ip[user_n] == request.client.host: player_color = chess.WHITE if color_choice == "White" else chess.BLACK ai_color = not player_color board.reset() return board_to_image() # --- Gradio UI --- with gr.Blocks() as demo: gr.Markdown("## ♟️ Chess AI") eval_val = gr.Markdown('Your Eval: 0.0') current_user = gr.Markdown("Current_user: None") with gr.Row(): color_choice = gr.Radio(choices=["White", "Black"], value="White", label="Choose your side") reset_btn = gr.Button("♻️ Reset Board") board_output = gr.Image(value=board_to_image(), label="Chess Board", type="numpy") with gr.Row(): move_input = gr.Textbox(label="Enter your move (UCI format, e.g., e2e4)") result = gr.Textbox(label="Result") submit = gr.Button("Play Move") with gr.Row(): name = gr.Textbox(label="Enter user name") wai = gr.Button("Wait") nx = gr.Button("Next") submit.click(make_move, inputs=[move_input], outputs=[result, board_output, eval_val]) reset_btn.click(reset_game, outputs=[board_output]) color_choice.change(set_color, inputs=[color_choice], outputs=board_output) wai.click(wait, inputs=[name], outputs=[]) nx.click(next,outputs=[current_user]) demo.launch()