darkmaria / templates /index.html
Docfile's picture
Update templates/index.html
2cbb5b0 verified
raw
history blame
13.7 kB
<!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 Flask</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Pour centrer le SVG et éviter qu'il ne soit trop large sur mobile */
.board-container svg {
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}
/* Simple highlight pour la dernière case jouée par l'IA */
.highlight-last-move rect.lastmove {
fill: rgba(255, 255, 0, 0.4) !important; /* Jaune semi-transparent */
}
</style>
</head>
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col items-center p-4">
<div class="container mx-auto max-w-4xl">
<h1 class="text-4xl font-bold text-center my-6 text-teal-400">Jeu d'Échecs</h1>
<div class="bg-gray-800 p-6 rounded-lg shadow-xl mb-6">
<h2 class="text-2xl font-semibold mb-3 text-sky-400">Configuration</h2>
<div class="flex flex-wrap gap-4 items-center">
<button id="setPvP" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Humain vs Humain
</button>
<div>
<button id="setPvAIWhite" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Jouer vs IA (Blancs)
</button>
<button id="setPvAIBlack" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline mt-2 sm:mt-0 sm:ml-2">
Jouer vs IA (Noirs)
</button>
</div>
<button id="resetGame" class="bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Nouvelle Partie (Reset)
</button>
</div>
<p class="mt-3 text-sm text-gray-400">Mode Actuel: <span id="currentMode" class="font-semibold">{{ game_mode.upper() }}</span></p>
<p id="playerColorInfo" class="mt-1 text-sm text-gray-400 {% if game_mode != 'ai' %}hidden{% endif %}">
Vous jouez avec les: <span id="currentPlayerColor" class="font-semibold">{{ player_color.capitalize() if player_color else 'N/A' }}</span>
</p>
</div>
<div class="grid md:grid-cols-3 gap-6">
<div class="md:col-span-2 bg-gray-800 p-2 sm:p-6 rounded-lg shadow-xl board-container">
<div id="boardDisplay" class="highlight-last-move">
{{ initial_board_svg|safe }}
</div>
</div>
<div class="bg-gray-800 p-6 rounded-lg shadow-xl">
<h3 class="text-xl font-semibold mb-3 text-sky-400">Informations</h3>
<p id="turnDisplay" class="mb-2">Tour des: <span class="font-bold">Blancs</span></p>
<p id="status" class="text-yellow-400 font-semibold mb-4 h-6"></p>
<form id="moveForm" class="space-y-3">
<div>
<label for="moveInput" class="block text-sm font-medium text-gray-300">Votre coup (ex: e2e4, Nf3):</label>
<input type="text" id="moveInput" name="move"
class="mt-1 block w-full bg-gray-700 border border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white"
placeholder="e.g., e2e4">
</div>
<button type="submit"
class="w-full bg-teal-600 hover:bg-teal-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline transition duration-150 ease-in-out">
Jouer
</button>
</form>
<div id="outcomeDisplay" class="mt-4 text-lg font-bold text-center">
{% if is_game_over %}
<p class="text-green-400">{{ outcome }}</p>
{% endif %}
</div>
<div class="mt-4">
<p class="text-sm text-gray-400">Dernier coup IA:</p>
<p id="lastAIMove" class="text-gray-200 font-mono">-</p>
</div>
</div>
</div>
</div>
<script>
const boardDisplay = document.getElementById('boardDisplay');
const moveForm = document.getElementById('moveForm');
const moveInput = document.getElementById('moveInput');
const statusDisplay = document.getElementById('status');
const turnDisplay = document.getElementById('turnDisplay').querySelector('span');
const outcomeDisplay = document.getElementById('outcomeDisplay');
const lastAIMoveDisplay = document.getElementById('lastAIMove');
const currentModeDisplay = document.getElementById('currentMode');
const playerColorInfoDisplay = document.getElementById('playerColorInfo');
const currentPlayerColorDisplay = document.getElementById('currentPlayerColor');
let currentFEN = "{{ initial_fen }}";
let gameMode = "{{ game_mode }}";
let playerColor = "{{ player_color if player_color else 'white' }}"; // Couleur du joueur humain en mode AI
let isPlayerTurn = true; // Utilisé en mode AI
function updateBoard(data) {
if (data.board_svg) {
boardDisplay.innerHTML = data.board_svg;
}
currentFEN = data.fen;
if (data.turn) {
turnDisplay.textContent = data.turn === 'white' ? 'Blancs' : 'Noirs';
} else {
// Déduire du FEN si non fourni explicitement
const fenTurn = data.fen.split(' ')[1];
turnDisplay.textContent = fenTurn === 'w' ? 'Blancs' : 'Noirs';
}
if (data.ai_move_uci) {
lastAIMoveDisplay.textContent = data.ai_move_uci;
} else if (!data.game_over) {
// Ne pas effacer si la partie est finie et que le dernier coup était humain
// lastAIMoveDisplay.textContent = "-";
}
if (data.game_over) {
statusDisplay.textContent = "Partie terminée!";
outcomeDisplay.innerHTML = `<p class="text-green-400">${data.outcome}</p>`;
moveInput.disabled = true;
moveForm.querySelector('button[type="submit"]').disabled = true;
} else {
statusDisplay.textContent = '';
outcomeDisplay.innerHTML = '';
moveInput.disabled = false;
moveForm.querySelector('button[type="submit"]').disabled = false;
}
// Gérer le tour du joueur en mode AI
updatePlayerTurnState();
}
function updatePlayerTurnState() {
const fenTurn = currentFEN.split(' ')[1]; // 'w' or 'b'
if (gameMode === 'ai') {
const aiIsWhite = (playerColor === 'black');
const aiIsBlack = (playerColor === 'white');
if ((aiIsWhite && fenTurn === 'w') || (aiIsBlack && fenTurn === 'b')) {
isPlayerTurn = false;
moveInput.disabled = true;
moveForm.querySelector('button[type="submit"]').disabled = true;
statusDisplay.textContent = "L'IA réfléchit...";
} else {
isPlayerTurn = true;
if (!currentFEN.split(' ')[0].includes('k') || !currentFEN.split(' ')[0].includes('K')) { // Check si la partie est terminée
moveInput.disabled = false;
moveForm.querySelector('button[type="submit"]').disabled = false;
}
statusDisplay.textContent = "À vous de jouer.";
}
} else { // PvP mode
isPlayerTurn = true; // Toujours au tour du joueur en PvP
moveInput.disabled = false;
moveForm.querySelector('button[type="submit"]').disabled = false;
}
}
moveForm.addEventListener('submit', async (e) => {
e.preventDefault();
const move = moveInput.value.trim();
if (!move) return;
statusDisplay.textContent = 'Traitement...';
lastAIMoveDisplay.textContent = "-"; // Clear last AI move when player submits
try {
const response = await fetch('/make_move', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ move: move })
});
const data = await response.json();
if (data.error) {
statusDisplay.textContent = `Erreur: ${data.error}`;
} else {
updateBoard(data);
moveInput.value = ''; // Clear input on successful move
}
} catch (error) {
console.error("Erreur lors de la communication:", error);
statusDisplay.textContent = "Erreur de communication avec le serveur.";
}
});
document.getElementById('resetGame').addEventListener('click', async () => {
statusDisplay.textContent = 'Réinitialisation...';
try {
const response = await fetch('/reset_game', { method: 'POST' });
const data = await response.json();
updateBoard(data); // data contient fen et board_svg
lastAIMoveDisplay.textContent = "-";
// Réinitialiser l'état du jeu pour une nouvelle partie
moveInput.disabled = false;
moveForm.querySelector('button[type="submit"]').disabled = false;
outcomeDisplay.innerHTML = ''; // Effacer le message de fin de partie
// Mettre à jour l'affichage du mode et de la couleur
currentModeDisplay.textContent = data.game_mode ? data.game_mode.toUpperCase() : 'PVP';
if (data.game_mode === 'ai' && data.player_color) {
currentPlayerColorDisplay.textContent = data.player_color.charAt(0).toUpperCase() + data.player_color.slice(1);
playerColorInfoDisplay.classList.remove('hidden');
} else {
playerColorInfoDisplay.classList.add('hidden');
}
// Mettre à jour l'état du tour
updatePlayerTurnState();
} catch (error) {
console.error("Erreur lors de la réinitialisation:", error);
statusDisplay.textContent = "Erreur lors de la réinitialisation.";
}
});
async function setGameMode(mode, pColor = 'white') {
statusDisplay.textContent = `Changement de mode vers ${mode.toUpperCase()}...`;
lastAIMoveDisplay.textContent = "-";
try {
const response = await fetch('/set_mode', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ game_mode: mode, player_color: pColor })
});
const data = await response.json();
if (data.error) {
statusDisplay.textContent = `Erreur: ${data.error}`;
} else {
gameMode = data.game_mode;
playerColor = data.player_color;
updateBoard(data); // data contient fen, board_svg, etc.
currentModeDisplay.textContent = gameMode.toUpperCase();
if (gameMode === 'ai') {
currentPlayerColorDisplay.textContent = playerColor.charAt(0).toUpperCase() + playerColor.slice(1);
playerColorInfoDisplay.classList.remove('hidden');
} else {
playerColorInfoDisplay.classList.add('hidden');
}
statusDisplay.textContent = data.message;
if (data.initial_ai_move_uci) {
lastAIMoveDisplay.textContent = data.initial_ai_move_uci;
}
}
} catch (error) {
console.error("Erreur de changement de mode:", error);
statusDisplay.textContent = "Erreur de changement de mode.";
}
}
document.getElementById('setPvP').addEventListener('click', () => setGameMode('pvp'));
document.getElementById('setPvAIWhite').addEventListener('click', () => setGameMode('ai', 'white'));
document.getElementById('setPvAIBlack').addEventListener('click', () => setGameMode('ai', 'black'));
// Initialiser l'état du tour au chargement de la page
updatePlayerTurnState();
// Afficher la couleur du joueur si en mode AI au chargement
if (gameMode === 'ai') {
currentPlayerColorDisplay.textContent = playerColor.charAt(0).toUpperCase() + playerColor.slice(1);
playerColorInfoDisplay.classList.remove('hidden');
}
</script>
</body>
</html>