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::player::{self, Player};
@@ -17,20 +17,44 @@ struct BettingPot {
/// **Value**: Pennies
bets: HashMap<u32, 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 {
pub fn new(players: Vec<u32>) -> BettingPot {
let mut m: HashMap<u32, u32> = HashMap::new();
pub fn new(players: Vec<u32>, starting_bets: Option<HashMap<u32, u32>>) -> BettingPot {
let mut m: HashMap<u32, u32> = starting_bets.unwrap_or_default();
for p in players {
m.insert(p, 0);
if !m.contains_key(&p) {
m.insert(p, 0);
}
}
BettingPot {
bets: m,
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) {
self.bets.remove(&id);
}
@@ -80,7 +104,7 @@ impl PokerGame {
PokerGame {
players,
table: vec![],
pots: vec![BettingPot::new(p_ids)],
pots: vec![BettingPot::new(p_ids, None)],
big_blind: 0,
stage: GameStage::PreFlop,
deck: create_deck(),
@@ -107,7 +131,16 @@ impl PokerGame {
pub fn get_bets(&mut self) {
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 mut current_bet = 0;
match action {
@@ -119,12 +152,66 @@ impl PokerGame {
}
player::TurnAction::Call => {
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));
}
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);
}
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 {
Fold,
Call,
AllIn(u32),
Raise(u32),
}