Inspiration
Poker is a game of hidden information: you never see your opponent's cards, and every bet both gives away and hides something. Casino Royale gave us a poker variant that almost no one has studied: Heads-Up Short Deck 5-card Pot-Limit Omaha. Off-the-shelf poker AI is built for Texas Hold'em and doesn't carry over. Flushes beat full houses, three of a kind beats a straight, and you must use exactly 2 of your 5 hole cards. We wanted to see how far a small, fast, data-driven bot could get on a game with no existing playbook.
What it does
EquityNet is a FastAPI bot that plays full 2,000-hand duplicate matches. On every decision it:
- Preflop: scores the 5-card starting hand with a small neural network that doesn't depend on suits, trained on simulated showdowns.
- Flop onward: estimates showdown equity, the share of the pot it expects to win, with a neural network trained on simulated runouts. On the river it can count outcomes exactly instead of estimating.
- Reads the opponent: tracks how often the opponent checks or bets on each street, and how often they fold to our turn raises. It uses those counts to adjust what hands it thinks the opponent holds.
- Picks the best legal action: compares the expected chip value of check, half-pot and pot. It only switches away from its safe default when the predicted gain beats a set share of the pot (12% on the turn, 15% on the river). ## How we built it Training data from simulation. We generated about 45,000 flop, turn and river situations with 80 rollouts each, scored by the organizers' own evaluator so hand rankings match the referee exactly. A win counts as 1, a tie as 0.5 and a loss as 0: $$\text{equity} = \frac{1}{N}\sum_{i=1}^{N}\left(\mathbb{1}[\text{win}_i] + \tfrac{1}{2}\,\mathbb{1}[\text{tie}_i]\right)$$
- PyTorch for training, NumPy for play. We trained in PyTorch and exported the weights to
.npzfiles, so the bot runs on CPU with NumPy only, with no PyTorch at match time. - A turn action-value model. On simulated turns, we played out every legal action on the same sampled hands and rivers and learned the chip gain of each. It's exported as compact decision trees that run on plain arrays.
- River calibration. A logistic model adjusts river equity using bet size, position and earlier aggression.
- Precomputed score tables for every 2-hole + 3-board combination, built at startup, so a full showdown evaluation is one array lookup. ## Challenges we ran into An 8-second thinking budget per 1,000 hands, about 4–7 ms per decision. Monte Carlo search on every decision was far too slow, so we moved the heavy work offline into trained models and lookup tables. The bot also tracks its own thinking time and stops the expensive planning before the budget runs out.
- Short-deck rules break intuition. Standard poker heuristics give wrong answers here, so every training label came from the actual evaluator, never from assumed hand rankings.
- No crashes allowed. Five errors forfeit a half, and a forfeit loses the match. Every decision has a fallback: if anything throws or picks an illegal move, the bot falls back to check/call.
- Duplicate scoring hides luck but not noise. Telling a real improvement from variance took long, multi-seed runs with confidence intervals. ## Accomplishments that we're proud of
What we learned
Inspiration
Poker is a game of hidden information: you never see your opponent's cards, and every bet both gives away and hides something. Casino Royale gave us a poker variant that almost no one has studied: Heads-Up Short Deck 5-card Pot-Limit Omaha. Off-the-shelf poker AI is built for Texas Hold'em and doesn't carry over. Flushes beat full houses, three of a kind beats a straight, and you must use exactly 2 of your 5 hole cards. We wanted to see how far a small, fast, data-driven bot could get on a game with no existing playbook.
What it does
EquityNet is a FastAPI bot that plays full 2,000-hand duplicate matches. On every decision it:
- Preflop: scores the 5-card starting hand with a small neural network that doesn't depend on suits, trained on simulated showdowns.
- Flop onward: estimates showdown equity, the share of the pot it expects to win, with a neural network trained on simulated runouts. On the river it can count outcomes exactly instead of estimating.
- Reads the opponent: tracks how often the opponent checks or bets on each street, and how often they fold to our turn raises. It uses those counts to adjust what hands it thinks the opponent holds.
- Picks the best legal action: compares the expected chip value of check, half-pot and pot. It only switches away from its safe default when the predicted gain beats a set share of the pot (12% on the turn, 15% on the river).
Everything it learns about an opponent lives in the per-half memory and uses only public information, as the rules require.
How we built it
- Training data from simulation. We generated about 45,000 flop, turn and river situations with 80 rollouts each, scored by the organizers' own evaluator so hand rankings match the referee exactly. A win counts as 1, a tie as 0.5 and a loss as 0: $$\text{equity} = \frac{1}{N}\sum_{i=1}^{N}\left(\mathbb{1}[\text{win}_i] + \tfrac{1}{2}\,\mathbb{1}[\text{tie}_i]\right)$$
- PyTorch for training, NumPy for play. We trained in PyTorch and exported the weights to
.npzfiles, so the bot runs on CPU with NumPy only, with no PyTorch at match time. - A turn action-value model. On simulated turns, we played out every legal action on the same sampled hands and rivers and learned the chip gain of each. It's exported as compact decision trees that run on plain arrays.
- River calibration. A logistic model adjusts river equity using bet size, position and earlier aggression.
- Precomputed score tables for every 2-hole + 3-board combination, built at startup, so a full showdown evaluation is one array lookup.
- Benchmarking with the official judge, fresh servers for each half, and multiple seeds against every baseline bot and against our own earlier versions.
Challenges we faced
- An 8-second thinking budget per 1,000 hands, about 4–7 ms per decision. Monte Carlo search on every decision was far too slow, so we moved the heavy work offline into trained models and lookup tables. The bot also tracks its own thinking time and stops the expensive planning before the budget runs out.
- Short-deck rules break intuition. Standard poker heuristics give wrong answers here, so every training label came from the actual evaluator, never from assumed hand rankings.
- No crashes allowed. Five errors forfeit a half, and a forfeit loses the match. Every decision has a fallback: if anything throws or picks an illegal move, the bot falls back to check/call.
- Duplicate scoring hides luck but not noise. Telling a real improvement from variance took long, multi-seed runs with confidence intervals.
What we learned
- A small model trained on the right simulated data beats hand-tuned rules. Our equity network's error was 5.5 percentage points against 19.4 for the rules-based estimate.
- Exploiting opponents works best when it's cautious: start from a sound default and deviate only when the evidence and the expected gain are both clear.
- Engineering limits (time, CPU, reliability) shaped the strategy as much as poker theory did. ## What's next for Heads Up - datajohn Self-play and CFR-style training to move toward an unexploitable strategy, and an action-value model for the flop.
Built With
- docker
- fastapi
- machine-learning
- numpy
- pytest
- python
- pytorch
- scikit-learn
- uvicorn