Throw Class¶
In Craps, a throw of the dice may change the state of the game. This
close relationship between the Throw
class and CrapsGame
class
leads us to design the Throw
class
in detail, along with a rough stub for the CrapsGame
class.
We’ll try to keep the Throw
class as a parallel with
the Bin
class in Roulette. It will hold a bunch of
individual Outcome
instances.
We’ll look at the nature of a Throw
in Throw Analysis.
This will lead us to look – again – at The Wrap vs. Extend Question. This is an important question related to how we’ll use a collection class.
In Throw Design we’ll look at the top-level superclass. There are a number of subclasses:
Once we have the throw defined, we can examine the outline of the game in Craps Game Design. This will show how game and throw collaborate. In Throw Deliverables we’ll enumerate the deliverables for this chapter.
Throw Analysis¶
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
instances
and each one had a collection of winning Outcome
instances.
The Outcome
objects were matched against the Bet
objects
created by the player.
In Craps, however, the throws of the dice serve three distinct purposes:
They resolve any of the one-roll proposition bets.
They may also resolve any hardways bets.
They may also change the game state. This may also resolve the game bets.
We’ll look at each of these responsibilities individually.
One-Throw Propositions. Each Throw
object can include a
collection of proposition Outcome
instances. These 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 Outcome
instances;
however, we’ll ignore the hop bets.
Multi-Throw Propositions. A Throw
object may resolve
hardways bets (as well as place bets and buy bets). There are three
possible conditions for a given throw:
Some hardways bets may be winners because the number was two equal dice.
Some bets may be losers because the number was two non-equal dice or a seven.
Some bets may remain unresolved because the dice were neither the target number, nor a seven.
This tells us that a Throw
object may be more than a simple collection of winning
Outcome
instances.
It seems sensible for a Throw
object must also contain a list of losing
Outcome
instances. For example, any of the two easy 8 rolls (6-2 or
5-3) would contain winning Outcome
instances for the place-8 bet
and buy-8 bet, as well as a losing Outcome
instances for a hardways-8
bet. The hard 8 roll (4-4), however, would contain winning Outcome
instances
for the place-8 bet, buy-8 bet, and hardways-8 bet
Game State Change. Most importantly, a Throw
object
can lead to a state change of the game. If the game ends, this will resolve
game-level bets. From the Craps Game Overview, we see that
the state changes depend on both the CrapsGame
object’s state.
The rules identify the following species of Throw
instance:
Craps. These are throws of 2, 3 or 12. In the come-out roll state, this is an immediate loss. In any other state, this is ignored. There are 4 of these throws.
Natural. This is a throw of 7. In the come-out roll state, this is an immediate win. In any other state, this is an immediate loss and a change of state back to the start of a game. There are 6 of these throws.
Eleven. This is a throw of 11. In the come-out roll state, this is an immediate win. In any other state, this is ignored. There are 2 of these throws.
Point. This is a throw of 4, 5, 6, 8, 9, or 10. In the come-out roll state, this establishes the point, and changes the game state. In any other state, this is is compared against the established point: if it matches, this is a win and a change of game state. Otherwise, no game state change occurs. There are a total of 24 of these throws.
The state change can be implemented by defining methods in CrapsGame
class
that match the varieties of Throw
. We can imagine that the
design for the CrapsGame
class will have four methods: craps()
,
natural()
, eleven()
, and point()
.
Each kind of Throw
subclass will call the matching method of
the CrapsGame
class, leading to possible state changes, and possible game bet resolution.
The game state changes lead us to design a hierarchy of Throw
subclasses. 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. All three create random events, and this leads us to a possible
superclass for the Bin
class and Throw
class: a RandomEvent
class.
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.
The Wrap vs. Extend Question¶
Note that an instance of the Throw
class is effectively a container for
a set of Outcome
instances. We have the standard
Wrap vs. Extend question that we need to answer here.
Wrap. Each
Throw
class can have an internal frozenset ofOutcome
objects.Extend. We base the
Throw
class on thefrozenset
class directly and add methods to add features.
We have a fairly large number of methods that are introduced in this design.
When we look back at Roulette, a Bin
object had no impact on the state
of the game. In Craps, though, there’s a need for each Throw
object
to update the current state of the game.
Both options seem sensible.
Lacking further information, we’ll focus on using a Wraps approach,
and define the Throw
class
so it has a frozenset
object as an attribute.
Throw Design¶
-
class
Throw
¶ The
Throw
class 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.
Fields¶
-
Throw.
outcomes
¶ A
Set
of one-rollOutcomes
that win with this throw.We’ll include the two numbers showing on the dice because it makes it easy to produce helpful debugging output. In the long run, the numbers don’t really matter as much as the state changes.
-
Throw.
d1
One of the two die values, from 1 to 6.
-
Throw.
d2
The other of the two die values, from 1 to 6.
Constructors¶
-
Throw.
__init__
(self, d1: int, d2: int, *outcomes: Outcome) → None Creates this throw, and associates the given
Set
ofOutcome
instances that are winning propositions.- Parameters
d1 – The value of one die
d2 – The value of the other die
outcomes – The various
Outcome
objects for this throw. These are bets immediately resolved as winners.
Methods¶
-
Throw.
hard
(self) → bool Returns
True
ifd1
is equal tod2
. This helps determine if hardways bets have been won or lost.
-
Throw.
updateGame
(self, game: CrapsGame) → None -
This method calls one of the
CrapsGame
state change methods:craps()
,natural()
,eleven()
,point()
. This may change the game state and resolve bets.
-
Throw.
__str__
(self) → str An easy-to-read string output method is also very handy. A form that looks like
1,2
works nicely.
Natural Throw Design¶
Constructors¶
-
NaturalThrow.
__init__
(self, d1: int, d2: int) → None¶ - Parameters
d1 – The value of one die
d2 – The value of the other die
Creates this
Throw
instance. The constraint is that . If the constraint is not satisfied, raise an exception.This uses the superclass constructor to add appropriate
Outcome
instances for a throw of 7.
Craps Throw Design¶
Constructors¶
-
CrapsThrow.
__init__
(self, d1: int, d2: int) → None¶ - Parameters
d1 – The value of one die
d2 – The value of the other die
Creates this
Throw
instance. The constraint is that . If the constraint is not satisfied, raise an exception.This uses the superclass constructor to add appropriate
Outcome
instances for a throw of craps.
Eleven Throw Design¶
-
class
ElevenThrow
¶ ElevenThrow
is a subclass ofThrow
for the number, 11. This is special because 11 has one effect on a come-out roll and a different effect on point rolls.
Constructors¶
-
ElevenThrow.
__init__
(self, d1: int, d2: int) → None¶ - Parameters
d1 – The value of one die
d2 – The value of the other die
Creates this
Throw
instance. The constraint is that . If the constraint is not satisfied, raise an exception.This uses the superclass constructor to add appropriate
Outcome
instances for a throw of 11.
Point Throw Design¶
-
class
PointThrow
¶ PointThrow
is a subclass ofThrow
for the point numbers 4, 5, 6, 8, 9 or 10.
Constructors¶
-
PointThrow.
__init__
(self, d1: int, d2: int) → None¶ - Parameters
d1 – The value of one die
d2 – The value of the other die
Creates this
Throw
instance. The constraint is that . If the constraint is not satisfied, raise an exception.This uses the superclass constructor to add appropriate
Outcome
instances for a throw of craps.
Craps Game Design¶
This is a stub class definition for CrapsGame
.
This initial design contains the interface used by the Throw
class hierarchy to implement game state changes. In a later section,
we’ll provide a more complete definition.
Fields¶
-
GrapsGame.
point
The current point. This will be replaced by a proper State design pattern.
Constructors¶
-
CrapsGame.
__init__
(self) → None Creates this game. A later version will use a constructor to include the
Dice
instance and theCrapsTable
instance.
Methods¶
-
CrapsGame.
craps
(self) → None¶ 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.
-
CrapsGame.
natural
(self) → None¶ Resolves all current 1-roll bets.
If the point is
None
, 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-
None
, 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.
-
CrapsGame.
eleven
(self) → None¶ Resolves all current 1-roll bets.
If the point is
None
, 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-
None
, 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.
-
CrapsGame.
point
(self, point: int) → None¶ - Parameters
point (integer) – The point value to set.
Resolves all current 1-roll bets.
If the point was
None
, this is a come out roll, and the value of the dice establishes the point.If the point was non-
None
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-
None
and this throw does not match the point, the state doesn’t change. 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.
-
Throw.
__str__
(self) → str An easy-to-read string output method is also very handy. 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"
whenpoint
isNone
.
Throw Deliverables¶
There are eleven deliverables for this exercise.
A stub class for
CrapsGame
with the various methods invoked by the throws. The design information includes details on bet resolution that doesn’t need to be fully implemented at the present time. For this stub class, the change to thepoint
variable is required for unit testing. The other information should be captured as comments and output statements that help confirm the correct behavior of the game.The
Throw
superclass, and the four subclasses:CrapsThrow
,NaturalThrow
,ElvenThrow
,PointThrow
.Five classes which perform unit tests on the various classes of the
Throw
class hierarchy.