PokerML

From the PokerML wiki

PokerML is a simulation-driven heads-up and multiplayer no-limit hold'em engine that blends heuristic game-tree search with configurable card and action abstractions to explore poker strategy. The engine is designed for researchers and strategy experimenters who want to inspect and modify poker abstractions, search depth, bet sizing, and range handling rather than a production solver. It implements Counterfactual regret minimization for iterative strategy training, Game state management to track poker hand state, Interactive play and self-play for human and bot gameplay, and Solver optimization to accelerate subgame solving.

flowchart LR
  n1[["Counterfactual regret minimization"]]
  n2[["Game state management"]]
  n3[["Interactive play and self-play"]]
  n4[["Legacy card utilities"]]
  n5[["Solver optimization"]]
  n1 -->|"20 calls, 13 imports"| n2
  n5 -->|"13 calls, 10 imports"| n1
  n5 -->|"12 calls, 11 imports"| n2
  n2 -->|"9 calls, 9 imports"| n1
  n3 -->|"6 calls, 6 imports"| n2
  n3 -->|"4 calls, 4 imports"| n1
  n1 -->|"4 calls, 3 imports"| n3
  n5 -->|"2 calls, 2 imports"| n3
  n1 -->|"1 call, 1 import"| n5
  n2 -->|"1 call, 1 import"| n3
  n2 -->|"1 call, 1 import"| n4
  n2 -->|"1 call, 1 import"| n5
  n3 -->|"1 import"| n5
Each box is a feature; an arrow points from the feature whose code calls or imports to the one it uses.

Purpose and features

Train poker strategies toward Nash equilibrium through Counterfactual regret minimization, which iteratively computes regrets for unchosen actions and updates play probabilities via regret matching.[1] (see Counterfactual regret minimization) Evaluate trained strategies by measuring their exploitability against a Local Best Response that tracks opponent ranges via Bayes' rule. (see Counterfactual regret minimization) Experiment with search depth, bet sizing, and range abstractions by modifying configurable parameters like BET_SIZINGS, SEARCH_MAX_DEPTH, and MONTE_CARLO_BASE without changing core solver logic.[2] Resolve subgames using a depth-limited solver that replaces the full game tree below a threshold with Solver optimization techniques including mutable game state, neural network leaf value estimation, and Numba-compiled regret matching. (see Solver optimization)

Play heads-up poker against a trained CFR bot in real-time through Interactive play and self-play, which includes human-versus-bot gameplay with live solver visualization and bot-versus-bot self-play sessions to detect strategy imbalances.[3] (see Interactive play and self-play)

Layers

  • The Counterfactual regret minimization layer implements the core CFR training algorithm, information set tracking, and strategy storage. (see Counterfactual regret minimization)
  • The Game state management layer models poker hand state as a GameState object that tracks position, action history, folded/all-in status, and exposes methods to apply actions and compute legal moves. (see Game state management)
  • The Interactive play and self-play layer provides CLI entry points for human-versus-bot gameplay and bot-versus-bot duplicate-matched sessions with frequency tracking. (see Interactive play and self-play)
  • The Solver optimization layer accelerates solving through mutable game state, neural network leaf value estimation, and Numba-compiled numerical routines. (see Solver optimization)
  • The Legacy card utilities layer provides card representation conversion, poker hand generation, suit abstraction functions, and preflop equity lookup tables. (see Legacy card utilities)

Request paths

  • Game state transitions in Game state management call determine_winners() from cfr/evaluator.py to resolve hands at showdown and update pot calculations via GameState._calculate_side_pots() in cfr/game_state.py.[4]
  • Training a strategy in Counterfactual regret minimization flows from train.py through CFRTrainer.train(), which constructs FastState objects and applies action abstractions to iterate the regret minimization loop.[5]
  • Playing a hand in Interactive play and self-play starts with GameState from Game state management, calls SubgameSolver.solve() from Solver optimization at decision points, and loads strategy to recommend actions.[6]
  • Self-play creates game states via Game state management, applies bot actions through a Bot instance that loads strategy and calls SubgameSolver, and tracks frequencies to measure strategy balance.[7]

Feature dependencies

  • Counterfactual regret minimization depends on Game state management for game state objects and action legality, importing GameState and get_position_name from cfr/game_state.py and using it throughout training.[8]
  • Counterfactual regret minimization depends on Solver optimization for mutable state representation, importing FastState and action encoding utilities from cfr/fast_state.py to serialize strategies during training.[9]
  • Counterfactual regret minimization depends on Interactive play and self-play for strategy persistence, calling load_strategy() and save_strategy() from cfr/strategy_store.py to resume training and store results.[10]
  • Solver optimization depends on Counterfactual regret minimization for blueprint strategy data and action abstractions, importing InfoSet, card abstractions, and action utilities from cfr/ modules.[11][12]
  • Solver optimization depends on Game state management for game constants and action translation, importing STARTING_STACK, SMALL_BLIND, and action-to-chip conversion from cfr/game_state.py.[13][14]
  • Interactive play and self-play depends on Game state management for game state construction and action validation, importing GameState, STARTING_STACK, and get_position_name to manage live gameplay.[15]
  • Interactive play and self-play depends on Counterfactual regret minimization for strategy loading and exploitation evaluation, importing card abstractions and strategy utilities from cfr/ modules.[16][17]
  • Interactive play and self-play depends on Solver optimization for real-time subgame resolution, importing SubgameSolver from cfr/subgame_solver.py to compute optimal plays during live games.[18]
  • Game state management depends on Counterfactual regret minimization for action legality and evaluation, calling determine_winners() from cfr/evaluator.py to resolve showdowns.[19]
  • Game state management depends on Legacy card utilities for card number-to-text conversion, calling CardUtils.numToCard() in server/game_manager.py to render cards to players.[20][21]
  • Game state management depends on Solver optimization for subgame solving, importing SubgameSolver from cfr/subgame_solver.py in server/bot.py to resolve real-time decisions.[22]
  • Solver optimization and Interactive play and self-play both depend on trained strategy files stored via Counterfactual regret minimization, calling load_strategy() to retrieve serialized blueprint strategies for solving and gameplay.[23][24]

References

  1. ^ README.md:L23-24@56ad610
  2. ^ README.md:L48-60@56ad610
  3. ^ README.md:L19@56ad610
  4. ^ cfr/game_state.py:L408-414@56ad610 (GameState.get_terminal_utility)
  5. ^ cfr/cfr_trainer.py:L19-30@56ad610
  6. ^ play.py:L13-17@56ad610
  7. ^ server/bot.py:L30-40@56ad610 (Bot.__init__)
  8. ^ cfr/cfr_trainer.py:L22@56ad610
  9. ^ cfr/cfr_trainer.py:L23-25@56ad610
  10. ^ cfr/cfr_trainer.py:L30@56ad610
  11. ^ cfr/depth_limited_solver.py:L17@56ad610
  12. ^ cfr/fast_state.py:L17-18@56ad610
  13. ^ cfr/depth_limited_solver.py:L18@56ad610
  14. ^ cfr/fast_state.py:L17-20@56ad610
  15. ^ play.py:L13@56ad610
  16. ^ play.py:L12@56ad610
  17. ^ play.py:L14-15@56ad610
  18. ^ play.py:L16@56ad610
  19. ^ cfr/game_state.py:L22@56ad610
  20. ^ server/game_manager.py:L15@56ad610
  21. ^ server/game_manager.py:L539@56ad610 (_cards)
  22. ^ server/bot.py:L23@56ad610
  23. ^ tests/test_benchmarks.py:L43@56ad610
  24. ^ play.py:L14@56ad610

This page was last edited on 24 March 2026, at commit 56ad610.