From 33452f55afcad603f72e054d56ad7848a3d09503 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 28 Oct 2026 23:24:08 +0100 Subject: v1.2.0: show the symbol paytable on the slots board --- src/client/games/slots.rs | 8 +++----- src/lib.rs | 1 + src/server/games/slots.rs | 29 ++++++++--------------------- src/slots.rs | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 26 deletions(-) create mode 100644 src/slots.rs (limited to 'src') diff --git a/src/client/games/slots.rs b/src/client/games/slots.rs index c367fcb..7e59919 100644 --- a/src/client/games/slots.rs +++ b/src/client/games/slots.rs @@ -1,10 +1,8 @@ use super::traits::{Game, GamePhase, GameState}; +use crate::slots::{paytable_line, REELS, ROWS}; /// Height of the game board. It must never depend on the spin result. pub const SLOT_BOARD_LINES: usize = 9; -pub const LINES: usize = 5; -pub const REELS: usize = 5; -pub const ROWS: usize = 3; pub struct SlotsGame; @@ -106,13 +104,13 @@ impl Game for SlotsGame { let grid = self.render_grid(&reels, &winning); format!( - "=== SLOTS ===\r\nBet: {} PLN Lines: {} Balance: {} PLN\r\n{}\r\n{}\r\n{}\r\n\r\n{}\r\n{}\r\n[+/-] Bet [SPACE] Spin [Q] Quit", + "=== SLOTS ===\r\nBet: {} PLN Balance: {} PLN\r\n{}\r\n{}\r\n{}\r\n{}\r\n{}\r\n{}\r\n[+/-] Bet [SPACE] Spin [Q] Quit", state.bet_amount, - LINES, balance, grid[0], grid[1], grid[2], + paytable_line(), self.render_status(state), self.render_win_lines(state) ) diff --git a/src/lib.rs b/src/lib.rs index e700173..a261ab0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,4 +8,5 @@ pub mod client; pub mod protocol; pub mod server; +pub mod slots; pub mod tofu; diff --git a/src/server/games/slots.rs b/src/server/games/slots.rs index 1d71c9d..e9f58b1 100644 --- a/src/server/games/slots.rs +++ b/src/server/games/slots.rs @@ -1,19 +1,9 @@ use super::traits::{Game, GameError, GamePhase, GameResult, GameState}; +use crate::slots::PAYTABLE; use rand::Rng; use std::collections::HashMap; -pub const REELS: usize = 5; -pub const ROWS: usize = 3; -pub const SYMBOLS: [char; 6] = ['C', 'L', 'O', 'G', 'D', 'S']; - -/// Five paylines, each entry is the row used on reel 0..4. -pub const PAYLINES: [[usize; REELS]; 5] = [ - [0, 0, 0, 0, 0], // line 1: top - [1, 1, 1, 1, 1], // line 2: middle - [2, 2, 2, 2, 2], // line 3: bottom - [0, 1, 2, 1, 0], // line 4: V - [2, 1, 0, 1, 2], // line 5: inverted V -]; +pub use crate::slots::{PAYLINES, REELS, ROWS, SYMBOLS}; #[derive(Clone, Copy)] struct Payout { @@ -37,15 +27,12 @@ pub struct SlotsGame { impl SlotsGame { pub fn new() -> Self { - let mut payouts = HashMap::new(); - - // RTP = 425/432 = 0.9838 (1.62% house edge) with five paylines. - payouts.insert('C', Payout { three: 2, four: 5, five: 15 }); - payouts.insert('L', Payout { three: 3, four: 7, five: 20 }); - payouts.insert('O', Payout { three: 3, four: 8, five: 25 }); - payouts.insert('G', Payout { three: 4, four: 12, five: 40 }); - payouts.insert('D', Payout { three: 6, four: 18, five: 70 }); - payouts.insert('S', Payout { three: 9, four: 30, five: 150 }); + let payouts = PAYTABLE + .iter() + .map(|&(symbol, three, four, five)| { + (symbol, Payout { three, four, five }) + }) + .collect(); Self { payouts, diff --git a/src/slots.rs b/src/slots.rs new file mode 100644 index 0000000..561c449 --- /dev/null +++ b/src/slots.rs @@ -0,0 +1,33 @@ +//! Shared slots rules used by both the server engine and the client board. + +pub const REELS: usize = 5; +pub const ROWS: usize = 3; +pub const SYMBOLS: [char; 6] = ['C', 'L', 'O', 'G', 'D', 'S']; + +/// Five paylines, each entry is the row used on reel 0..4. +pub const PAYLINES: [[usize; REELS]; 5] = [ + [0, 0, 0, 0, 0], // line 1: top + [1, 1, 1, 1, 1], // line 2: middle + [2, 2, 2, 2, 2], // line 3: bottom + [0, 1, 2, 1, 0], // line 4: V + [2, 1, 0, 1, 2], // line 5: inverted V +]; + +/// (symbol, 3-of-a-kind, 4-of-a-kind, 5-of-a-kind) multipliers of total bet. +pub const PAYTABLE: [(char, u64, u64, u64); 6] = [ + ('C', 2, 5, 15), + ('L', 3, 7, 20), + ('O', 3, 8, 25), + ('G', 4, 12, 40), + ('D', 6, 18, 70), + ('S', 9, 30, 150), +]; + +/// One-line paytable rendered under the reels. +pub fn paytable_line() -> String { + let entries: Vec = PAYTABLE + .iter() + .map(|(symbol, three, four, five)| format!("{symbol} {three}/{four}/{five}")) + .collect(); + format!("Pays 3/4/5 x bet: {}", entries.join(" ")) +} -- cgit v1.2.3