Step 3. Pick a spot, pick a custom bet menu, click solve. The strategy updates in seconds.Back to index
Training blueprint…
Blueprint iter0
Blueprint ε (mbb/g)—
Subgame iter—
Subgame ε (mbb/g)—
Section 1 · The spot
Where in the hand are you re-solving from?
Round 1 history (so far)
Board card
Round 2 history (so far)
Hero (you)
Section 2 · Your custom action menu
Pick the bet sizes you want available at this decision
When no bet is pending — pick check + sizes
When facing a bet — fold / call / raise sizes
Hero menu:— · Villain menu: blueprint defaults {x · h · p · t · a / f · c}
What this is. The blueprint already has a strategy for the standard menu {x, h, p, t, a}. Re-solve with a different menu and the bot's mix shifts to make best use of whatever sizes you offered. This is the architecture Pluribus and DeepStack run every decision, just at toy scale.
Section 3 · Re-solve
CFR on the subgame from this spot
Iter: 0ε = — mbb/gidle
Runs continuously. Click Stop at any time once the strategy looks stable — there's no fixed iteration target. Subgame ε measures how exploitable Hero's strategy is within the re-solve, given Villain plays the blueprint. For small spots (single decision, few actions) ε often converges to 0 in a couple hundred iterations — once it's flat at 0, Hero has found the best response and you can stop.
Section 4 · Hero strategy
Optimal mix per private card, with your custom menu
Reading the matrix. Each card cell shows the strategy mix as a stacked bar plus the per-action breakdown below. The EV badge is what Hero expects to win/lose from this spot with that card, in chips. Compare across J / Q / K to see how the chosen sizes get used differently by hand strength.
Section 5 · Ranges & baseline comparison
What we believe Villain holds — and what the blueprint would have done
Villain inferred range
From the blueprint strategies + observed actions
J —Q —K —
Blueprint EV (same spot, blueprint menu)
What you'd get without re-solving — for comparison
—
Section 6 · How it works under the hood
Subgame, Bayes, CFR — in plain English
Three concepts power the resolver. Each does one thing.
Subgame
The room you're solving
A subgame is the rest of a hand from a specific moment. Instead of solving the whole game from the very beginning, the engine "rewinds to here" and only solves what happens from this point on. Way smaller tree → way faster to solve. Pluribus and DeepStack do exactly this every decision they make.
Bayes
The eyes that read the past
Bayes' theorem updates a belief from evidence. You can't see Villain's card, but you can see their actions. Each action is evidence. Bayes converts the action history into a probability distribution over their hidden card — that's the range. Without it, the engine would assume Villain's card is uniformly random, ignoring everything they did.
CFR
The brain that picks the move
CFR is a no-regret learning algorithm. It runs thousands of iterations on the subgame tree, accumulating regret for each action ("I'd have done better if I'd taken this size"). The strategy then leans toward actions with positive regret. Over time it converges to the optimal mix — including frequencies for sizes that aren't in the blueprint.
The pipeline at every re-solve
STEP 01 · BAYES
Compute Villain's range
Walk the public history through the blueprint. Multiply P(action | each card) at each step. Normalize → range.
STEP 02 · SUBGAME
Build a small tree
Root chance node uses the Bayes range. Hero gets your custom menu; Villain plays the blueprint. Tree extends to terminals (showdown / fold).
STEP 03 · CFR
Solve the subgame
Iterate regret matching on the tree until Hero's strategy converges. Read off the frequencies + EV per card. ε measures how exploitable Hero is at convergence.
A concrete walkthrough you can run
Try this exact spot on the page above:
R1 = xx · Board = K · R2 = p · Hero = P2
Both players checked round 1. The board comes K. P1 then bet pot. You're sitting as P2 with one of three possible cards (J, Q, or K), facing a pot bet. Click Re-solve and observe:
Step
What the engine does
What you see
1. Bayes
For each possible (P1 card, P2 card), walk the line xx → board reveal → p through the blueprint and multiply the probability of each action. Normalize. Both checking R1 → weak hands. Then betting pot on K board → strong K signal.
Range bar in Section 5: P1 ≈ {J: 10%, Q: 15%, K: 75%}
2. Subgame
Engine builds a tree rooted here. Root chance samples (P1 card, P2 card) using the Bayes range. P2 (Hero) acts with the menu you toggled. If P2 raises, P1 reacts via blueprint. Then showdown or fold.
~21 Hero infosets (3 cards × ~7 actions)
3. CFR
Run regret matching on the tree. Each iteration, Hero plays the current mix, sees how each action would have performed, updates regret. Strategy gradually leans toward high-regret actions.
ε on chart drops to 0 (usually within hundreds of iters)
4. Read
After ε ≈ 0, the matrix in Section 4 shows Hero's optimal mix. K hands raise huge for value (range tells us P1 has K too — set-over-set means we lose, but board pairing wins). J hands fold. Q is the bluff-catch.
Strategy + EV per card in the J / Q / K cells
The mental model.Subgame is where we're solving. Bayes is who we're up against. CFR is what to do against them. Three different roles, one cohesive solver.
What if Villain bets a size the blueprint doesn't know?
The dropdown above only has blueprint sizes — h, p, t, a. If real-world Villain bets 0.7× pot, the dropdown can't represent it. The blueprint's range tracker doesn't know what to do with a size it never trained on.
The fix is action translation (Ganzfried & Sandholm 2013): map the off-tree bet probabilistically onto the two nearest blueprint sizes via the pseudo-harmonic formula. Pluribus and DeepStack run this every time an opponent makes a non-standard bet.
P(map down to A) = (B − x)(1 + A) / ((B − A)(1 + x))P(map up to B) = 1 − P(down to A) where A < x < B are pot fractions of (smaller blueprint size, real bet, larger blueprint size).
Try it: enter any bet size →
Real Villain bet (× pot)
Examples: 0.37 · 0.7 · 1.5 · 2.5
→
How to use this manually. The current resolver doesn't auto-merge translated branches. To approximate: pick whichever blueprint size has the higher translation weight (e.g., 0.7× pot → 53% of h, 47% of p → use h). For exactness, run the resolver in both branches and weight the strategies you read out by the translation probabilities. That's what a production solver does internally.
Why pseudo-harmonic, not arithmetic midpoint. Pot-fraction sizes scale multiplicatively — a bet of 2× pot is "twice as much pressure" as a bet of 1× pot in a meaningful sense. Naive linear rounding to the nearest size loses EV against opponents who exploit the rounding boundary. The pseudo-harmonic formula gives the harmonic-style midpoint that minimizes worst-case exploitability of the translation itself.