This post demonstrates how Petri nets handle complex multi-player state machines. Texas Hold'em poker requires turn-taking, role-based permissions, betting conditions, and a complete audit trail. Rather than coding these rules imperatively, we encode them structurally in a Petri net.
Try the interactive demo at pilot.pflow.xyz/texas-holdem.
Poker has intricate state:
Traditional implementations scatter this logic across conditionals. A Petri net makes it explicit and verifiable.
The core flow is a sequential state machine. Each betting round is a place, and phase transitions move the game forward:
Places represent game phases:
waiting — Before hand startspreflop — Hole cards dealt, first betting roundflop — Three community cards revealedturn_round — Fourth card revealedriver — Fifth card revealedshowdown — Final comparisoncomplete — Hand finishedTransitions like deal_flop require the previous phase and betting_done to be marked—ensuring all players have acted before advancing.
Each player has a turn place (p0_turn, p1_turn, etc.). When it's Player 0's turn, only p0_turn holds a token. Player actions consume their turn token and produce the next player's:
p0_check:
inputs: [p0_turn, p0_active]
outputs: [p1_turn]
This enforces strict turn order without explicit checks—the structure makes illegal moves impossible.
Not all transitions are available to all players. The model uses roles to restrict who can fire which transitions:
| Role | Transitions | Purpose |
|---|---|---|
dealer |
deal_flop, deal_turn, deal_river |
Only dealer advances phases |
player0 |
p0_fold, p0_check, p0_call, p0_raise |
Player-specific actions |
admin |
end_hand, determine_winner |
Game control |
When using go-pflow, the API enforces these roles—a player can't fire another player's transitions.
Some actions require additional conditions beyond token availability. Guards are boolean expressions that must evaluate true:
p0_raise:
guard: "bets[0] >= current_bet && chips[0] >= raise_amount"
This ensures:
Guards add business logic without complicating the Petri net structure. The net handles what can happen; guards handle when.
Every transition firing creates an immutable event:
[
{"action": "start_hand", "time": "10:00:00"},
{"action": "p0_raise", "amount": 50, "time": "10:00:15"},
{"action": "p1_call", "time": "10:00:23"},
{"action": "p2_fold", "time": "10:00:31"},
{"action": "deal_flop", "cards": ["Ah", "Ks", "7d"], "time": "10:00:35"}
]
This provides:
The Petri net's discrete transitions map perfectly to event sourcing—each firing is one event.
While the game runs discretely, ODE simulation provides strategic insights. By converting the Petri net to continuous dynamics, we can evaluate position strength:
The simulation treats possible outcomes as competing flows. Higher ODE values for win_p0 indicate stronger positions. This is similar to the tic-tac-toe ODE analysis, scaled up for poker's larger state space.
The full model has:
Places (17):
waiting, preflop, flop, turn_round, — Phase places
river, showdown, complete
p0_turn, p1_turn, p2_turn, — Turn tokens
p3_turn, p4_turn
p0_active, p1_active, p2_active, — Active markers
p3_active, p4_active
betting_done — Sync signal
Transitions (32):
start_hand, deal_flop, deal_turn, — Phase transitions
deal_river, go_showdown, determine_winner,
end_hand
p0_fold, p0_check, p0_call, p0_raise, — Player 0 actions
p1_fold, p1_check, p1_call, p1_raise, — Player 1 actions
... (5 players × 4 actions)
p0_skip, p1_skip, ... — Skip folded players
| Concept | Texas Hold'em Example |
|---|---|
| State machine | Betting rounds as sequential places |
| Turn control | Turn tokens enforce player order |
| Role-based access | Dealer vs player vs admin actions |
| Guards | Betting conditions (chips, amounts) |
| Event sourcing | Every action logged for replay/audit |
| ODE analysis | Strategic position evaluation |
Traditional game code mixes state, rules, and UI. A Petri net separates concerns:
This separation makes games:
Texas Hold'em demonstrates that Petri nets scale beyond simple workflows. Complex multi-player games with turn order, role permissions, and conditional logic fit naturally into the place-transition-arc paradigm.
The model doesn't contain poker strategy—it contains poker structure. Strategy emerges from analysis (ODE simulation) rather than being hardcoded. This separation of mechanism from policy is the core Petri net insight.
For foundational concepts: Tic-Tac-Toe Model
For the theory behind ODE analysis: Declarative Differential Models