Engine
Pure TypeScript, deterministic, no I/O. Emits semantic events (PIECE_PLACED, LINES_CLEARED, LEVEL_COMPLETED, CASHOUT…) that drive the client’s effects.
Developers
Puzzle Crash runs on a server-authoritative HTTP API. The same pure game engine runs on the server (to decide) and in the client (to animate). This page is an overview; the full reference lives in the repository.
Architecture
Pure TypeScript, deterministic, no I/O. Emits semantic events (PIECE_PLACED, LINES_CLEARED, LEVEL_COMPLETED, CASHOUT…) that drive the client’s effects.
Fastify, PostgreSQL and Redis. Each action runs in one transaction under a session lock: validate → apply → ledger → append history.
Sends intents with the expected version and an idempotency key; renders the authoritative state and events it gets back.
Conventions
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/players | Create a demo player with starting demo credits |
| GET | /v1/me | Balance and any pending session notice |
| POST | /v1/sessions | Start a round: debit stake, commit server seed, deal hand 0 |
| GET | /v1/sessions/active | Recover the live round after a reload or crash |
| POST | /v1/sessions/:id/actions | PLACE · CONTINUE · CASHOUT |
| POST | /v1/sessions/:id/heartbeat | Presence: keep the round alive while on screen |
| POST | /v1/sessions/:id/leave | Deliberate exit: starts the 5-minute leave grace |
| GET | /v1/sessions/:id/verification | Revealed seed, dealt hands, replay and hash-chain checks |
| GET | /v1/sessions | Round history |
| GET | /v1/config | Published rules: multiplier tables, cash-out levels, piece probabilities |
Session lifecycle
A round moves between a small set of states. Only the server moves it.
Example
Create a player, start a round and place the first piece:
API=https://puzzlecrash.urbanrats.com
TOKEN=$(curl -s -X POST $API/v1/players | jq -r .token)
S=$(curl -s -X POST $API/v1/sessions \
-H "authorization: Bearer $TOKEN" -H "idempotency-key: start-$(date +%s)" \
-H 'content-type: application/json' -d '{"difficulty":"medium","stake":100}')
ID=$(echo $S | jq -r .session.id)
curl -s -X POST $API/v1/sessions/$ID/actions \
-H "authorization: Bearer $TOKEN" -H "idempotency-key: a1-$(date +%s)" \
-H 'content-type: application/json' \
-d '{"type":"PLACE","slot":0,"x":0,"y":0,"expectedVersion":0}'
Operations