From d9f1fe513e6f7696809d3a9b4d44ca485fe99c97 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 17:18:34 +0100 Subject: v2.1.0: add European roulette with split bets and wheel animation --- docs/GAMES.md | 63 +++++++++++++++++++++++++++++++++++++++------------------ docs/TESTING.md | 14 +++++++++++++ 2 files changed, 57 insertions(+), 20 deletions(-) (limited to 'docs') diff --git a/docs/GAMES.md b/docs/GAMES.md index cbe355e..52ab1bf 100644 --- a/docs/GAMES.md +++ b/docs/GAMES.md @@ -5,18 +5,40 @@ | Game | Status | Notes | | --- | --- | --- | | Slots | Done | 5 reels x 3 rows, 5 paylines, 98.6% RTP | +| Roulette | Done | European wheel, split bets, 97.3% RTP | ## Planned | Game | Shape | Main open decisions | | --- | --- | --- | -| Roulette | One spin, many bets | European/French/American wheel; which bet types; 35:1 straight and other payouts | | Blackjack | Multi-step hand | Dealer hits/stands soft 17; double/split/insurance; blackjack payout; shoe persistence | | Crash | Real-time round | Crash-point distribution; cashout latency; provable fairness | -Roulette fits the current one-request-settle model most easily. Blackjack needs -server-side hand state and player actions. Crash needs a timed round loop and a -cashout action, so it should come last unless we redesign the loop first. +Blackjack needs server-side hand state and player actions. Crash needs a timed +round loop and a cashout action, so it should come after blackjack unless we +redesign the loop first. + +## Roulette + +- European wheel: 0-36, one green zero. +- Bets: red, black, even, odd, and straight numbers. +- Bets can be split across all of those; every winning bet is added together. +- Straight pays 35:1 (36x returned), outside bets pay 1:1 (2x returned). +- 0 loses all outside bets. RTP is 36/37 = 97.30%. + +Client controls inside roulette: + +``` +R / B / E / O add the current chip to red/black/even/odd +digits + Enter add the current chip to that number +C clear all bets ++ or = / - change the chip size +SPACE spin +Q leave the table +``` + +The result is shown as a CS:GO-style horizontal strip: the ball marker stays +fixed and the wheel numbers scroll beneath it, ending on the winning number. ## Audit schema @@ -35,35 +57,36 @@ plays ( ) ``` -`game_type` is the game that was played. `details` is a JSON object whose shape -depends on the game: +`details` is game-specific JSON: ```json // slots {"reels":"CCCCLLCLODGSDGS","win_type":"win","win_lines":"1","win_cells":"0,3,6"} -// rumoured future examples -{"player":["AS","10H"],"dealer":["9D","7C"],"outcome":"blackjack"} -{"bets":[{"kind":"straight","number":17,"amount":10}],"winning":17} -{"crash_point":2.41,"cashout":1.80} +// roulette +{"number":"17","color":"black","bets":"{\"red\":10,\"black\":10,\"even\":10,\"odd\":10,\"numbers\":[{\"number\":17,\"amount\":5}]}"} ``` -The balance updates and the `plays` insert happen in one transaction -(`database::apply_play`). The slots-specific wire fields (`reels`, `win_lines`, -`win_cells`) are still in `GAME_RESULT`, but the database no longer assumes -them. +The balance update and the `plays` insert happen in one transaction +(`database::apply_play`). -## Protocol gap +## Wire protocol -The current exchange is slots-shaped: +Slots keeps its original exchange: ``` -PLAY_START +PLAY_START slots GAME_RESULT ``` -Before blackjack, roulette, or crash can be added, the game session needs a -generic state/action protocol. A possible shape: +Roulette adds a compact bets payload and a roulette-specific result: + +``` +PLAY_START roulette +ROULETTE_RESULT +``` + +Blackjack and crash still need a generic state/action exchange, for example: ``` GAME_START @@ -71,4 +94,4 @@ GAME_ACTION [json] GAME_STATE # cards, bets, multiplier, legal actions, result ``` -That is a wire-protocol change and will be its own major version. +That will be its own protocol change. diff --git a/docs/TESTING.md b/docs/TESTING.md index 4d46855..2dcb01f 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -14,6 +14,7 @@ shared global database. Each test owns its state. | `tests/client_core.rs` | Client command/game flows via a headless screen applying logical effects. | | `tests/client_ui.rs` | Help, history, completion, bet parsing, display width, cursor math. | | `tests/protocol.rs` | Newline buffering and timeout/error classification. | +| `tests/roulette.rs` | European wheel, split-bet payouts, zero handling, result parser. | | `tests/server_core.rs` | Handler, bcrypt migration, SQL injection, transaction rollback, `plays` audit, sessions. | | `tests/server_setup.rs` | `--init` identity generation, PKCS#12 loadability, overwrite refusal. | | `tests/slots.rs` | Server slots payout rules and overflow handling. | @@ -63,6 +64,19 @@ Use an 80-column terminal because several output lines are width-sensitive. fingerprint fits 80 columns. 10. Windows: repeat 2-9 and confirm keys are not duplicated or printed twice. +## Manual roulette checklist + +1. `play roulette` shows the balance, chip size, empty bets, and controls. +2. `R`/`B`/`E`/`O` add one chip; digits + Enter add a number; `C` clears; + `+`/`=`/`-` change the chip size. +3. Space scrolls the wheel under a fixed ball marker and ends on the winning + number. +4. Check a split result: + - `17 black odd`: black+odd pay, red+even lose, straight 17 pays 36x. + - `0`: all outside bets lose; a straight 0 pays 36x. +5. The result board shows the winning number/color/parity, the payout, and the + new balance. The next spin reuses the placed bets. + ## Manual server checks - Register, log out, log in again (bcrypt path). -- cgit v1.2.3