chess/planning/CHESS_RULES.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

20 KiB

Chess Rules Reference

Table of Contents

  1. Game Objective
  2. Board Setup
  3. Piece Movement
  4. Special Moves
  5. Check and Checkmate
  6. Draw Conditions
  7. Chess Notation
  8. Rule Edge Cases

Game Objective

Chess is a two-player strategy game where the objective is to checkmate the opponent's king.

  • Checkmate: The king is under attack (in check) and cannot escape
  • Win Conditions: Checkmate or opponent resignation
  • Draw Conditions: Stalemate, insufficient material, threefold repetition, fifty-move rule, or agreement

Board Setup

Board Orientation

  • 8x8 grid with alternating light and dark squares
  • Bottom-right square from each player's perspective is a light square
  • Ranks (rows) numbered 1-8, files (columns) labeled a-h
  • White pieces start on ranks 1-2, black on ranks 7-8

Initial Position

  a b c d e f g h
8 ♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜  8
7 ♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟  7
6 · · · · · · · ·  6
5 · · · · · · · ·  5
4 · · · · · · · ·  4
3 · · · · · · · ·  3
2 ♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙  2
1 ♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖  1
  a b c d e f g h

FEN Notation: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

Piece Placement

White (bottom):

  • a1, h1: Rooks (♖)
  • b1, g1: Knights (♘)
  • c1, f1: Bishops (♗)
  • d1: Queen (♕)
  • e1: King (♔)
  • a2-h2: Pawns (♙)

Black (top):

  • a8, h8: Rooks (♜)
  • b8, g8: Knights (♞)
  • c8, f8: Bishops (♝)
  • d8: Queen (♛)
  • e8: King (♚)
  • a7-h7: Pawns (♟)

Mnemonic: "Queen on her own color" (white queen on light square, black queen on dark square)


Piece Movement

Pawn (♙ ♟)

Basic Movement:

  • Moves forward one square
  • From starting position, can move forward two squares
  • Captures diagonally forward one square
  • Cannot move backward

Special Rules:

  • Can only capture diagonally (not straight ahead)
  • Blocked if square directly ahead is occupied
  • See En Passant and Promotion

Diagram:

· · · · · · · ·
· · ♟ · ♟ · · ·  ← Can capture here
· · · ♙ · · · ·  ← Pawn position
· · · ↑ · · · ·  ← Can move here
· · · ↑ · · · ·  ← Can move here (if first move)

Implementation Note:

  • White pawns move up (decreasing row), black pawns move down (increasing row)
  • Starting rank: white on row 6, black on row 1
  • Promotion rank: white on row 0, black on row 7

Knight (♘ ♞)

Movement Pattern:

  • L-shaped: 2 squares in one direction, 1 square perpendicular
  • Can jump over other pieces
  • 8 possible moves maximum (if not blocked)

Movement Offsets:

(-2, -1)  (-2, +1)
   ↖  ↗
(-1,-2) ♘ (-1,+2)
   ↙  ↘
(+1,-2)   (+1,+2)
   ↖  ↗
(+2, -1)  (+2, +1)

Diagram:

· · X · X · · ·
· X · · · X · ·
· · · ♘ · · · ·
· X · · · X · ·
· · X · X · · ·

Implementation:

const knightMoves = [
    [-2, -1], [-2, 1], [-1, -2], [-1, 2],
    [1, -2], [1, 2], [2, -1], [2, 1]
];

Bishop (♗ ♝)

Movement Pattern:

  • Any number of squares diagonally
  • Cannot jump over pieces
  • Stays on same color squares entire game

Diagram:

X · · · · · · ·
· X · · · · · X
· · X · · · X ·
· · · ♗ · X · ·
· · · · X · · ·
· · · X · · · ·

Implementation:

const bishopDirections = [
    [-1, -1], // up-left
    [-1, +1], // up-right
    [+1, -1], // down-left
    [+1, +1]  // down-right
];

Rook (♖ ♜)

Movement Pattern:

  • Any number of squares horizontally or vertically
  • Cannot jump over pieces
  • Involved in castling (see Castling)

Diagram:

· · · X · · · ·
· · · X · · · ·
· · · X · · · ·
X X X ♖ X X X X
· · · X · · · ·
· · · X · · · ·

Implementation:

const rookDirections = [
    [-1, 0], // up
    [+1, 0], // down
    [0, -1], // left
    [0, +1]  // right
];

Queen (♕ ♛)

Movement Pattern:

  • Combines rook and bishop movement
  • Any number of squares in any direction
  • Cannot jump over pieces
  • Most powerful piece

Diagram:

X · · X · · · X
· X · X · · X ·
· · X X · X · ·
X X X ♕ X X X X
· · X X · X · ·
· X · X · · X ·

Implementation:

const queenDirections = [
    [-1, -1], [-1, 0], [-1, +1],
    [0, -1],           [0, +1],
    [+1, -1], [+1, 0], [+1, +1]
];

King (♔ ♚)

Movement Pattern:

  • One square in any direction
  • Cannot move into check
  • Involved in castling (see Castling)

Diagram:

· · · · · · · ·
· · X X X · · ·
· · X ♔ X · · ·
· · X X X · · ·

Implementation:

const kingMoves = [
    [-1, -1], [-1, 0], [-1, +1],
    [0, -1],           [0, +1],
    [+1, -1], [+1, 0], [+1, +1]
];

Critical Rules:

  • Cannot move into check (square attacked by opponent)
  • Cannot castle out of, through, or into check
  • Most important piece (game ends if checkmated)

Special Moves

Castling

Purpose: Protect king and activate rook

Types:

  1. Kingside Castling (O-O): King moves two squares toward h-file rook
  2. Queenside Castling (O-O-O): King moves two squares toward a-file rook

Conditions (ALL must be met):

  1. Neither king nor rook has moved previously
  2. No pieces between king and rook
  3. King is not in check
  4. King does not pass through check
  5. King does not end up in check

Kingside Castling (White):

Before:  · · · · ♔ · · ♖
After:   · · · · · ♖ ♔ ·
         e1 → g1, h1 → f1

Queenside Castling (White):

Before:  ♖ · · · ♔ · · ·
After:   · · ♔ ♖ · · · ·
         e1 → c1, a1 → d1

Implementation Logic:

function canCastle(king, rook, board) {
    // 1. Check if pieces have moved
    if (king.hasMoved || rook.hasMoved) return false;

    // 2. Check if path is clear
    const [minCol, maxCol] = [
        Math.min(king.col, rook.col),
        Math.max(king.col, rook.col)
    ];
    for (let col = minCol + 1; col < maxCol; col++) {
        if (board.getPiece(king.row, col)) return false;
    }

    // 3. Check if king is in check
    if (isKingInCheck(board, king.color)) return false;

    // 4. Check if king passes through check
    const direction = rook.col > king.col ? 1 : -1;
    for (let i = 1; i <= 2; i++) {
        const testCol = king.col + (direction * i);
        if (isSquareUnderAttack(board, king.row, testCol, opponentColor)) {
            return false;
        }
    }

    return true;
}

En Passant

Purpose: Prevent pawns from avoiding capture by double-stepping

Condition:

  • Opponent pawn moves two squares from starting position
  • Lands beside your pawn (same rank)
  • You can capture it as if it moved only one square
  • Must be done immediately (next move only)

Diagram:

Before:           After capture:
· · · · · · · ·   · · · · · · · ·
♟ · ♟ · · · · ·   · · ♟ · · · · ·
· ♙ · · · · · ·   · · ♙ · · · · ·  ← White pawn captures
♙ · · · · · · ·   · · · · · · · ·

FEN Notation:

  • En passant target square recorded in FEN
  • Example: ...w KQkq e6... (e6 is en passant target)

Implementation:

function canEnPassant(pawn, targetCol, gameState) {
    // Must be on correct rank
    const correctRank = pawn.color === 'white' ? 3 : 4;
    if (pawn.row !== correctRank) return false;

    // Check last move
    const lastMove = gameState.getLastMove();
    if (!lastMove || lastMove.piece.type !== 'pawn') return false;

    // Must have moved two squares
    const moveDistance = Math.abs(lastMove.to.row - lastMove.from.row);
    if (moveDistance !== 2) return false;

    // Must be adjacent
    return Math.abs(pawn.col - targetCol) === 1 &&
           lastMove.to.col === targetCol &&
           lastMove.to.row === pawn.row;
}

function executeEnPassant(board, pawn, targetRow, targetCol) {
    // Remove captured pawn
    const capturedPawn = board.getPiece(pawn.row, targetCol);
    board.setPiece(pawn.row, targetCol, null);

    // Move attacking pawn
    board.movePiece(pawn.row, pawn.col, targetRow, targetCol);

    return capturedPawn;
}

Pawn Promotion

Condition: Pawn reaches the opposite end of the board (rank 8 for white, rank 1 for black)

Options: Can promote to:

  • Queen (most common)
  • Rook
  • Bishop
  • Knight
  • Cannot promote to King or Pawn

Notation:

  • e8=Q - Pawn to e8, promotes to queen
  • axb8=N+ - Pawn captures on b8, promotes to knight with check

Diagram:

♟ · · · · · · ·  ← Black pawn about to promote
· · · · · · · ·
...
♙ · · · · · · ·  ← White pawn about to promote

Implementation:

function canPromote(pawn) {
    const promotionRank = pawn.color === 'white' ? 0 : 7;
    return pawn.row === promotionRank;
}

function promote(board, pawn, pieceType) {
    // pieceType: 'queen', 'rook', 'bishop', 'knight'
    const PieceClass = getPieceClass(pieceType);
    const newPiece = new PieceClass(pawn.color, pawn.position);
    board.setPiece(pawn.row, pawn.col, newPiece);
    return newPiece;
}

UI Consideration: Show dialog for player to choose promotion piece


Check and Checkmate

Check

Definition: King is under direct attack by opponent piece

Rules:

  • Player in check must get out of check
  • Cannot make any move that leaves king in check
  • Must respond with one of three options:
    1. Move king to safe square
    2. Block the attack
    3. Capture the attacking piece

Notation: Add + to move notation (e.g., Qh5+)

Implementation:

function isKingInCheck(board, color) {
    // Find king position
    const kingPos = findKing(board, color);
    if (!kingPos) return false; // Should never happen

    // Check if any opponent piece attacks king square
    for (let row = 0; row < 8; row++) {
        for (let col = 0; col < 8; col++) {
            const piece = board.getPiece(row, col);
            if (piece && piece.color !== color) {
                const moves = piece.getValidMoves(board);
                if (moves.some(m => m.row === kingPos.row && m.col === kingPos.col)) {
                    return true;
                }
            }
        }
    }

    return false;
}

Checkmate

Definition: King is in check and cannot escape

Conditions:

  1. King is in check
  2. King cannot move to safe square
  3. No piece can block the attack
  4. Attacking piece cannot be captured

Notation: Add # to move notation (e.g., Qf7#)

Result: Game ends, attacking player wins

Famous Checkmate Patterns:

Scholar's Mate (4 moves):

1. e4 e5
2. Bc4 Nc6
3. Qh5 Nf6??
4. Qxf7# (checkmate)

Back Rank Mate:

  a b c d e f g h
8 · · · · · ♜ ♚ ·  8  ← King trapped by own pawns
7 · · · · · ♟ ♟ ♟  7

Implementation:

function isCheckmate(board, color) {
    // Must be in check
    if (!isKingInCheck(board, color)) {
        return false;
    }

    // Check if any legal move exists
    for (let row = 0; row < 8; row++) {
        for (let col = 0; col < 8; col++) {
            const piece = board.getPiece(row, col);
            if (piece && piece.color === color) {
                const moves = piece.getValidMoves(board);

                for (const move of moves) {
                    // Simulate move
                    const testBoard = board.clone();
                    testBoard.movePiece(row, col, move.row, move.col);

                    // If king no longer in check, not checkmate
                    if (!isKingInCheck(testBoard, color)) {
                        return false;
                    }
                }
            }
        }
    }

    // No legal moves available
    return true;
}

Draw Conditions

Stalemate

Definition: Player has no legal moves but is NOT in check

Result: Game is a draw

Diagram:

  a b c d e f g h
8 · · · · · · ♔ ·  8
7 · · · · · ♕ · ·  7
6 · · · · · · · ♚  6  ← Black king, not in check

Black to move has no legal moves → Stalemate

Implementation:

function isStalemate(board, color) {
    // Must NOT be in check
    if (isKingInCheck(board, color)) {
        return false;
    }

    // But has no legal moves
    return !hasAnyLegalMove(board, color);
}

Insufficient Material

Definition: Neither player has enough pieces to force checkmate

Automatic Draw Conditions:

  • King vs King
  • King + Bishop vs King
  • King + Knight vs King
  • King + Bishop vs King + Bishop (same color squares)

Not Automatic Draw (checkmate still possible):

  • King + Rook vs King
  • King + Queen vs King
  • King + Pawn vs King
  • King + 2 Knights vs King (very rare, but possible)

Implementation:

function isInsufficientMaterial(board) {
    const pieces = getAllPieces(board);

    // King vs King
    if (pieces.length === 2) return true;

    // King + Minor piece vs King
    if (pieces.length === 3) {
        return pieces.some(p => p.type === 'bishop' || p.type === 'knight');
    }

    // King + Bishop vs King + Bishop (same color)
    if (pieces.length === 4) {
        const bishops = pieces.filter(p => p.type === 'bishop');
        if (bishops.length === 2) {
            return (bishops[0].position.row + bishops[0].position.col) % 2 ===
                   (bishops[1].position.row + bishops[1].position.col) % 2;
        }
    }

    return false;
}

Threefold Repetition

Definition: Same position occurs three times (not necessarily consecutive)

Criteria for "same position":

  • Same pieces on same squares
  • Same player to move
  • Same castling rights
  • Same en passant availability

Claim: Player can claim draw when position repeats third time

Implementation:

function isThreefoldRepetition(gameState) {
    const currentFEN = gameState.toFEN();
    const fenHistory = gameState.moveHistory.map(m => m.fen);

    let count = 0;
    for (const fen of fenHistory) {
        if (fen === currentFEN) {
            count++;
            if (count >= 3) return true;
        }
    }

    return false;
}

Fifty-Move Rule

Definition: 50 consecutive moves by each player with no pawn move or capture

Counter: Reset to 0 when:

  • Any pawn moves
  • Any piece is captured

Claim: Player can claim draw after 50 moves

Implementation:

function isFiftyMoveRule(gameState) {
    return gameState.halfMoveClock >= 100; // 50 moves per player
}

Draw by Agreement

Process:

  1. Player offers draw
  2. Opponent can accept or decline
  3. If accepted, game ends in draw

Notation: ½-½ in PGN


Chess Notation

Algebraic Notation (Standard)

Format: [Piece][From Square][Capture][To Square][Promotion][Check/Checkmate]

Pieces:

  • K = King
  • Q = Queen
  • R = Rook
  • B = Bishop
  • N = Knight
  • (no letter) = Pawn

Examples:

  • e4 - Pawn to e4
  • Nf3 - Knight to f3
  • Bxc6 - Bishop captures on c6
  • Qh5+ - Queen to h5, check
  • e8=Q# - Pawn to e8, promotes to queen, checkmate
  • O-O - Kingside castling
  • O-O-O - Queenside castling
  • Nbd7 - Knight from b-file to d7 (disambiguation)

Disambiguation: When two pieces of same type can move to same square:

  • Add file letter: Nbd7 (knight from b-file)
  • Add rank number: R1e2 (rook from rank 1)
  • Add both if needed: Qh4e1

FEN (Forsyth-Edwards Notation)

Purpose: Represent board position in single string

Format: [Position] [Turn] [Castling] [En Passant] [Halfmove] [Fullmove]

Example:

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

Components:

  1. Position (ranks 8-1, separated by /):

    • Lowercase = black pieces
    • Uppercase = white pieces
    • Numbers = empty squares
    • / = next rank
  2. Turn:

    • w = white to move
    • b = black to move
  3. Castling Rights:

    • K = white kingside
    • Q = white queenside
    • k = black kingside
    • q = black queenside
    • - = no castling available
  4. En Passant:

    • Target square (e.g., e3)
    • - if not available
  5. Halfmove Clock:

    • Moves since last capture/pawn move
  6. Fullmove Number:

    • Increments after black's move

Implementation:

function toFEN(board, gameState, currentTurn) {
    let fen = '';

    // Position
    for (let row = 0; row < 8; row++) {
        let emptyCount = 0;
        for (let col = 0; col < 8; col++) {
            const piece = board.getPiece(row, col);
            if (piece) {
                if (emptyCount > 0) {
                    fen += emptyCount;
                    emptyCount = 0;
                }
                fen += piece.toFENChar();
            } else {
                emptyCount++;
            }
        }
        if (emptyCount > 0) fen += emptyCount;
        if (row < 7) fen += '/';
    }

    // Turn
    fen += ` ${currentTurn[0]}`;

    // Castling
    fen += ` ${gameState.castlingRights || '-'}`;

    // En passant
    fen += ` ${gameState.enPassantTarget || '-'}`;

    // Clocks
    fen += ` ${gameState.halfMoveClock} ${gameState.fullMoveNumber}`;

    return fen;
}

PGN (Portable Game Notation)

Purpose: Record complete game with metadata

Format:

[Event "Casual Game"]
[Site "Online"]
[Date "2025.01.22"]
[Round "1"]
[White "Player 1"]
[Black "Player 2"]
[Result "1-0"]

1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7
6. Re1 b5 7. Bb3 d6 8. c3 O-O 9. h3 Nb8 1-0

Results:

  • 1-0 - White wins
  • 0-1 - Black wins
  • 1/2-1/2 - Draw
  • * - Game in progress

Rule Edge Cases

Illegal Positions

Positions that cannot occur:

  • Both kings in check simultaneously
  • Pawn on rank 1 or 8 (must have promoted)
  • More than 8 pawns of one color
  • More than 16 pieces of one color total
  • Castling when king/rook has moved

Ambiguous Captures

When multiple pieces can capture same square:

Raxe1  // Rook from a-file captures
R1xe1  // Rook from rank 1 captures
Qh4e1  // Queen from h4 captures (needs both)

Pawn Captures and Files

Pawn captures include file letter:

exd5   // Pawn from e-file captures on d5
e4     // Pawn moves to e4 (no capture)

Check and Illegal Moves

Invalid moves:

  • Moving into check
  • Not responding to check
  • Exposing own king to check

All must be prevented in implementation!


Implementation Checklist

Use this checklist to validate your chess implementation:

Basic Movement

  • All pieces move according to rules
  • Pieces cannot move through others (except knight)
  • Pieces cannot capture own color
  • Pawns move forward only
  • Pawns capture diagonally

Special Moves

  • Pawn double-move from start
  • En passant capture
  • En passant expires after one turn
  • Castling kingside
  • Castling queenside
  • Castling prevented by moved pieces
  • Cannot castle through check
  • Cannot castle in/out of check
  • Pawn promotion
  • Pawn promotion piece selection

Check/Checkmate

  • Detect when king is in check
  • Prevent moves that leave king in check
  • Force response to check
  • Detect checkmate
  • Detect stalemate

Draw Conditions

  • Insufficient material
  • Threefold repetition
  • Fifty-move rule
  • Draw by agreement

Notation

  • FEN export
  • FEN import
  • PGN export
  • Algebraic notation for moves
  • Move disambiguation

For implementation details, see IMPLEMENTATION_GUIDE.md

For API reference, see API_REFERENCE.md