Spaces:
Running on Zero
Running on Zero
File size: 5,020 Bytes
23ab0d8 3f4cf5e 7839e5e 4ee9ac9 23ab0d8 2d742d9 3f4cf5e 23ab0d8 3f4cf5e 23ab0d8 3f4cf5e 23ab0d8 2d742d9 23ab0d8 0a5571c a13a48e 75a591c e164a6e 0a5571c 23ab0d8 75a591c 23ab0d8 75a591c 23ab0d8 32c185e 3f4cf5e 7839e5e 4e63bca 23ab0d8 7839e5e e164a6e 3ae28d9 e164a6e 23ab0d8 e164a6e 3f4cf5e e164a6e 3ae28d9 e164a6e 75a591c 3ae28d9 75a591c 3ae28d9 75a591c e164a6e 23ab0d8 e164a6e 3f4cf5e 23ab0d8 7839e5e 23ab0d8 3f4cf5e 7839e5e 3f4cf5e 7839e5e 3f4cf5e 7839e5e 3f4cf5e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | import importlib.util
import gradio as gr
import chess
import chess.svg
import torch
import spaces
from huggingface_hub import hf_hub_download
from transformers import AutoModel, AutoConfig
MODEL_ID = "Datdanboi25/Charles-the-Chess-Bot"
REVISION = "63e2574705794b40899f642aaa619d1668e1e731"
config = AutoConfig.from_pretrained(MODEL_ID, revision=REVISION, trust_remote_code=True)
model = AutoModel.from_pretrained(
MODEL_ID, revision=REVISION, config=config, trust_remote_code=True
).eval()
_TOK_PATH = hf_hub_download(MODEL_ID, "tokenization_chess_policy.py", revision=REVISION)
_SPEC = importlib.util.spec_from_file_location("charles_tokenization", _TOK_PATH)
charles_tokenization = importlib.util.module_from_spec(_SPEC)
_SPEC.loader.exec_module(charles_tokenization)
board = chess.Board()
@spaces.GPU
def get_bot_move_uci(fen: str) -> str | None:
"""สำคัญ: รับ FEN เป็น argument แทนการอ่าน global `board`
เพราะฟังก์ชันนี้รันใน subprocess แยกของ ZeroGPU
ต้อง reconstruct board ในนั้นเอง ไม่งั้นจะได้สถานะเก่าค้าง"""
b = chess.Board(fen)
legal_moves = list(b.legal_moves)
if not legal_moves:
return None
inputs = charles_tokenization.build_model_inputs(
[b.copy(stack=False)], include_candidate_uci=True
)
ucis = inputs.pop("candidate_uci")[0]
with torch.inference_mode():
logits = model(**inputs).logits[0].float()
moves = [chess.Move.from_uci(u) for u in ucis]
best_idx = int(torch.argmax(logits))
return moves[best_idx].uci()
def make_move(user_move):
global board
try:
if board.is_game_over():
return "เกมจบแล้ว! กรุณากดเริ่มเกมใหม่", chess.svg.board(board)
move = chess.Move.from_uci(user_move.strip())
if move not in board.legal_moves:
check_hint = ""
if board.is_check():
check_hint = " ⚠️ ตอนนี้คุณโดนรุกอยู่! ต้องเดินแก้รุกก่อน (ย้ายราชาหนี / เอาตัวบัง / กินตัวที่รุก)"
return f"ตาเดินไม่ถูกต้องตามกฎ!{check_hint} (ตัวอย่าง: e2e4, g1f3)", chess.svg.board(board)
board.push(move)
except ValueError:
return "รูปแบบตาเดินไม่ถูกต้อง (ต้องเป็นแบบ UCI เช่น e2e4)", chess.svg.board(board)
if board.is_game_over():
if board.is_checkmate():
winner = "คุณ" if board.turn != chess.WHITE else "บอท"
# board.turn คือฝ่ายที่ต้องเดินแต่เดินไม่ได้ (โดนรุกฆาต) = ฝ่ายแพ้
loser = "บอท" if board.turn != chess.WHITE else "คุณ"
return f"♛ รุกฆาต! {loser}แพ้", chess.svg.board(board)
return "เกมจบแล้ว! เสมอ (Stalemate/Draw)", chess.svg.board(board)
bot_move_uci = get_bot_move_uci(board.fen())
if bot_move_uci:
bot_move = chess.Move.from_uci(bot_move_uci)
if bot_move in board.legal_moves:
board.push(bot_move)
check_note = " (รุก!)" if board.is_check() else ""
if board.is_checkmate():
msg = f"บอทเดิน: {bot_move.uci()} — ♛ รุกฆาต! คุณแพ้"
else:
msg = f"บอทเดิน: {bot_move.uci()}{check_note}"
else:
msg = f"บอทพยายามเดิน {bot_move_uci} แต่ผิดกฎ - ข้ามตานี้"
else:
msg = "บอทไม่สามารถเดินหมากได้ - ตาของคุณเดินต่อ"
return msg, chess.svg.board(board)
def reset_game():
global board
board = chess.Board()
return "เริ่มเกมใหม่เรียบร้อย", chess.svg.board(board)
with gr.Blocks() as demo:
gr.Markdown("# ♟️ ซ้อมหมากรุกกับ Charles the Chess Bot")
board_html = gr.HTML(chess.svg.board(board))
with gr.Row():
move_input = gr.Textbox(label="ใส่ตาเดินแบบ UCI (เช่น e2e4, g1f3):", placeholder="e2e4")
submit_btn = gr.Button("เดินหมาก", variant="primary")
reset_btn = gr.Button("เริ่มเกมใหม่")
status_text = gr.Textbox(label="สถานะ / ตาเดินของบอท")
submit_btn.click(make_move, inputs=[move_input], outputs=[status_text, board_html])
reset_btn.click(reset_game, outputs=[status_text, board_html])
demo.launch() |