Docfile commited on
Commit
1a3554c
·
verified ·
1 Parent(s): c60d866

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -105
app.py CHANGED
@@ -1,127 +1,208 @@
 
1
  from flask import Flask, render_template, request, jsonify, session
2
- from stockfish import Stockfish # Assurez-vous que le chemin est correct si besoin
3
- import chess # python-chess
 
 
 
4
 
5
  app = Flask(__name__)
6
- app.secret_key = 'super_secret_key_for_session' # Important pour les sessions
7
 
8
- # Pour simplifier, une instance globale. Pour une prod, gérer par session/jeu.
9
- # Assurez-vous que le binaire stockfish est dans votre PATH ou spécifiez le chemin.
10
  try:
11
- stockfish_path = "/usr/games/stockfish" # chemin vers votre binaire
12
- stockfish = Stockfish(path=stockfish_path, parameters={"Threads": 2, "Hash": 128})
13
- except Exception as e:
14
- print(f"Erreur à l'initialisation de Stockfish: {e}")
15
- print("Veuillez vérifier que Stockfish est installé et accessible via le PATH, ou spécifiez le chemin correct.")
16
- # Vous pourriez vouloir quitter l'application ou avoir un mode dégradé.
 
 
 
 
17
  stockfish = None
18
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  @app.route('/')
21
  def index():
22
  return render_template('index.html')
23
 
24
- @app.route('/new_game', methods=['POST'])
25
- def new_game():
26
- if not stockfish:
27
- return jsonify({"error": "Stockfish non initialisé"}), 500
28
-
29
- data = request.json
30
- mode = data.get('mode', 'human') # 'ai' or 'human'
31
 
32
- initial_fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
33
- session['fen'] = initial_fen
34
- session['mode'] = mode
35
- session['turn'] = 'w' # White's turn
36
- session['history'] = []
37
 
38
- stockfish.set_fen_position(initial_fen)
39
-
40
- # python-chess board (optionnel mais recommandé)
41
- session['board_pgn'] = chess.Board().fen() # Stocker le FEN pour reconstruire
42
-
43
- return jsonify({
44
- "fen": initial_fen,
45
- "turn": session['turn'],
46
- "message": "Nouvelle partie commencée."
47
- })
48
-
49
- @app.route('/move', methods=['POST'])
50
- def handle_move():
51
- if not stockfish:
52
- return jsonify({"error": "Stockfish non initialisé"}), 500
53
-
54
- if 'fen' not in session:
55
- return jsonify({"error": "Aucune partie en cours. Commencez une nouvelle partie."}), 400
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  data = request.json
58
- move_uci = data.get('move') # e.g., "e2e4"
59
-
60
- # Reconstruire l'état du board python-chess (si utilisé)
61
- board = chess.Board(session['fen'])
62
 
63
- # Validation du tour
64
- current_player_color = 'w' if board.turn == chess.WHITE else 'b'
65
- if session['turn'] != current_player_color:
66
- return jsonify({"error": "Pas votre tour.", "fen": session['fen'], "turn": session['turn']}), 400
67
-
68
- try:
69
- move_obj = board.parse_uci(move_uci)
70
- except ValueError:
71
- return jsonify({"error": "Format de coup invalide.", "fen": session['fen'], "turn": session['turn']}), 400
72
-
73
-
74
- if not stockfish.is_move_correct(move_uci) or move_obj not in board.legal_moves:
75
- return jsonify({"error": "Coup illégal.", "fen": session['fen'], "turn": session['turn']}), 400
76
-
77
- # Appliquer le coup humain
78
- stockfish.make_moves_from_current_position([move_uci])
79
- board.push(move_obj)
80
- session['fen'] = stockfish.get_fen_position() # ou board.fen()
81
- session['history'].append(move_uci)
82
- session['turn'] = 'b' if current_player_color == 'w' else 'w'
83
-
84
- ai_move_uci = None
85
- game_status = "En cours"
86
-
87
- if board.is_checkmate():
88
- game_status = f"Mat! {'Les Blancs' if board.turn == chess.BLACK else 'Les Noirs'} gagnent."
89
- elif board.is_stalemate() or board.is_insufficient_material() or board.is_seventyfive_moves() or board.is_fivefold_repetition():
90
- game_status = "Pat!"
91
-
92
- # Mode IA
93
- if session['mode'] == 'ai' and game_status == "En cours" and ( (board.turn == chess.BLACK and current_player_color == 'w') or \
94
- (board.turn == chess.WHITE and current_player_color == 'b') ) : # Tour de l'IA
95
- # S'assurer que stockfish a la bonne position si on utilise board.fen()
96
- stockfish.set_fen_position(board.fen())
97
- ai_move_uci = stockfish.get_best_move_time(1000) # 1 seconde de réflexion
98
- if ai_move_uci:
99
- ai_move_obj = board.parse_uci(ai_move_uci)
100
- stockfish.make_moves_from_current_position([ai_move_uci]) # Stockfish est déjà à jour
101
- board.push(ai_move_obj)
102
- session['fen'] = stockfish.get_fen_position() # ou board.fen()
103
- session['history'].append(ai_move_uci)
104
- session['turn'] = 'w' if session['turn'] == 'b' else 'b'
105
 
106
- if board.is_checkmate():
107
- game_status = f"Mat! {'Les Blancs' if board.turn == chess.BLACK else 'Les Noirs'} gagnent."
108
- elif board.is_stalemate() or board.is_insufficient_material() or board.is_seventyfive_moves() or board.is_fivefold_repetition():
109
- game_status = "Pat!"
110
- else: # Si l'IA ne retourne pas de coup (ce qui peut arriver si elle est matée/patée)
111
- if board.is_checkmate():
112
- game_status = f"Mat! {'Les Blancs' if board.turn == chess.BLACK else 'Les Noirs'} gagnent."
113
- elif board.is_stalemate():
114
- game_status = "Pat!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- return jsonify({
118
- "fen": session['fen'],
119
- "turn": session['turn'],
120
- "last_move_human": move_uci,
121
- "last_move_ai": ai_move_uci,
122
- "game_status": game_status,
123
- "history": session['history']
124
- })
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
  if __name__ == '__main__':
127
  app.run(debug=True)
 
1
+ # app.py
2
  from flask import Flask, render_template, request, jsonify, session
3
+ from stockfish import Stockfish
4
+ import uuid
5
+ import chess
6
+ import chess.pgn
7
+ from datetime import datetime
8
 
9
  app = Flask(__name__)
10
+ app.secret_key = 'your-secret-key-change-this'
11
 
12
+ # Configuration Stockfish
 
13
  try:
14
+ stockfish = Stockfish(
15
+ path="/usr/local/bin/stockfish", # Ajustez selon votre installation
16
+ parameters={
17
+ "Threads": 2,
18
+ "Hash": 256,
19
+ "Skill Level": 15, # Niveau IA (0-20)
20
+ "Minimum Thinking Time": 100
21
+ }
22
+ )
23
+ except:
24
  stockfish = None
25
+ print("Stockfish non trouvé. Mode IA désactivé.")
26
+
27
+ class ChessGame:
28
+ def __init__(self, game_id, mode='human'):
29
+ self.game_id = game_id
30
+ self.mode = mode # 'human' ou 'ai'
31
+ self.board = chess.Board()
32
+ self.moves_history = []
33
+ self.current_player = 'white'
34
+ self.game_status = 'active' # 'active', 'checkmate', 'stalemate', 'draw'
35
+ self.created_at = datetime.now()
36
+
37
+ def make_move(self, move_uci):
38
+ """Effectue un coup et retourne le résultat"""
39
+ try:
40
+ move = chess.Move.from_uci(move_uci)
41
+
42
+ if move in self.board.legal_moves:
43
+ self.board.push(move)
44
+ self.moves_history.append(move_uci)
45
+
46
+ # Changer de joueur
47
+ self.current_player = 'black' if self.current_player == 'white' else 'white'
48
+
49
+ # Vérifier l'état du jeu
50
+ self._update_game_status()
51
+
52
+ return {
53
+ 'success': True,
54
+ 'move': move_uci,
55
+ 'board_fen': self.board.fen(),
56
+ 'current_player': self.current_player,
57
+ 'game_status': self.game_status,
58
+ 'legal_moves': [move.uci() for move in self.board.legal_moves],
59
+ 'is_check': self.board.is_check()
60
+ }
61
+ else:
62
+ return {'success': False, 'error': 'Coup illégal'}
63
+
64
+ except Exception as e:
65
+ return {'success': False, 'error': str(e)}
66
+
67
+ def get_ai_move(self):
68
+ """Obtient le coup de l'IA via Stockfish"""
69
+ if not stockfish or self.mode != 'ai':
70
+ return None
71
+
72
+ try:
73
+ stockfish.set_fen_position(self.board.fen())
74
+ ai_move = stockfish.get_best_move()
75
+ return ai_move
76
+ except:
77
+ return None
78
+
79
+ def _update_game_status(self):
80
+ """Met à jour l'état du jeu"""
81
+ if self.board.is_checkmate():
82
+ winner = 'black' if self.current_player == 'white' else 'white'
83
+ self.game_status = f'checkmate_{winner}'
84
+ elif self.board.is_stalemate():
85
+ self.game_status = 'stalemate'
86
+ elif self.board.is_insufficient_material():
87
+ self.game_status = 'draw_material'
88
+ elif self.board.is_seventyfive_moves():
89
+ self.game_status = 'draw_75moves'
90
+ elif self.board.is_fivefold_repetition():
91
+ self.game_status = 'draw_repetition'
92
+
93
+ def get_board_state(self):
94
+ """Retourne l'état complet du plateau"""
95
+ return {
96
+ 'fen': self.board.fen(),
97
+ 'current_player': self.current_player,
98
+ 'game_status': self.game_status,
99
+ 'legal_moves': [move.uci() for move in self.board.legal_moves],
100
+ 'is_check': self.board.is_check(),
101
+ 'moves_history': self.moves_history,
102
+ 'move_count': len(self.moves_history)
103
+ }
104
+
105
+ # Stockage des parties en mémoire (remplacez par une base de données en production)
106
+ games = {}
107
 
108
  @app.route('/')
109
  def index():
110
  return render_template('index.html')
111
 
112
+ @app.route('/game/<mode>')
113
+ def game(mode):
114
+ if mode not in ['human', 'ai']:
115
+ return "Mode de jeu invalide", 400
 
 
 
116
 
117
+ # Créer une nouvelle partie
118
+ game_id = str(uuid.uuid4())
119
+ games[game_id] = ChessGame(game_id, mode)
120
+ session['game_id'] = game_id
 
121
 
122
+ return render_template('game.html', mode=mode, game_id=game_id)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ @app.route('/api/game/state')
125
+ def get_game_state():
126
+ game_id = session.get('game_id')
127
+ if not game_id or game_id not in games:
128
+ return jsonify({'error': 'Partie non trouvée'}), 404
129
+
130
+ game = games[game_id]
131
+ return jsonify(game.get_board_state())
132
+
133
+ @app.route('/api/game/move', methods=['POST'])
134
+ def make_move():
135
+ game_id = session.get('game_id')
136
+ if not game_id or game_id not in games:
137
+ return jsonify({'error': 'Partie non trouvée'}), 404
138
+
139
  data = request.json
140
+ move = data.get('move')
 
 
 
141
 
142
+ if not move:
143
+ return jsonify({'error': 'Coup manquant'}), 400
144
+
145
+ game = games[game_id]
146
+ result = game.make_move(move)
147
+
148
+ return jsonify(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
+ @app.route('/api/game/ai-move', methods=['POST'])
151
+ def get_ai_move():
152
+ game_id = session.get('game_id')
153
+ if not game_id or game_id not in games:
154
+ return jsonify({'error': 'Partie non trouvée'}), 404
155
+
156
+ game = games[game_id]
157
+
158
+ if game.mode != 'ai':
159
+ return jsonify({'error': 'Mode IA non activé'}), 400
160
+
161
+ if game.current_player != 'black': # IA joue les noirs
162
+ return jsonify({'error': 'Ce n\'est pas le tour de l\'IA'}), 400
163
+
164
+ ai_move = game.get_ai_move()
165
+ if not ai_move:
166
+ return jsonify({'error': 'IA ne peut pas jouer'}), 500
167
+
168
+ # Effectuer le coup de l'IA
169
+ result = game.make_move(ai_move)
170
+ result['ai_move'] = True
171
+
172
+ return jsonify(result)
173
 
174
+ @app.route('/api/game/reset', methods=['POST'])
175
+ def reset_game():
176
+ game_id = session.get('game_id')
177
+ if not game_id or game_id not in games:
178
+ return jsonify({'error': 'Partie non trouvée'}), 404
179
+
180
+ game = games[game_id]
181
+ # Réinitialiser la partie
182
+ games[game_id] = ChessGame(game_id, game.mode)
183
+
184
+ return jsonify({'success': True, 'message': 'Partie réinitialisée'})
185
 
186
+ @app.route('/api/game/legal-moves')
187
+ def get_legal_moves():
188
+ game_id = session.get('game_id')
189
+ if not game_id or game_id not in games:
190
+ return jsonify({'error': 'Partie non trouvée'}), 404
191
+
192
+ data = request.args
193
+ square = data.get('square')
194
+
195
+ if not square:
196
+ return jsonify({'error': 'Case manquante'}), 400
197
+
198
+ game = games[game_id]
199
+ legal_moves = []
200
+
201
+ for move in game.board.legal_moves:
202
+ if move.from_square == chess.parse_square(square):
203
+ legal_moves.append(chess.square_name(move.to_square))
204
+
205
+ return jsonify({'legal_moves': legal_moves})
206
 
207
  if __name__ == '__main__':
208
  app.run(debug=True)