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>
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:selectedpiece:movedpiece:capturedgame:checkgame:checkmategame:overturn: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:
- Rook.js (simplest - straight lines)
- Bishop.js (diagonal lines)
- Queen.js (combines rook + bishop)
- Knight.js (L-shapes, no blocking)
- King.js (one square, castling)
- 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
-
Check Validation Loop
- Don't call
isKingInCheck()insidegetValidMoves() - Use two-pass validation: piece moves → filter exposing king
- Don't call
-
Deep Cloning
- Board cloning must deep clone all pieces
- Use JSON or manual clone, not shallow copy
-
Event Listeners
- Remove old listeners before adding new ones
- Use event delegation for dynamically created elements
-
State Management
- Keep single source of truth (GameState)
- Don't duplicate state in multiple places
-
Performance
- Cache valid moves when position hasn't changed
- Use early returns in validation
- Avoid re-rendering entire board on each move
Testing Strategy
-
Unit Tests First
- Test each piece movement in isolation
- Test board operations
- Test validation logic
-
Integration Tests
- Test complete move flow
- Test check/checkmate scenarios
- Test special moves (castling, en passant)
-
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
- Review this guide with the team
- Set up development environment
- Start with Phase 1 (Foundation)
- Implement in order, testing as you go
- Use the code templates as starting points
- Reference coding standards for style
- Coordinate via memory for swarm work