Architecture
- Python 3.11+ with Hatchling build system
- Typer for CLI commands
- Rich for terminal rendering
- Textual for TUI interface (optional)
- fpdf2 for Print-and-Play PDF generation (optional)
- Engine-first design: plain dataclasses, no ORM
Module structure
Section titled “Module structure”src/portlight/ engine/ — economy, voyage, contracts, reputation, infrastructure, campaign, combat (personal + naval), companions, seasons, bounty, fleet, skills, weapon quality, injuries, narrative content/ — ports (20), goods (18), ships (5), routes (43), contracts (24 templates), factions (4), companions (10), melee weapons (8), ranged weapons (8), fighting styles (5), ship upgrades (18), armor, seasons, cultures, port institutions (134 NPCs) app/ — Typer CLI (50+ commands), Rich views, TUI screens, session manager, captain selection balance/ — balance harness: 7 policy bots, 7 scenarios, reporting stress/ — stress testing: 14 invariants, 9 compound scenarios receipts/ — trade receipt schema and hashing printandplay/ — board game PDF generator (cards, board, rules)Data flow
Section titled “Data flow”Every command goes through the GameSession, which mediates between the CLI and engine state:
- CLI command calls session method
- Session delegates to engine functions
- Engine mutates dataclass state
- Session auto-saves after every mutation
Session advance tick order
Section titled “Session advance tick order”Each day advances through a fixed sequence:
- Reputation tick — heat decay, standing adjustments
- Contract tick — expiry, stale offers, board refresh
- Infrastructure upkeep — warehouse, broker, license deductions
- Credit tick — interest accrual, due dates, defaults
- Market shift — restock, regional shocks, seasonal demand
- Voyage events — storms, pirates, inspections, cultural encounters
- Companion tick — morale shifts, departure triggers
- Campaign evaluation — milestone checks, profile tag scoring
- Auto-save
Save format
Section titled “Save format”JSON on the local filesystem. Save version 12 with full migration chain (v1-v12).
Compound state tuple:
(WorldState, ReceiptLedger, ContractBoard, InfrastructureState, CampaignState)
Testing
Section titled “Testing”- 1,836 tests across 72+ files
- Balance harness — 7 policy bots, 7 scenario packs, deterministic seeds
- Stress testing — 14 cross-system invariants, 9 compound scenarios
- Invariant enforcement — checked after every tick in stress runs
- Print-and-Play tests — content sourcing validation, PDF output verification
- CI: Python 3.11 + 3.12 + 3.13 matrix, ruff lint, paths-gated triggers