diff --git a/src/game.rs b/src/game.rs index 7dcf73a..11d5026 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,7 +1,6 @@ -use crate::{ - card::{create_deck, draw_card, PlayingCard}, - pokerplayer::PokerPlayer, -}; +use crate::card::{create_deck, draw_card, PlayingCard}; +use crate::player::{self, Player}; +use rand::Rng; enum GameStage { PreFlop, Flop, @@ -10,8 +9,29 @@ enum GameStage { Reveal, } -struct PokerGame { - players: Vec, +struct BettingPot { + players: Vec>, + pennies: u32, +} + +impl BettingPot { + pub fn distribute(&mut self) { + let player_count = self.players.len() as u32; + let split = self.pennies / player_count; + let remainder = self.pennies % player_count; + for p in &mut self.players { + p.pay(split); + } + if remainder > 0 { + let num = rand::thread_rng().gen_range(0..player_count) as usize; + self.players[num].pay(remainder); + } + } +} + +pub struct PokerGame { + players: Vec>, + pots: Vec, big_blind: u32, // Index of player who should post the Big Blind pot: u32, // Money in pennies stage: GameStage, @@ -19,10 +39,11 @@ struct PokerGame { } impl PokerGame { - pub fn new(players: Vec) -> PokerGame { + pub fn new(players: Vec>) -> PokerGame { let first_player = 0; PokerGame { players, + pots: vec![], big_blind: 0, pot: 0, stage: GameStage::PreFlop, diff --git a/src/main.rs b/src/main.rs index d4edcd2..1021d55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use std::vec; mod card; mod game; mod hand; -mod pokerplayer; +mod player; use crate::card::{create_deck, CardSuit, CardValue, PlayingCard}; use crate::hand::HandType; diff --git a/src/player.rs b/src/player.rs new file mode 100644 index 0000000..1991903 --- /dev/null +++ b/src/player.rs @@ -0,0 +1,259 @@ +use crate::card::PlayingCard; +use crate::game::PokerGame; +use crate::hand::PokerHand; +use std::io; + +pub enum TurnAction { + Fold, + Call, + Raise(u32), +} + +pub trait Player { + fn display_name(&self) -> &str; + fn deal_cards(&mut self, cards: Vec); + fn get_move(&self, game_state: &PokerGame) -> TurnAction; + fn money(&self) -> u32; + fn pay(&mut self, pennies: u32); + fn deduct(&mut self, pennies: u32, message: Option<&str>); + fn get_hand(&self, table: Vec) -> PokerHand; +} + +pub struct HumanPlayer { + name: String, + money: u32, + cards: Vec, +} + +impl HumanPlayer { + pub fn new(money: u32) -> HumanPlayer { + let mut user_input = String::new(); + print!("Enter your name\n> "); + let stdin = io::stdin(); + let _ = stdin.read_line(&mut user_input); + HumanPlayer { + name: user_input, + money, + cards: vec![], + } + } +} + +impl Player for HumanPlayer { + fn display_name(&self) -> &str { + &self.name + } + + fn deal_cards(&mut self, mut cards: Vec) { + self.cards.clear(); + self.cards.append(&mut cards); + } + + fn get_move(&self, game_state: &PokerGame) -> TurnAction { + let mut user_input = String::new(); + let stdin = io::stdin(); + loop { + print!("What would you like to do?\nR: Raise\nC: Call\n:F\n Fold\n> "); + let _ = stdin.read_line(&mut user_input); + if user_input.len() == 0 { + continue; + } + let first_char = user_input.to_lowercase().chars().next().unwrap(); + match first_char { + 'f' => { + return TurnAction::Fold; + } + 'r' => { + return TurnAction::Raise(self.get_raise()); + } + 'c' => { + return TurnAction::Call; + } + _ => { + continue; + } + } + } + } + + fn money(&self) -> u32 { + self.money + } + + fn pay(&mut self, pennies: u32) { + self.money = self.money + pennies; + println!("You received ${}.", (pennies as f64) / 100.0); + } + + fn deduct(&mut self, pennies: u32, message: Option<&str>) { + if pennies > self.money { + panic!("Deducted more money than the player had!"); + } + self.money = self.money - pennies; + if message.is_some() { + println!("{}", message.unwrap().to_string()); + } + } + + fn get_hand(&self, table: Vec) -> PokerHand { + let mut table_clone = table.clone(); + let mut total_cards = self.cards.clone(); + total_cards.append(&mut table_clone); + PokerHand::new(total_cards) + } +} + +impl HumanPlayer { + fn get_raise(&self) -> u32 { + let mut user_input: String = String::new(); + let stdin = io::stdin(); + loop { + print!("Enter your raise.\n> "); + let _ = stdin.read_line(&mut user_input); + let user_input = user_input.replace("$", ""); + if user_input.len() == 0 { + continue; + } + let money = user_input.parse::(); + match money { + Ok(_) => { + let pennies = (money.unwrap() * 100.0).floor() as u32; + if pennies > self.money { + println!("You flat-footed dingus, you don't have that much money!"); + } + return pennies; + } + Err(err) => { + print!("That's not a number, dufus. What, are you trying to bet your bitcoin wallet or something? Enter a number.\n>"); + continue; + } + } + } + } +} + +struct RemotePlayer { + name: String, + money: u32, + cards: Vec, +} + +impl RemotePlayer { + pub fn new(name: &str, money: u32) -> RemotePlayer { + RemotePlayer { + name: name.to_string(), + money, + cards: vec![], + } + } +} + +impl Player for RemotePlayer { + fn display_name(&self) -> &str { + &self.name + } + + fn deal_cards(&mut self, mut cards: Vec) { + self.cards.clear(); + self.cards.append(&mut cards); + } + + fn get_move(&self, game_state: &PokerGame) -> TurnAction { + todo!() + } + + fn money(&self) -> u32 { + self.money + } + + fn pay(&mut self, pennies: u32) { + self.money = self.money + pennies; + } + + fn deduct(&mut self, pennies: u32, message: Option<&str>) { + if pennies > self.money { + panic!("Deducted more money than the player had!"); + } + self.money = self.money - pennies; + } + + fn get_hand(&self, table: Vec) -> PokerHand { + let mut table_clone = table.clone(); + let mut total_cards = self.cards.clone(); + total_cards.append(&mut table_clone); + PokerHand::new(total_cards) + } +} + +struct BotPlayer { + name: String, + money: u32, + cards: Vec, +} + +impl BotPlayer { + pub fn new(name: &str, money: u32) -> BotPlayer { + BotPlayer { + name: format!("[BOT] {}", name.to_string()), + money, + cards: vec![], + } + } +} + +impl Player for BotPlayer { + fn display_name(&self) -> &str { + &self.name + } + + fn deal_cards(&mut self, mut cards: Vec) { + self.cards.clear(); + self.cards.append(&mut cards); + } + + fn get_move(&self, game_state: &PokerGame) -> TurnAction { + return TurnAction::Fold; + } + + fn money(&self) -> u32 { + self.money + } + + fn pay(&mut self, pennies: u32) { + self.money = self.money + pennies; + } + + fn deduct(&mut self, pennies: u32, message: Option<&str>) { + if pennies > self.money { + panic!("Deducted more money than the player had!"); + } + self.money = self.money - pennies; + } + + fn get_hand(&self, table: Vec) -> PokerHand { + let mut table_clone = table.clone(); + let mut total_cards = self.cards.clone(); + total_cards.append(&mut table_clone); + PokerHand::new(total_cards) + } +} + +// Ling Lallister +// Bao Amdahl +// Troy Cyberson +// Turbo Pocket +// Frances Netwall +// Nate Packer +// Lela Bacon +// Hinge Romton +// Deming Stellis +// Ryker Dedex +// Lillix Borg +// Alan Onishi +// Leeloo Phiser +// Cloud Sine +// Han Onishi +// Magda Hertz +// Akira Gallister +// Groat +// Tim diff --git a/src/pokerplayer.rs b/src/pokerplayer.rs deleted file mode 100644 index ef780ea..0000000 --- a/src/pokerplayer.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::card::PlayingCard; -use crate::hand::PokerHand; -use std::io; - -pub enum TurnAction { - Fold, - Call, - Raise(u32), -} - -pub struct PokerPlayer { - money: u32, - bet: u32, - cards: Vec, - is_remote: bool, -} - -impl PokerPlayer { - pub fn new(money: u32) -> Self { - PokerPlayer { - money, - bet: 0, - cards: vec![], - is_remote: false, - } - } - - pub fn deal_cards(&mut self, mut cards: Vec) { - self.cards.clear(); - self.cards.append(&mut cards); - // Todo send cards over the network - println!( - "You've been dealt the cards: {}, {}", - self.cards[0], self.cards[1] - ); - } - - pub fn get_hand(self, cards_on_table: &Vec) -> PokerHand { - let mut hand_cards = self.cards.clone(); - hand_cards.append(&mut cards_on_table.clone()); - let hand = PokerHand::new(hand_cards); - hand - } - - pub fn get_action(&self) -> TurnAction { - if self.is_remote { - return TurnAction::Fold; - } - - let mut user_input = String::new(); - let stdin = io::stdin(); - loop { - print!("What would you like to do?\nR: Raise\nC: Call\n:F\n Fold\n> "); - let _ = stdin.read_line(&mut user_input); - if user_input.len() == 0 { - continue; - } - let first_char = user_input.to_lowercase().chars().next().unwrap(); - match first_char { - 'f' => { - return TurnAction::Fold; - } - 'r' => { - return TurnAction::Raise(self.get_raise()); - } - 'c' => { - return TurnAction::Call; - } - _ => { - continue; - } - } - } - } - - pub fn get_raise(&self) -> u32 { - if self.is_remote { - return 0; - } - - let mut user_input: String = String::new(); - let stdin = io::stdin(); - loop { - print!("Enter your raise.\n> "); - let _ = stdin.read_line(&mut user_input); - let user_input = user_input.replace("$", ""); - if user_input.len() == 0 { - continue; - } - let money = user_input.parse::(); - match money { - Ok(_) => { - let pennies = (money.unwrap() * 100.0).floor() as u32; - if pennies > self.money { - println!("You flat-footed dingus, you don't have that much money!"); - } - return pennies; - } - Err(err) => { - print!("That's not a number, dufus. What, are you trying to bet your bitcoin wallet or something? Enter a number.\n>"); - continue; - } - } - } - } -}