A complete Flip 7 model in Python: the deck, the full multiplayer rules, a set of playable strategies, an exact optimal-stopping solver, and a command line to run it all. No dependencies beyond the standard library.
See blog post at https://stevemurch.com/flip-7-card-game-optimal-strategies/2026/08
| file | what it holds |
|---|---|
deck.py |
card model, the 94-card deck, draw/discard/reshuffle, one player's line and its score |
sim.py |
the game engine: turns, action cards, Flip 7, round and game end |
strategies.py |
decision policies, including a human prompt |
dp.py |
exact single-player optimal-stopping DP and the solved policy cache |
advice.py |
boils the solved table down to a rule a person can use |
main.py |
command line: play, sim, round, watch, rules |
test_flip7.py |
17 checks, including a DP against simulation cross-check |
runlog.py |
tees every run into results/ |
python3 main.py play # you against three bots
python3 main.py sim -n 4000 -p dp,ev,bust:0.25,sum:20
python3 main.py round -n 20000 -p ev,dp # one-round score distribution
python3 main.py watch -p ev,ev,ev # one game, card by card
python3 main.py rules # deck and scoring reference
python3 dp.py # solve the single-player game
python3 dp.py --all # every policy, exactly (~3 min)
python3 advice.py # the optimal rule, in one table
python3 odds.py # the full odds reference
python3 test_flip7.pyEvery run also writes what it printed to results/<command>-<timestamp>.txt.
Use -o PATH to choose the file or --no-file to skip it.
python3 main.py rules prints this list too.
| policy | how it decides |
|---|---|
sum:N |
Hit until the face values in front of you total N or more, then stay. The classic table rule. Cheap, and hard to beat by much. |
count:N |
Hit until you hold N distinct numbers. Worse than the sum rule: a line of 0 1 2 3 is safe and nearly worthless. |
bust:P |
Hit while the chance that the next card duplicates a number you already show stays under P. Risk-based, and blind to what is at stake. |
bustc:P |
The same rule, counting the discard pile exactly instead of only reading the table. |
ev |
Hit whenever taking one more card, then stopping, beats standing right now. One-step lookahead over the unseen cards, and it lands within a whisker of the exact optimum. |
evc |
The same one-step rule with perfect card counting. |
dp |
The exact solo optimum, looked up in a solved table of 1.8M states. Plans to the end of the round instead of one card ahead. |
endgame |
Wraps ev with race awareness: once someone is within 60 of the target it gambles when trailing and coasts when ahead. |
human |
Prompts you at the terminal, showing the table, your bust risk, and the value of one more card. |
All of them share the same targeting heuristics for the action cards: freeze yourself when you are sitting on points and the next flip is dangerous, otherwise freeze whoever is closest to Flip 7; take a Flip Three yourself only when your line is short and safe, otherwise hand it to the biggest threat; pass a spare Second Chance to whoever is furthest behind.
The deck is 94 cards: 79 numbers (one 0, one 1, two 2s, up to twelve 12s),
six modifiers (+2 +4 +6 +8 +10 and x2), and nine actions (three each of
Freeze, Flip Three, Second Chance).
Every player is dealt one face-up card, then each turn you Hit or Stay. Flip a number you already show and you bust for zero, unless you hold a Second Chance, which is discarded along with the duplicate. Seven distinct numbers is a Flip 7: +15, and the round ends at once for everyone, with the other unbusted players banking what they show.
Score is sum(numbers) * (2 if x2) + sum(pluses) + 15 if Flip 7. The order
matters: x2 doubles the numbers only, so 5 + 7 with x2 and +10 is 34, not 44.
Action cards resolve the instant they are flipped:
- Freeze — give it to any player still in the round, yourself included. They bank what they have and are out.
- Flip Three — give it to any player still in the round. They flip three cards one at a time, stopping early on a bust or a Flip 7. An action flipped during those three resolves immediately, then the remaining flips continue.
- Second Chance — keep it. If you already hold one you must pass the spare to another player in the round who has none; if nobody qualifies it is discarded.
The game ends after the round in which someone reaches 200. Highest total wins.
One round, played alone, is worth 22.23 points under exact optimal play.
That is dp.py on its 88-card model deck (Freeze and Flip Three are neutral for
a solo player who can pass them on, so they drop out of the model). Optimal play
busts 31.7% of the time and reaches Flip 7 on 1.55% of rounds. The reachable
state space is 1.83M states.
Simple thresholds give up less than you would guess. These are exact figures
from python3 dp.py --all, not simulations:
policy EV sd bust flip7
optimal 22.232 17.47 31.7% 1.55%
stand on sum 16 18.559 8.92 13.7% 0.00%
stand on sum 20 20.251 12.05 21.5% 0.00%
stand on sum 24 20.977 15.51 31.6% 0.01%
stand on 3 cards 19.705 12.91 24.1% 0.00%
stand on 4 cards 19.669 18.58 43.0% 0.00%
stand on 5 cards 16.462 22.16 61.6% 0.00%
bust risk < 0.25 20.988 15.89 32.9% 0.03%
bust risk < 0.35 18.773 21.92 55.1% 0.61%
bust risk < 0.45 14.058 24.71 73.8% 4.01%
The best simple rules — stand on a sum of 24, or hit while the bust risk is under 25% — are worth about 20.98, some 5.6% below perfect play. Stopping rules based on the sum of your numbers beat rules based on the count of your cards, because a line of 0, 1, 2, 3 is both very safe and nearly worthless. Chasing Flip 7 on purpose is a trap: the policies that reach it most often (bust risk under 0.45, 4% of rounds) are the worst policies in the table.
Optimal play scores 0 on 31.7% of rounds and otherwise piles up around 25-33. There is no useful middle: you bust, or you bank roughly thirty.
More points per round is not the same as more wins, and it gets worse as the
table fills up. bust:0.25 scores measurably fewer points a round than the
EV-maximizing ev bot, about 0.15. Whether that costs it anything depends
entirely on how many people it is playing against:
players games ev win% bust:0.25 win% ev pts/rd bust pts/rd
2 100,000 50.4% 49.6% 20.63 20.52
4 60,000 24.5% 25.6% 20.90 20.73
6 42,000 15.9% 17.4% 20.97 20.76
Heads-up, maximizing value wins. At four players it loses. At six it loses clearly, by about twelve standard errors. Nothing about the policies changed — only the number of people you have to beat. A bigger field raises the score you need, and the higher-variance bot reaches it more often, even while averaging less.
The lesson is about objectives, not about Flip 7. The solver answers "how many points will I score?" The game asks "will I finish first?" Those come apart, and they come apart further the more opponents you have.
A caution on method: the first version of this result came from a single 24,000-game run, looked significant at three standard errors, and did not replicate on a second seed. The field-size experiment above is what actually settled it.
Card counting is worth less than you would hope. In a single round off a fresh
deck it is worth nothing at all: over 100,000 rounds, ev and evc scored
20.21 each, because at that point the discard pile is almost empty and the table
tells you everything. Across a full game, where discards pile up, tracking them
gains about 0.2 points a round and about a point of win rate.
The whole optimal policy fits on a beer mat. advice.py weights every state
by how often it comes up and finds the best bust-risk cut-off for each hand
size:
numbers showing hit while bust risk is under
0 always hit
1 always hit
2 22%
3 23%
4 24%
5 25%
6 34%
That rule is worth 21.02, within 5.5% of a solved 1.8M-state table. Hit while the next card has under about a one-in-four chance of duplicating you, and push to one-in-three when a single card would give you Flip 7. Everything the exact solution knows beyond that — which modifiers you hold, which specific numbers are showing, whether a Second Chance is out — is worth about one point a round.
The risks above are quoted against the real 94-card deck, which is what you can
count at a table. The solver works on its 88-card model deck, so advice.py
converts.
- The DP solves one player in isolation. It treats Freeze and Flip Three as
neutral, and it leaves the duplicate card in the deck when a Second Chance
saves you (at most 3 cards in ~80).
sim.pyimplements both rules exactly, andtest_flip7.pychecks the simulated mean against the DP's 22.23. - No strategy plays the multiplayer game optimally. The targeting heuristics for Freeze and Flip Three are reasonable, not solved.
dp_hit.bin(4MB) is a generated cache of the solved policy, one byte per state. Delete it or runpython3 dp.py --rebuild-cacheto rebuild (~13s).