Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Advanced Chess Analyzer</title> | |
| <style> | |
| :root { | |
| --board-size: min(80vh, 600px); | |
| --square-size: calc(var(--board-size) / 8); | |
| --primary-dark: #2c3e50; | |
| --primary-light: #34495e; | |
| --highlight: #f1c40f; | |
| --move-highlight: rgba(46, 204, 113, 0.4); | |
| --check-highlight: rgba(231, 76, 60, 0.4); | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; | |
| background: var(--primary-dark); | |
| color: #ecf0f1; | |
| min-height: 100vh; | |
| display: flex; | |
| } | |
| .container { | |
| display: grid; | |
| grid-template-columns: var(--board-size) 300px; | |
| gap: 2rem; | |
| margin: auto; | |
| padding: 2rem; | |
| background: var(--primary-light); | |
| border-radius: 1rem; | |
| box-shadow: 0 10px 20px rgba(0,0,0,0.2); | |
| } | |
| .board-container { | |
| width: var(--board-size); | |
| height: var(--board-size); | |
| position: relative; | |
| } | |
| .chessboard { | |
| width: 100%; | |
| height: 100%; | |
| display: grid; | |
| grid-template-columns: repeat(8, 1fr); | |
| grid-template-rows: repeat(8, 1fr); | |
| border: 4px solid #2c3e50; | |
| border-radius: 4px; | |
| overflow: hidden; | |
| } | |
| .square { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: calc(var(--square-size) * 0.7); | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| position: relative; | |
| user-select: none; | |
| } | |
| .white { background: #f0d9b5; } | |
| .black { background: #b58863; } | |
| .square.selected { | |
| background: var(--highlight) ; | |
| } | |
| .square.valid-move::after { | |
| content: ''; | |
| position: absolute; | |
| width: 25%; | |
| height: 25%; | |
| background: rgba(0,0,0,0.2); | |
| border-radius: 50%; | |
| } | |
| .square.last-move { | |
| background: var(--move-highlight) ; | |
| } | |
| .square.check { | |
| background: var(--check-highlight) ; | |
| } | |
| .controls { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1rem; | |
| } | |
| .status-panel { | |
| background: rgba(0,0,0,0.2); | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| } | |
| .move-list { | |
| background: rgba(0,0,0,0.2); | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| flex-grow: 1; | |
| overflow-y: auto; | |
| height: 300px; | |
| } | |
| .move-row { | |
| display: grid; | |
| grid-template-columns: 30px 1fr 1fr; | |
| padding: 0.3rem; | |
| gap: 0.5rem; | |
| } | |
| .move-row:hover { | |
| background: rgba(255,255,255,0.1); | |
| border-radius: 0.3rem; | |
| } | |
| button { | |
| background: #3498db; | |
| color: white; | |
| border: none; | |
| padding: 0.8rem; | |
| border-radius: 0.5rem; | |
| cursor: pointer; | |
| font-weight: 500; | |
| transition: background 0.2s; | |
| } | |
| button:hover { | |
| background: #2980b9; | |
| } | |
| .piece { | |
| width: 100%; | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: calc(var(--square-size) * 0.7); | |
| cursor: grab; | |
| } | |
| .piece:active { | |
| cursor: grabbing; | |
| } | |
| @media (max-width: 1024px) { | |
| .container { | |
| grid-template-columns: 1fr; | |
| grid-template-rows: auto auto; | |
| } | |
| .board-container { | |
| margin: auto; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="board-container"> | |
| <div class="chessboard" id="board"></div> | |
| </div> | |
| <div class="controls"> | |
| <div class="status-panel"> | |
| <h3>Position Analysis</h3> | |
| <p id="status">White to move</p> | |
| <p id="evaluation">Evaluation: 0.0</p> | |
| </div> | |
| <div class="move-list" id="moveList"> | |
| <!-- Moves will be inserted here --> | |
| </div> | |
| <button onclick="analyzePosition()">Analyze Position</button> | |
| <button onclick="resetBoard()">Reset Board</button> | |
| </div> | |
| </div> | |
| <script> | |
| class ChessGame { | |
| constructor() { | |
| this.board = this.createInitialBoard(); | |
| this.currentPlayer = 'white'; | |
| this.selectedPiece = null; | |
| this.moveHistory = []; | |
| this.validMoves = [ | |
| {type: 'K', move: {dx: [-1,0,1], dy: [-1,0,1]}}, | |
| {type: 'Q', move: {dx: [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7], | |
| dy: [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7]}}, | |
| {type: 'R', move: {dx: [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7], | |
| dy: [0]}}, | |
| {type: 'B', move: {dx: [-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7], | |
| dy: [-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7]}}, | |
| {type: 'N', move: {dx: [-2,-2,-1,-1,1,1,2,2], | |
| dy: [-1,1,-2,2,-2,2,-1,1]}}, | |
| {type: 'P', move: {dx: [0], dy: [-1,1]}} | |
| ]; | |
| this.initializeBoard(); | |
| } | |
| createInitialBoard() { | |
| return [ | |
| ['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'], | |
| ['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'], | |
| [null, null, null, null, null, null, null, null], | |
| [null, null, null, null, null, null, null, null], | |
| [null, null, null, null, null, null, null, null], | |
| [null, null, null, null, null, null, null, null], | |
| ['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'], | |
| ['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖'] | |
| ]; | |
| } | |
| // Initialize the board display | |
| initializeBoard() { | |
| const boardElement = document.getElementById('board'); | |
| boardElement.innerHTML = ''; | |
| for (let row = 0; row < 8; row++) { | |
| for (let col = 0; col < 8; col++) { | |
| const square = document.createElement('div'); | |
| square.className = `square ${(row + col) % 2 === 0 ? 'white' : 'black'}`; | |
| square.dataset.row = row; | |
| square.dataset.col = col; | |
| square.onclick = (e) => this.handleSquareClick(e); | |
| if (this.board[row][col]) { | |
| const piece = document.createElement('div'); | |
| piece.className = 'piece'; | |
| piece.textContent = this.board[row][col]; | |
| square.appendChild(piece); | |
| } | |
| boardElement.appendChild(square); | |
| } | |
| } | |
| this.updateStatus(); | |
| } | |
| // Handle square clicks | |
| handleSquareClick(event) { | |
| const square = event.target.closest('.square'); | |
| const row = parseInt(square.dataset.row); | |
| const col = parseInt(square.dataset.col); | |
| if (this.selectedPiece) { | |
| this.tryMove(row, col); | |
| } else if (this.board[row][col]) { | |
| this.selectPiece(row, col); | |
| } | |
| } | |
| // Select a piece to move | |
| selectPiece(row, col) { | |
| const piece = this.board[row][col]; | |
| if (!piece) return; | |
| document.querySelectorAll('.square').forEach(sq => { | |
| sq.classList.remove('selected'); | |
| sq.classList.remove('valid-move'); | |
| }); | |
| document.querySelector(`[data-row="${row}"][data-col="${col}"]`).classList.add('selected'); | |
| this.selectedPiece = { row, col }; | |
| this.showValidMoves(row, col); | |
| } | |
| // Try to make a move | |
| tryMove(toRow, toCol) { | |
| if (this.isValidMove(this.selectedPiece.row, this.selectedPiece.col, toRow, toCol)) { | |
| this.makeMove(this.selectedPiece.row, this.selectedPiece.col, toRow, toCol); | |
| } | |
| document.querySelectorAll('.square').forEach(sq => { | |
| sq.classList.remove('selected'); | |
| sq.classList.remove('valid-move'); | |
| }); | |
| this.selectedPiece = null; | |
| } | |
| // Check if move is valid | |
| isValidMove(fromRow, fromCol, toRow, toCol) { | |
| // Simplified validation | |
| const piece = this.board[fromRow][fromCol]; | |
| return piece !== null; | |
| } | |
| // Execute a move | |
| makeMove(fromRow, fromCol, toRow, toCol) { | |
| const piece = this.board[fromRow][fromCol]; | |
| this.board[fromRow][fromCol] = null; | |
| this.board[toRow][toCol] = piece; | |
| this.moveHistory.push({ | |
| piece, | |
| from: { row: fromRow, col: fromCol }, | |
| to: { row: toRow, col: toCol } | |
| }); | |
| this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white'; | |
| this.initializeBoard(); | |
| this.updateMoveList(); | |
| } | |
| // Show valid moves for selected piece | |
| showValidMoves(row, col) { | |
| const piece = this.board[row][col]; | |
| const moves = this.getValidMoves(piece, row, col); | |
| moves.forEach(move => { | |
| const square = document.querySelector( | |
| `[data-row="${move.row}"][data-col="${move.col}"]` | |
| ); | |
| if (square) square.classList.add('valid-move'); | |
| }); | |
| } | |
| // Get valid moves for a piece | |
| getValidMoves(piece, row, col) { | |
| // Simplified move generation | |
| return [{row: row + 1, col}, {row: row - 1, col}, | |
| {row, col: col + 1}, {row, col: col - 1}] | |
| .filter(pos => pos.row >= 0 && pos.row < 8 && | |
| pos.col >= 0 && pos.col < 8); | |
| } | |
| // Update game status display | |
| updateStatus() { | |
| document.getElementById('status').textContent = | |
| `${this.currentPlayer.charAt(0).toUpperCase() + | |
| this.currentPlayer.slice(1)} to move`; | |
| } | |
| // Update move list display | |
| updateMoveList() { | |
| const moveList = document.getElementById('moveList'); | |
| moveList.innerHTML = ''; | |
| for (let i = 0; i < this.moveHistory.length; i += 2) { | |
| const moveRow = document.createElement('div'); | |
| moveRow.className = 'move-row'; | |
| const moveNumber = document.createElement('span'); | |
| moveNumber.textContent = `${Math.floor(i/2 + 1)}.`; | |
| const whiteMove = document.createElement('span'); | |
| whiteMove.textContent = this.formatMove(this.moveHistory[i]); | |
| const blackMove = document.createElement('span'); | |
| if (this.moveHistory[i + 1]) { | |
| blackMove.textContent = this.formatMove(this.moveHistory[i + 1]); | |
| } | |
| moveRow.appendChild(moveNumber); | |
| moveRow.appendChild(whiteMove); | |
| moveRow.appendChild(blackMove); | |
| moveList.appendChild(moveRow); | |
| } | |
| moveList.scrollTop = moveList.scrollHeight; | |
| } | |
| // Format move for display | |
| formatMove(move) { | |
| const files = 'abcdefgh'; | |
| const ranks = '87654321'; | |
| return `${move.piece}${files[move.from.col]}${ranks[move.from.row]}-${files[move.to.col]}${ranks[move.to.row]}`; | |
| } | |
| } | |
| const game = new ChessGame(); | |
| function analyzePosition() { | |
| const eval = (Math.random() * 2 - 1).toFixed(2); | |
| document.getElementById('evaluation').textContent = `Evaluation: ${eval}`; | |
| } | |
| function resetBoard() { | |
| game.board = game.createInitialBoard(); | |
| game.currentPlayer = 'white'; | |
| game.selectedPiece = null; | |
| game.moveHistory = []; | |
| game.initializeBoard(); | |
| } | |
| </script> | |
| </body> | |
| </html> |