File size: 9,522 Bytes
7bc796e 8dc0e70 7bc796e 8dc0e70 44bedb5 8a91eec 8dc0e70 44bedb5 8dc0e70 44bedb5 8a91eec 44bedb5 8dc0e70 7bc796e 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 8dc0e70 34d1909 44bedb5 8a91eec 44bedb5 34d1909 44bedb5 7bc796e 9f671a2 7bc796e 8dc0e70 44bedb5 8a91eec 44bedb5 34d1909 44bedb5 8a91eec 34d1909 44bedb5 34d1909 44bedb5 8a91eec 44bedb5 8a91eec 44bedb5 34d1909 44bedb5 34d1909 44bedb5 8a91eec 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 44bedb5 34d1909 8a91eec 8dc0e70 34d1909 44bedb5 8dc0e70 7bc796e 8dc0e70 |
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 182 183 184 185 186 187 188 189 190 191 192 193 194 |
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jeu d'Échecs</title>
<!-- Tailwind CSS via CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Pour une meilleure interaction avec le SVG */
.chess-board svg {
cursor: default; /* Ou 'pointer' sur les pièces si on gère les clics SVG */
}
.square { /* Styles pour les cases si on n'utilise pas SVG pour le rendu cliquable */
width: 40px; height: 40px;
display: flex; align-items: center; justify-content: center;
border: 1px solid #ccc;
}
.selected-square {
background-color: rgba(255, 255, 0, 0.5) !important;
}
</style>
</head>
<body class="bg-gray-100 flex flex-col items-center justify-center min-h-screen p-4">
<div class="bg-white p-6 rounded-lg shadow-xl w-full max-w-3xl">
<h1 class="text-3xl font-bold text-center text-gray-700 mb-6">Jeu d'Échecs</h1>
<div class="controls mb-4 flex flex-wrap gap-2 justify-center">
<button id="newGameHuman" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Nouvelle Partie (Humain vs Humain)
</button>
<button id="newGameAIWhite" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
Nouvelle Partie (Jouer Blancs vs IA)
</button>
<button id="newGameAIBlack" class="bg-gray-700 hover:bg-gray-900 text-white font-bold py-2 px-4 rounded">
Nouvelle Partie (Jouer Noirs vs IA)
</button>
</div>
<div class="game-area flex flex-col md:flex-row gap-4 items-start">
<!-- Échiquier (rendu par chess.svg) -->
<div id="boardDisplay" class="chess-board mx-auto md:mx-0 border-2 border-gray-500" style="width: 350px; height: 350px;">
<!-- Le SVG de l'échiquier sera injecté ici -->
{{ initial_board_svg|safe if initial_board_svg else "Chargement de l'échiquier..." }}
</div>
<!-- Informations et contrôles de la partie -->
<div class="info-panel flex-grow p-4 bg-gray-50 rounded-md shadow">
<h2 class="text-xl font-semibold mb-2">Informations</h2>
<p id="turnInfo" class="mb-1">Tour: Chargement...</p>
<p id="statusInfo" class="mb-3 font-medium">Statut: Chargement...</p>
<h3 class="text-lg font-semibold mb-1">Jouer un coup (ex: e2e4):</h3>
<div class="move-input flex gap-2 mb-3">
<input type="text" id="moveInput" placeholder="e.g., e2e4"
class="flex-grow p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500">
<button id="submitMove" class="bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-2 px-3 rounded">
Jouer
</button>
</div>
<p class="text-xs text-gray-500 mb-3">
Alternative: cliquez sur la case de départ puis la case d'arrivée sur un échiquier interactif (non implémenté ici, utilisez l'input).
</p>
<h3 class="text-lg font-semibold mb-1">Derniers coups:</h3>
<p id="playerMoveInfo" class="text-sm"></p>
<p id="aiMoveInfo" class="text-sm"></p>
</div>
</div>
</div>
<script>
const boardDisplay = document.getElementById('boardDisplay');
const turnInfo = document.getElementById('turnInfo');
const statusInfo = document.getElementById('statusInfo');
const moveInput = document.getElementById('moveInput');
const playerMoveInfo = document.getElementById('playerMoveInfo');
const aiMoveInfo = document.getElementById('aiMoveInfo');
let currentFen = "{{ initial_fen }}"; // FEN initial passé par Flask
let selectedSquare = null; // Pour une interaction de clic sur le plateau (non implémenté visuellement ici)
async function updateBoard(data) {
if (data.error) {
statusInfo.textContent = `Erreur: ${data.error}`;
if (data.board_svg) boardDisplay.innerHTML = data.board_svg; // Mettre à jour même en cas d'erreur de coup
return;
}
currentFen = data.fen;
boardDisplay.innerHTML = data.board_svg; // chess.svg fournit le plateau
turnInfo.textContent = `Tour: ${data.turn}`;
statusInfo.textContent = `Statut: ${data.status}`;
moveInput.value = '';
playerMoveInfo.textContent = data.player_move_san ? `Votre coup: ${data.player_move_san}` : "";
aiMoveInfo.textContent = data.ai_move_san ? `Coup IA: ${data.ai_move_san}` : "";
if (data.game_over) {
moveInput.disabled = true;
document.getElementById('submitMove').disabled = true;
// On pourrait ajouter une alerte ou un modal
setTimeout(() => alert(`Partie terminée ! ${data.status}`), 100);
} else {
moveInput.disabled = false;
document.getElementById('submitMove').disabled = false;
}
}
async function submitMove() {
const move = moveInput.value.trim().toLowerCase();
if (!move.match(/^[a-h][1-8][a-h][1-8]([qrbn])?$/)) { // Validation basique du format UCI
statusInfo.textContent = "Format de coup invalide (ex: e2e4, e7e8q).";
return;
}
playerMoveInfo.textContent = ""; // Clear previous move info
aiMoveInfo.textContent = "";
try {
const response = await fetch('/move', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ move: move })
});
const data = await response.json();
updateBoard(data);
} catch (error) {
console.error('Erreur lors de la soumission du coup:', error);
statusInfo.textContent = 'Erreur de communication avec le serveur.';
}
}
async function startNewGame(mode, playerPlaysWhite = true) {
playerMoveInfo.textContent = "";
aiMoveInfo.textContent = "";
try {
const response = await fetch('/new_game', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mode: mode, player_color_white: playerPlaysWhite})
});
const data = await response.json();
updateBoard(data);
statusInfo.textContent = `Nouvelle partie commencée. ${mode === 'ai' ? (playerPlaysWhite ? 'Vous jouez les Blancs.' : 'L\'IA joue les Blancs.') : 'Humain vs Humain.'}`;
} catch (error) {
console.error('Erreur lors du démarrage de la nouvelle partie:', error);
statusInfo.textContent = 'Erreur de communication avec le serveur.';
}
}
document.getElementById('submitMove').addEventListener('click', submitMove);
moveInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
submitMove();
}
});
document.getElementById('newGameHuman').addEventListener('click', () => startNewGame('human'));
document.getElementById('newGameAIWhite').addEventListener('click', () => startNewGame('ai', true));
document.getElementById('newGameAIBlack').addEventListener('click', () => startNewGame('ai', false));
// Initialiser l'état au chargement de la page (si une partie est en cours via session)
async function initializeBoardState() {
if (boardDisplay.innerHTML.includes("Chargement")) { // Si le SVG n'a pas été injecté par le serveur
try {
const response = await fetch('/get_board_state');
const data = await response.json();
updateBoard(data);
} catch (error) {
console.error('Erreur de récupération de l\'état initial:', error);
statusInfo.textContent = 'Erreur de chargement de la partie.';
}
} else { // Le SVG est déjà là, il faut juste mettre à jour les infos de statut
try {
const response = await fetch('/get_board_state'); // Récupérer le statut actuel
const data = await response.json();
turnInfo.textContent = `Tour: ${data.turn}`;
statusInfo.textContent = `Statut: ${data.status}`;
if (data.game_over) {
moveInput.disabled = true;
document.getElementById('submitMove').disabled = true;
}
} catch (error) {
console.error('Erreur de récupération de l\'état initial (infos):', error);
}
}
}
window.onload = initializeBoardState;
</script>
</body>
</html> |