WIP implementing betting logic

This commit is contained in:
2024-04-27 22:02:40 -04:00
parent bc1a7380f0
commit 055bd860b2
2 changed files with 96 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap; use std::collections::{HashMap, VecDeque};
use crate::card::{create_deck, draw_card, PlayingCard}; use crate::card::{create_deck, draw_card, PlayingCard};
use crate::player::{self, Player}; use crate::player::{self, Player};
@@ -17,20 +17,44 @@ struct BettingPot {
/// **Value**: Pennies /// **Value**: Pennies
bets: HashMap<u32, u32>, bets: HashMap<u32, u32>,
pot_total: u32, pot_total: u32,
/// If there are multiple pots, represents the max value of this pot.
/// Calls or raises above this go into the next pot.
pot_cap: Option<u32>,
} }
impl BettingPot { impl BettingPot {
pub fn new(players: Vec<u32>) -> BettingPot { pub fn new(players: Vec<u32>, starting_bets: Option<HashMap<u32, u32>>) -> BettingPot {
let mut m: HashMap<u32, u32> = HashMap::new(); let mut m: HashMap<u32, u32> = starting_bets.unwrap_or_default();
for p in players { for p in players {
m.insert(p, 0); if !m.contains_key(&p) {
m.insert(p, 0);
}
} }
BettingPot { BettingPot {
bets: m, bets: m,
pot_total: 0, pot_total: 0,
pot_cap: None,
} }
} }
pub fn cap_pot(&mut self, pennies: u32) -> HashMap<u32, u32> {
self.pot_cap = Some(pennies);
let mut new_map: HashMap<u32, u32> = HashMap::new();
self.bets.iter_mut().for_each(|bet| {
if *bet.1 > pennies {
let difference = *bet.1 - pennies;
self.pot_total -= difference;
*bet.1 = pennies;
new_map.insert(*bet.0, difference);
}
});
new_map
}
pub fn declare_winner(&self, id: u32, game: &mut PokerGame) {
game.get_player_mut(id).pay(self.pot_total);
}
pub fn remove_player(&mut self, id: u32) { pub fn remove_player(&mut self, id: u32) {
self.bets.remove(&id); self.bets.remove(&id);
} }
@@ -80,7 +104,7 @@ impl PokerGame {
PokerGame { PokerGame {
players, players,
table: vec![], table: vec![],
pots: vec![BettingPot::new(p_ids)], pots: vec![BettingPot::new(p_ids, None)],
big_blind: 0, big_blind: 0,
stage: GameStage::PreFlop, stage: GameStage::PreFlop,
deck: create_deck(), deck: create_deck(),
@@ -107,7 +131,16 @@ impl PokerGame {
pub fn get_bets(&mut self) { pub fn get_bets(&mut self) {
let ids: Vec<u32> = self.players.iter().map(|p| p.id()).collect(); let ids: Vec<u32> = self.players.iter().map(|p| p.id()).collect();
for id in ids {
// Queue of players that still need to bet. When this is empty,
// all players have placed there bets and the next round is ready to start.
let mut bet_queue: VecDeque<u32> = VecDeque::new();
self.players
.iter()
.for_each(|p| bet_queue.push_back(p.id()));
while !bet_queue.is_empty() {
let id = bet_queue.pop_front().unwrap();
let action = self.get_player(id).get_move(self); let action = self.get_player(id).get_move(self);
let mut current_bet = 0; let mut current_bet = 0;
match action { match action {
@@ -119,12 +152,66 @@ impl PokerGame {
} }
player::TurnAction::Call => { player::TurnAction::Call => {
if current_bet > 0 { if current_bet > 0 {
let message = format!("You called ${}", (current_bet as f64) / 100.0); let message = format!("You called ${}.", (current_bet as f64) / 100.0);
self.get_player_mut(id).deduct(current_bet, Some(&message)); self.get_player_mut(id).deduct(current_bet, Some(&message));
} }
let mut bet = current_bet.clone();
self.pots.iter_mut().for_each(|pot| match pot.pot_cap {
Some(cap) => {
if cap > bet {
panic!("There's something wrong with the logic, bet is less than the cap??");
}
pot.add_bet(id, cap);
bet -= cap;
},
None => {
if bet > 0 {
pot.add_bet(id, bet);
}
}
});
self.pots.last_mut().unwrap().add_bet(id, current_bet); self.pots.last_mut().unwrap().add_bet(id, current_bet);
} }
player::TurnAction::Raise(_) => todo!(), player::TurnAction::AllIn(amount) => {
// Remove money from player and add it to the pot
let message = format!(
"You went all in with your last ${}.",
(current_bet as f64) / 100.0
);
self.get_player_mut(id).deduct(amount, Some(&message));
self.pots.last_mut().unwrap().add_bet(id, amount);
// Take the difference between the current bet and create a new pot
let pot_cap = *self.pots.last().unwrap().bets.get(&id).unwrap();
let new_betmap = self.pots.last_mut().unwrap().cap_pot(pot_cap);
let new_pot_players: Vec<u32> = self
.players
.iter()
.filter(|p| p.id() != id)
.map(|p| p.id())
.collect();
let new_pot = BettingPot::new(new_pot_players, Some(new_betmap));
self.pots.push(new_pot);
}
player::TurnAction::Raise(raise) => {
// New current bet
current_bet = current_bet + raise;
let message = format!("You raised ${}.", (current_bet as f64) / 100.0);
// Remove money from player
self.get_player_mut(id).deduct(current_bet, Some(&message));
// Add money to current pot
self.pots.last_mut().unwrap().add_bet(id, current_bet);
// Reset queue of players waiting to bet.
// Everyone now has to decide whether to match the raise.
self.players.iter().for_each(|p| {
if !bet_queue.contains(&p.id()) && p.id() != id {
bet_queue.push_back(p.id())
}
});
}
} }
} }
} }

View File

@@ -6,6 +6,7 @@ use std::io;
pub enum TurnAction { pub enum TurnAction {
Fold, Fold,
Call, Call,
AllIn(u32),
Raise(u32), Raise(u32),
} }