games: a blackjack table you can actually sit down at

The engine, the escrow and the wire were all in place; nothing had a browser on
the end of it. This is that end: a lobby, a table, and the five endpoints between
them.

The browser holds no game. It sends intents and gets back a view — the cards it
is entitled to see, and the script of how they arrived, one event per card off
the shoe. The dealer's hole card is not in the payload at all until the reveal,
because a field the client is told to ignore is a field somebody reads in
devtools. The shoe lives in game_live_hands, which also means a redeploy
mid-hand no longer costs a player their stake: the hand is still there when they
come back.

The money is ordered so nothing can be spent twice. The stake leaves the stack in
the same statement that checks it exists, before a card is dealt. Every new hand
is seated with a plain INSERT, so a double-clicked Deal is decided by the primary
key rather than by a read that raced — it loses, gets its chips back, and the
hand in progress is untouched. A double takes its raise up front and hands it
straight back if the engine refuses the move.

Cards are dealt rather than swapped in — they fly out of the shoe and turn over,
which was a requirement and not a flourish. The faces and the chips are still
plain; that's next.
This commit is contained in:
prosolis
2026-07-13 23:20:42 -07:00
parent cb84e1d549
commit c69fbb63db
17 changed files with 1949 additions and 18 deletions

View File

@@ -102,6 +102,16 @@ label = "Amy (US, female)"
id = "en_US-ryan-high"
label = "Ryan (US, male, HQ)"
# The casino (games.parodia.dev). Signed-in only — there is real money in it — so
# it needs [web.auth] above, and web.auth.cookie_domain if the games host is a
# different subdomain from the news one. Chips are 1:1 with gogobee euros and
# cross the border through the escrow endpoints, which gogobee polls; matrix_server
# is how a player is named to that ledger (@<authentik username>:<matrix_server>).
[web.games]
enabled = false
host = "games.parodia.dev"
matrix_server = "parodia.dev"
# Every enabled source MUST set direct_route to a key from [matrix.channels] above.
# There is no automatic classification — Pete posts each story to its configured channel.
# Optional: language = "en" drops feed items whose per-item <language> tag is