Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files
app.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
# app.py
|
| 2 |
import os
|
| 3 |
-
import base64
|
| 4 |
import gradio as gr
|
| 5 |
import chess
|
| 6 |
import chess.svg
|
|
@@ -15,20 +14,15 @@ DEFAULT_MOVETIME_MS = 1500 # engine denktijd per zet
|
|
| 15 |
|
| 16 |
# -------- Helpers --------
|
| 17 |
def board_svg(board: chess.Board, last_move=None) -> str:
|
| 18 |
-
"""Geef een SVG
|
| 19 |
return chess.svg.board(
|
| 20 |
board=board,
|
| 21 |
lastmove=last_move,
|
| 22 |
check=board.is_check(),
|
| 23 |
coordinates=True,
|
| 24 |
-
size=
|
| 25 |
)
|
| 26 |
|
| 27 |
-
def svg_to_data_url(svg_text: str) -> str:
|
| 28 |
-
"""Returneer data-URL van SVG (zodat Gradio 'm kan tonen in HTML)."""
|
| 29 |
-
b64 = base64.b64encode(svg_text.encode("utf-8")).decode("ascii")
|
| 30 |
-
return f"data:image/svg+xml;base64,{b64}"
|
| 31 |
-
|
| 32 |
def new_engine(threads=DEFAULT_THREADS, hash_mb=DEFAULT_HASH_MB, ponder=False):
|
| 33 |
engine = chess.engine.SimpleEngine.popen_uci(STOCKFISH_PATH)
|
| 34 |
# Sterke UCI-opts
|
|
@@ -70,7 +64,8 @@ def engine_limit(state):
|
|
| 70 |
|
| 71 |
def render(state):
|
| 72 |
svg = board_svg(state["board"], last_move=state["last_move"])
|
| 73 |
-
|
|
|
|
| 74 |
|
| 75 |
# -------- Acties --------
|
| 76 |
def new_game(engine_color, movetime_ms, depth, threads, hash_mb):
|
|
@@ -84,6 +79,7 @@ def make_move(state, user_move):
|
|
| 84 |
return state, *render(state), f"Partij is al afgelopen: {board.result()}."
|
| 85 |
|
| 86 |
try:
|
|
|
|
| 87 |
mv = chess.Move.from_uci(user_move.strip())
|
| 88 |
if mv not in board.legal_moves:
|
| 89 |
return state, *render(state), "Ongeldige zet (niet legaal in deze stelling)."
|
|
@@ -96,6 +92,7 @@ def make_move(state, user_move):
|
|
| 96 |
img, fen = render(state)
|
| 97 |
return state, img, fen, f"Partij afgelopen: {board.result()}."
|
| 98 |
|
|
|
|
| 99 |
side_to_move = "white" if board.turn == chess.WHITE else "black"
|
| 100 |
if side_to_move == state["engine_color"]:
|
| 101 |
msg = engine_move(state)
|
|
@@ -124,6 +121,7 @@ def undo_move(state):
|
|
| 124 |
board: chess.Board = state["board"]
|
| 125 |
if len(board.move_stack) == 0:
|
| 126 |
return state, *render(state), "Geen zetten om terug te nemen."
|
|
|
|
| 127 |
board.pop()
|
| 128 |
if state["engine_color"] == ("white" if board.turn == chess.WHITE else "black") and len(board.move_stack) > 0:
|
| 129 |
board.pop()
|
|
@@ -143,11 +141,16 @@ def stop_engine(state):
|
|
| 143 |
return "Engine gestopt."
|
| 144 |
|
| 145 |
# -------- Gradio UI --------
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
gr.Markdown("# ♟️ Boss Chess (Stockfish)\nSpeel tegen een sterke NNUE-engine (Stockfish) in je browser.")
|
| 148 |
|
| 149 |
with gr.Row():
|
| 150 |
-
board_html = gr.HTML(label="Bord")
|
| 151 |
fen_out = gr.Textbox(label="FEN", interactive=False)
|
| 152 |
|
| 153 |
with gr.Row():
|
|
@@ -168,12 +171,14 @@ with gr.Blocks(title="Boss Chess (Stockfish)") as demo:
|
|
| 168 |
|
| 169 |
state = gr.State()
|
| 170 |
|
|
|
|
| 171 |
btn_new.click(new_game, [engine_color, movetime, depth, threads, hash_mb],
|
| 172 |
[state, board_html, fen_out, status])
|
| 173 |
btn_move.click(make_move, [state, user_move], [state, board_html, fen_out, status])
|
| 174 |
btn_undo.click(undo_move, [state], [state, board_html, fen_out, status])
|
| 175 |
btn_resign.click(resign, [state], [state, board_html, fen_out, status])
|
| 176 |
|
|
|
|
| 177 |
demo.load(new_game, [engine_color, movetime, depth, threads, hash_mb],
|
| 178 |
[state, board_html, fen_out, status])
|
| 179 |
|
|
|
|
| 1 |
# app.py
|
| 2 |
import os
|
|
|
|
| 3 |
import gradio as gr
|
| 4 |
import chess
|
| 5 |
import chess.svg
|
|
|
|
| 14 |
|
| 15 |
# -------- Helpers --------
|
| 16 |
def board_svg(board: chess.Board, last_move=None) -> str:
|
| 17 |
+
"""Geef een inline SVG van het bord terug (direct renderbaar in gr.HTML)."""
|
| 18 |
return chess.svg.board(
|
| 19 |
board=board,
|
| 20 |
lastmove=last_move,
|
| 21 |
check=board.is_check(),
|
| 22 |
coordinates=True,
|
| 23 |
+
size=520,
|
| 24 |
)
|
| 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
def new_engine(threads=DEFAULT_THREADS, hash_mb=DEFAULT_HASH_MB, ponder=False):
|
| 27 |
engine = chess.engine.SimpleEngine.popen_uci(STOCKFISH_PATH)
|
| 28 |
# Sterke UCI-opts
|
|
|
|
| 64 |
|
| 65 |
def render(state):
|
| 66 |
svg = board_svg(state["board"], last_move=state["last_move"])
|
| 67 |
+
# Geef inline SVG terug; gr.HTML rendert dit direct
|
| 68 |
+
return svg, state["board"].fen()
|
| 69 |
|
| 70 |
# -------- Acties --------
|
| 71 |
def new_game(engine_color, movetime_ms, depth, threads, hash_mb):
|
|
|
|
| 79 |
return state, *render(state), f"Partij is al afgelopen: {board.result()}."
|
| 80 |
|
| 81 |
try:
|
| 82 |
+
# UCI notatie (b.v. e2e4 of e7e8q)
|
| 83 |
mv = chess.Move.from_uci(user_move.strip())
|
| 84 |
if mv not in board.legal_moves:
|
| 85 |
return state, *render(state), "Ongeldige zet (niet legaal in deze stelling)."
|
|
|
|
| 92 |
img, fen = render(state)
|
| 93 |
return state, img, fen, f"Partij afgelopen: {board.result()}."
|
| 94 |
|
| 95 |
+
# engine aan zet?
|
| 96 |
side_to_move = "white" if board.turn == chess.WHITE else "black"
|
| 97 |
if side_to_move == state["engine_color"]:
|
| 98 |
msg = engine_move(state)
|
|
|
|
| 121 |
board: chess.Board = state["board"]
|
| 122 |
if len(board.move_stack) == 0:
|
| 123 |
return state, *render(state), "Geen zetten om terug te nemen."
|
| 124 |
+
# Neem 1 of 2 zetten terug zodat jij weer aan zet bent
|
| 125 |
board.pop()
|
| 126 |
if state["engine_color"] == ("white" if board.turn == chess.WHITE else "black") and len(board.move_stack) > 0:
|
| 127 |
board.pop()
|
|
|
|
| 141 |
return "Engine gestopt."
|
| 142 |
|
| 143 |
# -------- Gradio UI --------
|
| 144 |
+
CSS = """
|
| 145 |
+
#board { display: flex; justify-content: center; }
|
| 146 |
+
#board svg { max-width: 100%; height: auto; }
|
| 147 |
+
"""
|
| 148 |
+
|
| 149 |
+
with gr.Blocks(title="Boss Chess (Stockfish)", css=CSS) as demo:
|
| 150 |
gr.Markdown("# ♟️ Boss Chess (Stockfish)\nSpeel tegen een sterke NNUE-engine (Stockfish) in je browser.")
|
| 151 |
|
| 152 |
with gr.Row():
|
| 153 |
+
board_html = gr.HTML(label="Bord", elem_id="board")
|
| 154 |
fen_out = gr.Textbox(label="FEN", interactive=False)
|
| 155 |
|
| 156 |
with gr.Row():
|
|
|
|
| 171 |
|
| 172 |
state = gr.State()
|
| 173 |
|
| 174 |
+
# Callbacks
|
| 175 |
btn_new.click(new_game, [engine_color, movetime, depth, threads, hash_mb],
|
| 176 |
[state, board_html, fen_out, status])
|
| 177 |
btn_move.click(make_move, [state, user_move], [state, board_html, fen_out, status])
|
| 178 |
btn_undo.click(undo_move, [state], [state, board_html, fen_out, status])
|
| 179 |
btn_resign.click(resign, [state], [state, board_html, fen_out, status])
|
| 180 |
|
| 181 |
+
# Auto-start een partij
|
| 182 |
demo.load(new_game, [engine_color, movetime, depth, threads, hash_mb],
|
| 183 |
[state, board_html, fen_out, status])
|
| 184 |
|