Implement double-down, save interactive bank to disk

This commit is contained in:
Nick Pegg 2025-07-05 08:35:23 -07:00
parent c114094285
commit de22cb02f4
2 changed files with 119 additions and 36 deletions

View file

@ -3,11 +3,11 @@ use crate::hand::Hand;
use rand::prelude::*;
use std::sync::{Arc, RwLock};
#[derive(Debug, PartialEq)]
pub enum PlayerChoice {
Hit,
Stand,
// TODO
// DoubleDown,
DoubleDown,
// TODO
// Split,
// TODO
@ -26,7 +26,6 @@ pub enum PlayResult {
/// The state at the end of a round, useful for printing out
pub struct EndState {
pub result: PlayResult,
pub player_winnings: u64,
pub dealer_cards: Vec<Card>,
pub player_cards: Vec<Card>,
pub shuffled: bool,
@ -35,14 +34,12 @@ pub struct EndState {
impl EndState {
fn new(
result: PlayResult,
player_winnings: u64,
dealer_cards: Vec<Card>,
player_cards: Vec<Card>,
shuffled: bool,
) -> Self {
Self {
result,
player_winnings,
dealer_cards,
player_cards,
shuffled,
@ -104,7 +101,12 @@ impl Game {
/// and returns a choice (hit, stand, etc.).
///
/// Returns the winnings of the round
pub fn play<F>(self: &mut Self, bet: u32, player_decision: F) -> EndState
pub fn play<F>(
&mut self,
money_on_table: &mut u32,
bet_amount: u32,
player_decision: F,
) -> EndState
where
F: Fn(&Hand, &Card) -> PlayerChoice,
{
@ -116,6 +118,9 @@ impl Game {
shuffled = true;
}
let mut bet_amount = bet_amount;
*money_on_table -= bet_amount;
// Deal cards
let mut dealer_hand =
Hand::from([self.deal(), self.deal()].to_vec()).with_discard(self.discard.clone());
@ -126,16 +131,15 @@ impl Game {
if dealer_hand.is_blackjack() {
return EndState::new(
PlayResult::DealerBlackjack,
0,
dealer_hand.cards(),
player_hand.cards(),
shuffled,
);
} else if player_hand.is_blackjack() {
let returns = bet as f32 * self.blackjack_returns;
let returns = bet_amount as f32 * self.blackjack_returns;
*money_on_table += returns as u32;
return EndState::new(
PlayResult::Blackjack,
returns as u64,
dealer_hand.cards(),
player_hand.cards(),
shuffled,
@ -151,13 +155,19 @@ impl Game {
PlayerChoice::Hit => {
player_hand.push(self.deal());
}
PlayerChoice::DoubleDown => {
if *money_on_table >= bet_amount {
*money_on_table -= bet_amount;
bet_amount *= 2;
}
player_hand.push(self.deal());
}
}
// if player busts, immediately lose bet
if player_hand.value() > 21 {
return EndState::new(
PlayResult::Bust,
0,
dealer_hand.cards(),
player_hand.cards(),
shuffled,
@ -171,25 +181,25 @@ impl Game {
}
if dealer_hand.value() > 21 {
*money_on_table += bet_amount * 2;
EndState::new(
PlayResult::Win,
(bet * 2).into(),
dealer_hand.cards(),
player_hand.cards(),
shuffled,
)
} else if dealer_hand.value() < player_hand.value() {
*money_on_table += bet_amount * 2;
EndState::new(
PlayResult::Win,
(bet * 2).into(),
dealer_hand.cards(),
player_hand.cards(),
shuffled,
)
} else if dealer_hand.value() == player_hand.value() {
*money_on_table += bet_amount;
EndState::new(
PlayResult::Push,
bet.into(),
dealer_hand.cards(),
player_hand.cards(),
shuffled,
@ -197,7 +207,6 @@ impl Game {
} else {
EndState::new(
PlayResult::Lose,
0,
dealer_hand.cards(),
player_hand.cards(),
shuffled,