diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4d9636b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "rust-analyzer.showUnlinkedFileNotification": false +} \ No newline at end of file diff --git a/src/card.rs b/src/card.rs index a730b78..d28e00d 100644 --- a/src/card.rs +++ b/src/card.rs @@ -26,7 +26,7 @@ pub enum CardValue { Ace, } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Clone, Copy)] pub struct PlayingCard { pub value: CardValue, pub suit: CardSuit, diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..7dcf73a --- /dev/null +++ b/src/game.rs @@ -0,0 +1,69 @@ +use crate::{ + card::{create_deck, draw_card, PlayingCard}, + pokerplayer::PokerPlayer, +}; +enum GameStage { + PreFlop, + Flop, + Turn, + River, + Reveal, +} + +struct PokerGame { + players: Vec, + big_blind: u32, // Index of player who should post the Big Blind + pot: u32, // Money in pennies + stage: GameStage, + deck: Vec, +} + +impl PokerGame { + pub fn new(players: Vec) -> PokerGame { + let first_player = 0; + PokerGame { + players, + big_blind: 0, + pot: 0, + stage: GameStage::PreFlop, + deck: create_deck(), + } + } + + pub fn play_stage(&mut self) { + match self.stage { + GameStage::PreFlop => self.play_preflop(), + GameStage::Flop => self.play_flop(), + GameStage::Turn => self.play_turn_or_river(), + GameStage::River => self.play_turn_or_river(), + GameStage::Reveal => self.play_reveal(), + } + } + + /// Preflop: + /// - Deal cards to all of the players + /// - Collect big and small blinds + /// - Players make their first round of actions + fn play_preflop(&mut self) { + for player in &mut self.players { + let dealt_cards = vec![draw_card(&mut self.deck), draw_card(&mut self.deck)]; + player.deal_cards(dealt_cards); + } + } + + /// Flop: + /// - Play three cards to the table + /// - Players make a round of bets + fn play_flop(&self) {} + + /// Turn: + /// - Play another card to the table + /// - Players make a round of bets + fn play_turn_or_river(&self) {} + + /// Reveal: + /// - All players cards are revealed + /// - Hands are compared, winner is decided + /// - Payout is presented + fn play_reveal(&self) {} +} diff --git a/src/hand.rs b/src/hand.rs index 4c58f63..3ed81f6 100644 --- a/src/hand.rs +++ b/src/hand.rs @@ -16,7 +16,7 @@ pub enum HandType { } #[derive(PartialEq)] -struct PokerHand { +pub struct PokerHand { cards: Vec, } @@ -143,7 +143,7 @@ impl PartialOrd for PokerHand { } impl PokerHand { - fn new(mut cards: Vec) -> Self { + pub fn new(mut cards: Vec) -> Self { assert!(cards.len() == 5); // Sorted highest card first @@ -172,7 +172,7 @@ impl PokerHand { count } - fn hand_type(&self) -> HandType { + pub fn hand_type(&self) -> HandType { if is_straight_flush(self) { return HandType::StraightFlush; } diff --git a/src/main.rs b/src/main.rs index 9ea0ca0..d4edcd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,17 @@ #![allow(dead_code)] - +#![allow(unused_variables)] use std::vec; mod card; +mod game; mod hand; +mod pokerplayer; use crate::card::{create_deck, CardSuit, CardValue, PlayingCard}; use crate::hand::HandType; fn main() { - let mut deck = create_deck(); + let deck = create_deck(); let card1: PlayingCard = PlayingCard { suit: CardSuit::Clubs, diff --git a/src/pokerplayer.rs b/src/pokerplayer.rs new file mode 100644 index 0000000..ef780ea --- /dev/null +++ b/src/pokerplayer.rs @@ -0,0 +1,106 @@ +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; + } + } + } + } +}