From 9951e2d5afbcabb4bd8016b6d160653c1ec5ed8e Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 28 Oct 2026 23:45:43 +0100 Subject: v1.3.0: simplify payouts to bet x symbol x shape --- tests/slots.rs | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'tests/slots.rs') diff --git a/tests/slots.rs b/tests/slots.rs index bdf8f10..8bdd9af 100644 --- a/tests/slots.rs +++ b/tests/slots.rs @@ -1,6 +1,6 @@ //! Regression tests for the server-side 5x3 slots game. -use zagan_bet::slots::{paytable_lines, PAYTABLE}; +use zagan_bet::slots::{paytable_lines, LINE_NAMES, SHAPE_MULTIPLIERS, SYMBOL_MULTIPLIERS}; use zagan_bet::server::games::slots::{LineWin, SlotsGame, PAYLINES, REELS, ROWS}; use zagan_bet::server::games::traits::{Game, GamePhase}; @@ -44,7 +44,7 @@ fn the_wire_grid_is_five_reels_by_three_rows() { fn three_of_a_kind_on_the_top_line_pays() { let (winnings, wins) = payout(["CCCDD", "CLLGG", "CLOSS"], 10); - assert_eq!(winnings, 20, "CCC on line 1 pays 2x total bet"); + assert_eq!(winnings, 10, "CCC: 10 * C(1) * shape3(1)"); assert_eq!(lines(&wins), vec![1]); assert_eq!(wins[0].cells, vec![0, 3, 6]); } @@ -53,7 +53,7 @@ fn three_of_a_kind_on_the_top_line_pays() { fn four_of_a_kind_pays_more_than_three() { let (winnings, wins) = payout(["CCCCD", "LOGDS", "OGDSL"], 10); - assert_eq!(winnings, 50, "CCCC pays 5x total bet"); + assert_eq!(winnings, 30, "CCCC: 10 * C(1) * shape4(3)"); assert_eq!(lines(&wins), vec![1]); assert_eq!(wins[0].cells, vec![0, 3, 6, 9]); } @@ -62,7 +62,7 @@ fn four_of_a_kind_pays_more_than_three() { fn five_of_a_kind_pays_all_lines() { let (winnings, wins) = payout(["SSSSS", "SSSSS", "SSSSS"], 10); - assert_eq!(winnings, 7500, "five SSSSS lines at 150x each"); + assert_eq!(winnings, 7000, "five SSSSS lines: 5 * 10 * S(10) * shape5(14)"); assert_eq!(lines(&wins), vec![1, 2, 3, 4, 5]); assert_eq!(wins[0].cells, vec![0, 3, 6, 9, 12]); assert_eq!(wins[3].cells, vec![0, 4, 8, 10, 12]); @@ -73,7 +73,7 @@ fn five_of_a_kind_pays_all_lines() { fn the_v_payline_is_evaluated() { let (winnings, wins) = payout(["COGDC", "LCLCG", "OGCSD"], 10); - assert_eq!(winnings, 150, "V line with five C symbols pays 15x"); + assert_eq!(winnings, 140, "V line: 10 * C(1) * shape5(14)"); assert_eq!(lines(&wins), vec![4]); assert_eq!(wins[0].cells, vec![0, 4, 8, 10, 12]); } @@ -90,7 +90,7 @@ fn no_matching_line_pays_nothing() { fn winning_lines_are_added_together() { let (winnings, wins) = payout(["SSSSS", "LLLLL", "OOOOO"], 10); - assert_eq!(winnings, (150 + 20 + 25) * 10); + assert_eq!(winnings, (10 + 2 + 3) * 14 * 10); assert_eq!(lines(&wins), vec![1, 2, 3]); let mut cells: Vec = wins.iter().flat_map(|win| win.cells.clone()).collect(); @@ -102,21 +102,35 @@ fn winning_lines_are_added_together() { fn theoretical_rtp_is_just_under_one() { let rtp = SlotsGame::new().theoretical_rtp(); - assert!((rtp - 425.0 / 432.0).abs() < 1e-12); + assert!((rtp - 3835.0 / 3888.0).abs() < 1e-12); assert!(rtp < 1.0, "house edge must be positive"); assert!(rtp > 0.98, "house edge should be tiny"); } #[test] -fn the_paytable_lines_list_every_symbol_and_fit_80_columns() { +fn payline_names_match_the_paylines() { + assert_eq!(LINE_NAMES.len(), PAYLINES.len()); + assert_eq!(LINE_NAMES[3], "V"); + assert_eq!(LINE_NAMES[4], "inverted V"); +} + +#[test] +fn the_paytable_lines_show_the_product_formula_and_fit_80_columns() { let lines = paytable_lines(); let joined = lines.join(" "); - assert_eq!(lines.len(), 2, "paytable should be split into two lines"); - for (symbol, three, four, five) in PAYTABLE { + assert_eq!(lines.len(), 2, "paytable should be two lines"); + assert!(joined.contains("Pays bet x symbol x shape")); + for (symbol, multiplier) in SYMBOL_MULTIPLIERS { + assert!( + joined.contains(&format!("{symbol}{multiplier}")), + "paytable is missing symbol {symbol}" + ); + } + for (length, multiplier) in SHAPE_MULTIPLIERS { assert!( - joined.contains(&format!("{symbol} {three}/{four}/{five}")), - "paytable is missing {symbol}" + joined.contains(&format!("{length}:{multiplier}")), + "paytable is missing shape {length}" ); } for line in lines { @@ -140,7 +154,7 @@ fn a_spin_produces_a_finished_state_and_a_result_with_win_lines() { assert_eq!(state.phase, GamePhase::Finished); let result = game.calculate_result(&state).unwrap(); - assert_eq!(result.winnings, 20); + assert_eq!(result.winnings, 10); assert_eq!(result.result_data.get("win_type").unwrap(), "win"); assert_eq!(result.result_data.get("win_lines").unwrap(), "1"); assert_eq!(result.result_data.get("win_cells").unwrap(), "0,3,6"); -- cgit v1.2.3