In Craps, a throw of the dice may change the state of the game. This close relationship between the Throw and CrapsGame leads to another chicken-and-egg design problem. We’ll design Throw in detail, but provide a rough stub for CrapsGame.
Additionally, this chapter will introduce the subtle issue of over-engineering when doing design work. We’ll revist these issues a number of times in order to provde examples of good design and the issues that can lead to poor design.
The pair of dice can throw a total of 36 unique combinations. These are summarized into fifteen distinct outcomes: the eleven numbers from 2 to 12, plus the four hardways variations for 4, 6, 8 and 10.
In Roulette, the randomized positions on the wheel were called Bin s and each one had a very simple collection of winning Outcome s. In Craps, however, the randomized throws of the dice serve three purposes: they resolve simple one-roll proposition bets, they may resolve hardways bets, and they change the game state (which may resolve game bets). From this we can allocate three responsibilities. We’ll look at each of these responsibilities individually.
One-Throw Propositions. A Throw of the dice includes a collection of proposition Outcomes which are immediate winners. This collection will be some combination of 2, 3, 7, 11, 12, Field, Any Craps, or Horn. For completeness, we note that each throw could also contain one of the 21 hop-bet Outcomes; however, we’ll ignore the hop bets.
Multi-Throw Propositions. A Throw of the dice may resolve hardways bets (as well as place bets and buy bets). There are three possible conditions for a given throw: some bets may be winners, some bets may be losers, and some bets may remain unresolved. This tells us that a Throw may be more than a simple collection of winning Outcomes. A Throw must also contain a list of losing Outcomes. For example, any of the two easy 8 rolls (6-2 or 5-3) would contain winning Outcomes for the place-8 bet and buy-8 bet, as well as a losing Outcome for a hardways-8 bet. The hard 8 roll (4-4), however, would contain winning Outcome s for the place-8 bet, buy-8 bet, and hardways-8 bet
Game State Change. Most importantly, a Throw of the dice can lead to a state change of the Game. This may resolve game-level bets. From the Craps Game, we see that the state changes depend on both the Game state plus the kind of Throw. The rules identify the following species of Throw.
The state change can be implemented by defining methods in Game that match the varieties of Throw. We can imagine that the design for Game will have four methods: craps(), natural(), eleven(), and point(). Each kind of Throw will call the matching method of Game, leading to state changes, and possibly game bet resolution.
The game state changes lead us to design a hierarchy of Throw classes to enumerate the four basic kinds of throws. We can then initialize a Dice object with 36 Throw objects, each of the appropriate subclass. When all of the subclasses have an identical interface, this embodies the principle of polymorphism. For additional information, see On Polymorphism.
In looking around, we have a potential naming problem: both a wheel’s Bin and the dice’s Throw are somehow instances of a common abstraction. Looking forward, we may wind up wrestling with a deck of cards trying to invent a common nomenclature for all of these randomizers. They create random events, and this leads us to a possible superclass for Bin and Throw: RandomEvent.
Currently, we can’t identify any features that we can refactor up into the superclass. Rather than over-engineer this, we’ll hold off on complicating the design until we find something else that is common between our sources of random events. See the Soapbox on Over-Engineering as a continuation of this rant.
Throw is the superclass for the various throws of the dice. Each subclass is a different grouping of the numbers, based on the rules for Craps.
Returns true if d1 is equal to d2. This helps determine if hardways bets have been won or lost.
| Parameter: | game (CrapsGame) – the Game to be updated based on this throw. |
|---|
Calls one of the Game state change methods: craps(), natural(), eleven(), point(). This may change the game state and resolve bets.
An easy-to-read String output method is also very handy. This should return a String representation of the dice. A form that looks like 1,2 works nicely.
Natural Throw is a subclass of Throw for the natural number, 7.
| Parameters: |
|
|---|
Creates this throw. The constraint is that
. If the constraint is not satisfied, simply raise an exception.
This uses the superclass constructor to add appropriate Outcomes for a throw of 7.
A natural 7 is odd, and can never be made “the hard way”. This method always returns false.
| Parameter: | game (CrapsGame) – the Game to be updated based on this throw. |
|---|
Calls the natural() method of a game Game. This may change the game state and resolve bets.
Craps Throw is a subclass of Throw for the craps numbers 2, 3 and 12.
| Parameters: |
|
|---|
Creates this throw. The constraint is that
. If the constraint is not satisfied, simply raise an exception.
This uses the superclass constructor to add appropriate Outcomes for a throw of craps.
The craps numbers are never part of “hardways” bets. This method always returns false.
| Parameter: | game (CrapsGame) – the Game to be updated based on this throw. |
|---|
Calls the craps() method of a game Game. This may change the game state and resolve bets.
Eleven Throw is a subclass of Throw for the number, 11. This is special because 11 has one effect on a come-out roll and a different effect on point rolls.
| Parameters: |
|
|---|
Creates this throw. The constraint is that
. If the constraint is not satisfied, simply raise an exception.
This uses the superclass constructor to add appropriate Outcomes for a throw of 11.
Eleven is odd and never part of “hardways” bets. This method always returns false.
| Parameter: | game (CrapsGame) – the Game to be updated based on this throw. |
|---|
Calls the eleven() method of a game Game. This may change the game state and resolve bets.
Point Throw is a subclass of Throw for the point numbers 4, 5, 6, 8, 9 or 10.
| Parameters: |
|
|---|
Creates this throw. The constraint is that
. If the constraint is not satisfied, simply raise an exception.
This uses the superclass constructor to add appropriate Outcomes for a throw of craps.
Eleven is odd and never part of “hardways” bets. This method always returns false.
Returns true if d1 is equal to d2. This helps determine if hardways bets have been won or lost.
| Parameter: | game (CrapsGame) – the Game to be updated based on this throw. |
|---|
Calls the point() method of a game Game. This may change the game state and resolve bets.
CrapsGame is a preliminary design for the game of Craps. This initial design contains the interface used by the Throw class hierarchy to implement game state changes.
Creates this Game. This will be replaced by a constructor that uses Dice and CrapsTable.
Resolves all current 1-roll bets.
If the point is zero, this was a come out roll: Pass Line bets are an immediate loss, Don’t Pass Line bets are an immediate win.
If the point is non-zero, Come Line bets are an immediate loss; Don’t Come Line bets are an immediate win.
The state doesn’t change.
A future version will delegate responsibility to the craps() method of a current state object.
Resolves all current 1-roll bets.
If the point is zero, this was a come out roll: Pass Line bets are an immediate win; Don’t Pass Line bets are an immediate loss.
If the point is non-zero, Come Line bets are an immediate win; Don’t Come bets are an immediate loss; the point is also reset to zero because the game is over.
Also, hardways bets are all losses.
A future version will delegate responsibility to the natural() method of a current state object.
Resolves all current 1-roll bets.
If the point is zero, this is a come out roll: Pass Line bets are an immediate win; Don’t Pass Line bets are an immediate loss.
If the point is non-zero, Come Line bets are an immediate win; Don’t Come bets are an immediate loss.
The game state doesn’t change.
A future version will delegate responsibility to the eleven() method of a current state object.
| Parameter: | point (integer) – The point value to set. |
|---|
Resolves all current 1-roll bets.
If the point was zero, this is a come out roll, and the value of the dice establishes the point.
If the point was non-zero and this throw matches the point the game is over: Pass Line bets and associated odds bets are winners; Don’t Pass bets and associated odds bets are losers; the point is reset to zero.
Finally, if the point is non-zero and this throw does not match the point, the state doesn’t change; however, Come point and Don’t come point bets may be resolved. Additionally, hardways bets may be resolved.
A future version will delegate responsibility to the current state’s point() method to advance the game state.
An easy-to-read String output method is also very handy. This should return a String representation of the current state. The stub version of this class has no internal state object. This class can simply return a string representation of the point; and the string "Point Off" when point is zero.
There are eleven deliverables for this exercise.