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

601 lines
14 KiB
Markdown

# 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
```bash
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**:
```javascript
// 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**:
```javascript
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**:
```javascript
// 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**:
```javascript
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**:
```javascript
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
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```html
<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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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**:
```javascript
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):
```javascript
// 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`
```javascript
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`
```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