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>
19 KiB
API Reference - HTML Chess Game
Table of Contents
Core Classes
ChessGame
Main game controller that orchestrates all game logic.
Constructor
new ChessGame(config?: GameConfig)
Parameters:
config(optional): Configuration objectautoSave: boolean - Enable automatic saving (default: true)enableTimer: boolean - Enable move timer (default: false)timeControl: number - Time in milliseconds per player
Example:
const game = new ChessGame({
autoSave: true,
enableTimer: false
});
Properties
| Property | Type | Description |
|---|---|---|
board |
Board | The game board instance |
currentTurn |
'white' | 'black' | Current player's turn |
gameState |
GameState | Game state manager |
status |
GameStatus | Current game status |
winner |
'white' | 'black' | null | Winner if game ended |
Methods
makeMove()
Execute a chess move.
makeMove(fromRow: number, fromCol: number, toRow: number, toCol: number): MoveResult
Parameters:
fromRow: Source row (0-7)fromCol: Source column (0-7)toRow: Destination row (0-7)toCol: Destination column (0-7)
Returns: MoveResult
{
success: boolean,
move?: Move,
error?: string,
gameStatus?: GameStatus
}
Example:
const result = game.makeMove(6, 4, 4, 4); // e2 to e4
if (result.success) {
console.log('Move executed:', result.move.notation);
console.log('Game status:', result.gameStatus);
} else {
console.error('Invalid move:', result.error);
}
getLegalMoves()
Get all legal moves for a piece.
getLegalMoves(piece: Piece): Position[]
Parameters:
piece: The piece to get moves for
Returns: Array of legal positions
[
{row: 4, col: 4},
{row: 5, col: 4}
]
isInCheck()
Check if a player is in check.
isInCheck(color: Color): boolean
Parameters:
color: 'white' or 'black'
Returns: true if in check, false otherwise
newGame()
Start a new game.
newGame(): void
Resets the board and game state to initial position.
undo()
Undo the last move.
undo(): boolean
Returns: true if undo successful, false if no moves to undo
redo()
Redo a previously undone move.
redo(): boolean
Returns: true if redo successful, false if no moves to redo
resign()
Current player resigns.
resign(): void
Sets game status to ended with opponent as winner.
offerDraw()
Offer a draw to opponent.
offerDraw(): void
acceptDraw()
Accept a draw offer.
acceptDraw(): void
Sets game status to draw.
Board
Manages the chess board state and piece positions.
Constructor
new Board()
Properties
| Property | Type | Description |
|---|---|---|
grid |
(Piece | null)[][] | 8x8 grid of pieces |
Methods
getPiece()
Get piece at position.
getPiece(row: number, col: number): Piece | null
setPiece()
Place piece at position.
setPiece(row: number, col: number, piece: Piece | null): void
movePiece()
Move piece from one position to another.
movePiece(fromRow: number, fromCol: number, toRow: number, toCol: number): Piece | null
Returns: Captured piece if any
clone()
Create deep copy of board.
clone(): Board
Returns: New board instance with copied state
setupInitialPosition()
Set up standard chess starting position.
setupInitialPosition(): void
clear()
Remove all pieces from board.
clear(): void
toFEN()
Export board to FEN notation.
toFEN(): string
Returns: FEN string representing board state
Example:
const fen = board.toFEN();
// "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"
fromFEN()
Import board from FEN notation.
fromFEN(fen: string): void
Parameters:
fen: FEN notation string
GameState
Manages game state, move history, and metadata.
Constructor
new GameState()
Properties
| Property | Type | Description |
|---|---|---|
moveHistory |
Move[] | Array of all moves |
currentMove |
number | Current position in history |
capturedPieces |
CapturedPieces | Captured pieces by color |
status |
GameStatus | Current game status |
enPassantTarget |
Position | null | Available en passant target |
halfMoveClock |
number | Moves since capture/pawn move |
fullMoveNumber |
number | Full move counter |
Methods
recordMove()
Record a move in history.
recordMove(move: Move): void
getLastMove()
Get the most recent move.
getLastMove(): Move | null
undo()
Undo to previous state.
undo(): Move | null
Returns: Undone move or null
redo()
Redo to next state.
redo(): Move | null
Returns: Redone move or null
toFEN()
Export full game state to FEN.
toFEN(board: Board, currentTurn: Color): string
Returns: Complete FEN string
toPGN()
Export game to PGN notation.
toPGN(metadata?: PGNMetadata): string
Parameters:
metadata(optional): Game metadataevent: stringsite: stringdate: stringwhite: stringblack: stringresult: string
Returns: PGN formatted string
Example:
const pgn = gameState.toPGN({
event: "Casual Game",
white: "Player 1",
black: "Player 2",
date: "2025.01.22"
});
Piece Classes
Piece (Abstract Base Class)
Base class for all chess pieces.
Constructor
new Piece(color: Color, position: Position)
Parameters:
color: 'white' or 'black'position: {row: number, col: number}
Properties
| Property | Type | Description |
|---|---|---|
color |
'white' | 'black' | Piece color |
position |
Position | Current position |
type |
PieceType | Type of piece |
hasMoved |
boolean | Has piece moved |
Methods
getValidMoves()
Get all valid moves (without check validation).
getValidMoves(board: Board): Position[]
Returns: Array of valid positions
isValidMove()
Check if move to position is valid.
isValidMove(board: Board, toRow: number, toCol: number): boolean
clone()
Create copy of piece.
clone(): Piece
getSymbol()
Get Unicode symbol for piece.
getSymbol(): string
Returns: Unicode chess symbol (♔, ♕, ♖, etc.)
Pawn
Implements pawn-specific movement and rules.
Methods
getValidMoves()
getValidMoves(board: Board): Position[]
Special behavior:
- Forward 1 or 2 squares from starting position
- Diagonal captures
- En passant (handled separately)
- Promotion at last rank
Example:
const pawn = new Pawn('white', {row: 6, col: 4});
const moves = pawn.getValidMoves(board);
// [{row: 5, col: 4}, {row: 4, col: 4}] if starting position
Knight
Implements knight movement (L-shaped).
Methods
getValidMoves()
getValidMoves(board: Board): Position[]
Movement pattern: 2 squares in one direction, 1 square perpendicular
Bishop
Implements bishop movement (diagonals).
Methods
getValidMoves()
getValidMoves(board: Board): Position[]
Movement pattern: Any number of squares diagonally
Rook
Implements rook movement (straight lines).
Methods
getValidMoves()
getValidMoves(board: Board): Position[]
Movement pattern: Any number of squares horizontally or vertically
Queen
Implements queen movement (rook + bishop).
Methods
getValidMoves()
getValidMoves(board: Board): Position[]
Movement pattern: Combination of rook and bishop
King
Implements king movement and castling.
Methods
getValidMoves()
getValidMoves(board: Board): Position[]
Movement pattern: One square in any direction
canCastle()
Check if castling is possible.
canCastle(board: Board, side: 'kingside' | 'queenside'): boolean
Move System
MoveValidator
Static methods for move validation.
Methods
isMoveLegal()
Validate if move is legal (including check).
static isMoveLegal(
board: Board,
piece: Piece,
toRow: number,
toCol: number,
gameState: GameState
): boolean
isKingInCheck()
Check if king is under attack.
static isKingInCheck(board: Board, color: Color): boolean
isCheckmate()
Check if position is checkmate.
static isCheckmate(board: Board, color: Color): boolean
isStalemate()
Check if position is stalemate.
static isStalemate(board: Board, color: Color): boolean
hasAnyLegalMove()
Check if player has any legal moves.
static hasAnyLegalMove(board: Board, color: Color): boolean
SpecialMoves
Handles special chess moves.
Methods
canCastle()
Check if castling is legal.
static canCastle(
board: Board,
king: King,
rook: Rook,
side: 'kingside' | 'queenside'
): boolean
executeCastle()
Execute castling move.
static executeCastle(
board: Board,
king: King,
rook: Rook,
side: 'kingside' | 'queenside'
): void
canEnPassant()
Check if en passant is legal.
static canEnPassant(
board: Board,
pawn: Pawn,
targetCol: number,
gameState: GameState
): boolean
executeEnPassant()
Execute en passant capture.
static executeEnPassant(
board: Board,
pawn: Pawn,
targetRow: number,
targetCol: number
): Piece
Returns: Captured pawn
canPromote()
Check if pawn can be promoted.
static canPromote(pawn: Pawn): boolean
executePiece promotion()
Promote pawn to another piece.
static promote(
board: Board,
pawn: Pawn,
pieceType: 'queen' | 'rook' | 'bishop' | 'knight'
): Piece
Returns: New promoted piece
UI Components
BoardRenderer
Renders the chess board to DOM.
Constructor
new BoardRenderer(boardElement: HTMLElement, config?: RendererConfig)
Parameters:
boardElement: DOM element to render board intoconfig(optional):showCoordinates: boolean - Show rank/file labelspieceStyle: 'symbols' | 'images' - Piece rendering stylehighlightLastMove: boolean - Highlight last move
Methods
renderBoard()
Render complete board state.
renderBoard(board: Board, gameState: GameState): void
highlightMoves()
Highlight legal moves for a piece.
highlightMoves(moves: Position[]): void
clearHighlights()
Remove all move highlights.
clearHighlights(): void
selectSquare()
Select a square.
selectSquare(row: number, col: number): void
deselectSquare()
Deselect current square.
deselectSquare(): void
updateSquare()
Update a single square.
updateSquare(row: number, col: number, piece: Piece | null): void
DragDropHandler
Handles drag-and-drop interactions.
Constructor
new DragDropHandler(game: ChessGame, renderer: BoardRenderer)
Methods
enable()
Enable drag-and-drop.
enable(): void
disable()
Disable drag-and-drop.
disable(): void
Events
Emits custom events on board element:
piece-drag-start: Piece drag startedpiece-drag-over: Piece dragged over squarepiece-drop: Piece droppedpiece-drag-end: Drag ended
UIController
Manages all UI state and interactions.
Constructor
new UIController(game: ChessGame)
Methods
init()
Initialize UI components.
init(): void
updateGameStatus()
Update game status display.
updateGameStatus(status: GameStatus, message?: string): void
showPromotionDialog()
Show pawn promotion piece selection.
showPromotionDialog(callback: (pieceType: PieceType) => void): void
updateMoveHistory()
Update move history display.
updateMoveHistory(moves: Move[]): void
updateCapturedPieces()
Update captured pieces display.
updateCapturedPieces(captured: CapturedPieces): void
Utilities
Notation
Chess notation utilities.
Methods
positionToAlgebraic()
Convert position to algebraic notation.
static positionToAlgebraic(row: number, col: number): string
Example:
positionToAlgebraic(7, 4); // "e1"
positionToAlgebraic(0, 0); // "a8"
algebraicToPosition()
Convert algebraic notation to position.
static algebraicToPosition(notation: string): Position
Example:
algebraicToPosition("e4"); // {row: 4, col: 4}
moveToNotation()
Convert move to standard notation.
static moveToNotation(move: Move, board: Board): string
Example:
moveToNotation(move, board); // "Nf3", "Qxe5+", "O-O", etc.
Storage
LocalStorage wrapper for game persistence.
Methods
save()
Save game state.
static save(game: ChessGame, slotName: string = 'auto'): void
load()
Load game state.
static load(slotName: string = 'auto'): SavedGame | null
Returns:
{
fen: string,
pgn: string,
timestamp: number
}
list()
List all saved games.
static list(): string[]
Returns: Array of save slot names
delete()
Delete saved game.
static delete(slotName: string): void
Events
Game Events
The ChessGame instance emits events via EventTarget interface.
Available Events
move
Fired when a move is made.
game.addEventListener('move', (event) => {
console.log('Move:', event.detail.move);
console.log('Result:', event.detail.result);
});
Event Detail:
{
move: Move,
result: MoveResult
}
check
Fired when a king is in check.
game.addEventListener('check', (event) => {
console.log('King in check:', event.detail.color);
});
checkmate
Fired when checkmate occurs.
game.addEventListener('checkmate', (event) => {
console.log('Winner:', event.detail.winner);
});
stalemate
Fired when stalemate occurs.
game.addEventListener('stalemate', () => {
console.log('Game ended in stalemate');
});
promotion
Fired when pawn promotion is available.
game.addEventListener('promotion', (event) => {
// Show promotion dialog
showPromotionDialog(event.detail.pawn);
});
Data Structures
Types
type Color = 'white' | 'black';
type PieceType = 'pawn' | 'knight' | 'bishop' | 'rook' | 'queen' | 'king';
type GameStatus = 'active' | 'check' | 'checkmate' | 'stalemate' | 'draw' | 'resigned';
interface Position {
row: number; // 0-7
col: number; // 0-7
}
interface Move {
from: Position;
to: Position;
piece: Piece;
captured?: Piece;
notation: string;
special?: 'castle-kingside' | 'castle-queenside' | 'en-passant' | 'promotion';
promotedTo?: PieceType;
timestamp: number;
}
interface MoveResult {
success: boolean;
move?: Move;
error?: string;
gameStatus?: GameStatus;
}
interface CapturedPieces {
white: Piece[];
black: Piece[];
}
interface GameConfig {
autoSave?: boolean;
enableTimer?: boolean;
timeControl?: number;
}
interface RendererConfig {
showCoordinates?: boolean;
pieceStyle?: 'symbols' | 'images';
highlightLastMove?: boolean;
}
interface PGNMetadata {
event?: string;
site?: string;
date?: string;
white?: string;
black?: string;
result?: string;
}
interface SavedGame {
fen: string;
pgn: string;
timestamp: number;
}
Usage Examples
Basic Game Setup
import { ChessGame } from './js/game/ChessGame.js';
import { UIController } from './js/ui/UIController.js';
// Create game instance
const game = new ChessGame({
autoSave: true
});
// Initialize UI
const ui = new UIController(game);
ui.init();
// Listen for game events
game.addEventListener('move', (e) => {
console.log('Move made:', e.detail.move.notation);
});
game.addEventListener('checkmate', (e) => {
alert(`Checkmate! ${e.detail.winner} wins!`);
});
Making Moves Programmatically
// Make a move
const result = game.makeMove(6, 4, 4, 4); // e2 to e4
if (result.success) {
console.log('Move successful');
if (result.gameStatus === 'check') {
console.log('Check!');
}
} else {
console.error('Invalid move:', result.error);
}
Save and Load
// Save game
GameStorage.save(game.gameState, game.board);
// Load game
const saved = GameStorage.load();
if (saved) {
game.gameState.fromFEN(saved.fen);
}
Custom Event Handling
// Handle piece promotion
game.addEventListener('promotion', (event) => {
const pawn = event.detail.pawn;
// Show UI dialog
ui.showPromotionDialog((pieceType) => {
SpecialMoves.promote(game.board, pawn, pieceType);
});
});
Error Handling
All methods that can fail return result objects or throw descriptive errors:
try {
const result = game.makeMove(6, 4, 4, 4);
if (!result.success) {
console.error('Move failed:', result.error);
// Possible errors:
// - "No piece at source position"
// - "Not your turn"
// - "Invalid move for this piece"
// - "Move would leave king in check"
}
} catch (error) {
console.error('Unexpected error:', error);
}
Performance Considerations
- Move Validation: Cached when possible, invalidated on board changes
- Board Cloning: Deep copy only when necessary (undo/check simulation)
- DOM Updates: Batched and debounced to minimize reflows
- Event Handling: Use event delegation for board squares
Browser Compatibility
Minimum requirements:
- ES6+ support
- Drag and Drop API
- LocalStorage API
- CSS Grid
Supported browsers:
- Chrome 60+
- Firefox 54+
- Safari 10.1+
- Edge 79+
For implementation examples, see IMPLEMENTATION_GUIDE.md