Zual commited on
Commit
215ec13
·
verified ·
1 Parent(s): f92c57e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -79
app.py CHANGED
@@ -1,87 +1,112 @@
1
  import streamlit as st
2
  import chess
3
- import chess.svg
4
  import os
5
  import git
6
  import sys
7
  import random
 
8
 
9
  # Configuration de la page
10
  st.set_page_config(page_title="Échecs contre IA", layout="wide")
11
 
12
  def render_chessboard():
13
- """Render l'échiquier"""
14
- squares = None
15
- if st.session_state.selected_square is not None:
16
- squares = []
17
- from_square = chess.parse_square(st.session_state.selected_square)
18
- for move in st.session_state.board.legal_moves:
19
- if move.from_square == from_square:
20
- squares.append(move.to_square)
21
-
22
- board_svg = chess.svg.board(
23
- board=st.session_state.board,
24
- size=400,
25
- lastmove=st.session_state.board.peek() if st.session_state.board.move_stack else None,
26
- squares=chess.SquareSet(squares) if squares else None
27
- )
28
 
29
- return board_svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- def display_interactive_board():
32
- """Affiche l'échiquier avec les contrôles interactifs"""
33
- board_svg = render_chessboard()
34
-
35
- col1, col2, col3 = st.columns([1, 2, 1])
36
-
37
- with col2:
38
- # Afficher l'échiquier
39
- st.write(f"""
40
- <div style="display: flex; justify-content: center; position: relative;">
41
- {board_svg}
42
- <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;
43
- display: grid; grid-template-columns: repeat(8, 1fr);
44
- grid-template-rows: repeat(8, 1fr);">
45
- """, unsafe_allow_html=True)
46
-
47
- # Créer les boutons transparents pour chaque case
48
- for rank in range(7, -1, -1):
49
- for file in range(8):
50
- square_name = chess.square_name(chess.square(file, rank))
51
- if st.button("", key=f"square_{square_name}",
52
- use_container_width=True,
53
- help=square_name):
54
- handle_square_click(square_name)
55
-
56
- st.write("</div></div>", unsafe_allow_html=True)
57
 
58
- def handle_square_click(square_name):
59
- """Gère le clic sur une case"""
60
- square = chess.parse_square(square_name)
61
-
62
- # Si aucune pièce n'est sélectionnée
63
- if st.session_state.selected_square is None:
64
- piece = st.session_state.board.piece_at(square)
65
- if piece and piece.color == st.session_state.board.turn:
66
- st.session_state.selected_square = square_name
67
- st.rerun()
68
- # Si une pièce est déjà sélectionnée
69
- else:
70
- from_square = chess.parse_square(st.session_state.selected_square)
71
- move = chess.Move(from_square, square)
72
-
73
- if move in st.session_state.board.legal_moves:
74
- st.session_state.board.push(move)
75
- st.session_state.moves.append(st.session_state.board.san(move))
 
 
 
 
 
76
 
77
- # Tour de l'IA
78
- game_str = get_game_string()
79
- ai_move = get_ai_move(game_str)
80
- if ai_move:
81
- try_move(ai_move)
82
-
83
- st.session_state.selected_square = None
84
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  def calculate_max_length(move_count):
87
  """Calcule le max_length optimal"""
@@ -106,11 +131,11 @@ def setup_inference():
106
  )
107
  return ChessGenerator(config)
108
 
109
- # Initialisation
110
  try:
111
  generator = setup_inference()
112
  except Exception as e:
113
- st.error("Erreur lors de l'initialisation.")
114
  st.stop()
115
 
116
  # Initialisation de l'état
@@ -118,8 +143,6 @@ if 'board' not in st.session_state:
118
  st.session_state.board = chess.Board()
119
  if 'moves' not in st.session_state:
120
  st.session_state.moves = []
121
- if 'selected_square' not in st.session_state:
122
- st.session_state.selected_square = None
123
 
124
  def get_ai_move(prompt):
125
  """Obtient le coup de l'IA"""
@@ -133,10 +156,10 @@ def get_ai_move(prompt):
133
  else:
134
  moves = prompt.split()
135
  last_moves = " ".join(moves[-4:])
136
- if len(moves) % 2 == 0:
137
  next_move_num = f"{(len(moves)//2 + 1)}."
138
  response = generator.generate(f"{last_moves} {next_move_num}")
139
- else:
140
  response = generator.generate(f"{last_moves}")
141
 
142
  moves = response[0].split() if isinstance(response, list) else response.split()
@@ -188,12 +211,11 @@ def get_game_string():
188
  # Interface utilisateur
189
  st.title("♟️ Échecs contre IA")
190
 
191
- # Layout principal
192
  col1, col2 = st.columns([2, 1])
193
 
194
  with col1:
195
  # Échiquier interactif
196
- display_interactive_board()
197
 
198
  # Input texte comme méthode alternative
199
  move = st.text_input(
@@ -212,7 +234,7 @@ with col2:
212
  # Instructions
213
  st.markdown("""
214
  **Comment jouer:**
215
- - Cliquez sur une pièce puis sur la case de destination
216
  - Ou utilisez la notation algébrique :
217
  - Pion: e4, d5
218
  - Cavalier: Nf3, Nc6
@@ -227,7 +249,23 @@ with col2:
227
  if st.button("Nouvelle partie"):
228
  st.session_state.board = chess.Board()
229
  st.session_state.moves = []
230
- st.session_state.selected_square = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  st.rerun()
232
 
233
  # Gestion des coups via input texte
 
1
  import streamlit as st
2
  import chess
 
3
  import os
4
  import git
5
  import sys
6
  import random
7
+ from streamlit.components.v1 import html
8
 
9
  # Configuration de la page
10
  st.set_page_config(page_title="Échecs contre IA", layout="wide")
11
 
12
  def render_chessboard():
13
+ """Render un échiquier interactif avec chessboard.js"""
14
+ # Obtenir la position FEN actuelle
15
+ fen = st.session_state.board.fen()
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ # Code JavaScript et HTML pour l'échiquier interactif
18
+ html_content = f"""
19
+ <!DOCTYPE html>
20
+ <html>
21
+ <head>
22
+ <meta charset="UTF-8">
23
+ <link
24
+ rel="stylesheet"
25
+ href="https://unpkg.com/@chrisoakman/[email protected]/dist/chessboard-1.0.0.min.css"
26
+ integrity="sha384-q94+BZtLrkL1/ohfjR8c6L+A6qzNH9R2hBLwyoAfu3i/WCvQjzL2RQJ3uNHDISdU"
27
+ crossorigin="anonymous">
28
+ <script
29
+ src="https://code.jquery.com/jquery-3.5.1.min.js"
30
+ integrity="sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2"
31
+ crossorigin="anonymous">
32
+ </script>
33
+ <script
34
+ src="https://unpkg.com/@chrisoakman/[email protected]/dist/chessboard-1.0.0.min.js"
35
+ integrity="sha384-8Vi8VHwn3vjQ9eUHUxex3JSN/NFqUg3QbPyX8kWyb93+8AC/pPWTzj+nHtbC5bxD"
36
+ crossorigin="anonymous">
37
+ </script>
38
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.3/chess.min.js"></script>
39
+ </head>
40
+ <body>
41
+ <div id="board" style="width: 400px; margin: auto;"></div>
42
+ <script>
43
+ // Initialisation du jeu
44
+ var board = null;
45
+ var game = new Chess('{fen}');
46
+ var $status = $('#status');
47
+
48
+ function onDragStart (source, piece, position, orientation) {{
49
+ // Autoriser uniquement les pièces blanches à être déplacées
50
+ if (game.turn() === 'b' ||
51
+ game.game_over() ||
52
+ (game.turn() === 'w' && piece.search(/^b/) !== -1)) {{
53
+ return false;
54
+ }}
55
+ }}
56
 
57
+ function onDrop (source, target) {{
58
+ // Vérifier si le coup est légal
59
+ var move = game.move({{
60
+ from: source,
61
+ to: target,
62
+ promotion: 'q'
63
+ }});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ // Coup illégal
66
+ if (move === null) return 'snapback';
67
+
68
+ // Envoyer le coup à Streamlit
69
+ window.parent.postMessage({{
70
+ type: 'move',
71
+ move: move.san
72
+ }}, '*');
73
+ }}
74
+
75
+ function onSnapEnd () {{
76
+ board.position(game.fen());
77
+ }}
78
+
79
+ // Configuration de l'échiquier
80
+ var config = {{
81
+ position: '{fen}',
82
+ draggable: true,
83
+ onDragStart: onDragStart,
84
+ onDrop: onDrop,
85
+ onSnapEnd: onSnapEnd,
86
+ pieceTheme: 'https://unpkg.com/@chrisoakman/[email protected]/dist/img/chesspieces/wikipedia/{{piece}}.png'
87
+ }};
88
 
89
+ // Initialisation de l'échiquier
90
+ board = Chessboard('board', config);
91
+
92
+ // Gestion des messages de Streamlit
93
+ window.addEventListener('message', function(e) {{
94
+ if (e.data.type === 'update') {{
95
+ board.position(e.data.fen);
96
+ game.load(e.data.fen);
97
+ }}
98
+ }});
99
+ </script>
100
+ <style>
101
+ .highlight-square {{
102
+ box-shadow: inset 0 0 3px 3px yellow;
103
+ }}
104
+ </style>
105
+ </body>
106
+ </html>
107
+ """
108
+
109
+ html(html_content, height=450)
110
 
111
  def calculate_max_length(move_count):
112
  """Calcule le max_length optimal"""
 
131
  )
132
  return ChessGenerator(config)
133
 
134
+ # Initialisation du modèle
135
  try:
136
  generator = setup_inference()
137
  except Exception as e:
138
+ st.error("Erreur lors de l'initialisation du modèle.")
139
  st.stop()
140
 
141
  # Initialisation de l'état
 
143
  st.session_state.board = chess.Board()
144
  if 'moves' not in st.session_state:
145
  st.session_state.moves = []
 
 
146
 
147
  def get_ai_move(prompt):
148
  """Obtient le coup de l'IA"""
 
156
  else:
157
  moves = prompt.split()
158
  last_moves = " ".join(moves[-4:])
159
+ if len(moves) % 2 == 0: # Si on vient de finir un coup noir
160
  next_move_num = f"{(len(moves)//2 + 1)}."
161
  response = generator.generate(f"{last_moves} {next_move_num}")
162
+ else: # Si on vient de finir un coup blanc
163
  response = generator.generate(f"{last_moves}")
164
 
165
  moves = response[0].split() if isinstance(response, list) else response.split()
 
211
  # Interface utilisateur
212
  st.title("♟️ Échecs contre IA")
213
 
 
214
  col1, col2 = st.columns([2, 1])
215
 
216
  with col1:
217
  # Échiquier interactif
218
+ render_chessboard()
219
 
220
  # Input texte comme méthode alternative
221
  move = st.text_input(
 
234
  # Instructions
235
  st.markdown("""
236
  **Comment jouer:**
237
+ - Glissez-déposez les pièces blanches
238
  - Ou utilisez la notation algébrique :
239
  - Pion: e4, d5
240
  - Cavalier: Nf3, Nc6
 
249
  if st.button("Nouvelle partie"):
250
  st.session_state.board = chess.Board()
251
  st.session_state.moves = []
252
+ st.rerun()
253
+
254
+ # Gestion des messages du JavaScript
255
+ if 'js_move' in st.session_state:
256
+ move = st.session_state.js_move
257
+ st.session_state.js_move = None
258
+ if try_move(move):
259
+ game_str = get_game_string()
260
+ with st.spinner("L'IA réfléchit..."):
261
+ ai_move = get_ai_move(game_str)
262
+ if ai_move and try_move(ai_move):
263
+ if st.session_state.board.is_checkmate():
264
+ st.success("Échec et mat!")
265
+ elif st.session_state.board.is_game_over():
266
+ st.info("Partie terminée!")
267
+ else:
268
+ st.error("Problème avec le coup de l'IA")
269
  st.rerun()
270
 
271
  # Gestion des coups via input texte