system HF Staff commited on
Commit
2377b60
·
verified ·
1 Parent(s): a5f2e46

Deploy from ee772db

Browse files
Files changed (1) hide show
  1. app.py +35 -39
app.py CHANGED
@@ -12,7 +12,6 @@ Weights are resolved in this order:
12
 
13
  from __future__ import annotations
14
 
15
- import itertools
16
  import os
17
  import sys
18
  from pathlib import Path
@@ -137,10 +136,17 @@ def _bot_move(board: chess.Board, sims: int):
137
 
138
  def on_move(fen: str, sims: int, human_color: str):
139
  """Human just moved; reply with the bot's move (whichever side is to move).
140
- The human's board orientation equals their color."""
 
 
 
141
  board = chess.Board(fen)
142
  if board.is_game_over():
143
- return board.fen(), _result_text(board, human_color), eval_bar_html(board, human_color)
 
 
 
 
144
 
145
  san, value = _bot_move(board, sims)
146
 
@@ -149,21 +155,14 @@ def on_move(fen: str, sims: int, human_color: str):
149
  else:
150
  eval_str = f" (eval {value:+.2f})" if value is not None else ""
151
  status = f"Bot played **{san}**{eval_str}. Your move."
152
- return board.fen(), status, eval_bar_html(board, human_color)
153
-
154
-
155
- # Monotonic id so every New game yields a *distinct* setup dict. Without it,
156
- # replaying with the same colour returns an identical dict and the gr.render
157
- # block sees no change — so the board wouldn't reset.
158
- _game_counter = itertools.count(1)
159
 
160
 
161
- def new_game(play_as: str, sims: int) -> dict:
162
  """Start a fresh game. If the human plays Black, the bot (White) opens.
163
 
164
- Returns a ``setup`` dict that drives a ``gr.render`` block — changing it
165
- rebuilds the board so its orientation (chessboard.js, set only at mount)
166
- actually flips."""
167
  human_color = "black" if play_as == "Black" else "white"
168
  board = chess.Board()
169
  if human_color == "black":
@@ -171,9 +170,7 @@ def new_game(play_as: str, sims: int) -> dict:
171
  status = f"New game — you are **Black**. Bot opened with **{san}**. Your move."
172
  else:
173
  status = "New game — you are **White**. Make your move."
174
- setup = {"fen": board.fen(), "orientation": human_color,
175
- "color": human_color, "status": status, "nonce": next(_game_counter)}
176
- return setup, eval_bar_html(board, human_color)
177
 
178
 
179
  with gr.Blocks(title="ChessTransformer", theme=gr.themes.Soft()) as demo:
@@ -184,22 +181,29 @@ with gr.Blocks(title="ChessTransformer", theme=gr.themes.Soft()) as demo:
184
  "It reaches **~2100 Elo** vs Stockfish at full strength; this CPU demo "
185
  "runs at a lower sim count so moves come back quickly.\n\n"
186
  "**Pick your color and hit New game.** Drag a piece to move — the bot "
187
- "replies automatically. "
188
  "[GitHub repo →](https://github.com/tchauffi/ChessTransformer)"
189
  )
190
- setup = gr.State({"fen": START_FEN, "orientation": "white", "color": "white",
191
- "status": "You are **White**. Make your move.", "nonce": 0})
192
 
193
  with gr.Row():
194
- eval_col = gr.Column(scale=0, min_width=40)
195
- board_col = gr.Column(scale=3)
196
- ctrl_col = gr.Column(scale=1)
 
 
197
 
198
- # Eval bar (persistent, hidden by default) — sits left of the board.
199
  with eval_col:
200
  eval_bar = gr.HTML(eval_bar_html(chess.Board(), "white"), visible=False)
201
 
202
- # Controls first so `sims` exists when the render block references it.
 
 
 
 
 
 
 
203
  with ctrl_col:
204
  play_as = gr.Radio(["White", "Black"], value="White", label="Play as")
205
  sims = gr.Slider(32, 1200, value=DEFAULT_SIMS, step=8,
@@ -208,21 +212,13 @@ with gr.Blocks(title="ChessTransformer", theme=gr.themes.Soft()) as demo:
208
  show_eval = gr.Checkbox(False, label="Show evaluation bar")
209
  new_btn = gr.Button("New game", variant="primary")
210
 
211
- # The board lives in a gr.render so switching color rebuilds it with the new
212
- # orientation (chessboard.js only reads orientation at construction).
213
- with board_col:
214
- @gr.render(inputs=setup)
215
- def render_board(cfg):
216
- board = Chessboard(value=cfg["fen"], game_mode=True,
217
- orientation=cfg["orientation"], label="Drag to move")
218
- status = gr.Markdown(cfg["status"])
219
- board.move(
220
- lambda fen, s, _c=cfg["color"]: on_move(fen, s, _c),
221
- inputs=[board, sims], outputs=[board, status, eval_bar],
222
- )
223
-
224
  show_eval.change(lambda show: gr.update(visible=show), inputs=show_eval, outputs=eval_bar)
225
- new_btn.click(new_game, inputs=[play_as, sims], outputs=[setup, eval_bar])
 
226
 
227
 
228
  if __name__ == "__main__":
 
12
 
13
  from __future__ import annotations
14
 
 
15
  import os
16
  import sys
17
  from pathlib import Path
 
136
 
137
  def on_move(fen: str, sims: int, human_color: str):
138
  """Human just moved; reply with the bot's move (whichever side is to move).
139
+
140
+ A generator: first yields a "thinking" status (so the player sees the bot is
141
+ working during the ~1-3s CPU search), then yields the bot's reply. The board
142
+ is shown from White's side, so the eval bar is White-oriented."""
143
  board = chess.Board(fen)
144
  if board.is_game_over():
145
+ yield board.fen(), _result_text(board, human_color), eval_bar_html(board, "white")
146
+ return
147
+
148
+ # Immediate feedback while the search runs (board/eval unchanged for now).
149
+ yield gr.update(), "⏳ ChessTransformer is thinking…", gr.update()
150
 
151
  san, value = _bot_move(board, sims)
152
 
 
155
  else:
156
  eval_str = f" (eval {value:+.2f})" if value is not None else ""
157
  status = f"Bot played **{san}**{eval_str}. Your move."
158
+ yield board.fen(), status, eval_bar_html(board, "white")
 
 
 
 
 
 
159
 
160
 
161
+ def new_game(play_as: str, sims: int):
162
  """Start a fresh game. If the human plays Black, the bot (White) opens.
163
 
164
+ Returns (fen, status, eval_bar_html, human_color) written straight to the
165
+ statically-mounted board so a same-colour replay still resets it."""
 
166
  human_color = "black" if play_as == "Black" else "white"
167
  board = chess.Board()
168
  if human_color == "black":
 
170
  status = f"New game — you are **Black**. Bot opened with **{san}**. Your move."
171
  else:
172
  status = "New game — you are **White**. Make your move."
173
+ return board.fen(), status, eval_bar_html(board, "white"), human_color
 
 
174
 
175
 
176
  with gr.Blocks(title="ChessTransformer", theme=gr.themes.Soft()) as demo:
 
181
  "It reaches **~2100 Elo** vs Stockfish at full strength; this CPU demo "
182
  "runs at a lower sim count so moves come back quickly.\n\n"
183
  "**Pick your color and hit New game.** Drag a piece to move — the bot "
184
+ "replies automatically. (The board is shown from White's side.) "
185
  "[GitHub repo →](https://github.com/tchauffi/ChessTransformer)"
186
  )
187
+ human_color = gr.State("white")
 
188
 
189
  with gr.Row():
190
+ # Solid min_widths so the board container always has a size at mount —
191
+ # the chessboard.js component reloads the page if it inits at 0 width.
192
+ eval_col = gr.Column(scale=0, min_width=44)
193
+ board_col = gr.Column(scale=3, min_width=320)
194
+ ctrl_col = gr.Column(scale=1, min_width=200)
195
 
 
196
  with eval_col:
197
  eval_bar = gr.HTML(eval_bar_html(chess.Board(), "white"), visible=False)
198
 
199
+ # Board mounted statically (not in a gr.render) so it initializes once on the
200
+ # laid-out page — the dynamic remount was failing on mobile and triggering the
201
+ # component's window.location.reload() loop.
202
+ with board_col:
203
+ board = Chessboard(value=START_FEN, game_mode=True, orientation="white",
204
+ label="Drag to move", min_width=320)
205
+ status = gr.Markdown("You are **White**. Make your move.")
206
+
207
  with ctrl_col:
208
  play_as = gr.Radio(["White", "Black"], value="White", label="Play as")
209
  sims = gr.Slider(32, 1200, value=DEFAULT_SIMS, step=8,
 
212
  show_eval = gr.Checkbox(False, label="Show evaluation bar")
213
  new_btn = gr.Button("New game", variant="primary")
214
 
215
+ # on_move is a generator streams the "thinking" status; show_progress hidden
216
+ # so Gradio's overlay doesn't sit over the board.
217
+ board.move(on_move, inputs=[board, sims, human_color],
218
+ outputs=[board, status, eval_bar], show_progress="hidden")
 
 
 
 
 
 
 
 
 
219
  show_eval.change(lambda show: gr.update(visible=show), inputs=show_eval, outputs=eval_bar)
220
+ new_btn.click(new_game, inputs=[play_as, sims],
221
+ outputs=[board, status, eval_bar, human_color])
222
 
223
 
224
  if __name__ == "__main__":