feat: auto cash-out targets, 1% house edge, terminal aesthetic

Auto cash-out closes a position at exactly the chosen target rather than
the next tick's multiplier, and fires whenever the target is at or below
the crash point. This is the feature that makes the game playable over a
network, where manual timing is at the mercy of latency.

House edge drops from 2% to 1% across crash and scratch. Scratch prize
tables retuned so the published 99% RTP is exact.

Adds docs/API.md: the client uses no private endpoints, so anyone can
write a bot against the same API.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
drjones
2026-08-05 16:24:31 +00:00
parent dee3becd47
commit 48a9120fe4
14 changed files with 997 additions and 266 deletions

View File

@@ -7,10 +7,18 @@ outcomes any player can verify on their own phone.
## What it is
Three shared crash games — a rocket fighting gravity, a decaying orbit, and a
stacking tower — running on a five-minute heartbeat, plus instant scratch
tickets to play between rounds. Identity is a keypair your browser generates;
stacking tower — plus instant scratch tickets to play between rounds. Set an
auto cash-out target before the round and it closes at exactly your number, or
ride it and tap out by hand. Identity is a keypair your browser generates;
there is no account, no email, and no password.
The house edge is **1%** on everything. That is better than essentially
anything commercial, and it is deliberate: this is a game among friends, not a
revenue stream.
Everything is API-first — the browser client uses the same endpoints anyone
else can. Write a bot in twenty lines; see [docs/API.md](docs/API.md).
Everything runs on one machine: one Go binary with the client embedded,
PostgreSQL, and Redis.
@@ -77,7 +85,7 @@ One binary, with enforced internal boundaries:
| `pkg/ledger` | Append-only double-entry accounting |
| `pkg/scratch` | Scratch tickets and their published odds |
| `pkg/identity` | Keypair sign-in via signed challenge |
| `pkg/room` | Round lifecycle and live broadcast |
| `pkg/room` | Round lifecycle, auto cash-out, live broadcast |
Nine services on one machine would buy latency and 3am debugging, so this is
one process. Modules talk through interfaces only; extracting one into its own
@@ -101,6 +109,20 @@ The multiplier follows `m(t) = 1/(1 - t/T)²`, which diverges at exactly 60
seconds. No round can run longer, however extreme the crash point, and the
climb visibly accelerates as it goes — which is where the tension comes from.
## Testing
```bash
make test # unit and integration
make test-race # under the race detector
make cover # coverage per package
make db-reset # wipe the ledger; it is append-only and accumulates
```
Coverage sits around 85%, and the tests found and pinned three real money
bugs: a posting set that minted 18 quintillion millisatoshis by wrapping the
zero-sum check, a crash point that overflowed negative at the rarest seed, and
scratch tables that advertised 98% while paying 56%.
## Status
Built and tested:
@@ -109,7 +131,9 @@ Built and tested:
- three crash games with live multiplayer rounds
- two scratch tickets with verified-honest odds
- keypair identity, peer-to-peer transfers, transaction history
- auto cash-out targets that pay your exact number
- in-browser verifier
- a documented public API, good enough to write bots against
Not yet built: