Table of Contents
- Recap: From Kuhn to Leduc
- Leduc Poker: Rules & Structure
- What's New: Community Cards & Multiple Streets
- Information Sets in Multi-Street Games
- Chance Nodes & the CFR Extension
- Implementation Walkthrough
- Convergence & Game Size
- Strategy Analysis: What CFR Learns
- Interactive Demo: Play Leduc Poker
- Interactive Demo: Strategy Explorer
- Bridge to Real Poker
- References
1. Recap: From Kuhn to Leduc
In Chapter 2, we implemented CFR for Kuhn Poker — a game with 3 cards, 1 betting round, and 12 information sets. CFR placed a regret-matching learner at every information set and converged to Nash Equilibrium.
But Kuhn Poker is missing two features that make real poker interesting:
- Community cards — shared cards that change hand strength mid-game
- Multiple betting rounds — new betting after new information arrives
Leduc Poker, introduced by Southey et al. (2005), adds both of these features while remaining small enough to solve exactly. It's the standard benchmark for testing poker AI algorithms — complex enough to exhibit real poker phenomena like semibluffing, yet small enough for vanilla CFR to converge in seconds.
2. Leduc Poker: Rules & Structure
Deck: 6 cards — J♠ J♦ Q♠ Q♦ K♠ K♦ (two suits of three ranks)
Setup: Both players ante 1 chip. Each receives 1 private card.
Round 1 (pre-flop): Player 1 acts first. Check or Bet (2 chips). Standard poker betting with a maximum of 2 bets per round (one bet + one raise).
Community card: One card is dealt face-up from the remaining deck.
Round 2 (post-flop): Player 1 acts first again. Same structure, but bets are 4 chips (double the round 1 size).
Showdown: If a player's card matches the community card, they have a pair (the best possible hand). Otherwise, higher card wins. Pair > No pair. Among unpaired hands: K > Q > J.
Betting Actions
At each decision point, the available actions depend on what happened before:
| Situation | Available Actions |
|---|---|
| Opening (no one has bet) | Check or Bet |
| Facing a check | Check or Bet |
| Facing a bet (fewer than 2 bets so far) | Fold, Call, or Raise |
| Facing a bet (2 bets already) | Fold or Call |
Showdown Examples
| Player 1 | Player 2 | Community | Winner | Why |
|---|---|---|---|---|
| Q | K | Q | P1 | P1 has a pair (Q-Q) |
| J | K | Q | P2 | Neither pairs; K > J |
| K | Q | K | P1 | P1 has a pair (K-K) |
| J | J | K | Tie | Same rank, neither pairs |
3. What's New: Community Cards & Multiple Streets
Leduc introduces two concepts that are absent from Kuhn Poker but central to real poker:
Hand Strength Changes
In Kuhn, if you're dealt a Jack, you have the worst hand and it can never improve. In Leduc, a Jack can become a pair — the strongest possible hand — if a Jack appears as the community card. This possibility fundamentally changes how you should play before the community card is revealed.
A semibluff is a bet with a hand that isn't currently the best but has a chance to improve. In Kuhn, bluffs with a Jack are "pure bluffs" — the Jack can never win at showdown against a better hand. In Leduc, a pre-flop bet with a Queen isn't purely a bluff: if a Queen hits the board, you make a pair. This concept is one of the most important in real poker strategy.
Multi-Street Dynamics
Two betting rounds with different bet sizes (2 chips in round 1, 4 chips in round 2) create several new strategic dynamics:
- Pot control: Checking round 1 keeps the pot small. Betting builds it. The round 2 bet (4 chips) is double the round 1 bet, so pots grow quickly.
- Position compounds: Being in position (Player 2) for two streets of information is far more valuable than for one.
- Delayed aggression: Sometimes the optimal play is to check a strong hand in round 1 to trap the opponent into betting round 2.
- Commitment: After betting round 1, you've invested chips that make folding round 2 more costly (pot odds change).
4. Information Sets in Multi-Street Games
In Kuhn, an information set was simply: card + betting_history. In Leduc, information sets must also encode the community card (when it's been dealt):
Examples:
Q:— Holding a Queen, round 1, no actions yet (opening decision)Q:kb— Holding a Queen, round 1, Player 1 checked, Player 2 betQ|K:kk/— Holding a Queen, community card is King, round 1 was check-check, round 2 openingQ|K:bc/b— Holding a Queen, community King, round 1 was bet-call, round 2 Player 1 has bet
Since suits don't affect hand strength in Leduc (only the rank matters for pairing and kicker comparisons),
we use rank-only information sets. This means Q♠ and Q♦ are treated identically.
This natural abstraction reduces the number of information sets significantly.
We'll explore abstraction as a general technique in Chapter 4.
Counting Information Sets
Leduc has 288 information sets, compared to Kuhn's 12. Here's how they break down:
- Round 1: 3 card ranks × 6 decision points = 18 info sets
- Round 2: 9 card-board combinations × 5 round 1 endings × 6 round 2 decision points = 270 info sets
That's a 24× increase over Kuhn — still tractable for vanilla CFR, but large enough to see real scaling behavior.
5. Chance Nodes & the CFR Extension
The community card introduces a new type of node in the game tree: a chance node. Unlike player nodes (where a player chooses an action), chance nodes represent random events — in this case, which card is dealt from the remaining deck.
At a chance node, CFR averages over all possible outcomes, weighted by their probability. The key insight: chance probabilities must be included in the reach calculation for the counterfactual regret formula to work correctly in multi-street games.
After dealing two private cards (say J and Q), the remaining deck contains 4 cards: {J, Q, K, K}. The community card probabilities are:
- P(Jack) = 1/4 — one Jack remains
- P(Queen) = 1/4 — one Queen remains
- P(King) = 2/4 = 1/2 — two Kings remain
The CFR traversal handles chance nodes by recursing through each possible community card:
if state.is_chance_node:
value = 0.0
for board_card in unique_remaining:
prob = count[board_card] / total_remaining
# Chance probability enters the reach calculation
value += prob * cfr(deal_board(board_card),
reach_0 * prob,
reach_1 * prob)
return value
The counterfactual regret formula requires π-i(h) —
the product of all other players' probabilities leading to history h, including chance.
Different private card deals can reach the same round 2 information set through different community card probabilities.
For example, info set J|K:kk/ is reached with probability 1/2 when the opponent holds a Queen,
but only 1/4 when the opponent holds a King (because fewer Kings remain in the deck).
Without including these chance probabilities, the regret updates weight these scenarios equally when they shouldn't be.
6. Implementation Walkthrough
The companion code (lesson_03_leduc.py) implements a complete Leduc solver.
The structure follows the Kuhn solver from Chapter 2, with three additions:
Game State Class
Unlike Kuhn (where a simple string history sufficed), Leduc needs a state object to track private cards, community card, multi-round history, and pot sizes:
class LeducState:
cards: [player_0_card, player_1_card]
board: community_card or None
history: [[round_1_actions], [round_2_actions]]
pot: [player_0_investment, player_1_investment]
Variable Action Counts
Kuhn always has exactly 2 actions (pass/bet). Leduc has 2 or 3 depending on the situation. The regret and strategy arrays are sized dynamically per information set.
Best Response Computation
Computing exploitability requires a best response that respects information sets — the BR player must make the same decision at all game states within the same info set (they can't see the opponent's card). This is computed by aggregating action values across all consistent deals for each info set, then choosing the action that maximizes the total.
7. Convergence & Game Size
Vanilla CFR converges at rate O(1/√T), meaning exploitability halves roughly every 4× increase in iterations. Leduc converges more slowly than Kuhn in absolute terms (more information sets to update) but the same rate applies.
| Game | Info Sets | Terminal Nodes | Game Value (P1) |
|---|---|---|---|
| Rock-Paper-Scissors | 1 | 9 | 0.000 |
| Kuhn Poker | 12 | 30 | -0.056 (-1/18) |
| Leduc Poker | 288 | ~1,400 | ~-0.086 |
| NLHE (full) | ~1014 | ~10160 | varies |
The jump from 12 to 288 information sets is a 24× increase. The jump from Leduc to NLHE is roughly 1012×. This astronomical gap is why real poker requires the abstraction techniques we'll cover in Chapter 4.
8. Strategy Analysis: What CFR Learns
After convergence, the equilibrium strategies reveal genuine poker wisdom. Let's examine what CFR discovers.
Round 1 Opening (Player 1)
Player 1's opening strategy shows clear hand-strength differentiation:
- King (best hand): Bets ~76% — value betting with the strongest pre-flop hand
- Queen (middle): Bets ~74% — similar to King because both want to build the pot and have pair potential
- Jack (worst hand): Checks ~92% — mostly avoids building the pot with the weakest hand
Pre-flop, the difference between Q and K is small: both are unpaired, and both have a 1-in-4 chance of pairing on the board. K has a higher kicker, but the strategic difference is modest. The big distinction comes in round 2, after the community card reveals whether either player has made a pair.
Round 2 with a Pair
Having a pair (your card matches the community card) is extremely strong in Leduc. The strategies differ by pair strength:
- K-K (pair of Kings, the nuts): Bets ~97% — maximum value extraction
- Q-Q (pair of Queens): Mixed — bets about half the time, sometimes checks to trap
- J-J (pair of Jacks, weakest pair): Checks ~97% — a check-raise trap! The opponent can't beat a pair, so J-J prefers to induce bluffs then raise
With pair of Jacks (the weakest pair but still unbeatable by any unpaired hand), CFR learns to mostly check. Why? If you bet, unpaired opponents will fold and you win nothing extra. If you check, the opponent might bluff (they don't know you have a pair), and then you can raise for maximum value. This is the same logic behind "slow-playing" in real poker.
9. Interactive Demo: Play Leduc Poker
Play as Player 1 against a near-Nash opponent. Can you beat the equilibrium strategy?
Play Leduc Poker vs. Nash Bot
Balance: 0
Avg per hand: 0.000
10. Interactive Demo: Strategy Explorer
Explore the equilibrium strategies at different information sets. Select a card and situation to see what CFR's Nash approximation recommends.
Strategy Explorer
11. Bridge to Real Poker
Leduc Poker, with its 288 information sets, demonstrates that CFR scales gracefully to multi-street games. The algorithm didn't change — we just added chance node handling and let the same regret-matching update run at every decision point.
But real No-Limit Hold'em has roughly 1014 information sets. Even with fast hardware, we can't store a strategy table with 100 trillion entries. Chapter 4 introduces the techniques that bridge this gap:
- Card abstraction: Group similar hands into "buckets" (e.g., treat all flush draws as one category)
- Action abstraction: Limit the bet sizes to a manageable set (e.g., 1/2 pot, pot, all-in) instead of every possible chip count
- Monte Carlo CFR: Sample game tree paths instead of traversing everything, making each iteration much cheaper
The core insight remains: regret matching at every information set. Everything else — abstraction, sampling, pruning, discounting — is engineering to make that core idea work at scale.
12. References
About this paper
This paper introduced Leduc Hold'em as a benchmark game for poker AI research. The authors needed a game complex enough to exhibit interesting strategic behavior (community cards, multiple betting rounds) but small enough to solve exactly for comparison purposes. Leduc became the standard testbed for new poker AI algorithms, filling the gap between the trivially small Kuhn Poker and the intractably large Texas Hold'em.
Beyond introducing Leduc, the paper develops Bayesian opponent modeling techniques that adapt to an opponent's playing style. By maintaining probability distributions over possible opponent strategies, their system can exploit deviations from equilibrium play while maintaining robustness — a key challenge in practical poker AI.
Read the paper (PDF) →About this paper
The foundational CFR paper. Zinkevich et al. proved that applying regret matching independently at each information set in an extensive-form game yields average strategies that converge to Nash Equilibrium. The paper provided the first practical algorithm for solving large imperfect-information games, with convergence guarantees that scale polynomially in the game size.
The algorithm introduced here — vanilla CFR — is exactly what we implement in Chapters 2 and 3. While later variants (CFR+, Monte Carlo CFR, discounted CFR) improved practical performance, the core insight that local regret minimization yields global equilibrium remains the theoretical foundation of all modern poker solvers.
Read the paper (PDF) →About this paper
This paper introduced Monte Carlo CFR (MCCFR), which samples game tree paths instead of traversing the entire tree each iteration. This makes each iteration dramatically cheaper (proportional to the depth of the tree rather than its size), enabling CFR to scale to games far larger than what vanilla CFR can handle. The paper describes several sampling schemes: external sampling, chance sampling, and outcome sampling, each with different variance-convergence trade-offs.
MCCFR was a crucial step toward solving real poker. Without sampling, vanilla CFR requires traversing every one of Leduc's ~1,400 terminal nodes each iteration. For NLHE with ~10160 terminal nodes, full traversal is impossible. MCCFR made it feasible to apply CFR to games of this scale, and modern solvers like PIOsolver use variants of this sampling approach.
Read the paper →About this paper
CFR+ is a modification of vanilla CFR that clips cumulative regrets to zero (rather than allowing them to go negative) and uses linear averaging for the strategy sum. These seemingly minor changes dramatically accelerate convergence — often by orders of magnitude. CFR+ was a key component in the Cepheus project that "essentially solved" heads-up limit Texas Hold'em.
The intuition behind CFR+ is elegant: by preventing regrets from going deeply negative, the algorithm avoids situations where an action must accumulate enormous positive regret just to "dig out of a hole" before it starts influencing the strategy. This simple modification made CFR practical for the largest poker games ever solved exactly.
Read the paper (arXiv) →About this paper
Pluribus, the first AI to defeat elite human professionals in six-player no-limit Texas Hold'em, built on the CFR foundation we study in this course. The system used a modified form of Monte Carlo CFR to compute a "blueprint strategy" for the full game, then refined it in real-time during play using depth-limited search. The blueprint computation alone required about 12,400 CPU core hours and 128 GB of RAM.
Pluribus demonstrated that the CFR approach scales not just to heads-up poker but to multiplayer games — a setting where Nash Equilibrium isn't even guaranteed to exist in the same strong sense. The paper showed that near-equilibrium play, discovered through self-play with CFR variants, is sufficient to beat the world's best human players.
Read the paper (Science) →