Metadata-Version: 2.3
Name: poker-tui
Version: 0.3.1
Summary: A poker gym TUI: preflop trainer and LLM-agent cash game simulator (6-max, 100BB)
Keywords: poker,tui,textual,trainer,holdem
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Games/Entertainment :: Board Games
Requires-Dist: numpy>=2.0
Requires-Dist: textual>=8.2.8
Requires-Dist: treys>=0.1.8
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# Poker TUI

A terminal gym for no-limit hold'em: drill preflop decisions against GTO-style
charts, then play 6-max cash games (100bb) against agents powered by the local
`pi` coding-agent CLI. Built with [Textual](https://textual.textualize.io) and
managed with [uv](https://docs.astral.sh/uv/). Requires Python 3.11 or newer.

## Quick start

```bash
uvx poker-tui
```

`uvx` downloads the published package into an isolated, cached environment and
starts the TUI without a manual install. For a persistent command:

```bash
uv tool install poker-tui
poker-tui
```

Check the installed release with `poker-tui --version`.

Screens:

- **Preflop Trainer** — random spots (RFI + facing opens across all positions),
  where you choose one action or submit a complete mixed strategy, graded
  against built-in charts with frequencies.
  Reveals a 13x13 range grid after each decision, tracks accuracy by seat, and
  **"Why?" explanations** in three styles (*newb / learner / expert*) generated
  via `pi` and cached locally. Range charts and explanations can be
   opened full-screen; expanded range cells show the complete action mix in
   hover tooltips.
- **GTO Solver** — enter exact hole cards and choose an unopened or
  facing-open situation to inspect the locally stored strategy from the
  experimental heads-up CFR+ abstraction, including action frequencies and
  sizes. Solver results never fall back to the authored trainer charts.
- **Play vs Agents** — six-handed NLHE, unitless BB, auto-rebuy. Five villain
  seats decide via `pi` (one-shot LLM calls) with a fast heuristic bot as
  fallback. Dedicated seat chips keep each blind post and latest street action
  visible. Once you're out of a hand the rest plays out at high speed; `N`
  jumps to the next deal.
- **Stats** — quiz accuracy by spot and table results.
- **Agent Settings** — choose from models discovered through Pi for the default,
  trainer coach, and each of the five villains, or enter any custom
  `provider/model` ID. You can also switch to heuristic-only play.

Keys: `T` trainer · `V` solver · `P` play · `S` stats · `G` settings · `Q` quit · inside screens `N` next,
`Esc` back. Trainer actions use `F`/`C`/`R`; table actions use `F` to fold,
`C` to check or call, and `R` to raise at the selected size. `S` changes table
speed. In the trainer, `G` expands the revealed range and `X` expands a loaded
explanation; `M` switches between fixed-action and mixed-strategy answers.

Mixed strategies are scored by distribution overlap:
`score = sum(min(your frequency, baseline frequency))`, equivalently one minus
the total-variation distance. Against a 70% raise / 30% call baseline, an exact
70/30 submission scores 100%; pure raise scores 70%; pure call scores 30%.

## Agents

Villain brains come from the [`pi`](https://github.com/badlogic/pi-mono) CLI in
print mode (`pi -p --no-tools --no-session ...`). Each seat gets one of four
personas; invalid/failed LLM replies fall back to the heuristic bot
(chart-based preflop, Monte-Carlo-equity postflop) automatically.

Environment:

| Variable             | Effect                                              |
|----------------------|-----------------------------------------------------|
| `POKER_GYM_BOTS=heuristic` | skip LLM entirely (fast, free, offline)       |
| `POKER_GYM_PI_ARGS="--model anthropic/..."` | pick model/provider for pi |

The settings screen loads Pi's local model catalog and persists choices in
`settings.json`. Per-agent models can inherit the default, while leaving the
default unset uses Pi's own configured default. Environment variables override
saved settings, which is useful for one-off runs and automation.

## The solver

`poker_gym.solve` implements CFR+ over heads-up preflop subgames on top of a
169×169 all-in equity matrix (`poker_gym.equity`) computed by a custom
vectorized numpy 7-card evaluator that is fuzz-tested against `treys`.

```bash
uvx --from poker-tui poker-gym-solve --quality fast --jobs 4
uvx --from poker-tui poker-gym-stats
```

Quality tiers: `fast` (~2k trials/matchup), `standard` (4k), `thorough` (8k).
Builds are chunked with deterministic seeds and checkpointed, so they can be
interrupted and resumed, and parallelized with `--jobs`. On a Raspberry Pi,
prefer `--quality fast --jobs 4`; the evaluator is int32/vectorized to keep the
working set cache-friendly.

After the build completes, open **GTO Solver** from the main menu. Choose the
preflop situation, enter two cards in compact notation such as `As Qs`, and the
view shows the normalized fold/call/raise mix plus the solver's action size.
The view reads only local `kind='solver'` data and does not call or scrape an
external solver service.

Unopened-pot trees begin with the posted 0.5 BB small blind and 1 BB big blind.
They include a legal limp to 1 BB, followed by the big blind's check or fixed
4 BB isolation branch. Call amounts for blind defenders subtract chips already
posted. Re-run `poker-gym-solve` after upgrading if the view reports that older
charts need rebuilding; the cached equity matrix can be reused.

**Honest caveat:** the solver's game abstraction folds everyone but two
players and models postflop with constant-sum, relative equity-realization
factors. Calibration shows
this cannot reproduce position-dependent open frequencies (UTG and BTN become
literally the same game), so the **trainer grades against hand-calibrated
charts** modeled on published solver baselines; solver output is stored
separately as an experimental "solver view" (`kind='solver'` in the `charts`
table).

## Data

Everything persists under `$XDG_DATA_HOME/poker_gym` (default
`~/.local/share/poker_gym`): `gym.db` (quiz attempts, hand histories,
explanation cache, charts), `settings.json` (Pi model routing), and `equity.npz`.

## Development

```bash
uv sync
uv run poker-tui
uv run pytest -m "not slow"   # full suite minus long equity-matrix test
uv run pytest -m slow         # equity matrix sanity (builds a small matrix)
uv run python scripts/smoke_app.py    # headless TUI smoke test
```

Build the same artifacts uploaded to PyPI with:

```bash
uv build --clear
uv publish
```

Layout: `src/poker_gym/` — `cards`, `ranges` (chart DSL), `charts` (the
ranges themselves — edit freely, they're plain strings), `spots` (trainer),
`engine` (table state machine), `agents`, `explain`, `equity`, `solve`,
`db`, `cli`, `app`.
