No description
- TypeScript 76.8%
- Svelte 18%
- JavaScript 4.1%
- CSS 1%
Split the monolithic src/web/server.ts (~870 lines) into: - src/web/api.ts — session store, DTOs, round resolver, interactive bots - src/web/handlers.ts — pure handler logic (new-game, resolve, decide, etc.) The Vite dev server on :5175 is now the sole HTTP entry point: - client/vite.config.ts replaces client/vite.config.js (port 5173→5175) - client/vite-api-plugin.ts wires /api/* in-process — no proxy needed Removed: - src/web/server.ts (standalone Bun server on :3000) - src/web/public/index.html (vanilla HTML — Svelte client supersedes) - scripts/web-server.sh + systemd unit (server process management) - 7 npm scripts (web, web:dev, web:start, ...) Tests: tests/web.test.ts covers session management, handlers, and round resolution (68 tests, typecheck clean, smoke sims green). |
||
|---|---|---|
| client | ||
| docs | ||
| scratch | ||
| src | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| bun.lock | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
Princess Tower Simulator
Headless TypeScript simulation harness for the Princess Tower prototype.
This repo is intentionally not a playable client yet. Its purpose is to stress-test the rules design with bots, seeded simulations, batch sweeps, and HTML reports before production game work begins.
Docs
docs/princess_tower_draft.md— original design draft.docs/princess_tower_rules_questionnaire.md— answered simulator/rules ambiguity questionnaire.
Quick Start
bun install
bun run done
bun run sim -- --games 200 --bot0 balanced --bot1 balanced --suit0 Spades --suit1 Hearts
Outputs:
reports/latest.htmlreports/latest.json
Useful Commands
# Full verification before handing work back
bun run done
# One matchup
bun run sim -- --games 1000 --suit0 Spades --suit1 Diamonds --bot0 balanced --bot1 balanced
# Perfect-information bot context flag
bun run sim -- --games 1000 --visibility perfect
# Sweep all suit matchups across mortar costs 2/3/4
bun run sweep -- --games 100 --mortar-costs 2,3,4
# Default battle reward is fixed Gain 1 Mortar; legacy/experimental reward pools remain available
bun run sim -- --reward-mode draw_1
bun run sim -- --reward-mode economy
# No rewards, useful for isolating tower pace
bun run sim -- --reward-mode none
# Compare legacy/experimental Diamond variants
# per-card-only keeps only +1 battle power per Diamond battle card: no tie-break, no momentum.
bun run sweep -- --games 100 --diamond-mode formation
bun run sweep -- --games 100 --diamond-mode per-card
bun run sweep -- --games 100 --diamond-mode per-card-only
# Physical-deck experiment: tokenized card-mortar
bun run sim -- --games 1000 --mortar-mode discard-token
# Typecheck and tests only
bun run check
Bots
Current bots:
random— random legal-ish actions and random optional effects.build-first— prioritizes construction and uses battle conservatively.battle-greedy— commits strong battle formations aggressively.balanced— heuristic bot that weighs reward value, construction needs, mortar, and suit texture.
Implemented v0 Rules
The engine implements:
- 20-card suit decks, ranks 1-10 ×2. Hearts adds 2 jokers as wild cards.
- Simultaneous card commitment.
- Construction yards: up to one hand card enters the yard each round.
- Each construction phase can convert up to one yard card to mortar and create up to one floor total.
- Mortar wild floors, including same-phase yard-to-mortar then mortar-spend lines.
- Card-made mortar stores the card by default;
--mortar-mode discard-tokendiscards that card and creates token mortar so ranks can churn back through the deck. - Overtime tiebreaker floors beyond 10, constructed only from mortar.
- All listed rank effects.
- All four suit powers, with Hearts using 2 jokers and the default
maskflow: a battle joker surveils the top deck card, may discard it, then copies a rank from discard. During battle cleanup, Hearts may exile that joker to draw the copied mask card; otherwise the joker and mask card go to discard. Spades gains 1 mortar token after winning a battle. Diamonds uses the default momentum banner variant;--diamond-mode per-card-onlytests a lean variant where Diamonds only gets +1 battle power per committed battle card, with no tie-break or momentum. - Default battle reward is fixed Gain 1 Mortar. Legacy/experimental reward modes remain available by CLI flag.
- 100-round cap by default.
- Hidden/perfect bot visibility flag.
Notable v0 Interpretation
For the high-impact reward "Turn 1 enemy completed floor into mortar", the simulator removes the chosen floor and, in default stored-card mortar mode, the floor's card itself becomes mortar in that floor owner's mortar pile. If the chosen floor was already a mortar-built wild/extra floor, it becomes token mortar instead. In discard-token mortar mode, card-built floors discard their card and create token mortar instead.