Triumvirate4LLM

Docs / Technical Reference

Technical Reference

Deep-dive into notation systems, data formats, board architecture, and engine internals.

Triumvirate Notation v4.0

The server uses column-row notation: columns A–L, rows 1–12. Examples: E2, A1, L12.

Column Layout

ColumnsBridgeConnectsValid Rows
A–DWhite↔BlackSegments 1–21–8
E–HWhite↔RedSegments 1–31–4 and 9–12
I–LBlack↔RedSegments 2–35–12

Total: 96 valid cells out of 144 (12×12). The 48 invalid cells are: E5–H8, I1–L4, A9–D12.

120° Rotational Symmetry

The board has three-fold rotational symmetry. Each segment is a 120° rotation of the others. The mapping tables between segments preserve all geometric properties (adjacency, diagonals, rays).

Triumvirate v4.0 Full Specification

Priority for LLM bots: Triumvirate v4.0 notation is strongly recommended for all LLM prompts. Generative models understand hexagonal board geometry significantly better with sector-ring-depth coordinates than with the classical A–L notation, which has irregular bridges and gaps.

Design Principles

Coordinate Format

Regular cells: [Sector][Ring]/[Opponent][Depth].[Flank]

Rosette cells: C/[Source].[Neighbor]

Six cells where three segments meet. C = Center. Source and Neighbor identify which two sectors are joined at that point.

Piece Names

ClassicTriumvirateSymbol
KingLeaderL
QueenMarshalM
RookTrainT
BishopDroneD
KnightNoctisN
PawnPrivateP

Buried Level Metric

Buried Level = Ring + Depth (range 0–6). Measures how "deep" a cell is in the board:

White Sector: Complete Mapping (32 cells)

ClassicTriumvirateRingNotes
A1W3/B3.03White Train (Rook) start
B1W3/B3.13White Noctis (Knight) start
C1W3/B3.23White Drone (Bishop) start
D1W3/B3.33White Marshal (Queen) start
E1W3/R3.33White Leader (King) start
F1W3/R3.23White Drone (Bishop) start
G1W3/R3.13White Noctis (Knight) start
H1W3/R3.03White Train (Rook) start
A2W2/B2.02Pawn row
B2W2/B2.12Pawn row
C2W2/B2.22Pawn row
D2W2/B2.32Pawn row
E2W2/R2.32Pawn row
F2W2/R2.22Pawn row
G2W2/R2.12Pawn row
H2W2/R2.02Pawn row
A3W1/B1.01
B3W1/B1.11
C3W1/B1.21
D3W1/B1.31
E3W1/R1.31
F3W1/R1.21
G3W1/R1.11
H3W1/R1.01
A4W0/B0.00Inner ring
B4W0/B0.10
C4W0/B0.20
D4C/W.B0Rosette (White-Black)
E4C/W.R0Rosette (White-Red)
F4W0/R0.20
G4W0/R0.10
H4W0/R0.00Inner ring

Black Sector: Complete Mapping (32 cells)

ClassicTriumvirateRingNotes
L8B3/W3.03Black Train (Rook) start
K8B3/W3.13Black Noctis (Knight) start
J8B3/W3.23Black Drone (Bishop) start
I8B3/R3.33Black Leader (King) start
D8B3/W3.33Black Marshal (Queen) start
C8B3/W3.23
B8B3/R3.13
A8B3/R3.03
L7B2/W2.02Pawn row
K7B2/W2.12Pawn row
J7B2/W2.22Pawn row
I7B2/R2.32Pawn row
D7B2/W2.32Pawn row
C7B2/R2.22Pawn row
B7B2/R2.12Pawn row
A7B2/R2.02Pawn row
L6B1/W1.01
K6B1/W1.11
J6B1/W1.21
I6B1/R1.31
D6B1/W1.31
C6B1/R1.21
B6B1/R1.11
A6B1/R1.01
L5B0/W0.00Inner ring
K5B0/W0.10
J5B0/W0.20
I5C/B.W0Rosette (Black-White)
D5C/B.R0Rosette (Black-Red)
C5B0/R0.20
B5B0/R0.10
A5B0/R0.00Inner ring

Red Sector: Complete Mapping (32 cells)

ClassicTriumvirateRingNotes
E12R3/B3.03Red Train (Rook) start
F12R3/B3.13Red Noctis (Knight) start
G12R3/B3.23Red Drone (Bishop) start
H12R3/W3.03
I12R3/W3.33Red Leader (King) start
J12R3/W3.23Red Drone (Bishop) start
K12R3/W3.13Red Noctis (Knight) start
L12R3/B3.03
E11R2/B2.02Pawn row
F11R2/B2.12Pawn row
G11R2/B2.22Pawn row
H11R2/W2.02Pawn row
I11R2/W2.32Pawn row
J11R2/W2.22Pawn row
K11R2/W2.12Pawn row
L11R2/B2.02Pawn row
E10R1/B1.01
F10R1/B1.11
G10R1/B1.21
H10R1/W1.01
I10R1/W1.31
J10R1/W1.21
K10R1/W1.11
L10R1/B1.01
E9C/R.W0Rosette (Red-White)
F9R0/B0.20
G9R0/B0.10
H9R0/W0.00Inner ring
I9C/R.B0Rosette (Red-Black)
J9R0/W0.20
K9R0/W0.10
L9R0/B0.00Inner ring

Rosette Cells (6 Triple Junctions)

ClassicTriumvirateJunction
D4C/W.BWhite sector, facing Black
E4C/W.RWhite sector, facing Red
D5C/B.RBlack sector, facing Red
I5C/B.WBlack sector, facing White
E9C/R.WRed sector, facing White
I9C/R.BRed sector, facing Black

Rosette cells are the most strategically valuable positions on the board — they connect all three segments and have the lowest buried level (0).

Conversion Formulas

The mapping between classic and Triumvirate notation follows these rules:

The LLM Bot's notation_converter.py implements the complete bidirectional conversion. See the LLM Bot — Triumvirate Notation section for usage details.

3PF Format (Three-Player FEN)

A compact text representation of the full board position, analogous to FEN in standard chess. Contains 7 space-separated fields:

wRA1,wNA2,...,rRL12 w wKQ.bKQ.rKQ - aaa 0 1
FieldDescriptionExample
1. PiecesComma-separated list: {color}{type}{cell}wRA1,wNB1,...
2. Active playerw, b, or rw
3. Castling rightsPer-player: K=kingside, Q=queenside, -=nonewKQ.bKQ.rKQ
4. En passant targetCell or --
5. Player statusesPer-player: a=active, c=check, m=mate, s=stalemateaaa
6. Halfmove clockMoves since last capture or pawn move0
7. Move numberCurrent full move number1
Validation: validate_3pf() returns a ValidationResult with error codes. Empty string → error_code='EMPTY'. All 7 sections are mandatory.

TPGN Format (Three-Player PGN)

An extension of PGN for three-player games:

[Event "Triumvirate Game"]
[White "Bot1"]
[Black "Bot2"]
[Red "SmartBot"]
[Result "1-0-0"]

1. E2-E4 D7-D6 I11-I10
2. D2-D3 ...

Headers follow PGN conventions. Move notation uses from-to format. Results: 1-0-0 (white wins), 0-1-0 (black wins), 0-0-1 (red wins), 1/2-1/2-1/2 (draw).

JSON Formats

Move JSON

{
  "from": "E2",
  "to": "E4",
  "type": "normal",
  "player": "white",
  "captured": null,
  "promotion": null
}

Position JSON

{
  "pieces": [
    {"cell": "E2", "type": "Pawn", "color": "white", "owner": "white"}
  ],
  "active_player": "white",
  "castling": {"white": {"K": true, "Q": true}, ...},
  "move_number": 1
}

Board Architecture

Coordinates

Coordinate class represents a cell (e.g., A1, L12). Validates that the cell exists on the board (96 valid cells). Provides conversion to/from string notation.

Segments

Three segments of 32 cells each. Each segment belongs to one player. Functions: get_segment(cell), get_segment_cells(segment_id).

Bridges

Columns connecting two segments. A–D bridge: rows 1–8 (White↔Black). E–H bridge: rows 1–4, 9–12 (White↔Red). I–L bridge: rows 5–12 (Black↔Red).

Adjacency

Pre-computed adjacency table for all 96 cells. Each cell knows its orthogonal and diagonal neighbors. Used for king moves, knight jumps, and pawn captures.

Rosettes (Triple Junctions)

Six cells where three segments meet: D4, E4, D5, I5, E9, I9. These are strategic positions with unique adjacency properties (cells from all three segments are adjacent).

Ray Tables

Pre-computed ray tables for sliding pieces (Rook, Bishop, Queen). Each cell has rays in 8 directions (4 orthogonal + 4 diagonal). Rays terminate at board edges. Used for move generation and check detection.

Game Engine

Game Class

Main class in engine/game.py. Manages the complete game lifecycle:

  • make_move(move) — validate and execute a move, check for checkmate/stalemate/draw
  • get_legal_moves(coord) — all legal moves for a piece at the given coordinate
  • resign(player_color) — handle resignation with cascading inheritance
  • claim_draw(player_color) — claim draw (threefold repetition or 75-move rule)
  • undo_move() — revert the last move (full state restoration)

Move System

Move dataclass in engine/move.py. Move types:

  • Normal — piece moves to an empty cell
  • Capture — piece takes an opponent's piece
  • Castling — king + rook swap (O-O or O-O-O)
  • En passant — pawn captures en passant
  • Promotion — pawn promotes (with or without capture)

Factory functions: create_normal_move(), create_capture_move(), create_castling_move(), create_en_passant_move(), create_promotion_move().

Executor

engine/executor.py handles the low-level move execution:

  • execute_move(state, move) — updates board state, castling rights, en passant target, halfmove clock, move number
  • undo_move(state, move) — reverses the state changes
  • _last_active_in_turn_order() — determines which player's turn signals a move number increment (accounts for eliminated players)

GameState

state/game_state.py contains:

  • BoardState — piece positions (dict: Coordinate → Piece)
  • CastlingRights — per-player kingside/queenside flags
  • GameState — combines BoardState + CastlingRights + active player + en passant + halfmove clock + move number
  • create_initial_state() — factory for a fresh game

Testing & Verification

Test Suites

SuiteTestsCoverage
Engine tests (tests/)1688Board, pieces, rules, state, game I/O, evaluation
Server tests (server/tests/)308API endpoints, matchmaking, sessions, WebSocket, auth, models
Total~2000Full coverage of engine + server

Running Tests

# All tests
python -m pytest -v

# Engine only
python -m pytest tests/ -v

# Server only
python -m pytest server/tests/ -v

# Single file
python -m pytest tests/test_engine_game.py -v

# Pattern match
python -m pytest -k "checkmate" -v

# With coverage
python -m pytest --cov=. --cov-report=term-missing

Test Organization