I'm creating a single function called progress()
that is called after a player acts.
I think there are only 3 possible ways to end a poker game:
Here's the current pseudocode:
Determine 'players in game' (i.e. players who hasn't folded)
If there are two or more players in game
If there are players who hasn't acted
Start next player turn
Else (all players has acted)
If all players all-in, OR all players ALL-IN except one player
(If there are less than one player who can act)
Ends game fast-forward: showdown and determine winners
Else (two or more players who didn't act ALL-IN)
If this round is last round ('River')
Ends game normally: showdown and determine winners
Else
Begin next round
Else (there is only one player in game)
Ends game abruptly: that one remaining player wins
Is there anything I missed?
I think it's important to think in terms of betting rounds, not the game as a whole. A poker hand is a sequence of betting rounds. At the start of each round, some cards are dealt, some player is chosen to act first, and then players are visited in order until the round ends.
Among the data you need to keep (it's a lot) is the identity of the player who made the most recent raise in the current round (call them "the aggressor" even though it might just be big blind), and that amount. The actions that end a betting round are these:
A player calls. Next player is the aggressor. End round, continue game.
A player folds. Next player is the aggressor.
a. If more than one player has cards and un-bet money, end round, continue game as normal.
b. If two or more eligible players remain, but all but aggressor are all in, end round, continue game, but no more betting.
c. If only the aggressor has cards, end game and round. Do not deal any more cards.
If the game was not previously ended by (2c), then after the end of the final betting round, showdown cards, award pots.
(Note: minor exception here for live blinds and straddles, so add that bit in. And a bit of special-case code needed for the all-in for more than a call but less than a raise situation).
In pseudocode:
for each hand:
set "bluff" flag to false
clear all betting data
for each round:
if "bluff", break
deal some cards
while true:
visit each player
either force their action, or offer choices
if their action ends the round:
if it also ends the game (2c), set "bluff"
break (end round)
if "bluff", award all to bluffer.
else showdown, award pots as required