poker-agents
Neural agents that learn six-handed no-limit hold'em by playing each other,
validated against things they did not write: published exact results, and
10,000 real hands between Pluribus and elite professionals (PHH dataset, MIT,
doi:10.5281/zenodo.10796885).
What is checked, and against what
| Layer | Check | Ground truth | Status |
|---|---|---|---|
| Kuhn, Leduc rules + exact best response | uniform-play NashConv | OpenSpiel's published 0.9167 / 4.7472 | match to 1e-6 |
| Tabular CFR+ (reference solver) | converges | Kuhn value −1/18; Leduc NashConv < 0.02 | pass |
| Deep CFR (neural) on Leduc | exact NashConv as it learns | the tabular solver | 5.9 → ~0.35–0.47 after 100 iters; error is in the regret nets, not the policy fit (diag_leduc.py) |
| Six-max engine | replay every real hand | finishing_stacks of all 10,000 Pluribus hands | 10,000 / 10,000 to the chip |
| Six-max engine, abstraction | 10k random hands + 5k unequal-stack side pots | chip conservation, legality | pass |
| Imitation agents | held-out accuracy | 10% of hands never trained on | Pluribus 82.6%, pros 81.8% (majority guess 54% / 52%) |
| Any agent vs real play | same situations, compare action mix per holding | the real decisions | pa/compare.py |
| Any agent vs any field | duplicate matches, bb/100 ± SE | — | pa/league.py |
Six-handed play has no exact exploitability; the honest substitutes are the
duplicate league and the comparison with real play. A bb/100 is never quoted
without its standard error.
Pieces
pa/games/— Kuhn, Leduc, six-max NLHE (+nlhe_features.py, 214 inputs)pa/exploit.py,pa/cfr_tabular.py— exact referencespa/deep_cfr.py— Deep CFR (any number of players)pa/deep_cfr_batched.py— the same, batched + multiprocess for six-max.
Departure from the paper: one advantage net shared by all seats.
pa/remote.py— collection across machines over SSH (no open ports): jobs out,
samples back, compressed; each machine takes a job when it has a free slot, so
a slower machine just takes fewer. Samples are thinned at the source (a
uniform sample feeding a uniform reservoir), so traffic stays small.
pa/population.py— six independent learners (own networks, own memories),
seated at random every hand; scored against each other and fixed anchors to
detect cycling.
pa/clone.py— imitation agents from the real handspa/league.py,pa/compare.py— evaluation
Run
python -m venv --system-site-packages .venv && .venv/bin/pip install torch numpy phevaluator pytest
.venv/bin/python -m pytest -q
.venv/bin/python run_sixmax.py runs/sixmax-a 200 20000