Stack
How it is tested
A simulation you can test without a browser
Because the core has no DOM, no network, no clock and noMath.random(), every rule can be exercised headless in
Node. The PRNG state lives inside GameState, so the same seed gives the same career, every time.
The core test suite plays real games, not just units:
- Determinism: a full week played from seed 42 twice gives identical reports, and seed 43 gives different ones.
- Rules: capacity is never exceeded unless the door is forced, underage guests are stopped by security, permits and inspections have the documented consequences, a night runs 22:00 to 04:00 and ends with everyone gone.
- Long careers: a 60-day career is played day by day and every visible number is checked to be a valid number.
- Saves: save then load gives back exactly the same game, by day and mid-night, and older save formats still load and play on.
A bot that plays thousands of careers
Tuning a management game by hand is guesswork, so a bot plays it. The bot is a sensible, not optimal, player: each day it runs the AI CEO’s preparation, plays the night, and moves to the next day.pnpm balance plays one career per
seed and reports how careers end.
where
Defeats are further split by cause (bankruptcy after 3 days of negative cash, 3 violations, or reputation), and the
report shows the average day each venue level is reached. A second script,
pnpm balance:levels, breaks careers down
per venue level: fights per night, tax as a share of revenue, and profit per night.
A fast version of the bot also runs as a regular test: across 10 seeds it must survive the first 30 days and reach
venue level 2, so a bad change to the tuning fails CI before it reaches players.
Go services under the race detector
Both Go services are tested withgo test -race, after go vet and a gofmt check. The api suite covers the parts
that touch value: JWT verification, reading deposits from the chain, deposits credited exactly once, concurrent caps,
sales held and settled once, reconciliation, migrations on a live database. A test also guarantees the
api’s copy of the game data is identical to the simulation’s JSON. The relay suite covers routing and sender
stamping, join errors, host resume, kick and close, plus adversarial tests that attack it on purpose and must stay green.
Checks on every change
The PR checker is itself tested, so the rules the team writes are the rules CI enforces.
Related: Architecture · Live multiplayer