### Start Game Room HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Start a new game room by sending a POST request to the `/room/start` endpoint with authentication. The response includes the `room_id` for the newly created room. ```bash # Game room management (WebSocket-based live poker) curl -X POST http://localhost:8080/room/start \ -H "Authorization: Bearer eyJ..." # → { "room_id": "01234567-..." } ``` -------------------------------- ### Start Unified HTTP Server Source: https://context7.com/krukah/robopoker/llms.txt Start the unified `rbp-server` which exposes a JSON analysis API and WebSocket-based live game hosting. The server can be configured to bind to a specific address using the `BIND_ADDR` environment variable. ```bash # Start the unified server BIND_ADDR="0.0.0.0:8080" ./target/release/backend ``` -------------------------------- ### Get Full Averaged Strategy Distribution Source: https://context7.com/krukah/robopoker/llms.txt Demonstrates how to efficiently obtain the complete averaged strategy distribution for an information set in a single pass. ```rust // Full distribution for an info set in one pass (efficient) let dist = profile.averaged_distribution(&RpsTurn::P1); // dist is a Policy mapping each edge to its probability ``` -------------------------------- ### Connect to Game Room via WebSocket Source: https://context7.com/krukah/robopoker/llms.txt Connect to a game room using a WebSocket client. The connection URL requires the `room_id` obtained from starting a room. ```bash # Connect via WebSocket: # ws://localhost:8080/room/enter/{room_id} ``` -------------------------------- ### Programmatic Training with Trainer Trait Source: https://context7.com/krukah/robopoker/llms.txt Programmatically initiate training using the `Trainer` trait and `FastMode`. This function creates a `FastMode` trainer instance and starts the training process, which continues until interrupted or a budget is exhausted, after which it syncs to the database. ```rust use rbp_autotrain::{Trainer, FastMode}; async fn run_training(client: std::sync::Arc) { let trainer = FastMode::new(client).await; // Runs until interrupted or budget exhausted, then syncs to DB trainer.train().await; } ``` -------------------------------- ### Game Configuration Constants Source: https://context7.com/krukah/robopoker/llms.txt Defines core game configuration constants such as the number of players, starting stacks, and blind bet values. ```rust use rbp_core::*; // Game configuration assert_eq!(N, 2); // heads-up (2 players) assert_eq!(STACK, 100); // 100bb starting stacks assert_eq!(B_BLIND, 2); assert_eq!(S_BLIND, 1); ``` -------------------------------- ### Manage No-Limit Texas Hold'em State with Game Source: https://context7.com/krukah/robopoker/llms.txt The `Game` struct implements a memoryless, functional state machine for heads-up No-Limit Texas Hold'em. Use `Game::root()` to get the initial state and `apply()` for pure state transitions. It provides methods to query game state, legal actions, and advance to the next hand. Graceful action coercion is also supported. ```rust use rbp_gameplay::{Game, Action, Turn, Street}; use rbp_cards::Street as CardStreet; // Canonical root state: blinds posted, ready for dealer to act let game = Game::root(); assert_eq!(game.pot(), 3); // SB(1) + BB(2) assert_eq!(game.street(), CardStreet::Pref); assert!(matches!(game.turn(), Turn::Choice(_))); // dealer acts first // Enumerate legal actions let legal = game.legal(); // [Fold, Call(1), Raise(3), Shove(99)] assert!(legal.contains(&Action::Fold)); assert!(legal.iter().any(|a| matches!(a, Action::Raise(_)))); // Functional state transition let game = game.apply(Action::Call(1)).apply(Action::Check); assert!(game.must_deal()); // both players matched, deal flop // Deal community cards let flop = game.draw(); // random 3-card flop let game = game.apply(Action::Draw(flop)); assert_eq!(game.street(), CardStreet::Flop); assert!(matches!(game.turn(), Turn::Choice(_))); // Graceful action coercion (oversized raise → shove, fold without bet → check) let coerced = game.snap(Action::Raise(99999)); // → Shove(stack) // Terminal state let mut g = Game::root().apply(Action::Fold); assert!(g.must_stop()); let settlements = g.settlements(); // chip distributions per player println!("P0 net: {}", settlements[0].won()); // -1 (lost SB) println!("P1 net: {}", settlements[1].won()); // +1 (won SB) // Advance to next hand (returns None if player busts) let next = g.continuation().unwrap(); assert_eq!(next.street(), CardStreet::Pref); assert_eq!(next.pot(), 3); // Simulate a full session (stops when player busts) let total_hands = Game::root().hands().count(); println!("Hands played before bust: {}", total_hands); ``` -------------------------------- ### Health Check HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Perform a health check on the running server by sending a GET request to the `/health` endpoint. A successful response returns 'ok'. ```bash # Health check curl http://localhost:8080/health # → "ok" ``` -------------------------------- ### Generate Documentation Source: https://github.com/krukah/robopoker/blob/main/README.md Generate documentation for the workspace without dependencies and open it in a browser. ```bash cargo doc --workspace --no-deps --open ``` -------------------------------- ### Build with Database Features Source: https://github.com/krukah/robopoker/blob/main/README.md Build the workspace with specific features enabled, such as database integration. ```bash cargo build --workspace --features database ``` -------------------------------- ### Step-by-Step RPS Solver Training Source: https://context7.com/krukah/robopoker/llms.txt Shows how to train an RPS solver incrementally using the `step` method, allowing for periodic checkpointing or logging of exploitability. ```rust let mut solver = RPS::::default(); for i in 0..1000 { solver.step(); if i % 100 == 0 { println!("Epoch {}: exploitability = {:.4}", i, Solver::exploitability(&solver)); } } ``` -------------------------------- ### Run Training with Trainer Binary Source: https://context7.com/krukah/robopoker/llms.txt Use the trainer binary for production deployments. It supports various modes like status checks, clustering, fast in-memory training, and distributed training synchronized via PostgreSQL. Training duration can be controlled via environment variables. ```bash # Using the trainer binary (recommended for production): # cargo build --workspace --features database,server --release # # Check training status: # ./target/release/trainer --status # # Run clustering phase (hierarchical k-means, ~hours on 16 vCPU): # ./target/release/trainer --cluster # # Run fast in-memory MCCFR training: # ./target/release/trainer --fast # # Run distributed MCCFR (workers sync via PostgreSQL): # ./target/release/trainer --slow # # Set timed run via env var (e.g., 2 hours): # TRAIN_DURATION=2h ./target/release/trainer --fast # # Graceful stop: type Q + Enter # Hard stop: Ctrl+C ``` -------------------------------- ### Query Averaged Strategy from Profile Source: https://context7.com/krukah/robopoker/llms.txt Demonstrates how to query the Nash-approximating average strategy for a specific turn and edge from a solver's profile. ```rust use rbp_mccfr::{Profile, Solver, RPS, FlooredRegret, LinearWeight, ExternalSampling}; use rbp_mccfr::{RpsTurn, RpsEdge}; type Blueprint = RPS; let solver = Blueprint::default().solve(); let profile = solver.profile(); // Query averaged (Nash-approx) strategy for player P1, action Rock let prob_rock = Profile::averaged(profile, &RpsTurn::P1, &RpsEdge::R); println!("P1 Rock: {:.3}", prob_rock); // ≈ 0.40 in asymmetric RPS ``` -------------------------------- ### Build All Crates Source: https://github.com/krukah/robopoker/blob/main/README.md Use this command to build all the crates within the workspace. ```bash cargo build --workspace ``` -------------------------------- ### Initialize and Train NlheSolver Source: https://context7.com/krukah/robopoker/llms.txt Shows the initialization of an NlheSolver for No-Limit Hold'em using an in-memory encoder and profile, followed by running the training loop. ```rust use rbp_nlhe::{Flagship, NlheEncoder, NlheProfile, NlheSolver}; use rbp_mccfr::{Solver, PluribusRegret, LinearWeight, PluribusSampling}; // Build from in-memory encoder and profile (training from scratch) let encoder = NlheEncoder::default(); let profile = NlheProfile::default(); let solver = Flagship::new(profile, encoder); // Run training loop (production: use trainer binary for PostgreSQL + interrupt handling) let trained_solver = solver.solve(); ``` -------------------------------- ### Load NlheSolver from PostgreSQL Source: https://context7.com/krukah/robopoker/llms.txt Demonstrates loading a trained NlheSolver from a PostgreSQL database, requiring the 'database' feature to be enabled. ```rust // Load from PostgreSQL (requires `database` feature) #[cfg(feature = "database")] { use rbp_database::Hydrate; let client = rbp_database::db().await; let solver: Flagship = Flagship::hydrate(std::sync::Arc::new(client)).await; } ``` -------------------------------- ### Trainer Binary Usage Source: https://context7.com/krukah/robopoker/llms.txt Command-line interface for the trainer binary to manage training processes. ```APIDOC ## Trainer Binary Usage This section details how to use the `trainer` binary for various training orchestration tasks. ### Commands - **Check training status:** `./target/release/trainer --status` - **Run clustering phase:** `./target/release/trainer --cluster` - **Run fast in-memory MCCFR training:** `./target/release/trainer --fast` - **Run distributed MCCFR training:** `./target/release/trainer --slow` ### Environment Variables - **Set timed run duration:** `TRAIN_DURATION=2h ./target/release/trainer --fast` ### Interaction - **Graceful stop:** Type `Q` + Enter - **Hard stop:** Ctrl+C ``` -------------------------------- ### Basic Rust Usage of Robopoker Cards and Gameplay Source: https://github.com/krukah/robopoker/blob/main/README.md Demonstrates basic usage of the robopoker library for creating a hand and evaluating its strength, as well as working with game observations and calculating equity. ```rust use rbp::cards::*; use rbp::gameplay::*; // Create a hand and evaluate it let hand = Hand::from("AcKsQhJdTc9h8s"); let strength = hand.evaluate(); // Work with observations let obs = Observation::from(Street::Flop); let equity = obs.equity(); ``` -------------------------------- ### HTTP Server - Game Room Management Source: https://context7.com/krukah/robopoker/llms.txt Endpoints for managing live game rooms. ```APIDOC ## POST /room/start ### Description Starts a new game room. Requires authentication. ### Method `POST` ### Endpoint `/room/start` ### Parameters #### Headers - **Authorization** (string) - Required - Bearer token for authentication (e.g., "Bearer eyJ..."). ### Response #### Success Response (200) - **room_id** (string) - The unique identifier for the newly created game room. ### Request Example ```bash curl -X POST http://localhost:8080/room/start \ -H "Authorization: Bearer eyJ..." ``` ### Response Example ```json { "room_id": "01234567-..." } ``` ## WebSocket /room/enter/{room_id} ### Description Connects to a specific game room via WebSocket to participate in live games. ### Endpoint `ws://localhost:8080/room/enter/{room_id}` ### Parameters #### Path Parameters - **room_id** (string) - Required - The ID of the room to enter. ``` -------------------------------- ### User Registration HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Register a new user by sending a POST request to the `/auth/register` endpoint with JSON payload containing username and password. ```bash # Authentication curl -X POST http://localhost:8080/auth/register \ -H "Content-Type: application/json" \ -d '{"username": "alice", "password": "secret"}' ``` -------------------------------- ### Create and Draw Cards from a Deck Source: https://context7.com/krukah/robopoker/llms.txt Initialize a new deck and draw cards one by one. Ensures cards are removed from the deck after drawing. ```rust use rbp_cards::{Deck, Hand, Street}; let mut deck = Deck::new(); // Fresh 52-card deck (36 with shortdeck feature) // Draw random cards one at a time let card1 = deck.draw(); let card2 = deck.draw(); assert!(!deck.contains(&card1)); // card removed from deck ``` -------------------------------- ### Sampling Parameters Constants Source: https://context7.com/krukah/robopoker/llms.txt Defines parameters for sampling strategies, including temperature for exploration uniformity, smoothing factor (pseudocount), and a minimum action probability floor for curiosity. ```rust // Sampling parameters assert_eq!(SAMPLING_TEMPERATURE, 2.0_f32); // higher = more uniform exploration assert_eq!(SAMPLING_SMOOTHING, 0.5_f32); // pseudocount added to numerator/denominator assert_eq!(SAMPLING_CURIOSITY, 0.01_f32); // minimum action probability floor ``` -------------------------------- ### Query Action Probabilities from Trained Profile Source: https://context7.com/krukah/robopoker/llms.txt Provides a comment indicating how to query action probabilities for a given information set and edge from a trained NlheSolver's profile. ```rust // Query action probabilities from trained profile use rbp_mccfr::Profile; // profile.averaged(&info, &edge) → probability of taking edge at info set ``` -------------------------------- ### Subgame Solving and Profile Refinement Source: https://context7.com/krukah/robopoker/llms.txt Illustrates how to perform subgame solving from a given game history to refine a solver, then extract the updated profile. ```rust // Subgame solving from a game history (real-time refinement) use rbp_gameplay::Partial; let recall: Partial = todo!("from game history"); let sub_solver = trained_solver.subgame(&recall); let refined = sub_solver.solve(); let sub_profile = refined.into_profile(); ``` -------------------------------- ### Run Tests Source: https://github.com/krukah/robopoker/blob/main/README.md Execute all tests within the workspace to ensure code correctness. ```bash cargo test --workspace ``` -------------------------------- ### HTTP Server - API: Blueprint Strategy Source: https://context7.com/krukah/robopoker/llms.txt Queries the blueprint strategy for a given observation. ```APIDOC ## POST /api/blueprint ### Description Retrieves the blueprint strategy for a specified game observation. Requires a trained database. ### Method `POST` ### Endpoint `/api/blueprint` ### Parameters #### Request Body - **observation** (string) - Required - The game observation string (e.g., "AsKs~QsJsTs"). #### Headers - **Authorization** (string) - Required - Bearer token for authentication (e.g., "Bearer eyJ..."). - **Content-Type** (string) - Required - Must be `application/json`. ### Request Example ```bash curl -X POST http://localhost:8080/api/blueprint \ -H "Authorization: Bearer eyJ..." \ -H "Content-Type: application/json" \ -d '{"observation": "AsKs~QsJsTs"}' ``` ``` -------------------------------- ### HTTP Server - API: K-Nearest Neighbor Abstractions Source: https://context7.com/krukah/robopoker/llms.txt Performs K-nearest neighbor search on abstractions. ```APIDOC ## POST /api/nbr-knn-abs ### Description Finds K-nearest neighbor abstractions based on a given abstraction value. ### Method `POST` ### Endpoint `/api/nbr-knn-abs` ### Parameters #### Request Body - **abstraction** (integer) - Required - The abstraction value to search around. - **k** (integer) - Required - The number of nearest neighbors to retrieve. ### Request Example ```bash curl -X POST http://localhost:8080/api/nbr-knn-abs \ -H "Content-Type: application/json" \ -d '{"abstraction": 42, "k": 5}' ``` ``` -------------------------------- ### Query Instantaneous Strategy and Regrets Source: https://context7.com/krukah/robopoker/llms.txt Shows how to retrieve the current (instantaneous) strategy and accumulated regrets for a given turn and edge from a profile. ```rust // Query instantaneous (current) strategy let instant_rock = Profile::iterated(profile, &RpsTurn::P1, &RpsEdge::R); // Accumulated regrets let regret = profile.cum_regret(&RpsTurn::P1, &RpsEdge::R); ``` -------------------------------- ### HTTP Server - Authentication Source: https://context7.com/krukah/robopoker/llms.txt Endpoints for user registration and login. ```APIDOC ## POST /auth/register ### Description Registers a new user with the provided username and password. ### Method `POST` ### Endpoint `/auth/register` ### Parameters #### Request Body - **username** (string) - Required - The desired username. - **password** (string) - Required - The user's password. ### Request Example ```bash curl -X POST http://localhost:8080/auth/register \ -H "Content-Type: application/json" \ -d '{"username": "alice", "password": "secret"}' ``` ## POST /auth/login ### Description Logs in a user with the provided username and password. Returns an authentication token upon successful login. ### Method `POST` ### Endpoint `/auth/login` ### Parameters #### Request Body - **username** (string) - Required - The user's username. - **password** (string) - Required - The user's password. ### Request Example ```bash curl -X POST http://localhost:8080/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "alice", "password": "secret"}' ``` ### Response #### Success Response (200) - **token** (string) - The authentication token for subsequent requests. ### Response Example ```json { "token": "eyJ..." } ``` ``` -------------------------------- ### Calculate Exploitability Requiring Full Tree Source: https://context7.com/krukah/robopoker/llms.txt Illustrates the calculation of exploitability, which requires a fully built vanilla sampling tree. The placeholder indicates where the tree should be passed. ```rust // Exploitability (lower = closer to Nash equilibrium) // Requires building full tree via TreeBuilder with VanillaSampling let e = Profile::exploitability(profile, { // pass a full vanilla tree todo!("build tree first via Solver::exploitability()") }); ``` -------------------------------- ### Build Deck from Known Cards Source: https://context7.com/krukah/robopoker/llms.txt Construct a deck from the complement of a given set of known cards. Useful when some cards are already revealed. ```rust // Build deck from complement of known cards let mut known = Hand::try_from("AsKs").unwrap(); let remaining_deck = Deck::from(known.complement()); // 50-card deck ``` -------------------------------- ### User Login HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Log in a user by sending a POST request to the `/auth/login` endpoint with JSON payload containing username and password. A successful login returns an authentication token. ```bash curl -X POST http://localhost:8080/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "alice", "password": "secret"}' # → { "token": "eyJ..." } ``` -------------------------------- ### Train RPS Solver and Check Exploitability Source: https://context7.com/krukah/robopoker/llms.txt Demonstrates training a Rock-Paper-Scissors (RPS) game using the Solver trait with specific algorithm variants. Exploitability is checked after training. ```rust use rbp_mccfr::{ Solver, RPS, ExternalSampling, FlooredRegret, LinearWeight, PluribusSampling, PluribusRegret, }; // Rock-Paper-Scissors reference game — converges in ~16K iterations type RpsVariant = RPS; let solver = RpsVariant::default().solve(); println!("{}", solver); // prints strategy table with exploitability // Exploitability should be < 0.03 after 2^14 iterations let exploitability = Solver::exploitability(&solver); assert!(exploitability < 0.03); ``` -------------------------------- ### Query Blueprint Strategy HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Query the blueprint strategy for a given observation by sending a POST request to the `/api/blueprint` endpoint. Requires a trained database and an Authorization header. ```bash # Query blueprint strategy for an observation (requires trained DB) curl -X POST http://localhost:8080/api/blueprint \ -H "Authorization: Bearer eyJ..." \ -H "Content-Type: application/json" \ -d '{"observation": "AsKs~QsJsTs"}' ``` -------------------------------- ### Probabilistic Pruning Constants Source: https://context7.com/krukah/robopoker/llms.txt Configuration for probabilistic pruning (Pluribus variant), including the regret threshold for pruning candidates, the probability of exploring pruned actions, and a warm-up period before pruning activates. ```rust // Probabilistic pruning (Pluribus variant) assert_eq!(PRUNING_THRESHOLD, -3e5_f32); // regret threshold for pruning candidate assert_eq!(PRUNING_EXPLORE, 0.05_f32); // probability of still sampling pruned actions assert_eq!(PRUNING_WARMUP, 524288_usize); // warm-up epochs before pruning activates ``` -------------------------------- ### NlheSolver / Flagship - Production NLHE Solver Source: https://context7.com/krukah/robopoker/llms.txt NlheSolver is a specialized implementation of the Solver trait for No-Limit Hold'em (NLHE), utilizing NlheEncoder and NlheProfile. Flagship is a type alias configured for the Pluribus paper's specifications. ```APIDOC ## `NlheSolver` / `Flagship` — Production NLHE solver `NlheSolver` wires `NlheEncoder` (state→info abstraction) and `NlheProfile` (regret/weight storage) into the `Solver` trait for NLHE. `Flagship` is the type alias configured to match the Pluribus paper. ```rust use rbp_nlhe::{Flagship, NlheEncoder, NlheProfile, NlheSolver}; use rbp_mccfr::{Solver, PluribusRegret, LinearWeight, PluribusSampling}; // Build from in-memory encoder and profile (training from scratch) let encoder = NlheEncoder::default(); let profile = NlheProfile::default(); let solver = Flagship::new(profile, encoder); // Run training loop (production: use trainer binary for PostgreSQL + interrupt handling) let trained_solver = solver.solve(); // Load from PostgreSQL (requires `database` feature) #[cfg(feature = "database")] { use rbp_database::Hydrate; let client = rbp_database::db().await; let solver: Flagship = Flagship::hydrate(std::sync::Arc::new(client)).await; } // Subgame solving from a game history (real-time refinement) use rbp_gameplay::Partial; let recall: Partial = todo!("from game history"); let sub_solver = trained_solver.subgame(&recall); let refined = sub_solver.solve(); let sub_profile = refined.into_profile(); // Query action probabilities from trained profile use rbp_mccfr::Profile; // profile.averaged(&info, &edge) → probability of taking edge at info set ``` ``` -------------------------------- ### K-Nearest Neighbor Abstractions HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Perform a K-nearest neighbor abstraction search by sending a POST request to the `/api/nbr-knn-abs` endpoint with the desired abstraction and K value. ```bash # K-nearest neighbor abstractions curl -X POST http://localhost:8080/api/nbr-knn-abs \ -H "Content-Type: application/json" \ -d '{"abstraction": 42, "k": 5}' ``` -------------------------------- ### Create Observation from Street Source: https://context7.com/krukah/robopoker/llms.txt Construct an Observation object representing a game state at a specific street, using a random deal for the cards. ```rust use rbp_cards::{Observation, Street, Hand}; // Construct from street (random deal) let river_obs = Observation::from(Street::Rive); ``` -------------------------------- ### Add Robopoker Crates to Cargo.toml Source: https://context7.com/krukah/robopoker/llms.txt Add individual crates to your Cargo.toml to select only the layers you need. The full facade re-exports all public crates. ```toml [dependencies] # Full facade re-exports all public crates rbp = "1.0" # Or individual crates for lean dependency trees: rbp-cards = "1.0" # Card primitives, evaluation, equity rbp-gameplay = "1.0" # NLHE game engine rbp-mccfr = "1.0" # Generic CFR framework rbp-nlhe = "1.0" # NLHE-specific CFR wiring rbp-transport = "1.0" # Optimal transport / EMD rbp-clustering = "1.0" # K-means abstraction # Feature flags rbp-nlhe = { version = "1.0", features = ["database"] } # Enable PostgreSQL sink/source rbp-nlhe = { version = "1.0", features = ["server"] } # Enable Rayon parallel batch rbp-cards = { version = "1.0", features = ["shortdeck"] } # 36-card variant ``` -------------------------------- ### Expected Value by Observation HTTP Endpoint Source: https://context7.com/krukah/robopoker/llms.txt Calculate the expected value for a given observation by sending a POST request to the `/api/exp-wrt-obs` endpoint with the observation data. ```bash # Expected value for a given observation curl -X POST http://localhost:8080/api/exp-wrt-obs \ -H "Content-Type: application/json" \ -d '{"observation": "AhKh~QhJhTh"}' ``` -------------------------------- ### Create Observation from String Representation Source: https://context7.com/krukah/robopoker/llms.txt Construct an Observation object from a string format representing hole cards and board cards. Verifies the street of the observation. ```rust // Construct from string ("pocket ~ board") let obs = Observation::try_from("AsKs ~ QsJsTs").unwrap(); assert_eq!(obs.street(), Street::Rive); ``` -------------------------------- ### Add Robopoker to Cargo.toml Source: https://github.com/krukah/robopoker/blob/main/README.md Include Robopoker as a dependency in your project's Cargo.toml file. You can add the main crate or individual components. ```toml [dependencies] rbp = "1.0" # Or individual crates: rbp-cards = "1.0" rbp-gameplay = "1.0" rbp-mccfr = "1.0" ``` -------------------------------- ### K-Means Clustering Constants Source: https://context7.com/krukah/robopoker/llms.txt Specifies the cluster counts for K-means clustering at different stages of the game: flop, turn, and equity histogram. ```rust // K-means clustering assert_eq!(KMEANS_FLOP_CLUSTER_COUNT, 128); assert_eq!(KMEANS_TURN_CLUSTER_COUNT, 144); assert_eq!(KMEANS_EQTY_CLUSTER_COUNT, 101); // equity histogram: 0%–100% ``` -------------------------------- ### Parse and Construct Card Source: https://context7.com/krukah/robopoker/llms.txt Parse card strings into `Card` objects or construct them from `(Rank, Suit)`. Supports round-trip conversions to `u8` and `u32` for efficient storage and evaluation. ```rust use rbp_cards::{Card, Rank, Suit}; // Parse from two-character string let ace_spades = Card::try_from("As").unwrap(); assert_eq!(ace_spades.rank(), Rank::Ace); assert_eq!(ace_spades.suit(), Suit::S); // Construct from (Rank, Suit) let ten_clubs = Card::from((Rank::Ten, Suit::C)); println!("{}", ten_clubs); // "Tc" // Round-trip through u8 (compact storage / serialization) let n: u8 = u8::from(ace_spades); assert_eq!(Card::from(n), ace_spades); // Round-trip through u32 (bitmask format used by Evaluator) let m: u32 = u32::from(ace_spades); assert_eq!(Card::from(m), ace_spades); // Batch parse space-separated cards let cards = Card::parse("Ah Kd Qc Js Th").unwrap(); assert_eq!(cards.len(), 5); ``` -------------------------------- ### Enumerate Opponent Hole Card Observations Source: https://context7.com/krukah/robopoker/llms.txt Enumerate all possible opponent hole-card observations given a specific board and street. Calculates the total number of unique opponent hand combinations. ```rust // Enumerate all possible opponent hole-card observations (same board, different pocket) let opponent_count = obs.opponents().count(); assert_eq!(opponent_count, 990); // C(45, 2) for river ``` -------------------------------- ### MCCFR Training Budget Constants Source: https://context7.com/krukah/robopoker/llms.txt Sets the batch size for MCCFR training, determining the number of trees generated per iteration in parallel processing. A larger batch size can speed up training. ```rust // MCCFR training budgets assert_eq!(CFR_BATCH_SIZE_NLHE, 128); // trees per iteration (parallel) // CFR_TREE_COUNT_NLHE = 0x10000000 // ~268M trees for production ``` -------------------------------- ### Deal Community Cards from a Deck Source: https://context7.com/krukah/robopoker/llms.txt Deal community cards for different streets (flop, turn, river) from a deck. Demonstrates dealing a specific number of cards for each street. ```rust // Deal community cards for the next street let mut deck2 = Deck::new(); let flop = deck2.deal(Street::Pref); // deals 3 cards (pref → flop transition) let turn = deck2.deal(Street::Flop); // deals 1 card let river = deck2.deal(Street::Turn); // deals 1 card ``` -------------------------------- ### Evaluate 7-Card Hand for Best 5-Card Ranking Source: https://context7.com/krukah/robopoker/llms.txt Evaluates a 7-card hand to automatically find the best 5-card poker ranking. This is typical for Texas Hold'em scenarios. ```rust // 7-card hand (Texas Hold'em board + hole cards) — best 5 extracted automatically let eval = Evaluator::from(Hand::try_from("As Ah Kd Kc Qs Jh 9d").unwrap()); assert_eq!(eval.find_ranking(), Ranking::TwoPair(Rank::Ace, Rank::King)); ``` -------------------------------- ### Bijective Serialization of Observation Source: https://context7.com/krukah/robopoker/llms.txt Serialize an Observation object to a bijective i64 representation and deserialize it back. Ensures data integrity for database storage. ```rust // Bijective i64 serialization for database let bits: i64 = i64::from(obs); let recovered = Observation::from(bits); assert_eq!(obs, recovered); ``` -------------------------------- ### HTTP Server - API: Expected Value Source: https://context7.com/krukah/robopoker/llms.txt Calculates the expected value for a given observation. ```APIDOC ## POST /api/exp-wrt-obs ### Description Calculates the expected value of a game state given a specific observation. ### Method `POST` ### Endpoint `/api/exp-wrt-obs` ### Parameters #### Request Body - **observation** (string) - Required - The game observation string (e.g., "AhKh~QhJhTh"). ### Request Example ```bash curl -X POST http://localhost:8080/api/exp-wrt-obs \ -H "Content-Type: application/json" \ -d '{"observation": "AhKh~QhJhTh"}' ``` ``` -------------------------------- ### Profile Trait - Strategy Storage and Regret Matching Source: https://context7.com/krukah/robopoker/llms.txt The Profile trait manages accumulated regrets, strategy weights, epoch tracking, and reach probability computations. Key methods include iterated (current strategy via regret matching), averaged (Nash-approximating average strategy), exploitability, and frontier_evalue. ```APIDOC ## `Profile` trait — Strategy storage and regret matching `Profile` manages accumulated regrets, strategy weights, epoch tracking, and reach probability computations. Key methods: `iterated` (current strategy via regret matching), `averaged` (Nash-approximating average strategy), `exploitability`, and `frontier_evalue` (for depth-limited subgame solving). ```rust use rbp_mccfr::{Profile, Solver, RPS, FlooredRegret, LinearWeight, ExternalSampling}; use rbp_mccfr::{RpsTurn, RpsEdge}; type Blueprint = RPS; let solver = Blueprint::default().solve(); let profile = solver.profile(); // Query averaged (Nash-approx) strategy for player P1, action Rock let prob_rock = Profile::averaged(profile, &RpsTurn::P1, &RpsEdge::R); println!("P1 Rock: {:.3}", prob_rock); // ≈ 0.40 in asymmetric RPS // Query instantaneous (current) strategy let instant_rock = Profile::iterated(profile, &RpsTurn::P1, &RpsEdge::R); // Accumulated regrets let regret = profile.cum_regret(&RpsTurn::P1, &RpsEdge::R); // Full distribution for an info set in one pass (efficient) let dist = profile.averaged_distribution(&RpsTurn::P1); // dist is a Policy mapping each edge to its probability // Exploitability (lower = closer to Nash equilibrium) // Requires building full tree via TreeBuilder with VanillaSampling let e = Profile::exploitability(profile, { // pass a full vanilla tree todo!("build tree first via Solver::exploitability()") }); ``` ``` -------------------------------- ### Normalize Card Observations with Isomorphism Source: https://context7.com/krukah/robopoker/llms.txt Use `Isomorphism` to reduce observations to a canonical form, normalizing them under suit permutations. This is useful for comparing strategically identical situations that only differ by suit labeling. Round-trip conversions between `Isomorphism` and `Observation` are supported. ```rust use rbp_cards::{Isomorphism, Observation, Hand}; // Two observations that differ only by suit relabeling let a = Isomorphism::from(Observation::try_from("AdKd ~ QdJdTd").unwrap()); let b = Isomorphism::from(Observation::try_from("AsKs ~ QsJsTs").unwrap()); assert_eq!(a, b); // same strategic situation // Check if an observation is already canonical let obs = Observation::from(rbp_cards::Street::Rive); let is_canonical = Isomorphism::is_canonical(&obs); // Round-trip: Isomorphism → Observation → Isomorphism let iso = Isomorphism::from(obs); let obs2 = Observation::from(iso); let iso2 = Isomorphism::from(obs2); assert_eq!(iso, iso2); ``` -------------------------------- ### Sinkhorn Optimal Transport Constants Source: https://context7.com/krukah/robopoker/llms.txt Defines parameters for Sinkhorn optimal transport, including temperature, number of iterations, and tolerance for convergence. ```rust // Sinkhorn optimal transport assert_eq!(SINKHORN_TEMPERATURE, 0.025_f32); assert_eq!(SINKHORN_ITERATIONS, 128); assert_eq!(SINKHORN_TOLERANCE, 0.001_f32); ``` -------------------------------- ### Solver Trait - MCCFR Training Loop Source: https://context7.com/krukah/robopoker/llms.txt The Solver trait provides default implementations for core Counterfactual Regret Minimization (CFR) operations like step, solve, batch, tree, counterfactual, and exploitability. It is parameterized over various game types, strategy storage, and algorithm variants. ```APIDOC ## `Solver` trait — MCCFR training loop The `Solver` trait is the core CFR abstraction. It is parameterized over game types (`T`, `E`, `G`, `I`, `X`, `Y`), strategy storage (`P`, `N`), and algorithm variants (`R: RegretSchedule`, `W: PolicySchedule`, `S: SamplingScheme`). Provides default implementations for `step`, `solve`, `batch`, `tree`, `counterfactual`, and `exploitability`. ```rust use rbp_mccfr::{ Solver, RPS, ExternalSampling, FlooredRegret, LinearWeight, PluribusSampling, PluribusRegret, }; // Rock-Paper-Scissors reference game — converges in ~16K iterations type RpsVariant = RPS; let solver = RpsVariant::default().solve(); println!("{}", solver); // prints strategy table with exploitability // Exploitability should be < 0.03 after 2^14 iterations let exploitability = Solver::exploitability(&solver); assert!(exploitability < 0.03); // Step-by-step training (to interleave with checkpointing) let mut solver = RPS::::default(); for i in 0..1000 { solver.step(); if i % 100 == 0 { println!("Epoch {}: exploitability = {:.4}", i, Solver::exploitability(&solver)); } } // Algorithm variant selection cheat-sheet: // Best overall: FlooredRegret + ExternalSampling + ConstantWeight/LinearWeight // Flagship NLHE: PluribusRegret + PluribusSampling + LinearWeight // Worst working: DiscountedRegret + TargetedSampling (4× iterations, 2.5× tolerance) ``` ``` -------------------------------- ### Calculate River Equity Source: https://context7.com/krukah/robopoker/llms.txt Calculate the equity of a given observation on the river. Equity is represented as the fraction of random opponent hands that the current hand beats. ```rust // Exact equity on river (fraction of random opponent hands we beat) let equity = obs.equity(); // 0.0 – 1.0 println!("Equity: {:.1}%", equity * 100.0); ``` -------------------------------- ### Hand Bitmask Operations Source: https://context7.com/krukah/robopoker/llms.txt Utilize `Hand` for efficient bitwise set operations on cards. Supports construction from strings, set operations, suit filtering, membership checks, and iteration. ```rust use rbp_cards::{Card, Hand, Suit}; // Construct from string let hand = Hand::try_from("Ah Kd Qc Js Th").unwrap(); assert_eq!(hand.size(), 5); // Set operations let deck_minus_hand = hand.complement(); // remaining 47 cards let merged = Hand::or(hand, Hand::empty()); // union (idempotent) // Filter by suit let spades_only = hand.of(&Suit::S); // Contains check (O(1)) let ace = Card::try_from("Ah").unwrap(); assert!(hand.contains(&ace)); // Iteration (consumes hand — clone first to preserve) let mut iter = hand; while let Some(card) = iter.next() { println!("{}", card); // Th, Js, Qc, Kd, Ah (low to high) } // Collect from iterator let rebuilt: Hand = vec![ Card::try_from("2c").unwrap(), Card::try_from("Ks").unwrap(), ].into_iter().collect(); // Rank bitmask (collapses suit info, zero-alloc) let rank_bits: u16 = hand.ranks(); // 13-bit bitmask, one bit per rank present ``` -------------------------------- ### Evaluate Straight Flush Hand Source: https://context7.com/krukah/robopoker/llms.txt Evaluates a hand to determine if it is a Straight Flush and identifies the highest rank. No kickers are present for a straight flush. ```rust // Straight flush let eval = Evaluator::from(Hand::try_from("Ts Js Qs Ks As").unwrap()); assert_eq!(eval.find_ranking(), Ranking::StraightFlush(Rank::Ace)); assert_eq!(eval.find_kickers(Ranking::StraightFlush(Rank::Ace)), Kickers::from(vec![])); ``` -------------------------------- ### Evaluate Wheel Straight Source: https://context7.com/krukah/robopoker/llms.txt Evaluates a hand containing the A-2-3-4-5 straight, recognizing Ace as the low card for the wheel straight. ```rust // Wheel straight (A plays as low) let eval = Evaluator::from(Hand::try_from("As 2h 3d 4c 5s").unwrap()); assert_eq!(eval.find_ranking(), Ranking::Straight(Rank::Five)); ``` -------------------------------- ### Trainer Trait Programmatic Usage Source: https://context7.com/krukah/robopoker/llms.txt Programmatic usage of the `Trainer` trait for initiating training loops. ```APIDOC ## Programmatic Trainer Usage This section demonstrates how to use the `Trainer` trait programmatically within your Rust code. ### Method `Trainer::train()` ### Description Initiates the training process. The training continues until interrupted or a budget is exhausted, after which it syncs results to the database. ### Example ```rust use rbp_autotrain::{Trainer, FastMode}; async fn run_training(client: std::sync::Arc) { let trainer = FastMode::new(client).await; trainer.train().await; } ``` ``` -------------------------------- ### Compare Hand Strengths Source: https://context7.com/krukah/robopoker/llms.txt Compares two hands based on their evaluated strength, implementing the `Ord` trait for direct comparison. Handles both hole and board cards combined. ```rust use rbp_cards::{Hand, Strength}; use std::cmp::Ordering; let hero_hand = Hand::try_from("AsAh 2d3d4d").unwrap(); // hole + board together let villain_hand = Hand::try_from("KsKh 2d3d4d").unwrap(); let hero = Strength::from(hero_hand); let villain = Strength::from(villain_hand); match hero.cmp(&villain) { Ordering::Greater => println!("Hero wins"), Ordering::Less => println!("Villain wins"), Ordering::Equal => println!("Chop"), } // Output: "Hero wins" ``` -------------------------------- ### Evaluate Four of a Kind Hand Source: https://context7.com/krukah/robopoker/llms.txt Evaluates a hand for Four of a Kind and identifies the kicker. This snippet demonstrates how to extract both the rank of the four cards and the single kicker. ```rust // Four of a kind with kicker let eval = Evaluator::from(Hand::try_from("As Ah Ad Ac Ks").unwrap()); let rank = eval.find_ranking(); let kicks = eval.find_kickers(rank); assert_eq!(rank, Ranking::FourOAK(Rank::Ace)); assert_eq!(kicks, Kickers::from(vec![Rank::King])); ``` -------------------------------- ### HTTP Server - Health Check Source: https://context7.com/krukah/robopoker/llms.txt Endpoint to check the health status of the backend server. ```APIDOC ## GET /health ### Description Checks the health status of the backend server. Returns `"ok"` if the server is running. ### Method `GET` ### Endpoint `/health` ### Response #### Success Response (200) - **response** (string) - Indicates server status, typically `"ok"`. ### Request Example ```bash curl http://localhost:8080/health ``` ### Response Example ``` "ok" ``` ``` -------------------------------- ### Iterate Next-Street Children Source: https://context7.com/krukah/robopoker/llms.txt Iterate over all possible next-street children from a given observation. This is useful for tree search algorithms and clustering. ```rust // Iterate next-street children (used in clustering / tree search) let flop_obs = Observation::try_from("AsKs ~ ").unwrap(); // preflop let num_flops = flop_obs.children().count(); // ~ 19,600 possible flops (C(50,3)) ``` -------------------------------- ### Evaluate Full House Hand Source: https://context7.com/krukah/robopoker/llms.txt Evaluates a hand to identify a Full House, correctly determining the rank of the three-of-a-kind and the rank of the pair. ```rust // Full house — finds triple + pair let eval = Evaluator::from(Hand::try_from("Kh Ah Ad As Ks Qs Js").unwrap()); assert_eq!(eval.find_ranking(), Ranking::FullHouse(Rank::Ace, Rank::King)); ``` -------------------------------- ### Enumerate Betting Rounds with Street Source: https://context7.com/krukah/robopoker/llms.txt The `Street` enum represents the four betting rounds (Pref, Flop, Turn, Rive) and provides combinatorial constants. Use it for navigating between rounds, querying card counts, and accessing k-means clustering parameters. It also supports parsing from a single-character string representation. ```rust use rbp_cards::Street; // Navigation assert_eq!(Street::Pref.next(), Street::Flop); assert_eq!(Street::Rive.prev(), Street::Turn); // Card counts assert_eq!(Street::Pref.n_observed(), 2); // hole cards only assert_eq!(Street::Flop.n_observed(), 5); // hole + 3 board assert_eq!(Street::Flop.n_revealed(), 3); // 3 cards dealt on flop // Combinatorics assert_eq!(Street::Pref.n_isomorphisms(), 169); assert_eq!(Street::Flop.n_isomorphisms(), 1_286_792); // K-means clustering parameters let flop_clusters = Street::Flop.k(); // KMEANS_FLOP_CLUSTER_COUNT (128) let flop_iters = Street::Flop.t(); // KMEANS_FLOP_TRAINING_ITERATIONS (20) // Parse from string let s = Street::try_from("R").unwrap(); assert_eq!(s, Street::Rive); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.