Table of Contents
This section will describe a player who has a complex internal state. We will also digress on the way the states can be modeled using a group of polymorphic classes. This section also has an advanced exercise that shows some alternative implementations for the state objects, using the Singleton design pattern.
On the Internet, we found descriptions of a betting system called the “1-3-2-6” system. This system looks to recoup losses by waiting for four wins in a row. The sequence of numbers (1, 3, 2 and 6) are the multipliers to use when placing bets after winning. At each loss, the sequence resets to the multiplier of 1. At each win, the multiplier is advanced. After one win, the bet is now 3x. After a second win, the bet is reduced to 2x, and the winnings of 4x are “taken down” or removed from play. In the event of a third win, the bet is advanced to 6x. Should there be a fourth win, the player has doubled their money, and the sequence resets.
This betting system makes our player more stateful than in
previous betting systems. When designing
SevenReds, we noted that this player was
stateful, but deferred any more serious design consideration until
now.
In this case, the description of the betting system seems to identify four states: no wins, one win, two wins, and three wins. In each of these states, we have specific bets to place, and state transition rules that tell us what to do next. The following table summarizes the states, the bets and the transition rules.
| Next State | |||
|---|---|---|---|
| State | Bet | On Win | On Loss |
| No Wins | 1 | One Win | No Wins |
| One Win | 3 | Two Wins | No Wins |
| Two Wins | 2 | Three Wins | No Wins |
| Three Wins | 6 | No Wins | No Wins |
When we are in a given state, the table gives us the amount to bet in the Bet column. If this bet wins, we transition to the state named in the Win column, otherwise, we transition to the state named in the Lost column. We always start in the No Wins state.
We can exploit the State design pattern to design this more sophisticated player. This pattern suggests that we design a hierarchy of classes to represent these four states. Each state will have a slightly different bet amount, and a different next state when a bet wins. Each individual state class will be relatively simple, but we will have isolated the processing unique to each state into separate classes.
One of the consequences of the State design pattern is that it obligates us to
define the interface between the Player and the
object that holds the Player's current state.
It seems best to have the state object follow our table and provide
three methods: currentBet,
nextWon, and
nextLost. The Player
can use these methods of the state object to place bets and pick a new
state.
The state's currentBet method will
construct a Bet from an
Outcome that the Player
keeps, and the multiplier that is unique to the state. As the state
changes, the multiplier moves between 1, 3, 2 and 6.
The state's nextWon method constructs a
new state object based on the state transition table when the last bet
was a winner.
The state's nextLost method constructs
a new state based on the state transition table when the last bet was
a loser. In this case, all of the various states create a new instance
of the NoWins object, resetting the multiplier
to 1 and starting the sequence over again.