A from-scratch implementation of a complete game-theoretically optimal (GTO) poker AI, built across five progressive stages — from foundational CFR to real-time search — following the architecture of Pluribus (Brown & Sandholm, Science, 2019).
Each stage exists to solve a specific limitation of the one before it. None of the five are optional shortcuts — each is a real bottleneck in scaling CFR from toy games to full No-Limit Hold’em.
Stage 1+2 Vanilla CFR + MCCFR Leduc Hold'em (6-card toy game)
↓
Stage 3 Card Abstraction k-means with Earth Mover's Distance
↓ 8 preflop / 12 flop / 12 turn / 8 river buckets
Stage 4 Deep CFR Neural network approximation of regret
↓ Reservoir buffers + linear CFR weighting
Stage 5 Real-Time Search Depth-limited subgame solving
Blueprint oracle at leaf nodes
Vanilla CFR and Monte Carlo CFR (external sampling), implemented on Leduc Hold’em — a tractable 2-player, 6-card game that is the standard research testbed for poker AI algorithms.
Core idea: at each information set, compute counterfactual regret for each action not taken. Strategy at the next iteration is proportional to cumulative positive regret. The average strategy across iterations — not the final one — converges to Nash equilibrium.
MCCFR replaces full game-tree traversal with sampling, which is what makes the approach computationally tractable at all beyond toy games. This is the bottleneck Stage 1+2 solves: compute.
Full No-Limit Hold’em has roughly 10¹⁶⁰ game states — far beyond anything that can be enumerated directly. Card abstraction groups strategically similar hands into buckets so the resulting game tree becomes solvable.
EMD clustering groups hands by the distribution of equity across possible runouts, not just the mean — which is what distinguishes a made hand from a draw with an identical average equity. This is the bottleneck Stage 3 solves: state-space scale.
Scales CFR to full NLHE by replacing the tabular strategy/regret store with neural networks that generalize across similar, even previously-unseen, game states.
This is the bottleneck Stage 4 solves: generalization — moving from a strategy table that only knows states it has explicitly seen, to a function that can estimate strategy for any state.
The technique that distinguishes Pluribus from earlier poker AI systems. At each decision point, the current subgame is re-solved in real time, using the Stage 4 blueprint network as a value estimator at leaf nodes rather than relying purely on the pre-trained strategy.
This is the bottleneck Stage 5 solves: blind spots — a pre-trained blueprint strategy that hasn’t seen a specific live situation in enough depth gets sharpened against what’s actually happening in that subgame, rather than falling back on a coarser pre-computed approximation.
| Property | This repo | Pluribus |
|---|---|---|
| Algorithm | Deep CFR + depth-limited search | Blueprint CFR + subgame solving |
| Players | 2 (heads-up) | 6 |
| Bet abstraction | 5 sizes | 14 sizes |
| Traversals | ~50k (demo) | 12,400 × 1,000 iterations |
| Hardware | Single CPU | 64-core CPU |
| Training time | ~30 min | ~8 days |
The architecture is faithful to the published papers; scale is the main difference. This is a heads-up (2-player) implementation — multi-way extension is a real, unsolved engineering challenge in this codebase, not a small extension of the current code.
poker_ai/
├── main.py # Stage 1+2 entry point
├── train_abstracted.py # Stage 3 entry point
│
├── cfr/
│ └── leduc_cfr.py # Vanilla CFR for Leduc Hold'em
├── mccfr/
│ └── leduc_mccfr.py # External sampling MCCFR
├── abstraction/
│ ├── equity.py # MC equity, histograms, EMD
│ ├── card_abstraction.py # Multi-street k-means clustering
│ └── abstracted_cfr.py # MCCFR on abstracted game
├── deep_cfr/
│ ├── game_engine.py # Full NLHE: stacks, all-ins, features
│ ├── networks.py # AdvantageNet, StrategyNet, buffers
│ ├── traversal.py # Deep CFR external sampling traversal
│ └── run_convergence.py # Tight convergence run
└── stage5/
├── search.py # Subgame solver, blueprint oracle
└── evaluate.py # Tournament evaluation framework
See Algorithms for implementation-level detail on the math behind each stage, and Results for full benchmark methodology.