darkmaria / app.py
Docfile's picture
Update app.py
0356fb2 verified
raw
history blame
7.5 kB
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)