How the DD Poker Hand Simulator Analyzes Hand Ranges: Full Enumeration vs. Monte Carlo
The DD Poker hand simulator evaluates hole cards against opponent ranges using either exhaustive enumeration or Monte Carlo sampling, depending on the board state, to calculate exact or approximate equity percentages.
DD Poker is an open-source Java engine for Texas Hold'em that includes sophisticated tools for poker hand analysis. The HoldemSimulator class in code/poker/src/main/java/com/donohoedigital/games/poker/engine/HoldemSimulator.java serves as the core hand range analyzer. It processes millions of combinations to determine win probabilities against specific opponent ranges or random hands while remaining responsive through the DDProgressFeedback interface.
Three Simulation Modes in HoldemSimulator.java
The simulator selects its execution strategy based on the number of known community cards. This adaptive approach balances mathematical precision with computational feasibility.
Full Enumeration for Late Streets
When the board contains four or five known cards (turn or river), the simulator uses the iterate(...) method to perform full enumeration. This mode loops over every possible opponent hand that matches the defined range and iterates through all remaining board cards (three or fewer). Because the deck has limited remaining combinations at this stage, the simulator can calculate exact win-loss-tie statistics without approximation.
Statistical Simulation for Early Streets
When the board has three or fewer cards (preflop or flop), the simulator switches to simulate(...), a Monte Carlo method. This mode randomly draws opponent hands and completes the board for a configurable number of trials (defaulting to approximately 4,000 iterations based on DEFAULT_PRECISION). This statistical approach avoids the combinatorial explosion that would make exhaustive enumeration prohibitively expensive on early streets.
All-Hands Random Sampling
For ad-hoc analysis without a specific range defined, the simulator falls back to an all-hands (random) mode. It generates a large random sample of opponent hands from the entire remaining deck, providing a "quick-look" equity calculation against an unspecified opponent holding.
Core Workflow and Execution Path
The simulation process follows a rigorous pipeline defined in HoldemSimulator.java:
-
Deck Initialization – Creates a fresh
Deckobject (52 cards) and removes known hole cards and community cards usingremoveCards(). -
Range Selection – Calls
HandGroup.getProfileList()to retrieve predefined range profiles (e.g., "premium hands", "suited connectors"). -
Path Selection – Evaluates board length to choose between
simulate()(statistical) for ≥3 cards oriterate()(enumeration) for ≥4 cards. -
Hand Evaluation – Uses
HandInfoFaster.getScore(...)to obtain numeric hand strength values. This optimized engine leverages pre-computed lookup tables for rapid evaluation. -
Result Aggregation – Collects outcomes in
StatResultobjects mapped by range name, returning a finalStatResultscollection to the caller. -
Progress Updates – Calls
perc(...)andmsg(...)on theDDProgressFeedbackinterface every N iterations (capped at 50,000 for UI responsiveness), allowing real-time progress bars and cancellation.
Key Classes Supporting Hand Range Analysis
Several specialized classes work together to enable accurate hand range simulation:
-
HandGroup(HandGroup.java) – Defines named hand-range profiles and expands compact notation (e.g., "AQs+", "KQs") into concreteHandlists usingHandList. -
HandInfoFaster(HandInfoFaster.java) – A fast hand-evaluation engine that returns numeric scores for hand-plus-board combinations, enabling thescore(...)comparisons that determine win/loss/tie outcomes. -
Deck(Deck.java) – Manages the 52-card deck state during simulation, providingnextCard(),removeCards(), andaddRandom()methods to handle card removal and random drawing. -
UI Integration –
SimulatorDialog.javaandPokerSimulatorPanel.javainstantiateHoldemSimulatorand provide concreteDDProgressFeedbackimplementations for interactive use. -
AI Integration –
V2Player.javademonstrates programmatic usage, calling the simulator to evaluate opponent ranges during automated decision-making.
Practical Implementation: Running the Simulator
Below is a concrete example of invoking the statistical simulation directly:
// Build a hole hand (e.g., Ace of spades + King of hearts)
Hand hole = new Hand(Card.ACE_SPADES, Card.KING_HEARTS);
// Community board: flop only (three cards)
Hand community = new Hand(Card.TEN_DIAMONDS, Card.JACK_CLUBS, Card.QUEEN_SPADES);
// Optional UI progress listener (null = silent)
DDProgressFeedback progress = null;
// Run a statistical simulation with default precision (≈ 4,000 trials)
StatResults results = HoldemSimulator.simulate(hole, community, progress);
// Retrieve the outcome for a specific hand-range profile, e.g., "All Hands"
StatResult allHands = results.get(HoldemSimulator.ALL_HANDS);
System.out.printf("Win: %.2f%%, Lose: %.2f%%, Tie: %.2f%%%n",
allHands.getWinPct(), allHands.getLosePct(), allHands.getTiePct());
When called from the UI layer, the progress parameter receives live updates that drive the progress bar in SimulatorDialog.
Range Definition: From Compact Notation to Concrete Hands
The simulator handles hand ranges through a two-phase resolution process. First, HandGroup contains a HandList that expands compact range descriptions (e.g., "AA", "Broadway", "Suited A-K") into concrete lists of Hand objects.
For iteration mode, the simulator removes each hand's cards from the deck and enumerates all remaining board cards, yielding exact counts. For sampling mode, it randomly selects hands from this pre-expanded list (or generates completely random hands if the list is null), then completes the board randomly. The handCount parameter derives from the range size multiplied by a precision factor, ensuring statistically significant results without unnecessary computation.
Summary
- Adaptive Strategy: The simulator switches between exhaustive
iterate()for late streets (≥4 cards) and Monte Carlosimulate()for early streets (≤3 cards). - Performance Optimization:
HandInfoFasterprovides sub-millisecond hand strength calculations via lookup tables. - Range Handling:
HandGrouptranslates human-readable range notation into processable hand lists. - UI Integration: The
DDProgressFeedbackinterface enables real-time progress reporting and cancellation inSimulatorDialog. - Dual API: The engine supports both interactive UI usage and programmatic AI integration (as demonstrated in
V2Player.java).
Frequently Asked Questions
How does the simulator decide between enumeration and sampling?
The decision is based entirely on the number of known community cards. As implemented in HoldemSimulator.java, if the board has four or five cards, the code invokes iterate(...) for full enumeration. For three or fewer cards, it calls simulate(...) to use statistical Monte Carlo sampling, avoiding the billions of combinations that would result from exhaustive preflop calculations.
What role does HandInfoFaster play in the simulation?
HandInfoFaster is the evaluation engine that converts a seven-card hand (two hole cards plus five board cards) into a numeric score representing hand strength. According to the source, it uses pre-computed lookup tables to generate scores rapidly, allowing the simulator to evaluate millions of hands per second when iterating or sampling.
Can the hand simulator run without a graphical interface?
Yes. The HoldemSimulator.simulate() and iterate() methods accept a DDProgressFeedback parameter that can be set to null for silent execution. The V2Player AI class demonstrates this headless usage, calling the simulator programmatically to analyze opponent ranges during game play without any UI dependencies.
How are specific hand ranges like "AQs+" or "suited connectors" defined in the code?
Ranges are defined in HandGroup.java, which stores predefined profiles (e.g., "premium", "broadway", "suited connectors"). The class expands compact notation into concrete Hand objects stored in a HandList. When the simulator runs, it iterates over or samples from these pre-expanded lists to represent the opponent's possible holdings accurately.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →