Vortex Chess Library: Complete Architecture & API Overview
Vortex Chess is a robust, lightweight JavaScript chess rules library designed to handle complex move generation, legality checking, serialization, and game state management. What sets it apart is its native support for both standard 2-player chess and the complex 4-player chess variant.
Below is a detailed breakdown of its internal structure, core mechanics, and public API.
1. Project Structure
The codebase is organized into distinct domains separating the core engine from state management and user-facing APIs.
4chess/
├── index.js [ Main entry point ]
├── package.json [ ES module, v1.0.0 ]
├── README.md [ API documentation ]
├── chess-engine/ [ Core Implementation ]
│ ├── index.js
│ ├── api/ [ User-Facing API ]
│ │ ├── chess.js # Main Chess class
│ │ ├── errors.js # InvalidMove/FEN errors
│ │ ├── pgn.js # PGN export/import
│ │ └── san.js # SAN notation converter
│ ├── core/ [ Engine Core ]
│ │ ├── variants.js # STANDARD & FOUR_PLAYER configs
│ │ ├── board.js # Board & piece storage
│ │ ├── moveGen.js # Pseudo-legal move gen
│ │ ├── legality.js # Legal move filtering
│ │ ├── makeMove.js # Execution & Undo
│ │ ├── attackMap.js # Square attack detection
│ │ └── zobrist.js # Position hashing
│ ├── io/ [ Serialization ]
│ │ └── fen.js # FEN import/export
│ └── state/ [ State Management ]
│ └── gameState.js # Turn, castling, clocks
├── test/ [ Test Suite ]
│ └── verify.js # Verification tests
└── bench/ [ Benchmarks ]
└── perft.js # Nodes-per-second test
2. Architecture Overview
The library utilizes a strict three-layer architectural design, ensuring that IO parsing doesn’t interfere with core board math, and state is completely separated from move generation.
2.1 The Three-Layer Design
+---------------------------------------------------------+
| API LAYER |
| Validates user input, converts notations (SAN/PGN) |
| [ chess.js ] [ pgn.js ] [ san.js ] |
+---------------------------------------------------------+
|
(Parsed Moves / FEN) | (Sanitized State Data)
V
+---------------------------------------------------------+
| CORE ENGINE |
| Mathematical grid, pseudo/legal move gen, execution |
| [ board.js ] [ moveGen.js ] [ legality.js ] |
+---------------------------------------------------------+
|
(Board State Updates) | (Hash / State Checks)
V
+---------------------------------------------------------+
| STATE & I/O |
| Turn tracking, castling rights, Zobrist hashing |
| [ gameState.js ] [ zobrist.js ] [ fen.js ] |
+---------------------------------------------------------+
2.2 Key Classes
- Chess: The main game controller (
api/chess.js). - Board: Handles piece storage and coordinate math (
core/board.js). - GameState: Tracks turns, castling rights, clocks, and player status (
state/gameState.js). - MoveList: Handles packed move integer storage (
core/moveGen.js).
3. Supported Variants
3.1 Standard Chess (standard@v1)
- Board: 8×8 grid
- Players: 2 (White=0, Black=1)
- FEN: Standard formatting
- Castling: Standard
KQkqnotation
3.2 Four-Player Chess (4player@v1)
The 4-player variant features a massive 14x14 grid with 3x3 dead zones in the corners to create a cross-like battlefield.
a b c d e f g h i j k l m n
+------------------------------------------+
14 |/////////| RED (Up) |/////////| 14
13 |/////////| [R][N][B][K][Q][B][N][R]///////| 13
12 |///DEAD//| [P][P][P][P][P][P][P][P]/DEAD//| 12
11 +---------+ +-----+ 11
10 | [P] [P] | 10
9 |G [P] [P] B| 9
8 |R [P] CENTER [P] L| 8
7 |E [P] BATTLEFIELD [P] U| 7
6 |E [P] [P] E| 6
5 |N [P] [P] | 5
4 +---------+ +-----+ 4
3 |///DEAD//| [P][P][P][P][P][P][P][P]/DEAD//| 3
2 |/////////| [R][N][B][Q][K][B][N][R]///////| 2
1 |/////////| YELLOW (Down) |/////////| 1
+------------------------------------------+
a b c d e f g h i j k l m n
- Pawn Directions: Up (Red), Right (Blue), Down (Yellow), Left (Green).
- FEN: Uses an 8-character castling field (e.g.,
KQKQKQKQor_). - Player Labels: R (Red), B (Blue), Y (Yellow), G (Green).
4. Core Mechanics
4.1 32-Bit Move Encoding
To achieve high performance, moves are packed into a single 32-bit integer (Int32). This reduces garbage collection overhead and memory footprints during deep tree searches (like in Perft tests).
Bit: 31 20 19 16 15 8 7 0
+----------------------------+----------+-----------+-----------+
| Unused / Padding | Flags | To Square |From Square|
| (12 bits) | (4 bits) | (8 bits) | (8 bits) |
+----------------------------+----------+-----------+-----------+
Promo piece (Bits 20-22) ^
Flag Definitions:
- 0: QUIET (Normal move)
- 1: DOUBLE_PUSH
- 2: CASTLE_K / 3: CASTLE_Q
- 4: CAPTURE / 5: EP_CAPTURE
- 8: PROMO / 12: PROMO_CAPTURE
4.2 Move Generation Pipeline
- Pseudo-legal generation:
generateMoves()evaluates board math to find all theoretical piece movements. - Legality filtering:
getLegalMoves()runs check-validation to filter out moves that leave/put the friendly king in check. - Make/Undo:
makeMove()andunmakeMove()mutate the board and state array with full reversibility.
4.3 4-Player Elimination Mechanics
Vortex natively supports the complex elimination rules of 4-way chess:
- King Capture: Capturing a king instantly eliminates that player.
- Checkmate Elimination: Players with no legal moves who are in check are eliminated.
- Stalemate: Players with no legal moves (but not in check) are eliminated (no stalemate draws in 4P).
- Piece Poofing: When a player is eliminated, all of their remaining pieces are immediately removed (“poofed”) from the board.
// Internal Execution Flow (chess.js)
if (board.variant.numPlayers > 2) {
if (undo.captured !== Pieces.EMPTY && getType(undo.captured) === Pieces.KING) {
const capturedColor = getColor(undo.captured);
this._state.eliminatePlayer(capturedColor);
const poofed = poofPieces(this._board, capturedColor);
undo.eliminatedAtOnce.push(...poofed);
}
this._processCheckmateEliminations(undo);
}
5. Public API Highlights
5.1 Basic Usage
import { Chess } from 'vortex-chess';
// Standard chess
const game = new Chess();
game.move('e4');
game.move('e5');
// 4-player chess setup
const fourPlayer = new Chess({ variant: '4player' });
fourPlayer.move('e4'); // Red moves
fourPlayer.move('c7'); // Blue moves
5.2 Move Input / Output
| Input Format | Example |
|---|---|
| SAN string | game.move('Nf3') |
| Coordinate Obj | game.move({ from: 'e2', to: 'e4' }) |
| With Promotion | game.move({ from: 'a7', to: 'a8', promotion: 'q' }) |
Returned Move Object:
{
"from": "e2",
"to": "e4",
"piece": "p",
"captured": undefined,
"promotion": undefined,
"flags": "n",
"san": "e4",
"color": "w"
}
5.3 Serialization
- FEN Management:
game.fen()(Export),game.load(fen)(Import). - JSON: Full deterministic state roundtrip via
game.toJSON(). - PGN Output: Supports multi-player formatting:
game.pgn({ format: '4player' }).
6. Advanced Engine Exports
For developers wanting to build UI components or AI bots without the overhead of the main controller:
export { Board, Pieces } from './core/board.js';
export { GameState } from './state/gameState.js';
export { getLegalMoves, isMoveLegal, findKing, inCheck } from './core/legality.js';
export { makeMove, unmakeMove } from './core/makeMove.js';
export { computeHash } from './core/zobrist.js';
export { exportFEN, parseFEN } from './io/fen.js';
export { moveToSAN, sanToMove } from './api/san.js';
7. Key Technical Details
- Zobrist Hashing: Uses 64-bit hashes with seeded RNG for twofold/threefold repetition detection.
- Precomputed Target Caching: Knight and king move tables are statically cached to remove boundary offset calculations in tight loops.
- Directional Attack Maps: Backward ray-tracing detection with wrap-guards for non-standard board geometries.