# Kuhn Poker CFR exploitability experiment

This public bundle reproduces the measurements used by GTO Gecko's article
“Poker Solver Convergence: Reproduce Exploitability in Kuhn Poker” and its
Japanese edition.

## What is measured

- Two-player, three-card Kuhn Poker with one ante and one optional one-ante bet.
- Deterministic full-tree vanilla counterfactual regret minimization (CFR).
- Six ordered private-card deals, each evaluated exactly on every iteration.
- The strategy used after the current update and the reach-weighted average of
  all strategies used so far.
- An information-set-consistent exact best response for each player, found by
  enumerating all 64 pure plans available to that responder.
- `NashConv` as the sum of both unilateral improvements against the profile, and
  `exploitability = NashConv / 2`, the OpenSpiel convention for this
  two-player zero-sum game.

Utilities are net antes per deal. A value of `0.001` therefore means one
thousandth of an ante per hand in this toy game. It is not a percentage, a
big-blind rate, a local action-frequency error, or a claim about another game.

The exact Kuhn game value for the first player is `-1/18` ante per deal. That
value checks the on-policy payoff; exploitability requires both best responses.

## Files

- `experiment.json`: complete contract, checkpoints, trace and final policies.
- `convergence.csv`: current-versus-average measurements through 100,000 runs.
- `final-strategies.csv`: every final information-set probability.
- `convergence.svg` / `convergence-ja.svg`: localized, log-scale charts.
- `game-tree.svg` / `game-tree-ja.svg`: localized complete betting trees.
- `generate.mjs`: deterministic game, CFR and exact-best-response source.
- `verify.py`: independent Python implementation and artifact checks.
- `MANIFEST.sha256`: SHA-256 digest for every file above and this README.

## Reproduce

From the repository root with Node.js 22 and Python 3 available:

```text
node scripts/generate-kuhn-poker-exploitability.mjs
node --test tests/kuhn-poker-exploitability-data.test.mjs
python public/data/kuhn-poker-exploitability/verify.py
python -O public/data/kuhn-poker-exploitability/verify.py
```

The Python verifier implements the game tree, full CFR pass and pure-plan best
response independently. It also rejects a response table that keys on the
opponent's hidden card: a best responder may act on its own card and public
history only.

## Scope

Kuhn Poker is deliberately tiny. It makes every branch and best response
auditable, but it does not model Hold'em ranges, multiple bet sizes, future
streets, rake, ICM, abstraction or a commercial solver's implementation. The
experiment teaches how to read a strategy-level convergence metric; it does not
certify any other solve.

Generated 2026-09-07. No private solver output or customer data is included.
