chess/docs/implementation/implementation-guide.md
Christoph Wagner 5ad0700b41 refactor: Consolidate repository structure - flatten from workspace pattern
Restructured project from nested workspace pattern to flat single-repo layout.
This eliminates redundant nesting and consolidates all project files under version control.

## Migration Summary

**Before:**
```
alex/ (workspace, not versioned)
├── chess-game/ (git repo)
│   ├── js/, css/, tests/
│   └── index.html
└── docs/ (planning, not versioned)
```

**After:**
```
alex/ (git repo, everything versioned)
├── js/, css/, tests/
├── index.html
├── docs/ (project documentation)
├── planning/ (historical planning docs)
├── .gitea/ (CI/CD)
└── CLAUDE.md (configuration)
```

## Changes Made

### Structure Consolidation
- Moved all chess-game/ contents to root level
- Removed redundant chess-game/ subdirectory
- Flattened directory structure (eliminated one nesting level)

### Documentation Organization
- Moved chess-game/docs/ → docs/ (project documentation)
- Moved alex/docs/ → planning/ (historical planning documents)
- Added CLAUDE.md (workspace configuration)
- Added IMPLEMENTATION_PROMPT.md (original project prompt)

### Version Control Improvements
- All project files now under version control
- Planning documents preserved in planning/ folder
- Merged .gitignore files (workspace + project)
- Added .claude/ agent configurations

### File Updates
- Updated .gitignore to include both workspace and project excludes
- Moved README.md to root level
- All import paths remain functional (relative paths unchanged)

## Benefits

 **Simpler Structure** - One level of nesting removed
 **Complete Versioning** - All documentation now in git
 **Standard Layout** - Matches open-source project conventions
 **Easier Navigation** - Direct access to all project files
 **CI/CD Compatible** - All workflows still functional

## Technical Validation

-  Node.js environment verified
-  Dependencies installed successfully
-  Dev server starts and responds
-  All core files present and accessible
-  Git repository functional

## Files Preserved

**Implementation Files:**
- js/ (3,517 lines of code)
- css/ (4 stylesheets)
- tests/ (87 test cases)
- index.html
- package.json

**CI/CD Pipeline:**
- .gitea/workflows/ci.yml
- .gitea/workflows/release.yml

**Documentation:**
- docs/ (12+ documentation files)
- planning/ (historical planning materials)
- README.md

**Configuration:**
- jest.config.js, babel.config.cjs, playwright.config.js
- .gitignore (merged)
- CLAUDE.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:05:26 +01:00

14 KiB

Implementation Guide - Chess Game

Overview

Step-by-step guide for implementing the HTML chess game with single-player functionality.

Phase 1: Foundation (Day 1)

Step 1.1: Create Project Structure

mkdir chess-game
cd chess-game
mkdir -p css js/{models,controllers,views,engine,utils} assets/{pieces,sounds} tests
touch index.html css/{main,board,pieces,game-controls,animations}.css

Step 1.2: Implement Constants.js

File: js/utils/Constants.js

Key Elements:

  • Board dimensions (8x8)
  • Piece types and colors
  • Initial piece positions
  • Game status constants

Test Criteria:

  • All constants are immutable (use Object.freeze())
  • Initial positions are valid board coordinates
  • No duplicate piece positions

Step 1.3: Implement Helpers.js

File: js/utils/Helpers.js

Key Functions:

// Position validation
isValidPosition(row, col)

// Position comparison
positionsEqual(pos1, pos2)

// Coordinate conversion
algebraicToPosition('e4')  // → {row: 4, col: 4}
positionToAlgebraic({row: 4, col: 4})  // → 'e4'

// Array utilities
deepClone(obj)

Test Criteria:

  • Boundary testing (row/col 0-7)
  • Invalid input handling
  • Correct algebraic notation conversion

Step 1.4: Implement EventBus.js

File: js/utils/EventBus.js

Key Features:

  • Subscribe to events
  • Publish events
  • Unsubscribe from events

Events to Support:

  • piece:selected
  • piece:moved
  • piece:captured
  • game:check
  • game:checkmate
  • game:over
  • turn:changed

Phase 2: Data Models (Days 2-3)

Step 2.1: Implement Board.js

File: js/models/Board.js

Key Methods:

constructor()                      // Initialize 8x8 grid
getPieceAt(position)              // Get piece at position
setPieceAt(position, piece)       // Place piece
removePieceAt(position)           // Remove piece
movePiece(from, to)               // Move piece (update positions)
getAllPieces()                    // Get all pieces on board
getPiecesByColor(color)           // Get pieces of one color
clone()                           // Deep copy board state
reset()                           // Reset to initial state

Data Structure:

// Use 2D array
this._squares = Array(8).fill(null).map(() => Array(8).fill(null));

// Or use Map for sparse storage
this._pieces = new Map(); // key: 'row-col', value: Piece

Test Criteria:

  • Initial setup has 32 pieces
  • Can get/set pieces correctly
  • Clone creates independent copy
  • Moving piece updates both positions

Step 2.2: Implement Piece.js (Base Class)

File: js/models/Piece.js

Properties:

constructor(color, position, type) {
  this.color = color;          // 'white' or 'black'
  this.position = position;     // {row, col}
  this.type = type;            // 'pawn', 'rook', etc.
  this.hasMoved = false;       // For castling/pawn moves
}

Methods:

move(newPosition)              // Update position
getValidMoves(board)          // Abstract - override in subclasses
canMoveTo(position, board)    // Check if specific move is valid
clone()                       // Create copy

Step 2.3: Implement Individual Pieces

Files: js/models/pieces/*.js

Implementation Order:

  1. Rook.js (simplest - straight lines)
  2. Bishop.js (diagonal lines)
  3. Queen.js (combines rook + bishop)
  4. Knight.js (L-shapes, no blocking)
  5. King.js (one square, castling)
  6. Pawn.js (most complex - promotion, en passant)

Example: Pawn.js Template

import Piece from '../Piece.js';

class Pawn extends Piece {
  constructor(color, position) {
    super(color, position, 'pawn');
  }

  getValidMoves(board) {
    const moves = [];
    const direction = this.color === 'white' ? -1 : 1;
    const startRow = this.color === 'white' ? 6 : 1;

    // One square forward
    // Two squares forward (if on start row)
    // Diagonal captures
    // En passant (if applicable)

    return moves;
  }
}

export default Pawn;

Test Each Piece:

  • Starting position moves
  • Capture moves
  • Blocked moves
  • Edge of board
  • Special moves (castling, en passant, promotion)

Step 2.4: Implement GameState.js

File: js/models/GameState.js

Properties:

constructor() {
  this.currentPlayer = 'white';
  this.moveHistory = [];
  this.capturedPieces = [];
  this.isCheck = false;
  this.isCheckmate = false;
  this.isStalemate = false;
  this.enPassantTarget = null;  // For en passant validation
}

Methods:

switchTurn()
addMove(move)                  // {piece, from, to, captured}
getLastMove()
isGameOver()
reset()

Phase 3: Game Engine (Days 4-5)

Step 3.1: Implement MoveValidator.js

File: js/engine/MoveValidator.js

Key Methods:

isValidMove(piece, from, to, board)
  // 1. Check if move is in piece's valid moves
  // 2. Check if move doesn't expose king to check
  // 3. Return true/false

wouldExposeKing(piece, from, to, board)
  // Simulate move and check if king is in check

isPiecePinned(piece, board)
  // Check if piece is pinned to king

Step 3.2: Implement MoveGenerator.js

File: js/engine/MoveGenerator.js

Key Methods:

getAllValidMoves(color, board)
  // Get all legal moves for a color
  // Used for: check detection, AI, stalemate

hasValidMoves(color, board)
  // Quick check if player can move

Step 3.3: Implement CheckDetector.js

File: js/engine/CheckDetector.js

Key Methods:

isKingInCheck(color, board)
  // Check if king is under attack

isCheckmate(color, board)
  // Check if in check AND no valid moves

isStalemate(color, board)
  // Check if NOT in check AND no valid moves

getAttackingPieces(color, board)
  // Get pieces attacking the king

Step 3.4: Implement RuleEngine.js

File: js/engine/RuleEngine.js

Special Rules:

canCastle(king, rook, board)
  // Kingside or queenside castling

isEnPassantValid(pawn, target, board, gameState)
  // Check en passant conditions

handlePawnPromotion(pawn, choice = 'queen')
  // Promote pawn to chosen piece

Phase 4: Views (Days 6-7)

Step 4.1: Implement BoardView.js

File: js/views/BoardView.js

Key Methods:

render(board)
  // Create 64 squares with alternating colors
  // Add coordinate labels (a-h, 1-8)

highlightSquare(position, className)
  // Highlight selected piece or valid moves

clearHighlights()

getSquareElement(position)
  // Get DOM element for position

HTML Structure:

<div class="board">
  <div class="square light" data-row="0" data-col="0"></div>
  <!-- ... 64 squares -->
</div>

Step 4.2: Implement PieceView.js

File: js/views/PieceView.js

Key Methods:

renderPiece(piece, square)
  // Create piece element and add to square
  // Use Unicode symbols or images

removePiece(position)

movePiece(from, to, animate = true)
  // Animate piece movement

enableDragDrop(pieceElement, callbacks)
  // Setup drag and drop handlers

Piece Representation:

const PIECE_SYMBOLS = {
  'white-king': '♔',
  'white-queen': '♕',
  'white-rook': '♖',
  // ... or use images
};

Step 4.3: Implement UIManager.js

File: js/views/UIManager.js

UI Elements:

showMessage(text, type = 'info')
  // Display status message

showCheckIndicator(color)

showPromotionDialog(callback)
  // Show piece selection for pawn promotion

updateTurnIndicator(color)

updateCapturedPieces(pieces)

enableControls() / disableControls()

Phase 5: Controllers (Days 8-9)

Step 5.1: Implement MoveController.js

File: js/controllers/MoveController.js

Workflow:

handleMoveAttempt(piece, from, to) {
  // 1. Validate move
  if (!this.validator.isValidMove(piece, from, to, board)) {
    return { success: false, reason: 'Invalid move' };
  }

  // 2. Execute move
  const capturedPiece = this.executeMove(piece, from, to);

  // 3. Check for special rules
  if (piece.type === 'pawn' && this._isPromotionRow(to)) {
    this._handlePromotion(piece);
  }

  // 4. Update game state
  this.gameState.addMove({piece, from, to, captured: capturedPiece});

  // 5. Check for check/checkmate
  this._checkGameStatus();

  // 6. Switch turn
  this.gameState.switchTurn();

  return { success: true, captured: capturedPiece };
}

Step 5.2: Implement GameController.js

File: js/controllers/GameController.js

Main Loop:

class GameController {
  constructor(board, gameState, moveController, uiManager) {
    // Initialize dependencies
    this._setupEventListeners();
  }

  startNewGame() {
    // Reset board and state
    // Render initial position
    // Start player's turn
  }

  _setupEventListeners() {
    // Listen for square clicks
    // Handle piece selection
    // Handle move attempts
  }

  _handleSquareClick(row, col) {
    if (!this.selectedPiece) {
      // Try to select piece
      this._selectPiece(row, col);
    } else {
      // Try to move selected piece
      this._attemptMove(row, col);
    }
  }
}

Step 5.3: Implement AIController.js

File: js/controllers/AIController.js

AI Strategy (Start Simple):

// Level 1: Random valid move
getRandomMove(color, board) {
  const validMoves = this.moveGen.getAllValidMoves(color, board);
  return validMoves[Math.floor(Math.random() * validMoves.length)];
}

// Level 2: Material evaluation
getBestMove(color, board, depth = 2) {
  // Minimax algorithm
  // Evaluate position based on piece values
  // Return best move
}

Piece Values:

  • Pawn: 1
  • Knight: 3
  • Bishop: 3
  • Rook: 5
  • Queen: 9
  • King: ∞

Phase 6: Integration (Day 10)

Step 6.1: Create main.js

File: js/main.js

import Board from './models/Board.js';
import GameState from './models/GameState.js';
import GameController from './controllers/GameController.js';
// ... import all dependencies

// Wait for DOM
document.addEventListener('DOMContentLoaded', () => {
  // Initialize models
  const board = new Board();
  const gameState = new GameState();

  // Initialize views
  const boardView = new BoardView(document.querySelector('.board'));
  const uiManager = new UIManager();

  // Initialize controllers
  const moveController = new MoveController(/* dependencies */);
  const gameController = new GameController(/* dependencies */);

  // Start game
  gameController.startNewGame();
});

Step 6.2: Create index.html

File: index.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/main.css">
  <link rel="stylesheet" href="css/board.css">
  <link rel="stylesheet" href="css/pieces.css">
  <link rel="stylesheet" href="css/game-controls.css">
  <link rel="stylesheet" href="css/animations.css">
</head>
<body>
  <main class="game-container">
    <section class="game-info">
      <h1>Chess Game</h1>
      <div class="turn-indicator">White's Turn</div>
      <div class="status-message"></div>
    </section>

    <section class="board-container">
      <div class="board"></div>
    </section>

    <aside class="game-controls">
      <button id="new-game">New Game</button>
      <button id="undo">Undo</button>
      <div class="captured-pieces">
        <div class="captured-white"></div>
        <div class="captured-black"></div>
      </div>
    </aside>
  </main>

  <script type="module" src="js/main.js"></script>
</body>
</html>

Critical Implementation Notes

Common Pitfalls

  1. Check Validation Loop

    • Don't call isKingInCheck() inside getValidMoves()
    • Use two-pass validation: piece moves → filter exposing king
  2. Deep Cloning

    • Board cloning must deep clone all pieces
    • Use JSON or manual clone, not shallow copy
  3. Event Listeners

    • Remove old listeners before adding new ones
    • Use event delegation for dynamically created elements
  4. State Management

    • Keep single source of truth (GameState)
    • Don't duplicate state in multiple places
  5. Performance

    • Cache valid moves when position hasn't changed
    • Use early returns in validation
    • Avoid re-rendering entire board on each move

Testing Strategy

  1. Unit Tests First

    • Test each piece movement in isolation
    • Test board operations
    • Test validation logic
  2. Integration Tests

    • Test complete move flow
    • Test check/checkmate scenarios
    • Test special moves (castling, en passant)
  3. Manual Testing Scenarios

    • Scholar's mate (4-move checkmate)
    • Fool's mate (2-move checkmate)
    • Castling (both sides)
    • Pawn promotion
    • Stalemate positions

Dependencies Between Components

Phase 1 (Utils) → Phase 2 (Models) → Phase 3 (Engine) → Phase 4 (Views) → Phase 5 (Controllers) → Phase 6 (Integration)

Parallel Development:

  • Views can be developed alongside Engine
  • AI can be developed after basic game works
  • Tests can be written alongside implementation

Success Criteria

Minimum Viable Product (MVP)

  • All pieces move according to chess rules
  • Can detect check
  • Can detect checkmate
  • Player vs player works
  • Can start new game

Full Feature Set

  • Player vs computer AI
  • Pawn promotion
  • Castling (both sides)
  • En passant
  • Stalemate detection
  • Move history
  • Undo move
  • Highlight valid moves
  • Capture display
  • Animated moves

Estimated Timeline

  • Phase 1: 4 hours
  • Phase 2: 8 hours
  • Phase 3: 8 hours
  • Phase 4: 6 hours
  • Phase 5: 8 hours
  • Phase 6: 4 hours
  • Testing & Polish: 8 hours

Total: ~45 hours (1-2 weeks for one developer)

Next Steps

  1. Review this guide with the team
  2. Set up development environment
  3. Start with Phase 1 (Foundation)
  4. Implement in order, testing as you go
  5. Use the code templates as starting points
  6. Reference coding standards for style
  7. Coordinate via memory for swarm work