From: Axy Date: Tue, 23 Jun 2026 13:11:12 +0000 (+0200) Subject: Crappy but somewhat decent impl for part of it X-Git-Url: https://git.uwuaxy.net/sitemap.xml?a=commitdiff_plain;p=axy%2Fft%2Fpoker.git Crappy but somewhat decent impl for part of it --- 9db260ef01a4068396503b2824f6313efd5366d9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..444e6f7 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,140 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "poker" +version = "0.1.0" +dependencies = [ + "rand", + "strum", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1e8179b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "poker" +version = "0.1.0" +edition = "2024" + +[dependencies] +rand = "0.10.1" +strum = { version = "0.28.0", features = ["derive"] } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a73928b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,167 @@ +use std::iter::from_fn; + +use rand::{rng, seq::SliceRandom}; +use strum::VariantArray; + +#[derive(VariantArray, Clone, Copy)] +enum Color { + Spade, + Heart, + Diamond, + Clubs, +} + +#[derive(VariantArray, Clone, Copy)] +enum CardKind { + Two, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine, + Ten, + Jack, + Queen, + King, + Ace, +} + +#[derive(Clone, Copy)] +struct Card { + color: Color, + kind: CardKind, +} + +enum PlayAction { + Fold, + CheckCall, + Raise(u64), +} + +struct Player { + money: u64, + folded: bool, + curr_bet: u64, + hand: [Card; 2], + strategy: Box PlayAction>, +} + +impl Player { + fn bet(&mut self, amount: u64) { + if self.folded { + return; + } + let amount = amount.min(self.money); + self.money -= amount; + self.folded = self.money == 0; + self.curr_bet += amount; + } +} + +#[derive(VariantArray, Clone, Copy)] +enum GameState { + PreFlop, + Flop, + Turn, + River, +} + +struct Game { + players: Vec, + deck: Vec, + board: Vec, + sb: u64, + bb: u64, +} + +impl Game { + fn should_showdown(&mut self) -> bool { + self.players.iter().filter(|p| !p.folded).count() == 1 + } + fn betting_step(&mut self, step: GameState) { + let mut i = 0; + let mut amount_to_match = self + .players + .iter() + .max_by_key(|p| p.curr_bet) + .unwrap() + .curr_bet; + let mut bet_end = 0; + if let GameState::PreFlop = step { + self.players[0].bet(self.sb); + self.players[0].bet(self.bb); + amount_to_match += self.bb; + bet_end = 2; + i += 2; + } + while !self.should_showdown() { + if self.players[i].folded { + i = (i + 1) % self.players.len(); + continue; + } + match (self.players[i].strategy)(i, &*self) { + PlayAction::Fold => self.players[i].folded = true, + PlayAction::CheckCall => { + let amount = amount_to_match - self.players[i].curr_bet; + self.players[i].bet(amount) + } + PlayAction::Raise(n) => { + let amount = amount_to_match - self.players[i].curr_bet + n; + self.players[i].bet(amount); + amount_to_match += n; + } + } + i = (i + 1) % self.players.len(); + if i == bet_end { + break; + } + } + } + fn deal_step(&mut self, step: GameState) { + match step { + GameState::PreFlop => { + self.board.clear(); + self.deck.clear(); + self.deck.extend(CardKind::VARIANTS.iter().flat_map(|kind| { + Color::VARIANTS.into_iter().map(|color| Card { + color: *color, + kind: *kind, + }) + })); + self.deck.shuffle(&mut rng()); + for player in &mut self.players { + player.hand = [self.deck.pop().unwrap(), self.deck.pop().unwrap()] + } + } + GameState::Flop => self.board.extend(from_fn(|| self.deck.pop()).take(3)), + GameState::Turn => self.board.extend(self.deck.pop()), + GameState::River => self.board.extend(self.deck.pop()), + } + } + fn play_round(&mut self) { + for step in GameState::VARIANTS { + self.deal_step(*step); + self.betting_step(*step); + if self.should_showdown() { + break; + } + } + self.round_showdown(); + } + fn round_showdown(&mut self) {} + fn play(&mut self) -> Option { + loop { + self.players.rotate_left(1); + self.players.retain(|p| p.money != 0); + if self.players.len() < 2 { + return self.players.pop(); + } + } + } +} + +fn main() { + println!("Hello, world!"); +}