]> Untitled Git - axy/ft/poker.git/commitdiff
Crappy but somewhat decent impl for part of it master
authorAxy <gilliardmarthey.axel@gmail.com>
Tue, 23 Jun 2026 13:11:12 +0000 (15:11 +0200)
committerAxy <gilliardmarthey.axel@gmail.com>
Tue, 23 Jun 2026 13:11:12 +0000 (15:11 +0200)
.gitignore [new file with mode: 0644]
Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
src/main.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ea8c4bf
--- /dev/null
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..444e6f7
--- /dev/null
@@ -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 (file)
index 0000000..1e8179b
--- /dev/null
@@ -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 (file)
index 0000000..a73928b
--- /dev/null
@@ -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<dyn Fn(usize, &Game) -> 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<Player>,
+    deck: Vec<Card>,
+    board: Vec<Card>,
+    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<Player> {
+        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!");
+}