From 2915d826f744612e0d975282f5bddf13270b9f3f Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 28 Oct 2026 23:19:52 +0100 Subject: v1.1.0: highlight winning symbols on the slots board --- src/server/games/slots.rs | 49 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) (limited to 'src/server/games/slots.rs') diff --git a/src/server/games/slots.rs b/src/server/games/slots.rs index 2ef1b46..1d71c9d 100644 --- a/src/server/games/slots.rs +++ b/src/server/games/slots.rs @@ -22,6 +22,13 @@ struct Payout { five: u64, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LineWin { + pub line: usize, + /// Column-major cell indices of the matched symbols. + pub cells: Vec, +} + pub struct SlotsGame { payouts: HashMap, /// Deterministic grid for tests and demos, in column-major order. @@ -65,10 +72,11 @@ impl SlotsGame { .collect() } - /// Evaluate one spin. Returns the total win and the 1-based winning lines. - pub fn calculate_payout(&self, grid: &[char], bet: u64) -> (u64, Vec) { + /// Evaluate one spin. Returns the total win and the winning lines with + /// the column-major cells that should be highlighted. + pub fn calculate_payout(&self, grid: &[char], bet: u64) -> (u64, Vec) { let mut total = 0u64; - let mut winning_lines = Vec::new(); + let mut wins = Vec::new(); for (index, pattern) in PAYLINES.iter().enumerate() { let Some(&first) = grid.get(pattern[0]) else { @@ -99,10 +107,19 @@ impl SlotsGame { }; total = total.saturating_add(bet.saturating_mul(multiplier)); - winning_lines.push(index + 1); + let cells = pattern + .iter() + .enumerate() + .take(run) + .map(|(col, row)| col * ROWS + row) + .collect(); + wins.push(LineWin { + line: index + 1, + cells, + }); } - (total, winning_lines) + (total, wins) } /// Exact theoretical return to player for the current paytable. @@ -213,12 +230,27 @@ impl Game for SlotsGame { ))); } - let (winnings, winning_lines) = self.calculate_payout(&grid, state.bet_amount); + let (winnings, wins) = self.calculate_payout(&grid, state.bet_amount); let win_type = classify_win(winnings, state.bet_amount); - let win_lines = if winning_lines.is_empty() { + let win_lines = if wins.is_empty() { + "-".to_string() + } else { + wins.iter() + .map(|win| win.line.to_string()) + .collect::>() + .join(",") + }; + + let mut cells: Vec = wins + .iter() + .flat_map(|win| win.cells.iter().copied()) + .collect(); + cells.sort_unstable(); + cells.dedup(); + let win_cells = if cells.is_empty() { "-".to_string() } else { - winning_lines + cells .iter() .map(usize::to_string) .collect::>() @@ -229,6 +261,7 @@ impl Game for SlotsGame { result_data.insert("reels".to_string(), reel_string.clone()); result_data.insert("win_type".to_string(), win_type.to_string()); result_data.insert("win_lines".to_string(), win_lines); + result_data.insert("win_cells".to_string(), win_cells); Ok(GameResult { session_id: state.session_id.clone(), -- cgit v1.2.3