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