A retro-styled browser trading game inspired by the Drug Wars gameplay loop.
Players move between real U.S. city markets, buy/sell illegal cat breeds, manage heat risk, and survive escalating debt pressure.
- Runtime: Val Town HTTP Val (
main.ts) - Web framework:
Hono - Persistence: Val-scoped SQLite via
https://esm.town/v/std/sqlite/main.ts - Binary/media: Val Town
blob(avatar path still supports blob keys, UI uses pixel presets) - Frontend: server-rendered HTML + vanilla JS
main.ts: HTTP routes, DB bootstrap/migrations, rendering, and game actionsauth.ts: session cookie parsing, session token lifecycle, authenticated user lookupconfig.ts: static game config (markets, breeds, pixel avatar metadata)rules.ts: pure game logic helpers (borrow terms and heat streak cap)rules_test.ts: script-based regression tests forrules.ts
- Register or log in.
- Check market prices for each breed.
- Buy cats where prices are low.
- Travel to another city (travel advances day and raises heat).
- Sell for profit.
- Manage debt before deadline.
- Debt has a due day (
debt_due_day). - Borrowing:
- increases cash and debt
- applies escalating fee by borrow tier (capped)
- extends due window, capped to at most 90 days ahead
- Missing debt deadline while debt > 0 triggers bankruptcy:
- inventory wiped
- run reset to baseline state
- Travel increases heat and can trigger a DHS bust event.
- Bust events may seize inventory and fine cash.
- Heat cannot stay at 100% for more than 2 consecutive turns; on the 3rd turn it is forced down to 95%.
Account identity and avatar key.
Cookie-token sessions with expiry.
Current market, cash, debt, heat, day, cargo, debt due day, borrow tier, and heat max streak.
City list and enforcement risk profile.
Base economy metadata for each cat breed.
Owned quantity per breed per user.
Daily per-market generated prices per user.
Tracks one-way migration IDs that have been applied.
POST /api/registerPOST /api/loginPOST /api/logoutGET /api/me
POST /api/buyPOST /api/sellPOST /api/travelPOST /api/borrowPOST /api/pay-debt
POST /api/avatar/presetGET /api/pixel-avatar/:avatarIdGET /api/avatar/:userId
initDb() creates base tables and then runs idempotent tracked migrations:
2026-03-02-add-player_state-debt_due_day2026-03-02-add-player_state-borrow_count2026-03-02-add-player_state-heat_max_streak2026-03-02-backfill-debt_due_day
Applied migrations are recorded in schema_migrations.
Run the script file directly in Val Town:
rules_test.ts
It validates:
- borrow fee escalation and cap behavior
- debt-ceiling clamping
- due-date 90-day cap
- heat 100% streak cooldown behavior
- Val is public:
pchinjr/cat-wars - Auth/session logic extracted into
auth.ts - Static game config extracted into
config.ts - Core deterministic rules extracted into
rules.ts - Regression coverage added for extracted rules via
rules_test.ts
- Add tests for route-level behaviors (
/api/travel,/api/borrow, bankruptcy reset). - Introduce a tiny data-access layer to remove inline SQL from route handlers.
- Add structured event logging for travel, bust, borrow, and bankruptcy actions.
- Add multiplayer-ready turn clock abstraction for synchronized city market ticks.
