rusty_marvin/README.md
Jan-Peter v. Hunnius 912445d992 Fix supersonic evaluator and documentation examples
- Remove debug_assert(false) from supersonic evaluator
- Disable buggy supersonic generator
- Fix documentation examples in README.md and holdem_core/README.md
2026-05-25 14:30:16 +02:00

13 KiB
Raw Permalink Blame History

Poker Simulation Testbed

Crates.io Documentation License

A comprehensive poker simulation testbed and unit test framework for bot development. Features two Rust-native hand evaluators — the Cactus Kev perfect-hash evaluator (~100 KB tables) and the Supersonic LUT trie evaluator (~124 MB tables) — designed for automated poker bot testing, strategy analysis, and simulation at scale.

Recent Updates

  • Supersonic Evaluator: New high-throughput LUT trie evaluator (~124 MB) for O(n) hand evaluation
  • Dual Evaluator Architecture: Choose between Cactus Kev (compact) and Supersonic (fast) per use case
  • Simulation Testbed: Run cash games, SNGs, and MTTs with configurable bots via TOML
  • Input Validation: Added comprehensive validation to Card::new() ensuring rank (0-12) and suit (0-3) are within valid ranges
  • Enhanced Documentation: All public methods now include working code examples and panic condition documentation
  • Error Handling: Improved error handling throughout the codebase with proper Result types

Features

  • Bot Testing Framework: Specifically designed for automated poker bot testing and development
  • Dual Evaluators: Cactus Kev (compact ~100 KB) and Supersonic LUT trie (~124 MB) hand evaluators
  • Blazing Fast: Sub-microsecond hand evaluation using perfect hash and trie-based lookup
  • Memory Efficient: Choose between compact Cactus Kev tables or high-throughput Supersonic trie
  • Standards Compliant: Based on proven poker evaluation algorithms
  • Multi-Hand Support: Evaluate 5, 6, or 7-card poker hands
  • Texas Hold'em Ready: Optimized for Texas Hold'em bot analysis and testing
  • Comprehensive Testing: Extensive test suite with millions of verification cases
  • Deterministic Results: Consistent hand evaluation for reproducible bot testing
  • Simulation Engine: Run cash games, SNGs, and MTTs with configurable bots via TOML

Performance

Cactus Kev Evaluator

Hand Type Evaluation Time Method
5-Card ~50-100ns Single prime-product hash → table lookup
6-Card ~300-500ns Six 5-card lookups
7-Card ~1-2µs 21 enumeration + HashMap cache

Supersonic Evaluator

Hand Type Evaluation Time Method
5-Card O(5) array lookups Direct trie traversal
6-Card O(6) array lookups Direct trie traversal
7-Card O(7) array lookups Direct trie traversal

Documentation

For detailed project information, see:

  • VISION.md - Project goals and architectural vision
  • ROADMAP.md - Future development phases and implementation plan

Installation

Add this to your Cargo.toml:

[dependencies]
holdem_core = "0.1.0"

Quick Start - Bot Testing

use holdem_core::{Card, Hand, HoleCards, Board, Evaluator};
use std::str::FromStr;

// Create cards from string notation
let ace_spades = Card::from_str("As").unwrap();
let king_spades = Card::from_str("Ks").unwrap();

// Create hole cards from notation
let hole_cards = HoleCards::from_notation("AKs").unwrap();

// Create a board with community cards
let board = Board::new()
    .with_flop([
        Card::from_str("Qh").unwrap(),
        Card::from_str("Jh").unwrap(),
        Card::from_str("Th").unwrap(),
    ]).unwrap()
    .with_turn(Card::from_str("2c").unwrap()).unwrap()
    .with_river(Card::from_str("3d").unwrap()).unwrap();

// Create a hand from hole cards and board
let hand = Hand::from_hole_cards_and_board(&hole_cards, &board).unwrap();

// Evaluate the hand
let evaluator = Evaluator::new().unwrap();
let hand_value = evaluator.evaluate_hand(&hand);
println!("Hand rank: {:?}", hand_value.rank);

Bot Testing Capabilities

This framework provides specialized capabilities for poker bot testing and development:

Automated Bot Testing

  • Standardized Evaluation: Consistent hand evaluation across both Cactus Kev and Supersonic evaluators
  • Performance Benchmarking: Fast evaluation for large-scale bot performance testing
  • Range Analysis: Efficient hand range evaluation for bot strategy analysis
  • Decision Tree Testing: Quick hand strength calculation for bot decision trees

Dual Evaluator Support

  • Cactus Kev: Compact ~100 KB tables with prime-product hashing — ideal for memory-constrained environments
  • Supersonic: High-throughput ~124 MB LUT trie with O(n) array lookups — fastest for bulk evaluation
  • Algorithmic Fallback: Rule-based evaluator serves as correctness oracle for validation

Bot Development Features

  • Hole Card Analysis: Fast evaluation of starting hand strength for pre-flop bots
  • Post-Flop Analysis: Efficient board texture and hand strength analysis
  • Incremental Evaluation: Multi-street hand evaluation for complex bot scenarios
  • Memory Efficient: Optimized for bot testing environments with limited resources

Algorithm Overview

This library provides two hand evaluators with different performance/memory tradeoffs:

Cactus Kev Evaluator (compact)

Uses prime-product hashing into two small lookup tables (~100 KB total):

  1. Prime Product Hashing: Each rank maps to a unique prime; the product of 5 primes uniquely identifies the hand
  2. Dual Lookup Tables: 1,287 flush entries + 6,175 unsuited entries = 7,462 total (~30 KB)
  3. 7-card Cache: C(7,5)=21 enumeration with HashMap cache for amortized O(1) lookups
  4. Zero Collisions: Validated against all 2,598,960 five-card hands

Supersonic Evaluator (high-throughput)

Uses a pre-computed LUT trie (~124 MB) for O(n) array lookups:

  1. Trie Structure: 32,487,834 u32 entries organized in pages of 53 (one per card + base)
  2. Direct Lookup: Follow hand_ranks[p + card_index + 1] for each card — no enumeration needed
  3. Packed Hand Rank: 16-bit format (category + equivalency class) for compact result representation
  4. Best for Bulk: Fastest evaluator for large-scale simulations and batch evaluation

Table Generation

Lookup tables are generated automatically on first use and persisted to disk:

  • Cactus Kev: Small tables (~100 KB) generated in-memory from prime products
  • Supersonic: Large LUT trie (~124 MB) loaded from pre-generated binary file

Hand Types

The evaluator recognizes all standard poker hand types:

Hand Type Description Example
Straight Flush Five cards in sequence, same suit A♠ K♠ Q♠ J♠ T♠
Four of a Kind Four cards of same rank A♠ A♥ A♦ A♣ K♦
Full House Three of a kind + one pair K♠ K♥ K♦ Q♠ Q♥
Flush Five cards of same suit A♠ J♠ 8♠ 5♠ 2♠
Straight Five cards in sequence A♦ K♣ Q♥ J♠ T♦
Three of a Kind Three cards of same rank Q♠ Q♥ Q♦ A♣ 7♦
Two Pair Two different pairs J♠ J♥ 7♦ 7♣ A♦
One Pair Two cards of same rank A♠ A♥ K♦ Q♣ 7♦
High Card No matching cards A♠ K♥ Q♦ J♣ 9♦

Bot Testing Examples

Texas Hold'em Bot Analysis

use holdem_core::{Card, Hand, HoleCards, Board, Evaluator};
use std::str::FromStr;

let evaluator = Evaluator::new().unwrap();

// Bot analyzes hole cards + flop for decision making
let hole_cards = HoleCards::from_notation("AKs").unwrap();
let board = Board::new()
    .with_flop([
        Card::from_str("Td").unwrap(),
        Card::from_str("Jc").unwrap(),
        Card::from_str("Qh").unwrap(),
    ]).unwrap();

// Bot evaluates complete hand strength
let hand = Hand::from_hole_cards_and_board(&hole_cards, &board).unwrap();
let hand_value = evaluator.evaluate_hand(&hand);
println!("Hand strength after flop: {:?}", hand_value.rank);

// Bot uses this for post-flop decision making
if hand_value.rank as u8 >= 4 { // Straight or better
    println!("Bot: Continuing with strong hand");
}

Bot Range Analysis

use holdem_core::{Card, Hand, Evaluator};
use std::str::FromStr;

let evaluator = Evaluator::new().unwrap();

// Bot analyzes range of starting hands for pre-flop strategy
let premium_hands = vec![
    Hand::from_notation("As Ah").unwrap(),
    Hand::from_notation("Ks Kh").unwrap(),
    Hand::from_notation("Qs Qh").unwrap(),
    Hand::from_notation("As Ks").unwrap(),
];

for hand in premium_hands {
    let hand_value = evaluator.evaluate_hand(&hand);
    println!("Bot range analysis - {}: {:?}", hand, hand_value.rank);
}

Advanced Usage

7-Card Hand Evaluation for Bot Testing

use holdem_core::{Card, Hand, HoleCards, Board, Evaluator};
use std::str::FromStr;

let evaluator = Evaluator::new().unwrap();

// Texas Hold'em complete hand: 2 hole cards + 5 community cards
let hole_cards = HoleCards::from_notation("AKs").unwrap();
let board = Board::new()
    .with_flop([
        Card::from_str("Td").unwrap(),
        Card::from_str("Jc").unwrap(),
        Card::from_str("Qh").unwrap(),
    ]).unwrap()
    .with_turn(Card::from_str("9s").unwrap()).unwrap()
    .with_river(Card::from_str("2d").unwrap()).unwrap();

// Bot evaluates best possible hand from all 7 cards
let hand = Hand::from_hole_cards_and_board(&hole_cards, &board).unwrap();
let hand_value = evaluator.evaluate_hand(&hand);
println!("Bot best hand rank: {:?}", hand_value.rank);

Testing

Run the comprehensive test suite:

cargo test

Run performance benchmarks:

cargo test --release hand_eval_integration_test -- --nocapture

Simulation Testbed

The holdem_sim binary provides a CLI for running poker simulations with configurable bots, game types, and formats. It supports cash games, Sit & Go (SNG) tournaments, and Multi-Table Tournaments (MTT).

Running Simulations

# Run a cash game simulation
cargo run --bin holdem_sim -- holdem_core/examples/configs/cash_game.toml

# Run with a specific seed for reproducibility
cargo run --bin holdem_sim -- holdem_core/examples/configs/cash_game.toml --seed 42

# Override the number of hands
cargo run --bin holdem_sim -- holdem_core/examples/configs/cash_game.toml --hands 5000

Example Configuration (Cash Game)

[game]
game_type = "Cash"
num_seats = 6
small_blind = 10
big_blind = 20
ante = 0
starting_chips = 10000
num_hands = 1000

[game.bet_limit]
type = "no_limit"
min_raise = 20

[[game.bots]]
bot_type = "call_bot"
name = "Alice"

[[game.bots]]
bot_type = "fold_bot"
name = "Bob"

[[game.bots]]
bot_type = "random_bot"
name = "Charlie"

Example configs are available in holdem_core/examples/configs/:

Built-in Bots

Bot Description
call_bot Calls every bet, never raises or folds
fold_bot Folds whenever facing a bet, otherwise checks
raise_bot Raises with configurable aggression thresholds
random_bot Takes random legal actions with configurable tendencies

Example Output

=== Simulation Results ===
Hands played: 1000

Player Statistics:
  Alice (call_bot)
    Hands: 1000 | VPIP: 100.0% | PFR: 0.0% | Win: $45,230
  Bob (fold_bot)
    Hands: 1000 | VPIP: 0.0% | PFR: 0.0% | Win: -$32,100
  Charlie (random_bot)
    Hands: 1000 | VPIP: 67.3% | PFR: 22.1% | Win: -$13,130

Mathematical Foundation

Cactus Kev — Perfect Hash Algorithm

The Cactus Kev evaluator uses prime-product hashing:

Hash = prime(rank₁) × prime(rank₂) × ... × prime(rank₅)
Index = Hash % TABLE_SIZE
Rank = TABLE[Index]

Each rank maps to a unique prime (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41), so the product of 5 primes uniquely identifies the hand pattern.

Supersonic — LUT Trie Algorithm

The Supersonic evaluator uses a pre-computed trie of 32.5M u32 entries:

p = INITIAL_STATE (page 1 base)
for each card:
    p = hand_ranks[p + card_index + 1]
rank = p  // (for 7-card hands)

Each step is a single array lookup — no hashing, no enumeration, no branching.

References

  • Cactus Kev: Perfect hash algorithm for 5-card poker hand evaluation
  • Supersonic: LUT trie evaluator for high-throughput hand evaluation
  • Poker Standards: Standard poker hand ranking rules
  • Poker Testbed: Framework designed for automated bot testing and analysis

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Areas for improvement:

  • Hardware acceleration (SIMD optimizations)
  • Additional poker variants (Omaha, Stud, etc.)
  • Memory-mapped table loading
  • Distributed table generation
  • Advanced benchmarking tools

Support

For questions, issues, or contributions, please:

  1. Check existing documentation
  2. Review test cases for usage examples
  3. Open GitHub issues for bugs or feature requests
  4. Submit pull requests with comprehensive tests

Performance Note: The Cactus Kev evaluator generates its small lookup tables (~100 KB) in-memory on first use. The Supersonic evaluator requires a pre-generated ~124 MB LUT file loaded at startup.