chess/planning/architecture/api-interfaces.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

API Interfaces and Component Contracts

Public API Interfaces

1. IChessBoard Interface

interface IChessBoard {
  // Properties
  readonly squares: Square[];
  readonly activePiece: ChessPiece | null;

  // Square operations
  getSquare(file: number, rank: number): Square;
  getSquareByNotation(notation: string): Square;
  setPiece(square: Square, piece: ChessPiece): void;
  removePiece(square: Square): ChessPiece | null;
  getPiece(square: Square): ChessPiece | null;

  // Board queries
  isSquareOccupied(square: Square): boolean;
  isSquareEmpty(square: Square): boolean;
  getSquareColor(square: Square): 'light' | 'dark';
  findKing(color: 'white' | 'black'): Square | null;
  getAllPieces(color?: 'white' | 'black'): ChessPiece[];

  // Visual operations
  highlightSquares(squares: Square[]): void;
  clearHighlights(): void;

  // State management
  clone(): IChessBoard;
  reset(): void;
  toFEN(): string;
  fromFEN(fen: string): void;
}

2. IChessPiece Interface

interface IChessPiece {
  // Properties
  readonly type: PieceType;
  readonly color: 'white' | 'black';
  position: Square | null;
  hasMoved: boolean;

  // Move generation
  getPossibleMoves(board: IChessBoard): Square[];
  getLegalMoves(board: IChessBoard, gameState: IGameState): Square[];
  canMoveTo(square: Square, board: IChessBoard): boolean;
  getAttackingSquares(board: IChessBoard): Square[];

  // Piece information
  getValue(): number;
  getNotation(): string;
  getImagePath(theme?: string): string;

  // Utilities
  clone(): IChessPiece;
  equals(other: IChessPiece): boolean;
}

3. IGameEngine Interface

interface IGameEngine {
  // Properties
  readonly gameState: IGameState;
  readonly currentPlayer: 'white' | 'black';
  readonly moveHistory: IMove[];
  readonly status: GameStatus;

  // Game lifecycle
  initializeGame(config?: GameConfig): void;
  reset(): void;

  // Move execution
  executeMove(from: Square, to: Square, promotion?: PieceType): IMove | null;
  undoMove(): IMove | null;
  redoMove(): IMove | null;

  // Game state queries
  isCheck(color: 'white' | 'black'): boolean;
  isCheckmate(color: 'white' | 'black'): boolean;
  isStalemate(): boolean;
  isDraw(): boolean;
  isGameOver(): boolean;
  getWinner(): 'white' | 'black' | 'draw' | null;

  // Turn management
  switchTurn(): void;
  getCurrentPlayer(): 'white' | 'black';

  // State management
  getGameState(): IGameState;
  loadGameState(state: IGameState): void;
  saveGame(): string;
  loadGame(saveData: string): void;

  // Events
  on(event: string, handler: Function): void;
  off(event: string, handler: Function): void;
  emit(event: string, data?: any): void;
}

4. IMoveValidator Interface

interface IMoveValidator {
  // Primary validation
  isMoveLegal(from: Square, to: Square, gameState: IGameState): boolean;
  validateMove(move: IMove, gameState: IGameState): ValidationResult;

  // Specific validations
  isPseudoLegal(from: Square, to: Square, board: IChessBoard): boolean;
  wouldExposeKing(move: IMove, gameState: IGameState): boolean;
  validateCastling(king: Square, rook: Square, gameState: IGameState): boolean;
  validateEnPassant(from: Square, to: Square, gameState: IGameState): boolean;
  validatePromotion(move: IMove): boolean;

  // Threat detection
  isSquareAttacked(square: Square, byColor: 'white' | 'black', gameState: IGameState): boolean;
  getAttackingPieces(square: Square, byColor: 'white' | 'black', gameState: IGameState): IChessPiece[];
  isKingInCheck(color: 'white' | 'black', gameState: IGameState): boolean;

  // Cache management
  clearCache(): void;
}

interface ValidationResult {
  valid: boolean;
  reason?: string;
  code?: string;
}

5. IGameController Interface

interface IGameController {
  // Initialization
  initialize(config: GameConfig): void;
  startNewGame(config?: GameConfig): void;

  // User interaction
  handleSquareClick(square: Square): void;
  handlePieceDrag(piece: IChessPiece, fromSquare: Square): void;
  handlePieceDrop(toSquare: Square): void;
  selectSquare(square: Square): void;
  deselectSquare(): void;

  // Game actions
  makeMove(from: Square, to: Square, promotion?: PieceType): boolean;
  offerDraw(): void;
  acceptDraw(): void;
  resign(color: 'white' | 'black'): void;
  requestUndo(): void;

  // Game management
  pauseGame(): void;
  resumeGame(): void;
  saveGame(): string;
  loadGame(saveData: string): void;
  exportPGN(): string;

  // Configuration
  setGameMode(mode: 'pvp' | 'pva' | 'ava'): void;
  setAIDifficulty(level: number): void;
  updateSettings(settings: Partial<GameConfig>): void;

  // Queries
  getGameState(): IGameState;
  getCurrentPlayer(): 'white' | 'black';
  getGameStatus(): GameStatus;
  getLegalMovesFor(square: Square): Square[];
}

6. IMoveGenerator Interface

interface IMoveGenerator {
  // Move generation
  generateAllMoves(gameState: IGameState, color: 'white' | 'black'): IMove[];
  generatePieceMoves(piece: IChessPiece, gameState: IGameState): IMove[];
  generateCaptures(gameState: IGameState, color: 'white' | 'black'): IMove[];
  generateQuietMoves(gameState: IGameState, color: 'white' | 'black'): IMove[];

  // Special moves
  generateCastlingMoves(color: 'white' | 'black', gameState: IGameState): IMove[];
  generateEnPassantMoves(color: 'white' | 'black', gameState: IGameState): IMove[];
  generatePromotionMoves(pawn: IChessPiece, gameState: IGameState): IMove[];

  // Move ordering
  orderMoves(moves: IMove[], gameState: IGameState): IMove[];

  // Performance testing
  perft(depth: number, gameState: IGameState): number;

  // Cache
  clearCache(): void;
}

7. IGameHistory Interface

interface IGameHistory {
  // Properties
  readonly moves: IMove[];
  readonly currentIndex: number;
  readonly canUndo: boolean;
  readonly canRedo: boolean;

  // History operations
  addMove(move: IMove, position: string): void;
  getMove(index: number): IMove | null;
  getAllMoves(): IMove[];
  clear(): void;

  // Navigation
  undo(): IMove | null;
  redo(): IMove | null;
  goToMove(index: number): IMove | null;

  // Queries
  getMoveCount(): number;
  getLastMove(): IMove | null;
  isThreefoldRepetition(): boolean;
  getFiftyMoveCount(): number;

  // Export
  toPGN(metadata?: PGNMetadata): string;
  toJSON(): string;
  exportMoves(): string[];

  // Import
  fromPGN(pgn: string): void;
  fromJSON(json: string): void;
  importMoves(moves: string[]): void;
}

8. IUIController Interface

interface IUIController {
  // Rendering
  renderBoard(board: IChessBoard): void;
  renderPiece(piece: IChessPiece, square: Square): void;
  renderGameStatus(status: GameStatus): void;
  updateCapturedPieces(pieces: { white: PieceType[], black: PieceType[] }): void;

  // Animations
  animateMove(from: Square, to: Square, duration?: number): Promise<void>;
  animateCapture(square: Square): Promise<void>;
  animatePromotion(square: Square, newPiece: PieceType): Promise<void>;

  // Visual feedback
  highlightSquare(square: Square, type: HighlightType): void;
  clearHighlights(): void;
  showLegalMoves(moves: Square[]): void;
  hideLegalMoves(): void;
  showCheck(color: 'white' | 'black'): void;

  // Dialogs
  showPromotionDialog(color: 'white' | 'black'): Promise<PieceType>;
  showGameOverDialog(result: GameResult): void;
  showSettingsDialog(): void;

  // Interactions
  enableDragAndDrop(): void;
  disableDragAndDrop(): void;
  enableClickToMove(): void;
  disableClickToMove(): void;

  // Sound
  playSound(soundType: SoundType): void;

  // Theme
  setTheme(theme: string): void;
}

enum HighlightType {
  SELECTED = 'selected',
  LEGAL_MOVE = 'legal-move',
  LAST_MOVE = 'last-move',
  CHECK = 'check',
  ATTACKED = 'attacked'
}

enum SoundType {
  MOVE = 'move',
  CAPTURE = 'capture',
  CASTLE = 'castle',
  CHECK = 'check',
  CHECKMATE = 'checkmate',
  DRAW = 'draw',
  ILLEGAL = 'illegal'
}

9. IAIPlayer Interface

interface IAIPlayer {
  // Configuration
  setDifficulty(level: number): void;
  setThinkingTime(ms: number): void;
  setSearchDepth(depth: number): void;

  // Move calculation
  calculateMove(gameState: IGameState): Promise<IMove>;
  evaluatePosition(gameState: IGameState): number;

  // Search
  search(gameState: IGameState, depth: number): SearchResult;
  minimax(depth: number, alpha: number, beta: number, gameState: IGameState): number;

  // Opening book
  hasOpeningMove(gameState: IGameState): boolean;
  getOpeningMove(gameState: IGameState): IMove | null;

  // Status
  isThinking(): boolean;
  cancelCalculation(): void;

  // Events
  on(event: 'move-ready' | 'thinking' | 'evaluation-update', handler: Function): void;
  off(event: string, handler: Function): void;
}

interface SearchResult {
  bestMove: IMove;
  score: number;
  depth: number;
  nodesSearched: number;
  timeElapsed: number;
  principalVariation: IMove[];
}

10. IThemeManager Interface

interface IThemeManager {
  // Theme management
  setTheme(themeName: string): void;
  getTheme(): Theme;
  getAvailableThemes(): string[];

  // Custom themes
  registerTheme(theme: Theme): void;
  unregisterTheme(themeName: string): void;

  // Import/Export
  loadTheme(themeData: string): void;
  exportTheme(themeName: string): string;

  // Apply styles
  applyColors(): void;
  applyPieceSet(): void;
}

interface Theme {
  name: string;
  lightSquares: string;
  darkSquares: string;
  highlightColor: string;
  legalMoveColor: string;
  selectedColor: string;
  checkColor: string;
  pieceSet: string;
  borderStyle?: string;
  coordinatesColor?: string;
}

Event System API

Event Emitter Base

interface IEventEmitter {
  on(event: string, handler: Function): void;
  off(event: string, handler: Function): void;
  once(event: string, handler: Function): void;
  emit(event: string, data?: any): void;
  removeAllListeners(event?: string): void;
}

Game Events

// Event payloads
interface MoveExecutedEvent {
  move: IMove;
  gameState: IGameState;
  isCheck: boolean;
  isCheckmate: boolean;
}

interface PieceSelectedEvent {
  piece: IChessPiece;
  square: Square;
  legalMoves: Square[];
}

interface GameOverEvent {
  status: GameStatus;
  winner: 'white' | 'black' | 'draw' | null;
  reason: string;
}

interface TurnChangedEvent {
  player: 'white' | 'black';
  moveNumber: number;
}

interface CheckDetectedEvent {
  color: 'white' | 'black';
  attackingPieces: IChessPiece[];
}

Factory Interfaces

Piece Factory

interface IPieceFactory {
  createPiece(type: PieceType, color: 'white' | 'black', position?: Square): IChessPiece;
  createPawn(color: 'white' | 'black', position?: Square): IChessPiece;
  createKnight(color: 'white' | 'black', position?: Square): IChessPiece;
  createBishop(color: 'white' | 'black', position?: Square): IChessPiece;
  createRook(color: 'white' | 'black', position?: Square): IChessPiece;
  createQueen(color: 'white' | 'black', position?: Square): IChessPiece;
  createKing(color: 'white' | 'black', position?: Square): IChessPiece;
}

Game Factory

interface IGameFactory {
  createGame(config?: GameConfig): IGameEngine;
  createGameFromFEN(fen: string, config?: GameConfig): IGameEngine;
  createGameFromPGN(pgn: string, config?: GameConfig): IGameEngine;
}

Utility Interfaces

Notation Converter

interface INotationConverter {
  moveToSAN(move: IMove, gameState: IGameState): string;
  moveToLAN(move: IMove): string;
  moveToUCI(move: IMove): string;
  sanToMove(san: string, gameState: IGameState): IMove | null;
  uciToMove(uci: string, gameState: IGameState): IMove | null;
}

FEN Parser

interface IFENParser {
  parse(fen: string): IGameState;
  generate(gameState: IGameState): string;
  validate(fen: string): boolean;
}

PGN Parser

interface IPGNParser {
  parse(pgn: string): PGNGame;
  generate(game: IGameEngine): string;
  validate(pgn: string): boolean;
}

interface PGNGame {
  metadata: PGNMetadata;
  moves: string[];
  result: string;
}

interface PGNMetadata {
  event?: string;
  site?: string;
  date?: string;
  round?: string;
  white?: string;
  black?: string;
  result?: string;
  [key: string]: string | undefined;
}

Plugin Interface

interface IChessPlugin {
  name: string;
  version: string;

  // Lifecycle hooks
  initialize(game: IGameEngine): void;
  destroy(): void;

  // Optional hooks
  onMoveExecuted?(move: IMove, gameState: IGameState): void;
  onGameStart?(config: GameConfig): void;
  onGameEnd?(result: GameResult): void;
  onTurnChange?(player: 'white' | 'black'): void;

  // Custom functionality
  getAPI?(): any;
}

Service Interfaces

Storage Service

interface IStorageService {
  saveGame(key: string, game: IGameEngine): void;
  loadGame(key: string): IGameEngine | null;
  deleteGame(key: string): void;
  listSavedGames(): string[];

  saveSetting(key: string, value: any): void;
  loadSetting(key: string): any;

  clearAll(): void;
}

Network Service (Future)

interface INetworkService {
  connect(gameId: string): Promise<void>;
  disconnect(): void;
  sendMove(move: IMove): void;
  onMoveReceived(handler: (move: IMove) => void): void;

  syncGameState(gameState: IGameState): void;
  requestSync(): void;

  chat(message: string): void;
  onChatMessage(handler: (message: ChatMessage) => void): void;
}

Usage Example

// Initialize game
const gameFactory = new GameFactory();
const game = gameFactory.createGame({
  mode: 'pvp',
  theme: 'classic',
  soundEnabled: true
});

// Set up UI
const uiController = new UIController('#board-container');
uiController.renderBoard(game.getBoard());

// Handle moves
game.on('move-executed', (event: MoveExecutedEvent) => {
  uiController.animateMove(event.move.from, event.move.to);
  uiController.renderGameStatus(event.gameState.status);
});

// User interaction
uiController.on('square-clicked', (square: Square) => {
  const legalMoves = game.getLegalMovesFor(square);
  uiController.showLegalMoves(legalMoves);
});

// Execute move
game.executeMove(fromSquare, toSquare);

This API design ensures loose coupling, clear contracts, and easy testing while providing flexibility for future extensions.