WIP implementing betting logic
This commit is contained in:
101
src/game.rs
101
src/game.rs
@@ -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 {
|
||||
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())
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::io;
|
||||
pub enum TurnAction {
|
||||
Fold,
|
||||
Call,
|
||||
AllIn(u32),
|
||||
Raise(u32),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user