Rah6 — Roll a Hard 6
A Balatro-leaning co-op craps game with 1:1 real-casino bet fidelity.
Welcome to the living documentation for Rah6. The dice and bet menu at the table are real-casino faithful — odds, payouts, and working/off behavior all match a real table. A Balatro-style chip/joker layer sits on top: shooter chips bend dice physics, bettor chips multiply payouts. Runs play through rising “blinds”; between blinds you shop for chips, level rare bets, and recruit shooters.
The canonical source of truth is
docs/design.mdin the repository. This site is the navigable mirror of that design plus developer onboarding.
Quick Links
Game Design
- Design Overview — vision, pillars, the purist test
- Bet Catalog — the full v1 casino bet set at real-casino payouts
- Chip Dispatch Contract — how chips sit on top without breaking the math
- Roguelike Layer (A2) — runs, antes, shop, bet leveling
Developer Guide
- Getting Started — run + test the three workspaces
- Architecture — the engine → server → client flow + engine purity
- Extension Surface — where to add a bet, chip, or action
- Persistence & Replay — save-on-action and replay-from-initial-state
Internal
- Decisions Log — the dated record of every load-bearing decision
- GitHub Repository
The Two Load-Bearing Rules
Everything in Rah6 hangs off two non-negotiable invariants:
- The purist test. Strip every chip and the table must play as a faithful real-money craps game. No exceptions. This is enforced mechanically by the chip dispatch contract, not by convention.
- Engine purity. The engine is a pure reducer over JSON-serializable state, deterministic from a seed — no I/O, no clocks, no
Math.random. This is what makes online co-op, save/resume, replay, and deterministic tests all the same problem, solved once.
Stack
| Layer | Tech | Responsibility |
|---|---|---|
engine/ | Pure TypeScript | Reducer + bet catalog + chip registry. No I/O. |
server/ | Express + ws + Postgres | The only thing that runs the reducer. Persists + broadcasts. |
client/ | React + Vite | Renders state, sends actions over HTTP + WS. |
Default port: 6336 (“hard six: 3+3 = 6, 6”). Postgres is optional — the server boots in memory-only mode if DATABASE_URL is unset.
This documentation is kept in sync with the implementation. When a decision changes, update docs/design.md first, then mirror it here.