# pokerkit scripts a hand as a list of state changes

> PokerKit models a poker hand as an object you mutate one action at a time, deal_hole, deal_board, complete_bet_or_raise_to, and every example in the documentation is a real televised pot replayed call by call. That makes it a simulator and evaluator rather than a solver, and the published releases stop at v0.7.6 while setup.py already carries a development version.

**uoftcprg/pokerkit** — An open-source Python library for poker game simulations, hand evaluations, and statistical analysis

- Repository: https://github.com/uoftcprg/pokerkit
- Website: https://pokerkit.readthedocs.io/
- Stars: 503 · Forks: 81
- Language: Python
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/uoftcprg-pokerkit

## A hand is an object you mutate one call at a time

The API's shape decides everything else. A game is created through a factory that takes the rule parameters, and from then on nothing happens implicitly: you call `deal_hole` with a string of cards, `deal_board` with community cards, `burn_card` with `??` for the unknown burned card, and then the betting actions in order. There is no event loop, no scheduler and no random draw inside the state object. The factory arguments change with the discipline rather than with the hand: the three-handed Dwan and Ivey example asks for uniform antes with a single ante value and no mode, while the six-handed short-deck example passes the blinds as a mapping with the seat index as the key. What you get is a transcript you can assert against, which is exactly why the documentation's examples read like annotated recordings of real pots rather than like game play. Install is one command on Python 3.11 or above:

```bash
pip install pokerkit
```

## The examples are televised pots used as test cases

Three hands are worked through in full, and each is a real pot. The first is the four-runout all-in between Phil Hellmuth and Ernest Wiggins, with six named players and a final stack print of `[inf, 79400, 149700, inf, 37400, inf]`. The second is the million-dollar pot between Tom Dwan and Phil Ivey. The third is short-deck hold'em with a six-handed table. Two conventions make them reproducible. Players whose starting stack was never mentioned are set to `math.inf`, and a hole card that was never revealed is dealt as `????`. Both are honest placeholders rather than guesses, and both mean the printed result can be checked against the footage. In the Ivey hand one player is dealt as `????` and the closing line is `[572100, inf, 1109500]`, so a hole card that was never shown stays unknown all the way to the print rather than being invented to make the example tidy.

## The action sequence is the readable part

Pre-flop action in the Wiggins example is seven lines, and they say everything about the interface:

```python
state.fold()  # Negreanu
state.complete_bet_or_raise_to(2800)  # Brunson
state.fold()  # Laak
state.check_or_call()  # Tony G
state.complete_bet_or_raise_to(12600)  # Hellmuth
state.check_or_call()  # Wiggins
state.check_or_call()  # Brunson
state.check_or_call()  # Tony G
```

Each line is a legal move in the current position, so the sequence doubles as documentation of what is allowed when. `complete_bet_or_raise_to` takes an absolute amount rather than a raise increment, which keeps the transcript readable and sidesteps the ambiguity of minimum raises at different streets. Naming the actor in the trailing comment is what turns the script into a record of who did what.

## Multi-runout is declared before the cards appear

All-in hands with more than one possible runout are handled by telling the state how many players are still live before dealing anything:

```python
state.select_runout_count(4)  # Hellmuth
state.select_runout_count(None)  # Wiggins

# Below is the first runout.

state.burn_card('??')
state.deal_board('Jh')  # Turn
state.burn_card('??')
state.deal_board('Ad')  # River
```

A player folded out of the pot passes `None`. After that, each runout is dealt by hand, burn card, turn, burn card, river, and the final stacks are printed once all four are in. For Monte Carlo work the implication is direct: the library does not shuffle for you, so the randomness, the seeding and the enumeration all stay in code you control, which is the right shape for research and the wrong shape for a quick sample.

## Automations are where custom variants come from

Rule variation is handled at construction time by an automation tuple. The Wiggins example passes seven of them, covering ante posting, bet collection, blind or straddle posting, hole card showing or mucking, hand killing, chip pushing and chip pulling, plus a flag for whether antes are uniform, the antes themselves, the blinds, a minimum bet, the starting stacks, the player count and a mode that can be set to a cash game. The short-deck example instantiates `NoLimitShortDeckHoldem`, so a variant with a different deck is a different class from the factory's point of view, while rule mechanics inside it are a different tuple. A variant that mucks unclaimed pots or skips the hand-killing step is a different tuple rather than a subclass, which is a compact way to express the differences between poker disciplines.

## Pure Python, and the tooling that claims to prove it

The reliability claim is specific and checkable: static type checking, extensive doctests and unit tests, reaching 99 percent coverage. The tooling behind it appears in `requirements.txt`, which lists build, coverage, flake8, interrogate, mypy, Sphinx and twine, and nothing else. No runtime library appears there, which is consistent with a pure-Python implementation, and interrogate in particular is a docstring-coverage tool, so the doctest claim is enforced by something rather than asserted. Documentation is reStructuredText, with `code-block` directives for every example and the site built by Sphinx through a readthedocs configuration, and the sources live in `docs/` with a `TODOS.rst` at the root for what is still planned. The project also lists itself as intended for education as well as development, which matches how the examples are written.

## Version 0.7.7.dev0 in setup.py, v0.7.6 as the newest tag

Packaging is a single `setup.py` with no pyproject file, which is a deliberate-looking choice for a library this old and this stable, and the metadata marks it Development Status 5, Production/Stable, with Python 3.11, 3.12 and 3.13 declared. The version there is 0.7.7.dev0 while the newest published release is v0.7.6 from 2026-09-17, so the development branch is one increment ahead of anything on PyPI. The keyword list is a good description of intent, naming imperfect-information games, game theory, hold'em, an evaluator, an engine and strategies, and crediting the open-source engines Libratus and Pluribus by name. The project is maintained by a research group whose name expands to Universal, Open, Free, and Transparent Computer Poker Research Group, which is also the author field in the packaging metadata.

## Where PokerKit is the wrong tool

It simulates and evaluates; it does not decide. There is no opponent model, no search and no policy, so if the question is what an agent should do, this library gives you the environment and you build the rest. It is also not the fastest way to evaluate a single seven-card hand: the feature list advertises high-speed hand evaluations, but a dedicated evaluator library is a smaller dependency for that job, and this one is pure Python where the fastest evaluators are C. What it is for is breadth and correctness across variants, and for the cases where a rule subtlety is the thing you are testing.

## Conclusion

pokerkit fits research work where the rules have to be exact and the plumbing has to disappear: enumerating variants, replaying a hand to check a rule change, building a Monte Carlo study over a rule variant. It does not fit a solver, a strategy engine or an online bot, and a pure-Python implementation will not match a compiled evaluator for raw throughput. Verify two things before you build on it: which Python versions you can run, since 3.11 or above is required, and whether your own Monte Carlo loop drives the deck, because the documented usage deals every card explicitly rather than shuffling for you.

## FAQ

### How do I install PokerKit?

Run pip install pokerkit on Python 3.11 or above, which is the version floor the project declares and tests against, with 3.12 and 3.13 also listed in the classifiers. The documentation is hosted at pokerkit.readthedocs.io.

### How does PokerKit model a hand?

You create a state object through a variant factory such as NoLimitTexasHoldem.create_state, passing automations, antes, blinds, a minimum bet, starting stacks, a player count and an optional mode. You then mutate it with explicit calls like deal_hole, deal_board, burn_card, fold, check_or_call and complete_bet_or_raise_to.

### Can PokerKit deal cards randomly for Monte Carlo work?

The documented usage deals every card explicitly, including burned cards as '??', and declares multi-runout with select_runout_count before the runouts appear. Randomness and seeding therefore live in your own loop rather than inside the state object.

### Which poker variants does PokerKit support?

The library covers major and minor variants, with classes such as NoLimitTexasHoldem and NoLimitShortDeckHoldem in the examples. Rule differences are expressed through the automation tuple passed at construction, and the architecture is intended to let users define their own games.

### What testing does PokerKit claim?

Static type checking, extensive doctests and unit tests, at 99 percent code coverage. The development requirements include mypy for type checking, flake8, interrogate for docstring coverage, coverage for measurement, Sphinx for the documentation and twine for publishing.

## Sources

- [License: MIT](https://github.com/uoftcprg/pokerkit/blob/main/LICENSE)
- [Project website](https://pokerkit.readthedocs.io/)
- [README](https://github.com/uoftcprg/pokerkit/blob/main/README.md)
- [Releases](https://github.com/uoftcprg/pokerkit/releases)
- [uoftcprg/pokerkit on GitHub](https://github.com/uoftcprg/pokerkit)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/uoftcprg-pokerkit
