Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -5,14 +5,43 @@ import os
|
|
5 |
import git
|
6 |
import sys
|
7 |
import random
|
8 |
-
import base64
|
9 |
-
from streamlit.components.v1 import html
|
10 |
|
11 |
# Configuration de la page
|
12 |
st.set_page_config(page_title="Échecs contre IA", layout="wide")
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
def render_chessboard():
|
15 |
-
"""Render un échiquier interactif en SVG"""
|
16 |
board_svg = chess.svg.board(
|
17 |
board=st.session_state.board,
|
18 |
size=400,
|
@@ -20,35 +49,33 @@ def render_chessboard():
|
|
20 |
squares=get_legal_moves_squares() if st.session_state.show_hints else None,
|
21 |
)
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
.
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
</div>
|
45 |
-
"""
|
46 |
-
html(html_content, height=450)
|
47 |
|
48 |
def get_legal_moves_squares():
|
49 |
"""Obtenir les cases des coups légaux pour la pièce sélectionnée"""
|
50 |
squares = []
|
51 |
-
if st.session_state.selected_square:
|
52 |
legal_moves = st.session_state.board.legal_moves
|
53 |
from_square = chess.parse_square(st.session_state.selected_square)
|
54 |
for move in legal_moves:
|
@@ -56,18 +83,10 @@ def get_legal_moves_squares():
|
|
56 |
squares.append(chess.square_name(move.to_square))
|
57 |
return squares
|
58 |
|
59 |
-
# Initialisation des variables de session
|
60 |
-
if 'board' not in st.session_state:
|
61 |
-
st.session_state.board = chess.Board()
|
62 |
-
if 'moves' not in st.session_state:
|
63 |
-
st.session_state.moves = []
|
64 |
-
if 'selected_square' not in st.session_state:
|
65 |
-
st.session_state.selected_square = None
|
66 |
-
if 'show_hints' not in st.session_state:
|
67 |
-
st.session_state.show_hints = True
|
68 |
-
|
69 |
def calculate_max_length(move_count):
|
70 |
-
"""
|
|
|
|
|
71 |
base_length = 10
|
72 |
increment = 1
|
73 |
max_length = 100
|
@@ -89,12 +108,23 @@ def setup_inference():
|
|
89 |
)
|
90 |
return ChessGenerator(config)
|
91 |
|
|
|
92 |
try:
|
93 |
generator = setup_inference()
|
94 |
except Exception as e:
|
95 |
st.error("Erreur lors de l'initialisation.")
|
96 |
st.stop()
|
97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
def get_ai_move(prompt):
|
99 |
"""Obtient le coup de l'IA"""
|
100 |
moves_count = len(st.session_state.moves)
|
@@ -102,15 +132,15 @@ def get_ai_move(prompt):
|
|
102 |
generator.config.max_length = dynamic_max_length
|
103 |
|
104 |
try:
|
105 |
-
if not prompt:
|
106 |
response = generator.generate("1.")
|
107 |
else:
|
108 |
moves = prompt.split()
|
109 |
last_moves = " ".join(moves[-4:])
|
110 |
-
if len(moves) % 2 == 0:
|
111 |
next_move_num = f"{(len(moves)//2 + 1)}."
|
112 |
response = generator.generate(f"{last_moves} {next_move_num}")
|
113 |
-
else:
|
114 |
response = generator.generate(f"{last_moves}")
|
115 |
|
116 |
moves = response[0].split() if isinstance(response, list) else response.split()
|
@@ -125,6 +155,7 @@ def get_ai_move(prompt):
|
|
125 |
except ValueError:
|
126 |
pass
|
127 |
|
|
|
128 |
legal_moves = list(st.session_state.board.legal_moves)
|
129 |
if legal_moves:
|
130 |
random_move = random.choice(legal_moves)
|
@@ -161,28 +192,22 @@ def get_game_string():
|
|
161 |
# Interface utilisateur
|
162 |
st.title("♟️ Échecs contre IA")
|
163 |
|
|
|
164 |
col1, col2 = st.columns([2, 1])
|
165 |
|
166 |
with col1:
|
167 |
-
#
|
168 |
render_chessboard()
|
169 |
|
170 |
# Input texte comme méthode alternative
|
171 |
move = st.text_input(
|
172 |
-
"
|
173 |
key=f"move_input_{len(st.session_state.moves)}",
|
174 |
placeholder="ex: e4, Nf3, O-O"
|
175 |
)
|
176 |
|
177 |
-
# Option pour afficher les coups légaux
|
178 |
-
st.checkbox("Afficher les coups possibles", value=True, key="show_hints")
|
179 |
-
|
180 |
with col2:
|
181 |
-
# Informations
|
182 |
-
current_max_length = calculate_max_length(len(st.session_state.moves))
|
183 |
-
st.info(f"Longueur de génération actuelle: {current_max_length} tokens")
|
184 |
-
|
185 |
-
# Historique
|
186 |
st.subheader("Partie en cours")
|
187 |
game_str = get_game_string()
|
188 |
if game_str:
|
@@ -202,6 +227,9 @@ with col2:
|
|
202 |
- Roque: O-O ou O-O-O
|
203 |
""")
|
204 |
|
|
|
|
|
|
|
205 |
# Nouvelle partie
|
206 |
if st.button("Nouvelle partie"):
|
207 |
st.session_state.board = chess.Board()
|
@@ -209,42 +237,6 @@ with col2:
|
|
209 |
st.session_state.selected_square = None
|
210 |
st.rerun()
|
211 |
|
212 |
-
# Gestion des clics sur l'échiquier (à implémenter avec st.experimental_get_query_params)
|
213 |
-
params = st.experimental_get_query_params()
|
214 |
-
if 'square' in params:
|
215 |
-
clicked_square = params['square'][0]
|
216 |
-
if st.session_state.selected_square is None:
|
217 |
-
# Premier clic - sélection de la pièce
|
218 |
-
piece = st.session_state.board.piece_at(chess.parse_square(clicked_square))
|
219 |
-
if piece and piece.color == st.session_state.board.turn:
|
220 |
-
st.session_state.selected_square = clicked_square
|
221 |
-
else:
|
222 |
-
# Deuxième clic - déplacement
|
223 |
-
from_square = chess.parse_square(st.session_state.selected_square)
|
224 |
-
to_square = chess.parse_square(clicked_square)
|
225 |
-
move = chess.Move(from_square, to_square)
|
226 |
-
|
227 |
-
if move in st.session_state.board.legal_moves:
|
228 |
-
# Appliquer le coup
|
229 |
-
st.session_state.board.push(move)
|
230 |
-
st.session_state.moves.append(st.session_state.board.san(move))
|
231 |
-
st.session_state.selected_square = None
|
232 |
-
|
233 |
-
# Tour de l'IA
|
234 |
-
with st.spinner("L'IA réfléchit..."):
|
235 |
-
ai_move = get_ai_move(get_game_string())
|
236 |
-
if ai_move and try_move(ai_move):
|
237 |
-
if st.session_state.board.is_checkmate():
|
238 |
-
st.success("Échec et mat!")
|
239 |
-
elif st.session_state.board.is_game_over():
|
240 |
-
st.info("Partie terminée!")
|
241 |
-
else:
|
242 |
-
st.error("Problème avec le coup de l'IA")
|
243 |
-
st.rerun()
|
244 |
-
else:
|
245 |
-
st.session_state.selected_square = None
|
246 |
-
st.rerun()
|
247 |
-
|
248 |
# Gestion des coups via input texte
|
249 |
if move:
|
250 |
if try_move(move):
|
|
|
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 handle_click(square_name):
|
13 |
+
"""Gère les clics sur l'échiquier"""
|
14 |
+
if 'selected_square' not in st.session_state:
|
15 |
+
st.session_state.selected_square = None
|
16 |
+
|
17 |
+
if st.session_state.selected_square is None:
|
18 |
+
# Premier clic - sélection de la pièce
|
19 |
+
square = chess.parse_square(square_name)
|
20 |
+
piece = st.session_state.board.piece_at(square)
|
21 |
+
if piece and piece.color == st.session_state.board.turn:
|
22 |
+
st.session_state.selected_square = square_name
|
23 |
+
else:
|
24 |
+
# Deuxième clic - déplacement
|
25 |
+
from_square = chess.parse_square(st.session_state.selected_square)
|
26 |
+
to_square = chess.parse_square(square_name)
|
27 |
+
move = chess.Move(from_square, to_square)
|
28 |
+
|
29 |
+
if move in st.session_state.board.legal_moves:
|
30 |
+
san_move = st.session_state.board.san(move)
|
31 |
+
st.session_state.board.push(move)
|
32 |
+
st.session_state.moves.append(san_move)
|
33 |
+
st.session_state.selected_square = None
|
34 |
+
|
35 |
+
# Tour de l'IA
|
36 |
+
game_str = get_game_string()
|
37 |
+
ai_move = get_ai_move(game_str)
|
38 |
+
if ai_move:
|
39 |
+
try_move(ai_move)
|
40 |
+
|
41 |
+
st.session_state.selected_square = None
|
42 |
+
|
43 |
def render_chessboard():
|
44 |
+
"""Render un échiquier interactif en SVG avec des boutons pour chaque case"""
|
45 |
board_svg = chess.svg.board(
|
46 |
board=st.session_state.board,
|
47 |
size=400,
|
|
|
49 |
squares=get_legal_moves_squares() if st.session_state.show_hints else None,
|
50 |
)
|
51 |
|
52 |
+
st.write(f"""
|
53 |
+
<div style="display: flex; justify-content: center;">
|
54 |
+
<div style="position: relative; width: 400px;">
|
55 |
+
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;">
|
56 |
+
{board_svg}
|
57 |
+
</div>
|
58 |
+
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;
|
59 |
+
display: grid; grid-template-columns: repeat(8, 1fr);
|
60 |
+
height: 400px;">
|
61 |
+
""", unsafe_allow_html=True)
|
62 |
+
|
63 |
+
# Créer une grille de boutons transparents
|
64 |
+
for rank in range(7, -1, -1):
|
65 |
+
for file in range(8):
|
66 |
+
square = chess.square(file, rank)
|
67 |
+
square_name = chess.square_name(square)
|
68 |
+
if st.button("", key=f"square_{square_name}",
|
69 |
+
help=square_name,
|
70 |
+
use_container_width=True):
|
71 |
+
handle_click(square_name)
|
72 |
+
|
73 |
+
st.write("</div></div></div>", unsafe_allow_html=True)
|
|
|
|
|
74 |
|
75 |
def get_legal_moves_squares():
|
76 |
"""Obtenir les cases des coups légaux pour la pièce sélectionnée"""
|
77 |
squares = []
|
78 |
+
if hasattr(st.session_state, 'selected_square') and st.session_state.selected_square:
|
79 |
legal_moves = st.session_state.board.legal_moves
|
80 |
from_square = chess.parse_square(st.session_state.selected_square)
|
81 |
for move in legal_moves:
|
|
|
83 |
squares.append(chess.square_name(move.to_square))
|
84 |
return squares
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
def calculate_max_length(move_count):
|
87 |
+
"""
|
88 |
+
Calcule le max_length optimal basé sur le nombre de coups joués
|
89 |
+
"""
|
90 |
base_length = 10
|
91 |
increment = 1
|
92 |
max_length = 100
|
|
|
108 |
)
|
109 |
return ChessGenerator(config)
|
110 |
|
111 |
+
# Initialisation
|
112 |
try:
|
113 |
generator = setup_inference()
|
114 |
except Exception as e:
|
115 |
st.error("Erreur lors de l'initialisation.")
|
116 |
st.stop()
|
117 |
|
118 |
+
# Initialisation de l'état
|
119 |
+
if 'board' not in st.session_state:
|
120 |
+
st.session_state.board = chess.Board()
|
121 |
+
if 'moves' not in st.session_state:
|
122 |
+
st.session_state.moves = []
|
123 |
+
if 'selected_square' not in st.session_state:
|
124 |
+
st.session_state.selected_square = None
|
125 |
+
if 'show_hints' not in st.session_state:
|
126 |
+
st.session_state.show_hints = True
|
127 |
+
|
128 |
def get_ai_move(prompt):
|
129 |
"""Obtient le coup de l'IA"""
|
130 |
moves_count = len(st.session_state.moves)
|
|
|
132 |
generator.config.max_length = dynamic_max_length
|
133 |
|
134 |
try:
|
135 |
+
if not prompt: # Premier coup
|
136 |
response = generator.generate("1.")
|
137 |
else:
|
138 |
moves = prompt.split()
|
139 |
last_moves = " ".join(moves[-4:])
|
140 |
+
if len(moves) % 2 == 0: # Si on vient de finir un coup noir
|
141 |
next_move_num = f"{(len(moves)//2 + 1)}."
|
142 |
response = generator.generate(f"{last_moves} {next_move_num}")
|
143 |
+
else: # Si on vient de finir un coup blanc
|
144 |
response = generator.generate(f"{last_moves}")
|
145 |
|
146 |
moves = response[0].split() if isinstance(response, list) else response.split()
|
|
|
155 |
except ValueError:
|
156 |
pass
|
157 |
|
158 |
+
# En cas d'échec, jouer un coup légal aléatoire
|
159 |
legal_moves = list(st.session_state.board.legal_moves)
|
160 |
if legal_moves:
|
161 |
random_move = random.choice(legal_moves)
|
|
|
192 |
# Interface utilisateur
|
193 |
st.title("♟️ Échecs contre IA")
|
194 |
|
195 |
+
# Mise en page principale
|
196 |
col1, col2 = st.columns([2, 1])
|
197 |
|
198 |
with col1:
|
199 |
+
# Échiquier interactif
|
200 |
render_chessboard()
|
201 |
|
202 |
# Input texte comme méthode alternative
|
203 |
move = st.text_input(
|
204 |
+
"Ou saisissez votre coup ici",
|
205 |
key=f"move_input_{len(st.session_state.moves)}",
|
206 |
placeholder="ex: e4, Nf3, O-O"
|
207 |
)
|
208 |
|
|
|
|
|
|
|
209 |
with col2:
|
210 |
+
# Informations de la partie
|
|
|
|
|
|
|
|
|
211 |
st.subheader("Partie en cours")
|
212 |
game_str = get_game_string()
|
213 |
if game_str:
|
|
|
227 |
- Roque: O-O ou O-O-O
|
228 |
""")
|
229 |
|
230 |
+
# Option pour afficher les coups possibles
|
231 |
+
st.checkbox("Afficher les coups possibles", key="show_hints")
|
232 |
+
|
233 |
# Nouvelle partie
|
234 |
if st.button("Nouvelle partie"):
|
235 |
st.session_state.board = chess.Board()
|
|
|
237 |
st.session_state.selected_square = None
|
238 |
st.rerun()
|
239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
# Gestion des coups via input texte
|
241 |
if move:
|
242 |
if try_move(move):
|