From b5a52fc0312afdf5d5fbe53275dc88d6d881c2ff Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 18:22:40 +0100 Subject: v2.2.0: add blackjack with reserved bets and hit/stand/double --- tests/blackjack.rs | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 tests/blackjack.rs (limited to 'tests/blackjack.rs') diff --git a/tests/blackjack.rs b/tests/blackjack.rs new file mode 100644 index 0000000..79721d3 --- /dev/null +++ b/tests/blackjack.rs @@ -0,0 +1,139 @@ +use zagan_bet::blackjack::{ + card_label, card_value, fresh_shoe, hand_total, is_blackjack, BlackjackState, +}; +use zagan_bet::server::games::blackjack::BlackjackGame; + +fn hand(deck: &[&str], bet: u64) -> zagan_bet::server::games::blackjack::BlackjackHand { + let deck = deck.iter().map(|card| card.to_string()).collect(); + BlackjackGame::with_deck(deck).deal(bet) +} + +#[test] +fn card_values_and_soft_totals_are_correct() { + assert_eq!(card_value("AS"), 11); + assert_eq!(card_value("10H"), 10); + assert_eq!(card_value("KD"), 10); + assert_eq!(card_label("AS"), "A♠"); + assert_eq!(card_label("10H"), "10♥"); + + let cards = |values: &[&str]| values.iter().map(|card| card.to_string()).collect::>(); + assert_eq!(hand_total(&cards(&["AS", "10H"])), 21); + assert_eq!(hand_total(&cards(&["AS", "9H"])), 20); + assert_eq!(hand_total(&cards(&["AS", "AS", "9H"])), 21); + assert!(is_blackjack(&cards(&["AS", "KH"]))); + assert!(!is_blackjack(&cards(&["AS", "9H"]))); +} + +#[test] +fn a_six_deck_shoe_has_312_cards() { + let shoe = fresh_shoe(); + assert_eq!(shoe.len(), 312); + assert_eq!(shoe.iter().filter(|card| card.as_str() == "AS").count(), 6); +} + +#[test] +fn a_natural_blackjack_settles_immediately() { + let hand = hand(&["AS", "9D", "KH", "8C"], 10); + + assert!(hand.is_done()); + assert_eq!(hand.result, "blackjack"); + assert_eq!(hand.winnings, 25); // 10 + 15 + assert_eq!(hand.player_total(), 21); +} + +#[test] +fn a_player_hand_can_hit_to_21() { + let mut hand = hand(&["10S", "9D", "6H", "8C", "5D"], 10); + assert_eq!(hand.player_total(), 16); + assert_eq!(hand.dealer_total(), 17); + + hand.hit().unwrap(); + + assert!(hand.is_done()); + assert_eq!(hand.player_total(), 21); + assert_eq!(hand.result, "win"); + assert_eq!(hand.winnings, 20); +} + +#[test] +fn hitting_over_21_busts() { + let mut hand = hand(&["10S", "9D", "6H", "8C", "KD"], 10); + hand.hit().unwrap(); + + assert!(hand.is_done()); + assert_eq!(hand.result, "bust"); + assert_eq!(hand.winnings, 0); +} + +#[test] +fn doubling_adds_the_base_bet_and_draws_one_card() { + let mut hand = hand(&["5S", "9D", "5H", "8C", "10D"], 10); + assert_eq!(hand.player_total(), 10); + + hand.double().unwrap(); + + assert_eq!(hand.player.len(), 3); + assert_eq!(hand.bet, 20); + assert_eq!(hand.player_total(), 20); + assert_eq!(hand.result, "win"); + assert_eq!(hand.winnings, 40); +} + +#[test] +fn the_dealer_busts_and_the_player_wins() { + let mut hand = hand(&["10S", "7H", "8H", "9C", "10H"], 10); + assert_eq!(hand.player_total(), 18); + assert_eq!(hand.dealer_total(), 16); + + hand.stand(); + + assert_eq!(hand.dealer_total(), 26); + assert_eq!(hand.result, "win"); + assert_eq!(hand.winnings, 20); +} + +#[test] +fn the_dealer_stands_on_soft_17() { + let mut hand = hand(&["10S", "AD", "8H", "6C"], 10); + assert_eq!(hand.dealer_total(), 17); + + hand.stand(); + + assert_eq!(hand.dealer.len(), 2, "dealer must stand on soft 17"); + assert_eq!(hand.result, "win"); + assert_eq!(hand.winnings, 20); +} + +#[test] +fn equal_totals_push() { + let mut hand = hand(&["10S", "10D", "8H", "8C"], 10); + hand.stand(); + + assert_eq!(hand.result, "push"); + assert_eq!(hand.winnings, 10); +} + +#[test] +fn dealer_blackjack_wins_unless_player_also_has_it() { + let dealer_blackjack = hand(&["10S", "AS", "8H", "KD"], 10); + assert_eq!(dealer_blackjack.result, "lose"); + assert_eq!(dealer_blackjack.winnings, 0); + + let both = hand(&["AS", "AD", "KH", "KC"], 10); + assert_eq!(both.result, "push"); + assert_eq!(both.winnings, 10); +} + +#[test] +fn the_player_state_hides_the_hole_card() { + let hand = hand(&["10S", "9D", "6H", "8C"], 10); + let state: BlackjackState = hand.state("session-1", 990); + + assert_eq!(state.phase, "player"); + assert_eq!(state.dealer, vec!["9D".to_string(), "?".to_string()]); + assert_eq!(state.dealer_total, 9); + assert_eq!(state.player_total, 16); + assert_eq!(state.actions, vec!["hit", "stand", "double"]); + assert_eq!(state.bet, 10); + assert_eq!(state.balance, 990); +} -- cgit v1.2.3