Remove the entire strategy module (StrategyBot, ModularStrategy, StrategyContext, ActionRecorder, HandAnalyzer, HandHelper) from holdem_core. Strategy implementations will live in external crates (e.g., super_marvin) and register via bot_factory::register_bot_type. - Delete holdem_core/src/game/strategy/ (6 files, ~1900 lines) - Delete holdem_core/src/game/bots/strategy_bot.rs - Remove strategy_bot from bots/mod.rs module declarations and re-exports - Update bot_factory.rs doc example to show generic custom bot pattern |
||
|---|---|---|
| .. | ||
| examples/configs | ||
| src | ||
| tests | ||
| Cargo.toml | ||
| README.md | ||
holdem_core - High-Performance Poker Hand Evaluation
A state-of-the-art Rust library for ultra-fast poker hand evaluation featuring two evaluators: the Cactus Kev perfect-hash evaluator (~100 KB tables) and the Supersonic LUT trie evaluator (~124 MB tables). Supports 5, 6, and 7-card Texas Hold'em hands.
🚀 Features
- Dual Evaluators: Cactus Kev (compact ~100 KB) and Supersonic LUT trie (~124 MB) hand evaluators
- Ultra-Fast Evaluation: Sub-microsecond hand evaluation using perfect hash or O(n) trie lookups
- Memory Options: Choose between ~100 KB Cactus Kev tables or ~124 MB Supersonic trie depending on use case
- Zero Collisions: Validated against all 2,598,960 five-card hands
- Thread Safe: Singleton pattern with lazy initialization for shared resources
- Mathematically Correct: Comprehensive property-based testing and validation
- Persistent Storage: Automatic table generation and file-based persistence
- Modular Design: Clean separation of concerns with well-defined interfaces
📈 Performance
Hand Evaluation Speed
- 5-card hands: O(1) — single prime-product hash → table lookup (~50-100 ns)
- 6-card hands: O(6) — six 5-card lookups (~300-500 ns)
- 7-card hands: O(1) amortized —
HashMapcache hit; O(21) on cache miss (~1-2 µs)
Memory Usage
- Cactus Kev tables: ~30 KB (1,287 flush + 6,175 unsuited entries = 7,462 total)
- 7-card cache: Variable — grows with unique hands seen (amortized O(1) lookups)
- Total base footprint: ~100 KB (vs. previous ~130 MB trie approach)
🏗️ Architecture
The library provides two hand evaluators with different performance/memory tradeoffs:
Cactus Kev Evaluator (compact)
- 5-card evaluation: O(1) via prime-product hashing into two small tables (7,462 entries total, ~30 KB). Each rank maps to a prime; the product of 5 primes uniquely identifies the hand. Zero collisions, validated against all 2,598,960 hands.
- 7-card evaluation: Amortized O(1) via C(7,5)=21 enumeration over the 5-card tables, with a
HashMapcache keyed by the product of 52 distinct card primes.
Supersonic Evaluator (high-throughput)
- 5/6/7-card evaluation: O(n) array lookups via a pre-computed LUT trie (~124 MB, 32,487,834
u32entries). No enumeration or hashing needed — each card is a single array dereference. Packed 16-bit hand rank format (category + equivalency class).
Key modules:
- [
evaluator] - Core hand evaluation engine with publicEvaluatorAPI - [
evaluator::cactus_kev] - Cactus Kev perfect-hash 5-card evaluator - [
evaluator::supersonic] - Supersonic LUT trie evaluator (5/6/7-card) - [
evaluator::tables] -JumpTablewrapper around Cactus Kev + 7-card cache - [
evaluator::algorithmic_evaluator] - Rule-based evaluator (correctness oracle) - [
evaluator::singleton] - Thread-safe singleton pattern for shared evaluator instance - [
evaluator::file_io] - Atomic file operations with checksum validation - [
evaluator::integration] - Integration utilities for holdem_core types - [
evaluator::errors] - Comprehensive error handling and reporting
🛠️ Quick Start
Basic Usage
use math::{Evaluator, HandRank};
use holdem_core::{Card, Hand};
use std::str::FromStr;
// Get the singleton evaluator instance
let evaluator = Evaluator::instance();
// Create a hand from string notation
let hand = Hand::from_notation("As Ks Qs Js Ts").unwrap();
// Evaluate the hand
let hand_value = evaluator.evaluate_hand(&hand);
println!("Hand rank: {:?}", hand_value.rank);
println!("Hand value: {}", hand_value.value);
Advanced Usage with Integration
use math::evaluator::integration::HandEvaluator;
use holdem_core::{HoleCards, Board};
// Evaluate hole cards with a board
let hole_cards = HoleCards::from_strings(&["As", "Ks"]).unwrap();
let board = Board::from_strings(&["Qs", "Js", "Ts", "7h", "3d"]).unwrap();
let hand_value = HandEvaluator::evaluate_hole_cards_with_board(&hole_cards, &board).unwrap();
println!("Final hand: {}", HandEvaluator::format_hand_value(hand_value));
🎯 Hand Ranking System
The library implements the complete poker hand ranking system:
- Royal Flush - A♠ K♠ Q♠ J♠ T♠
- Straight Flush - Five consecutive cards of same suit
- Four of a Kind - Four cards of same rank
- Full House - Three of a kind plus a pair
- Flush - Five cards of same suit
- Straight - Five consecutive cards (A-5 is lowest)
- Three of a Kind - Three cards of same rank
- Two Pair - Two pairs of different ranks
- One Pair - Two cards of same rank
- High Card - No matching cards (highest card wins)
🔧 Installation
Add this to your Cargo.toml:
[dependencies]
holdem_core = "0.1.0"
📚 Documentation
API Documentation
- Crate Documentation - Complete API reference
- Examples - Comprehensive usage examples
- Benchmarks - Performance characteristics
Module Documentation
- Evaluator Module - Core evaluation engine and public API
- Cactus Kev Module - 5-card perfect hash evaluator
- Supersonic Module - LUT trie evaluator (5/6/7-card)
- Tables Module - JumpTable with Cactus Kev + 7-card cache
- File I/O Module - Persistent storage
- Integration Module - holdem_core integration
🧪 Testing
The library includes comprehensive testing:
# Run all tests
cargo test
# Run property-based tests
cargo test property_tests
# Run performance benchmarks
cargo test benchmarks
# Run integration tests
cargo test integration_tests
Test Coverage
- Property-based testing: 100% coverage of edge cases and invariants
- Performance validation: Automated performance regression detection
- Error handling: Comprehensive error condition testing
- Thread safety: Concurrent access pattern validation
🔒 Thread Safety & Concurrency
The evaluator is designed for high-concurrency applications:
- Read-only operations: All evaluation methods are thread-safe
- Lock-free design: No runtime synchronization overhead
- Arc-based sharing: Safe sharing across unlimited threads
- Atomic initialization: Thread-safe lazy initialization
💾 File Management
Lookup tables are automatically managed:
- Automatic generation: Tables created on first use if missing
- Atomic writes: Safe concurrent file operations with rollback
- Checksum validation: SHA-256 integrity verification
- Corruption recovery: Automatic regeneration of corrupted tables
🎮 Real-World Applications
Poker Server Implementation
use math::Evaluator;
use std::sync::Arc;
struct PokerServer {
evaluator: Arc<Evaluator>,
}
impl PokerServer {
fn new() -> Result<Self, String> {
let evaluator = Arc::new(Evaluator::instance());
Ok(Self { evaluator })
}
fn evaluate_hand(&self, cards: &[Card; 5]) -> HandValue {
self.evaluator.evaluate_5_card(cards)
}
fn process_game_state(&self, game_state: GameState) -> GameResult {
// High-performance hand evaluation for poker server
// Can handle 100,000+ hands per second
todo!()
}
}
Poker Analysis Tool
use math::evaluator::integration::{HandEvaluator, HandEvaluation};
use holdem_core::{Hand, HoleCards, Board};
struct PokerAnalyzer {
evaluator: math::Evaluator,
}
impl PokerAnalyzer {
fn analyze_range(&self, hole_cards_list: &[&str], board: &Board) -> RangeAnalysis {
let mut analysis = RangeAnalysis::default();
for notation in hole_cards_list {
let hole_cards = HoleCards::from_strings(&[notation]).unwrap();
let hand = Hand::from_hole_cards_and_board(&hole_cards, board).unwrap();
let hand_value = hand.evaluate();
// Analyze hand strength distribution
analysis.total_hands += 1;
// ... analysis logic
}
analysis
}
}
🔍 Performance Monitoring
Built-in performance monitoring and diagnostics:
use math::Evaluator;
// Monitor evaluation performance
let evaluator = Evaluator::instance();
// Check table file status
let table_info = evaluator.get_table_info().unwrap();
println!("Table files: {:?}", table_info);
// Validate table integrity
let is_valid = evaluator.validate_table_files().unwrap();
println!("Tables valid: {}", is_valid);
🚨 Error Handling
Comprehensive error handling for all failure modes:
use math::{Evaluator, evaluator::errors::EvaluatorError};
match Evaluator::new() {
Ok(evaluator) => println!("Evaluator ready"),
Err(EvaluatorError::FileNotFound(msg)) => {
println!("Table files missing: {}", msg);
println!("Will be generated automatically");
}
Err(EvaluatorError::ChecksumValidationFailed(msg)) => {
println!("Table corruption detected: {}", msg);
println!("Tables will be regenerated");
}
Err(e) => println!("Error: {}", e),
}
📊 Benchmarks
Run the built-in benchmarks to verify performance:
# Run performance benchmarks
cargo test benchmarks -- --nocapture
# Expected output:
# 5-card evaluation: ~10-20 million hands/second
# 7-card evaluation: ~500K-1 million hands/second (amortized with cache)
# Memory usage: ~100 KB base (tables) + variable cache
🤝 Integration with holdem_core
Seamless integration with the holdem_core ecosystem:
- Card compatibility: Uses holdem_core::Card for all card operations
- Hand integration: Supports holdem_core::Hand for evaluation
- Hole cards support: Integration with HoleCards and Board types
- String notation: Supports standard poker hand notation parsing
🏆 Achievements
This implementation represents a significant achievement in poker hand evaluation:
- World-class performance: Among the fastest poker evaluators available
- Mathematical rigor: 100% accuracy with comprehensive validation
- Production ready: Robust error handling and recovery mechanisms
- Developer friendly: Clean APIs with comprehensive documentation
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Cactus Kev: Original perfect hash algorithm implementation
- Supersonic: LUT trie evaluator for high-throughput hand evaluation
- PokerStove: Inspiration for lookup table approach
- Rust Community: Excellent tools and libraries for systems programming
🔗 Links
Built with ❤️ for the poker and Rust communities