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