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