Charlie KrugThe Build Log

← All posts

A poker bot bluffs 20% of the time, and can prove why

Bluff Call turns a solved three-card poker game into a playable lesson, then shows the exact equilibrium frequency behind every move.

A bluff can lose chips and still be right. The harder question is whether it was right before the cards turned over. In a three-card poker game solved in 1950, that answer can be a number instead of an opinion.

Bluff Call is a playable version of Kuhn poker. There is one Jack, one Queen, one King, and one card per player. You ante a chip, check or bet, then call or fold if the other player bets. A hand takes seconds, but it keeps the useful parts of poker: hidden information, bluffing, value betting, and the risk of paying to see a card.

I built it because most poker-adjacent opponents cannot give an honest answer after a hand. A rule-based bot can explain its rules, and a trained model can report what it chose, but neither provides ground truth. Kuhn poker is small enough that its Nash equilibrium can be written down and checked by hand.

Poker small enough to solve

The equilibrium is not a fixed list of moves. It is a mixed strategy, which means some actions are correct only at a particular frequency. Bluff Call fixes the solution's parameter at alpha = 0.2. When opening the betting, that means betting a Jack 20% of the time, never betting a Queen, and betting a King 60% of the time.

Those percentages are connected. If I never bluff with the worst card, an opponent can fold too comfortably. If I always bluff, calling becomes profitable. Mixing in enough Jack bets makes the opponent indifferent at the boundary, while the King bets collect value often enough to pay for those bluffs. Neither player can improve their long-run result just by changing strategy alone. That is the useful meaning of equilibrium here, not that every hand ends well.

The opponent samples each move from the solved probability for its card and the exact betting history. The post-hand proof reads from that same table. It names the actor, card, chosen action, and equilibrium frequency for every decision that actually occurred. There is no second set of explanation rules trying to justify the bot after the fact.

The loss can still be the lesson

The reveal is the main screen, not a consolation screen. If a 20% Jack bluff runs into a King, the bankroll falls even though the sampled action was valid. One result cannot judge a mixed strategy. Frequencies only become visible across repeated hands, which is why the game keeps a session bankroll, an accuracy score, and a ledger containing both cards and the full action sequence.

There is an important limit: this is not a tiny hold'em trainer. Kuhn poker has no community cards, bet sizing, or multi-street decisions. Its entire value comes from giving those things up. The smaller game tree is what makes the answer exact and readable instead of a solver chart with thousands of branches.

The implementation is similarly small. The deck, betting state, equilibrium table, and reveal run in TypeScript in the browser, with an injected random-number source so tests can reproduce deals and mixed-strategy choices. A numeric URL seed reproduces a sequence when I need to inspect a hand. There is no account or backend, and the static build keeps the lesson inspectable all the way down.

Try it

Open Bluff Call, play the first card you are dealt, and pause when the red margin proof appears. Compare your move with its exact frequency, then play a few more hands and watch for the difference between a bad outcome and a bad decision. The equilibrium table and game source are on GitHub.

Bluff Call is live. Free, in your browser, no signup.

This post is part of the build log: every app my automated factory ships gets written up here, honestly. Browse everything at apps.charliekrug.com. Comments are open below.

Comments

Loading comments…