/** * Board.js - Chess board state management * Manages 8x8 grid and piece positions */ import { Pawn } from '../pieces/Pawn.js'; import { Rook } from '../pieces/Rook.js'; import { Knight } from '../pieces/Knight.js'; import { Bishop } from '../pieces/Bishop.js'; import { Queen } from '../pieces/Queen.js'; import { King } from '../pieces/King.js'; export class Board { constructor() { this.grid = this.initializeGrid(); } /** * Initialize empty 8x8 grid * @returns {Array>} 8x8 grid */ initializeGrid() { return Array(8).fill(null).map(() => Array(8).fill(null)); } /** * Setup standard chess starting position */ setupInitialPosition() { // Black pieces (row 0-1) this.grid[0][0] = new Rook('black', { row: 0, col: 0 }); this.grid[0][1] = new Knight('black', { row: 0, col: 1 }); this.grid[0][2] = new Bishop('black', { row: 0, col: 2 }); this.grid[0][3] = new Queen('black', { row: 0, col: 3 }); this.grid[0][4] = new King('black', { row: 0, col: 4 }); this.grid[0][5] = new Bishop('black', { row: 0, col: 5 }); this.grid[0][6] = new Knight('black', { row: 0, col: 6 }); this.grid[0][7] = new Rook('black', { row: 0, col: 7 }); // Black pawns for (let col = 0; col < 8; col++) { this.grid[1][col] = new Pawn('black', { row: 1, col }); } // White pawns for (let col = 0; col < 8; col++) { this.grid[6][col] = new Pawn('white', { row: 6, col }); } // White pieces (row 7) this.grid[7][0] = new Rook('white', { row: 7, col: 0 }); this.grid[7][1] = new Knight('white', { row: 7, col: 1 }); this.grid[7][2] = new Bishop('white', { row: 7, col: 2 }); this.grid[7][3] = new Queen('white', { row: 7, col: 3 }); this.grid[7][4] = new King('white', { row: 7, col: 4 }); this.grid[7][5] = new Bishop('white', { row: 7, col: 5 }); this.grid[7][6] = new Knight('white', { row: 7, col: 6 }); this.grid[7][7] = new Rook('white', { row: 7, col: 7 }); } /** * Get piece at position * @param {number} row - Row index (0-7) * @param {number} col - Column index (0-7) * @returns {Piece|null} Piece or null if empty */ getPiece(row, col) { if (!this.isInBounds(row, col)) return null; return this.grid[row][col]; } /** * Set piece at position * @param {number} row - Row index * @param {number} col - Column index * @param {Piece|null} piece - Piece to place */ setPiece(row, col, piece) { if (!this.isInBounds(row, col)) return; this.grid[row][col] = piece; if (piece) { piece.position = { row, col }; } } /** * Move piece from one position to another * @param {number} fromRow - Source row * @param {number} fromCol - Source column * @param {number} toRow - Destination row * @param {number} toCol - Destination column * @returns {Piece|null} Captured piece if any */ movePiece(fromRow, fromCol, toRow, toCol) { const piece = this.getPiece(fromRow, fromCol); if (!piece) return null; const captured = this.getPiece(toRow, toCol); // Move the piece this.setPiece(toRow, toCol, piece); this.setPiece(fromRow, fromCol, null); // Mark piece as moved piece.hasMoved = true; return captured; } /** * Check if position is within board bounds * @param {number} row - Row index * @param {number} col - Column index * @returns {boolean} True if in bounds */ isInBounds(row, col) { return row >= 0 && row < 8 && col >= 0 && col < 8; } /** * Create deep copy of board * @returns {Board} Cloned board */ clone() { const cloned = new Board(); for (let row = 0; row < 8; row++) { for (let col = 0; col < 8; col++) { const piece = this.grid[row][col]; if (piece) { cloned.grid[row][col] = piece.clone(); } } } return cloned; } /** * Clear all pieces from board */ clear() { this.grid = this.initializeGrid(); } /** * Export board to FEN notation (board part only) * @returns {string} FEN string */ toFEN() { let fen = ''; for (let row = 0; row < 8; row++) { let emptyCount = 0; for (let col = 0; col < 8; col++) { const piece = this.grid[row][col]; if (piece) { if (emptyCount > 0) { fen += emptyCount; emptyCount = 0; } fen += piece.toFENChar(); } else { emptyCount++; } } if (emptyCount > 0) { fen += emptyCount; } if (row < 7) { fen += '/'; } } return fen; } /** * Find king position for given color * @param {string} color - 'white' or 'black' * @returns {Position|null} King position or null */ findKing(color) { for (let row = 0; row < 8; row++) { for (let col = 0; col < 8; col++) { const piece = this.grid[row][col]; if (piece && piece.type === 'king' && piece.color === color) { return { row, col }; } } } return null; } /** * Get all pieces of a specific color * @param {string} color - 'white' or 'black' * @returns {Array} Array of pieces */ getPiecesByColor(color) { const pieces = []; for (let row = 0; row < 8; row++) { for (let col = 0; col < 8; col++) { const piece = this.grid[row][col]; if (piece && piece.color === color) { pieces.push(piece); } } } return pieces; } }