use std::fmt;
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum GameVariant {
TexasHoldem,
OmahaHoldem4, OmahaHoldem5, OmahaHoldem6, }
impl fmt::Display for GameVariant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GameVariant::TexasHoldem => write!(f, "Texas Hold'em"),
GameVariant::OmahaHoldem4 => write!(f, "Pot-Limit Omaha (4-card)"),
GameVariant::OmahaHoldem5 => write!(f, "Pot-Limit Omaha (5-card)"),
GameVariant::OmahaHoldem6 => write!(f, "Pot-Limit Omaha (6-card)"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BettingStructure {
NoLimit,
PotLimit,
FixedLimit,
}
impl fmt::Display for BettingStructure {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BettingStructure::NoLimit => write!(f, "No-Limit"),
BettingStructure::PotLimit => write!(f, "Pot-Limit"),
BettingStructure::FixedLimit => write!(f, "Fixed-Limit"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GameRules {
pub variant: GameVariant,
pub betting_structure: BettingStructure,
pub small_blind: u32,
pub big_blind: u32,
pub ante: u32,
pub min_players: usize,
pub max_players: usize,
pub hole_cards: usize,
pub is_pot_limit: bool,
}
impl GameRules {
pub fn nlhe(small_blind: u32, big_blind: u32) -> Self {
Self {
variant: GameVariant::TexasHoldem,
betting_structure: BettingStructure::NoLimit,
small_blind,
big_blind,
ante: 0,
min_players: 2,
max_players: 10,
hole_cards: 2,
is_pot_limit: false,
}
}
pub fn plo4(small_blind: u32, big_blind: u32) -> Self {
Self {
variant: GameVariant::OmahaHoldem4,
betting_structure: BettingStructure::PotLimit,
small_blind,
big_blind,
ante: 0,
min_players: 2,
max_players: 10,
hole_cards: 4,
is_pot_limit: true,
}
}
pub fn plo5(small_blind: u32, big_blind: u32) -> Self {
Self {
variant: GameVariant::OmahaHoldem5,
betting_structure: BettingStructure::PotLimit,
small_blind,
big_blind,
ante: 0,
min_players: 2,
max_players: 10,
hole_cards: 5,
is_pot_limit: true,
}
}
pub fn plo6(small_blind: u32, big_blind: u32) -> Self {
Self {
variant: GameVariant::OmahaHoldem6,
betting_structure: BettingStructure::PotLimit,
small_blind,
big_blind,
ante: 0,
min_players: 2,
max_players: 9, hole_cards: 6,
is_pot_limit: true,
}
}
pub fn plo(small_blind: u32, big_blind: u32) -> Self {
Self::plo4(small_blind, big_blind)
}
pub fn with_ante(mut self, ante: u32) -> Self {
self.ante = ante;
self
}
pub fn with_player_limits(mut self, min: usize, max: usize) -> Self {
self.min_players = min;
self.max_players = max;
self
}
pub fn min_raise(&self) -> u32 {
self.big_blind
}
pub fn is_valid_raise(&self, current_bet: u32, raise_to: u32, pot_size: u32) -> bool {
match self.betting_structure {
BettingStructure::NoLimit => {
raise_to >= current_bet + self.min_raise()
},
BettingStructure::PotLimit => {
let min_valid = current_bet + self.min_raise();
let max_valid = current_bet + pot_size;
raise_to >= min_valid && raise_to <= max_valid
},
BettingStructure::FixedLimit => {
raise_to == current_bet + self.big_blind
},
}
}
}