Docfile commited on
Commit
56eb498
·
verified ·
1 Parent(s): 39851f5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -165
app.py CHANGED
@@ -1,181 +1,133 @@
1
- from flask import Flask, render_template, request, jsonify, session
2
- from flask_session import Session # Pour gérer les sessions côté serveur si besoin de plus de complexité
3
- import chess
4
- import chess.svg
5
- from stockfish import Stockfish
6
  import os
7
 
8
  app = Flask(__name__)
9
 
10
- # Configuration de la clé secrète pour les sessions Flask
11
- app.config["SECRET_KEY"] = os.urandom(24) # Ou une chaîne fixe pour le développement
 
 
12
 
13
- # Configuration pour Flask-Session (stocke les sessions côté serveur, ex: filesystem)
14
- # Ceci est optionnel pour cet exemple simple où FEN est petit, mais bon pour des états plus complexes.
15
- app.config["SESSION_PERMANENT"] = False
16
- app.config["SESSION_TYPE"] = "filesystem" # Peut être redis, memcached, etc.
17
- Session(app)
18
-
19
- # --- IMPORTANT : MODIFIEZ CE CHEMIN ---
20
- # Mettez le chemin absolu vers votre exécutable Stockfish
21
- # Exemples:
22
- # Windows: "C:\\Chemin\\Vers\\Stockfish\\stockfish_15.1_win_x64_avx2.exe"
23
- # macOS/Linux: "/usr/local/bin/stockfish" ou "./stockfish-ubuntu-x86-64-avx2"
24
- STOCKFISH_PATH = "/usr/local/bin/stockfish" # <--- MODIFIEZ CECI !
25
 
 
26
  try:
27
- stockfish = Stockfish(path=STOCKFISH_PATH,
28
- depth=15, # Profondeur de recherche par défaut
29
- parameters={
30
- "Skill Level": 5, # Niveau de compétence (0-20)
31
- "Threads": 2, # Nombre de threads CPU à utiliser
32
- "Hash": 128 # Mémoire pour la table de transposition (en Mo)
33
- })
34
- print(f"Stockfish initialisé avec succès. Version: {stockfish.get_stockfish_major_version()}")
35
  except Exception as e:
36
- print(f"ERREUR: Impossible d'initialiser Stockfish. Vérifiez le chemin: {STOCKFISH_PATH}")
37
- print(f"Détail de l'erreur: {e}")
38
- stockfish = None # Pour que l'app puisse démarrer même si SF échoue (mode IA sera désactivé)
39
 
40
  @app.route('/')
41
  def index():
42
- """Affiche la page principale du jeu."""
43
- # Initialiser un nouveau plateau si aucun n'existe dans la session
44
- if 'board_fen' not in session:
45
- board = chess.Board()
46
- session['board_fen'] = board.fen()
47
- session['game_mode'] = 'human' # ou 'ai'
48
- session['player_color'] = chess.WHITE # Si l'humain joue les blancs contre l'IA
49
- return render_template('index.html', initial_fen=session['board_fen'])
50
-
51
- @app.route('/new_game', methods=['POST'])
52
- def new_game():
53
- """Commence une nouvelle partie."""
54
- data = request.get_json()
55
- mode = data.get('mode', 'human') # 'human' ou 'ai'
56
- player_plays_white = data.get('player_color_white', True) # True si le joueur joue blanc
57
-
58
- board = chess.Board()
59
- session['board_fen'] = board.fen()
60
- session['game_mode'] = mode
61
- session['player_color'] = chess.WHITE if player_plays_white else chess.BLACK
62
-
63
- ai_move_uci = None
64
- ai_move_san = None
65
 
66
- if mode == 'ai' and not player_plays_white: # L'IA joue les blancs (premier coup)
67
- if stockfish:
68
- stockfish.set_fen_position(board.fen())
69
- best_move_uci = stockfish.get_best_move()
70
- if best_move_uci:
71
- move = chess.Move.from_uci(best_move_uci)
72
- ai_move_san = board.san(move)
73
- board.push(move)
74
- session['board_fen'] = board.fen()
75
- ai_move_uci = best_move_uci
76
- else:
77
- return jsonify({'error': 'Stockfish non disponible'}), 500
78
-
79
- return jsonify({
80
- 'fen': board.fen(),
81
- 'board_svg': chess.svg.board(board=board, size=350),
82
- 'turn': 'Blanc' if board.turn == chess.WHITE else 'Noir',
83
- 'game_over': board.is_game_over(),
84
- 'status': get_game_status(board),
85
- 'ai_move_uci': ai_move_uci,
86
- 'ai_move_san': ai_move_san
87
- })
88
-
89
- @app.route('/move', methods=['POST'])
90
  def make_move():
91
- """Gère un coup du joueur et potentiellement la réponse de l'IA."""
92
- if 'board_fen' not in session:
93
- return jsonify({'error': 'Partie non initialisée. Commencez une nouvelle partie.'}), 400
94
-
95
- board = chess.Board(session['board_fen'])
96
- game_mode = session.get('game_mode', 'human')
97
- player_color = session.get('player_color', chess.WHITE)
98
-
99
- data = request.get_json()
100
- move_uci = data.get('move') # ex: "e2e4"
101
-
102
- if not move_uci:
103
- return jsonify({'error': 'Aucun coup fourni'}), 400
104
-
105
- player_move_san = None
106
  try:
107
- move = chess.Move.from_uci(move_uci)
108
- if move in board.legal_moves:
109
- player_move_san = board.san(move)
110
- board.push(move)
111
- session['board_fen'] = board.fen()
112
- else:
113
- return jsonify({'error': 'Coup illégal', 'fen': board.fen(), 'board_svg': chess.svg.board(board=board, size=350)}), 400
114
- except ValueError:
115
- return jsonify({'error': 'Format de coup invalide', 'fen': board.fen(), 'board_svg': chess.svg.board(board=board, size=350)}), 400
116
-
117
- ai_move_uci = None
118
- ai_move_san = None
119
- game_over = board.is_game_over()
120
- status = get_game_status(board)
121
-
122
- if not game_over and game_mode == 'ai' and board.turn != player_color:
123
- if stockfish:
124
- stockfish.set_fen_position(board.fen())
125
- best_move_ai_uci = stockfish.get_best_move_time(1000) # L'IA réfléchit max 1 seconde
126
- if best_move_ai_uci:
127
- ai_chess_move = chess.Move.from_uci(best_move_ai_uci)
128
- ai_move_san = board.san(ai_chess_move)
129
- board.push(ai_chess_move)
130
- session['board_fen'] = board.fen()
131
- ai_move_uci = best_move_ai_uci
132
- game_over = board.is_game_over() # Vérifier à nouveau après le coup de l'IA
133
- status = get_game_status(board)
134
- else:
135
- status = "Stockfish non disponible. L'IA ne peut pas jouer."
136
-
137
-
138
- return jsonify({
139
- 'fen': board.fen(),
140
- 'board_svg': chess.svg.board(board=board, size=350, lastmove=move if not ai_move_uci else ai_chess_move),
141
- 'turn': 'Blanc' if board.turn == chess.WHITE else 'Noir',
142
- 'game_over': game_over,
143
- 'status': status,
144
- 'player_move_san': player_move_san,
145
- 'ai_move_uci': ai_move_uci,
146
- 'ai_move_san': ai_move_san,
147
- 'last_move_uci': move_uci if not ai_move_uci else ai_move_uci
148
- })
149
-
150
- @app.route('/get_board_state')
151
- def get_board_state():
152
- if 'board_fen' not in session:
153
- return jsonify({'error': 'Partie non initialisée'}), 404
154
- board = chess.Board(session['board_fen'])
155
- return jsonify({
156
- 'fen': board.fen(),
157
- 'board_svg': chess.svg.board(board=board, size=350),
158
- 'turn': 'Blanc' if board.turn == chess.WHITE else 'Noir',
159
- 'game_over': board.is_game_over(),
160
- 'status': get_game_status(board)
161
- })
162
-
163
- def get_game_status(board):
164
- if board.is_checkmate():
165
- return f"Échec et mat ! {'Les Noirs' if board.turn == chess.WHITE else 'Les Blancs'} gagnent."
166
- if board.is_stalemate():
167
- return "Pat ! Partie nulle."
168
- if board.is_insufficient_material():
169
- return "Matériel insuffisant. Partie nulle."
170
- if board.is_seventyfive_moves():
171
- return "Règle des 75 coups. Partie nulle."
172
- if board.is_fivefold_repetition():
173
- return "Répétition (5 fois). Partie nulle."
174
- if board.is_check():
175
- return "Échec !"
176
- return "Partie en cours."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
  if __name__ == '__main__':
179
- if not os.path.exists("flask_session"): # Crée le dossier pour les sessions si besoin
180
- os.makedirs("flask_session")
181
- app.run(debug=True)
 
1
+ from flask import Flask, render_template, request, jsonify
2
+ from stockfish import Stockfish, StockfishException
 
 
 
3
  import os
4
 
5
  app = Flask(__name__)
6
 
7
+ # --- Configuration Stockfish ---
8
+ STOCKFISH_PATH = "/usr/games/stockfish" # Modifiez selon votre installation
9
+ # STOCKFISH_PATH = "/opt/homebrew/bin/stockfish" # macOS
10
+ # STOCKFISH_PATH = "stockfish" # Si dans le PATH
11
 
12
+ STOCKFISH_DEPTH = 12
13
+ STOCKFISH_PARAMS = {
14
+ "Threads": 2,
15
+ "Hash": 128,
16
+ "UCI_LimitStrength": False,
17
+ "Skill Level": 15 # Niveau modéré (0-20)
18
+ }
 
 
 
 
 
19
 
20
+ # Initialiser Stockfish
21
  try:
22
+ sf = Stockfish(path=STOCKFISH_PATH, depth=STOCKFISH_DEPTH, parameters=STOCKFISH_PARAMS)
23
+ print(f"Stockfish initialisé: {sf._path}")
 
 
 
 
 
 
24
  except Exception as e:
25
+ print(f"Erreur Stockfish: {e}")
26
+ sf = None
 
27
 
28
  @app.route('/')
29
  def index():
30
+ return render_template('index.html')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ @app.route('/api/move', methods=['POST'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  def make_move():
34
+ if not sf:
35
+ return jsonify({'error': 'Stockfish non disponible'}), 500
36
+
 
 
 
 
 
 
 
 
 
 
 
 
37
  try:
38
+ data = request.get_json()
39
+ fen = data.get('fen')
40
+ user_move = data.get('move')
41
+
42
+ # Définir la position
43
+ sf.set_fen_position(fen)
44
+
45
+ # Vérifier et jouer le coup utilisateur
46
+ if not sf.is_move_correct(user_move):
47
+ return jsonify({'error': f'Coup invalide: {user_move}'}), 400
48
+
49
+ sf.make_moves_from_current_position([user_move])
50
+
51
+ # Vérifier si la partie est terminée après le coup utilisateur
52
+ eval_after_user = sf.get_evaluation()
53
+ user_fen = sf.get_fen_position()
54
+
55
+ if eval_after_user.get("type") == "mate" and eval_after_user.get("value") == 0:
56
+ return jsonify({
57
+ 'fen': user_fen,
58
+ 'stockfish_move': None,
59
+ 'evaluation': eval_after_user,
60
+ 'game_over': True,
61
+ 'result': 'Mat ou Pat'
62
+ })
63
+
64
+ # Obtenir le coup de Stockfish
65
+ stockfish_move = sf.get_best_move()
66
+
67
+ if not stockfish_move:
68
+ return jsonify({
69
+ 'fen': user_fen,
70
+ 'stockfish_move': None,
71
+ 'evaluation': eval_after_user,
72
+ 'game_over': True,
73
+ 'result': 'Partie terminée'
74
+ })
75
+
76
+ # Jouer le coup de Stockfish
77
+ sf.make_moves_from_current_position([stockfish_move])
78
+ final_fen = sf.get_fen_position()
79
+ final_eval = sf.get_evaluation()
80
+
81
+ # Vérifier si la partie est terminée après le coup de Stockfish
82
+ game_over = False
83
+ result = None
84
+ if final_eval.get("type") == "mate":
85
+ game_over = True
86
+ if final_eval.get("value") == 0:
87
+ result = "Mat ou Pat"
88
+ elif final_eval.get("value") > 0:
89
+ result = "Stockfish gagne"
90
+ else:
91
+ result = "Vous gagnez"
92
+
93
+ return jsonify({
94
+ 'fen': final_fen,
95
+ 'stockfish_move': stockfish_move,
96
+ 'evaluation': final_eval,
97
+ 'game_over': game_over,
98
+ 'result': result
99
+ })
100
+
101
+ except StockfishException as e:
102
+ return jsonify({'error': f'Erreur Stockfish: {str(e)}'}), 500
103
+ except Exception as e:
104
+ return jsonify({'error': f'Erreur: {str(e)}'}), 500
105
+
106
+ @app.route('/api/analyze', methods=['POST'])
107
+ def analyze_position():
108
+ if not sf:
109
+ return jsonify({'error': 'Stockfish non disponible'}), 500
110
+
111
+ try:
112
+ data = request.get_json()
113
+ fen = data.get('fen')
114
+
115
+ sf.set_fen_position(fen)
116
+ evaluation = sf.get_evaluation()
117
+ best_move = sf.get_best_move()
118
+
119
+ return jsonify({
120
+ 'evaluation': evaluation,
121
+ 'best_move': best_move
122
+ })
123
+
124
+ except Exception as e:
125
+ return jsonify({'error': f'Erreur analyse: {str(e)}'}), 500
126
+
127
+ @app.route('/api/new_game', methods=['POST'])
128
+ def new_game():
129
+ starting_fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
130
+ return jsonify({'fen': starting_fen})
131
 
132
  if __name__ == '__main__':
133
+ app.run(debug=True, port=5000)