# Implementation Guide - HTML Chess Game

## 🎯 Purpose

This guide provides a step-by-step roadmap for implementing the HTML chess game. Follow this guide sequentially to build a robust, maintainable chess application.

## 📋 Prerequisites

Before starting implementation:
- [ ] Read [HANDOFF_CHECKLIST.md](HANDOFF_CHECKLIST.md)
- [ ] Review [API_REFERENCE.md](API_REFERENCE.md)
- [ ] Study architecture diagrams in [diagrams/](diagrams/)
- [ ] Understand chess rules from [CHESS_RULES.md](CHESS_RULES.md)
- [ ] Set up development environment (see [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md))

## 🏗️ Implementation Phases

### Phase 1: Project Setup and Core Architecture (Days 1-3)

#### 1.1 Initialize Project Structure
```bash
# Create directory structure
mkdir -p chess-game/{css,js/{game,pieces,moves,ui,utils},assets/pieces,tests/{unit,integration}}
cd chess-game
```

#### 1.2 Create Base HTML (index.html)
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chess Game</title>
    <link rel="stylesheet" href="css/board.css">
    <link rel="stylesheet" href="css/pieces.css">
    <link rel="stylesheet" href="css/ui.css">
</head>
<body>
    <div id="app">
        <header>
            <h1>Chess Game</h1>
            <div id="game-status"></div>
        </header>
        <main>
            <div id="chess-board"></div>
            <aside id="game-info">
                <div id="move-history"></div>
                <div id="captured-pieces"></div>
                <div id="game-controls"></div>
            </aside>
        </main>
    </div>
    <script type="module" src="js/main.js"></script>
</body>
</html>
```

**Key Points:**
- Use semantic HTML5 elements
- Include meta viewport for responsiveness
- Link CSS files in correct order
- Use type="module" for ES6 modules

#### 1.3 Create Core Classes

**Step 1:** Board.js - Board state management
```javascript
// js/game/Board.js
export class Board {
    constructor() {
        this.grid = this.initializeGrid();
        this.setupInitialPosition();
    }

    initializeGrid() {
        return Array(8).fill(null).map(() => Array(8).fill(null));
    }

    setupInitialPosition() {
        // Initialize pieces in starting position
        // See API_REFERENCE.md for detailed method signatures
    }

    getPiece(row, col) {
        return this.grid[row][col];
    }

    setPiece(row, col, piece) {
        this.grid[row][col] = piece;
    }

    movePiece(fromRow, fromCol, toRow, toCol) {
        // Move piece and return captured piece if any
    }
}
```

**Step 2:** Piece.js - Base piece class
```javascript
// js/pieces/Piece.js
export class Piece {
    constructor(color, position) {
        this.color = color; // 'white' or 'black'
        this.position = position; // {row, col}
        this.hasMoved = false;
    }

    getValidMoves(board) {
        // Override in subclasses
        throw new Error('getValidMoves must be implemented');
    }

    isValidMove(board, toRow, toCol) {
        const validMoves = this.getValidMoves(board);
        return validMoves.some(move =>
            move.row === toRow && move.col === toCol
        );
    }
}
```

**Step 3:** ChessGame.js - Game controller
```javascript
// js/game/ChessGame.js
export class ChessGame {
    constructor() {
        this.board = new Board();
        this.currentTurn = 'white';
        this.gameState = 'active'; // 'active', 'check', 'checkmate', 'stalemate', 'draw'
        this.moveHistory = [];
        this.selectedSquare = null;
    }

    makeMove(fromRow, fromCol, toRow, toCol) {
        // Validate and execute move
        // Update game state
        // Record in history
        // Switch turns
    }
}
```

**Testing Phase 1:**
```javascript
// tests/unit/Board.test.js
describe('Board', () => {
    it('should initialize 8x8 grid', () => {
        const board = new Board();
        expect(board.grid.length).toBe(8);
        expect(board.grid[0].length).toBe(8);
    });

    it('should setup initial position correctly', () => {
        const board = new Board();
        // Verify piece positions
    });
});
```

---

### Phase 2: Piece Implementation (Days 4-7)

#### 2.1 Implement Each Piece Type

**Implementation Order (simplest to most complex):**
1. Rook (straight lines)
2. Bishop (diagonals)
3. Queen (rook + bishop)
4. Knight (L-shapes)
5. King (one square)
6. Pawn (most complex with special moves)

**Example: Rook.js**
```javascript
// js/pieces/Rook.js
import { Piece } from './Piece.js';

export class Rook extends Piece {
    constructor(color, position) {
        super(color, position);
        this.type = 'rook';
    }

    getValidMoves(board) {
        const moves = [];
        const directions = [
            [-1, 0], // up
            [1, 0],  // down
            [0, -1], // left
            [0, 1]   // right
        ];

        for (const [dRow, dCol] of directions) {
            let currentRow = this.position.row + dRow;
            let currentCol = this.position.col + dCol;

            while (this.isInBounds(currentRow, currentCol)) {
                const targetPiece = board.getPiece(currentRow, currentCol);

                if (!targetPiece) {
                    // Empty square - can move here
                    moves.push({row: currentRow, col: currentCol});
                } else {
                    // Piece in the way
                    if (targetPiece.color !== this.color) {
                        // Can capture opponent piece
                        moves.push({row: currentRow, col: currentCol});
                    }
                    break; // Can't move further in this direction
                }

                currentRow += dRow;
                currentCol += dCol;
            }
        }

        return moves;
    }

    isInBounds(row, col) {
        return row >= 0 && row < 8 && col >= 0 && col < 8;
    }
}
```

**Critical Implementation Notes:**

**Pawn.js Special Cases:**
```javascript
getValidMoves(board) {
    const moves = [];
    const direction = this.color === 'white' ? -1 : 1;
    const startRow = this.color === 'white' ? 6 : 1;

    // Forward move
    const oneForward = this.position.row + direction;
    if (!board.getPiece(oneForward, this.position.col)) {
        moves.push({row: oneForward, col: this.position.col});

        // Two squares forward from starting position
        if (this.position.row === startRow) {
            const twoForward = this.position.row + (direction * 2);
            if (!board.getPiece(twoForward, this.position.col)) {
                moves.push({row: twoForward, col: this.position.col});
            }
        }
    }

    // Diagonal captures
    const captureOffsets = [-1, 1];
    for (const offset of captureOffsets) {
        const captureCol = this.position.col + offset;
        const targetPiece = board.getPiece(oneForward, captureCol);

        if (targetPiece && targetPiece.color !== this.color) {
            moves.push({row: oneForward, col: captureCol});
        }
    }

    // En passant (handled in SpecialMoves.js)

    return moves;
}
```

**Testing Each Piece:**
```javascript
// tests/unit/pieces/Rook.test.js
describe('Rook', () => {
    it('should move vertically and horizontally', () => {
        const board = new Board();
        const rook = new Rook('white', {row: 4, col: 4});
        board.setPiece(4, 4, rook);

        const moves = rook.getValidMoves(board);

        // Should have 14 moves (7 vertical + 7 horizontal)
        expect(moves.length).toBe(14);
    });

    it('should be blocked by pieces', () => {
        // Test blocking scenarios
    });

    it('should capture opponent pieces', () => {
        // Test capture scenarios
    });
});
```

---

### Phase 3: Move Validation and Special Moves (Days 8-12)

#### 3.1 MoveValidator.js

**Purpose:** Validate moves, check for check/checkmate

```javascript
// js/moves/MoveValidator.js
export class MoveValidator {
    static isMoveLegal(board, piece, toRow, toCol, gameState) {
        // 1. Check if move is in piece's valid moves
        if (!piece.isValidMove(board, toRow, toCol)) {
            return false;
        }

        // 2. Simulate move
        const simulatedBoard = this.simulateMove(board, piece, toRow, toCol);

        // 3. Check if own king is in check after move
        if (this.isKingInCheck(simulatedBoard, piece.color)) {
            return false;
        }

        return true;
    }

    static isKingInCheck(board, color) {
        // Find king position
        const kingPos = this.findKing(board, color);

        // Check if any opponent piece can attack king
        for (let row = 0; row < 8; row++) {
            for (let col = 0; col < 8; col++) {
                const piece = board.getPiece(row, col);
                if (piece && piece.color !== color) {
                    const moves = piece.getValidMoves(board);
                    if (moves.some(m => m.row === kingPos.row && m.col === kingPos.col)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    static isCheckmate(board, color) {
        // King must be in check
        if (!this.isKingInCheck(board, color)) {
            return false;
        }

        // Check if any legal move exists
        return !this.hasAnyLegalMove(board, color);
    }

    static isStalemate(board, color) {
        // King must NOT be in check
        if (this.isKingInCheck(board, color)) {
            return false;
        }

        // But no legal moves available
        return !this.hasAnyLegalMove(board, color);
    }
}
```

#### 3.2 SpecialMoves.js

**Castling Implementation:**
```javascript
// js/moves/SpecialMoves.js
export class SpecialMoves {
    static canCastle(board, king, rook) {
        // 1. Neither piece has moved
        if (king.hasMoved || rook.hasMoved) {
            return false;
        }

        // 2. No pieces between king and rook
        const [minCol, maxCol] = [
            Math.min(king.position.col, rook.position.col),
            Math.max(king.position.col, rook.position.col)
        ];

        for (let col = minCol + 1; col < maxCol; col++) {
            if (board.getPiece(king.position.row, col)) {
                return false;
            }
        }

        // 3. King not in check
        if (MoveValidator.isKingInCheck(board, king.color)) {
            return false;
        }

        // 4. King doesn't pass through check
        const direction = rook.position.col > king.position.col ? 1 : -1;
        for (let i = 1; i <= 2; i++) {
            const col = king.position.col + (direction * i);
            const simulatedBoard = this.simulateKingMove(board, king, col);
            if (MoveValidator.isKingInCheck(simulatedBoard, king.color)) {
                return false;
            }
        }

        return true;
    }

    static executeCastle(board, king, rook) {
        // Move king two squares
        // Move rook to other side of king
        // Mark both as moved
    }
}
```

**En Passant Implementation:**
```javascript
static canEnPassant(board, pawn, targetCol, gameState) {
    // 1. Pawn must be on correct rank
    const correctRank = pawn.color === 'white' ? 3 : 4;
    if (pawn.position.row !== correctRank) {
        return false;
    }

    // 2. Adjacent square has opponent pawn
    const adjacentPawn = board.getPiece(pawn.position.row, targetCol);
    if (!adjacentPawn || adjacentPawn.type !== 'pawn' || adjacentPawn.color === pawn.color) {
        return false;
    }

    // 3. That pawn just moved two squares
    const lastMove = gameState.moveHistory[gameState.moveHistory.length - 1];
    if (!lastMove || lastMove.piece !== adjacentPawn) {
        return false;
    }

    const moveDistance = Math.abs(lastMove.to.row - lastMove.from.row);
    return moveDistance === 2;
}
```

**Pawn Promotion:**
```javascript
static canPromote(pawn) {
    const promotionRank = pawn.color === 'white' ? 0 : 7;
    return pawn.position.row === promotionRank;
}

static promote(board, pawn, pieceType) {
    // Replace pawn with chosen piece (queen, rook, bishop, knight)
    const PieceClass = this.getPieceClass(pieceType);
    const newPiece = new PieceClass(pawn.color, pawn.position);
    board.setPiece(pawn.position.row, pawn.position.col, newPiece);
    return newPiece;
}
```

---

### Phase 4: UI Implementation (Days 13-17)

#### 4.1 BoardRenderer.js

```javascript
// js/ui/BoardRenderer.js
export class BoardRenderer {
    constructor(boardElement) {
        this.boardElement = boardElement;
        this.selectedSquare = null;
        this.highlightedMoves = [];
    }

    renderBoard(board, gameState) {
        this.boardElement.innerHTML = '';

        for (let row = 0; row < 8; row++) {
            for (let col = 0; col < 8; col++) {
                const square = this.createSquare(row, col);
                const piece = board.getPiece(row, col);

                if (piece) {
                    const pieceElement = this.createPieceElement(piece);
                    square.appendChild(pieceElement);
                }

                this.boardElement.appendChild(square);
            }
        }
    }

    createSquare(row, col) {
        const square = document.createElement('div');
        square.className = 'square';
        square.classList.add((row + col) % 2 === 0 ? 'light' : 'dark');
        square.dataset.row = row;
        square.dataset.col = col;
        return square;
    }

    createPieceElement(piece) {
        const pieceEl = document.createElement('div');
        pieceEl.className = `piece ${piece.color} ${piece.type}`;
        pieceEl.draggable = true;
        pieceEl.innerHTML = this.getPieceSymbol(piece);
        return pieceEl;
    }

    highlightMoves(moves) {
        this.clearHighlights();
        moves.forEach(move => {
            const square = this.getSquare(move.row, move.col);
            square.classList.add('legal-move');
        });
        this.highlightedMoves = moves;
    }

    clearHighlights() {
        this.highlightedMoves.forEach(move => {
            const square = this.getSquare(move.row, move.col);
            square.classList.remove('legal-move');
        });
        this.highlightedMoves = [];
    }
}
```

#### 4.2 DragDropHandler.js

```javascript
// js/ui/DragDropHandler.js
export class DragDropHandler {
    constructor(game, renderer) {
        this.game = game;
        this.renderer = renderer;
        this.setupEventListeners();
    }

    setupEventListeners() {
        const board = this.renderer.boardElement;

        board.addEventListener('dragstart', (e) => this.onDragStart(e));
        board.addEventListener('dragover', (e) => this.onDragOver(e));
        board.addEventListener('drop', (e) => this.onDrop(e));
        board.addEventListener('dragend', (e) => this.onDragEnd(e));

        // Also support click-to-move
        board.addEventListener('click', (e) => this.onClick(e));
    }

    onDragStart(e) {
        if (!e.target.classList.contains('piece')) return;

        const square = e.target.parentElement;
        const row = parseInt(square.dataset.row);
        const col = parseInt(square.dataset.col);

        e.dataTransfer.setData('text/plain', JSON.stringify({row, col}));
        e.dataTransfer.effectAllowed = 'move';

        // Highlight legal moves
        const piece = this.game.board.getPiece(row, col);
        if (piece && piece.color === this.game.currentTurn) {
            const legalMoves = this.game.getLegalMoves(piece);
            this.renderer.highlightMoves(legalMoves);
        }
    }

    onDragOver(e) {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';
    }

    onDrop(e) {
        e.preventDefault();

        const from = JSON.parse(e.dataTransfer.getData('text/plain'));
        const square = e.target.closest('.square');
        if (!square) return;

        const toRow = parseInt(square.dataset.row);
        const toCol = parseInt(square.dataset.col);

        this.game.makeMove(from.row, from.col, toRow, toCol);
    }

    onDragEnd(e) {
        this.renderer.clearHighlights();
    }
}
```

#### 4.3 CSS Styling

**board.css:**
```css
#chess-board {
    display: grid;
    grid-template-columns: repeat(8, 60px);
    grid-template-rows: repeat(8, 60px);
    gap: 0;
    border: 2px solid #333;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.square {
    width: 60px;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    transition: background-color 0.2s;
}

.square.light {
    background-color: #f0d9b5;
}

.square.dark {
    background-color: #b58863;
}

.square.selected {
    background-color: #9bc700;
}

.square.legal-move::after {
    content: '';
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: rgba(0, 0, 0, 0.2);
    position: absolute;
}

.square.legal-move.has-piece::after {
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: 3px solid rgba(255, 0, 0, 0.5);
}
```

---

### Phase 5: Game State Management (Days 18-21)

#### 5.1 GameState.js

```javascript
// js/game/GameState.js
export class GameState {
    constructor() {
        this.moveHistory = [];
        this.capturedPieces = {white: [], black: []};
        this.currentMove = 0;
        this.status = 'active';
    }

    recordMove(from, to, piece, captured, notation) {
        this.moveHistory.push({
            from,
            to,
            piece,
            captured,
            notation,
            timestamp: Date.now()
        });
        this.currentMove++;
    }

    undo() {
        if (this.currentMove === 0) return null;
        this.currentMove--;
        return this.moveHistory[this.currentMove];
    }

    redo() {
        if (this.currentMove >= this.moveHistory.length) return null;
        const move = this.moveHistory[this.currentMove];
        this.currentMove++;
        return move;
    }

    toFEN() {
        // Export game state to FEN notation
        // See CHESS_RULES.md for FEN format
    }

    fromFEN(fen) {
        // Import game state from FEN notation
    }

    toPGN() {
        // Export move history to PGN notation
    }
}
```

#### 5.2 Storage Integration

```javascript
// js/utils/storage.js
export class GameStorage {
    static save(gameState, board) {
        const data = {
            fen: gameState.toFEN(),
            pgn: gameState.toPGN(),
            timestamp: Date.now()
        };
        localStorage.setItem('chess-game-save', JSON.stringify(data));
    }

    static load() {
        const saved = localStorage.getItem('chess-game-save');
        return saved ? JSON.parse(saved) : null;
    }

    static clear() {
        localStorage.removeItem('chess-game-save');
    }
}
```

---

### Phase 6: Testing and Polish (Days 22-25)

#### 6.1 Unit Testing Checklist

- [ ] All piece movement tests
- [ ] Move validation tests
- [ ] Special move tests (castling, en passant, promotion)
- [ ] Check/checkmate detection tests
- [ ] Stalemate detection tests
- [ ] FEN/PGN notation tests
- [ ] Storage tests

#### 6.2 Integration Testing

```javascript
// tests/integration/gameplay.test.js
describe('Full Game Scenarios', () => {
    it('should handle Scholar\'s Mate', () => {
        const game = new ChessGame();

        game.makeMove(6, 4, 4, 4); // e4
        game.makeMove(1, 4, 3, 4); // e5
        game.makeMove(7, 5, 4, 2); // Bc4
        game.makeMove(1, 1, 2, 2); // Nc6
        game.makeMove(7, 3, 3, 7); // Qh5
        game.makeMove(1, 6, 2, 5); // Nf6
        game.makeMove(3, 7, 1, 5); // Qxf7#

        expect(game.gameState.status).toBe('checkmate');
        expect(game.winner).toBe('white');
    });
});
```

#### 6.3 Performance Optimization

- Memoize legal move calculations
- Use efficient data structures
- Minimize DOM manipulations
- Lazy load piece images
- Debounce UI updates

#### 6.4 Accessibility

- Add ARIA labels
- Keyboard navigation support
- Screen reader compatibility
- High contrast mode
- Focus indicators

---

## 🚨 Common Pitfalls and Solutions

### Problem 1: Check Detection Recursion
**Issue:** Checking for check while validating moves causes infinite recursion

**Solution:**
```javascript
// Separate validation from check detection
static getValidMoves(board, piece) {
    // Get moves without check validation
}

static getLegalMoves(board, piece) {
    // Filter valid moves by check constraint
    return this.getValidMoves(board, piece)
        .filter(move => !this.leavesKingInCheck(board, piece, move));
}
```

### Problem 2: En Passant State
**Issue:** En passant opportunity expires after one turn

**Solution:** Track in game state:
```javascript
class GameState {
    constructor() {
        this.enPassantTarget = null; // Reset after each move
    }
}
```

### Problem 3: Castling Through Check
**Issue:** Need to validate intermediate squares

**Solution:** Check each square king passes through:
```javascript
for (let col = kingCol; col !== targetCol; col += direction) {
    if (isSquareAttacked(board, kingRow, col, opponentColor)) {
        return false;
    }
}
```

### Problem 4: Drag and Drop Touch Support
**Issue:** Drag and drop doesn't work on mobile

**Solution:** Add touch event handlers:
```javascript
boardElement.addEventListener('touchstart', handleTouchStart);
boardElement.addEventListener('touchmove', handleTouchMove);
boardElement.addEventListener('touchend', handleTouchEnd);
```

---

## ✅ Implementation Checklist

### Core Functionality
- [ ] Board initialization
- [ ] All piece types implemented
- [ ] Move validation working
- [ ] Check detection
- [ ] Checkmate detection
- [ ] Stalemate detection
- [ ] Castling
- [ ] En passant
- [ ] Pawn promotion

### UI
- [ ] Board rendering
- [ ] Piece rendering
- [ ] Drag and drop
- [ ] Click to move
- [ ] Legal move highlighting
- [ ] Game status display
- [ ] Move history display
- [ ] Captured pieces display

### Game Management
- [ ] New game
- [ ] Undo/redo
- [ ] Save/load
- [ ] Resign
- [ ] Offer/accept draw

### Testing
- [ ] Unit tests (80%+ coverage)
- [ ] Integration tests
- [ ] Manual testing completed
- [ ] Browser compatibility tested

### Polish
- [ ] Animations
- [ ] Sound effects (optional)
- [ ] Responsive design
- [ ] Accessibility features
- [ ] Error handling

---

## 📚 Next Steps

After completing implementation:
1. Review [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md) for deployment
2. Conduct code review using provided checklist
3. Perform user acceptance testing
4. Deploy to production

---

**Questions?** Refer to [API_REFERENCE.md](API_REFERENCE.md) for detailed method signatures and [CHESS_RULES.md](CHESS_RULES.md) for chess logic clarification.
