Throw Class

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.

Throw Overview

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.

  • Craps. These are throws of 2, 3 or 12. On a come-out roll, this is an immediate loss. On any other roll, this is ignored. There are 4 of these throws.
  • Natural. This is a throw of 7. On a come-out roll, this is an immediate win. On any other roll, this is an immediate loss and a change of state. There are 6 of these throws.
  • Eleven. This is a throw of 11. On a come-out roll, this is an immediate win. On any other roll, this is ignored. There are 2 of these throws.
  • Point. This is a throw of 4, 5, 6, 8, 9, or 10. On a come-out roll, this estanblishes the point, and changes the game state. On any other roll, this is is compared against the established point: if it matches, this is a win and a change of game state. Otherwise, it doesn’t match and no game state change occurs. There are a total of 24 of these throws, with actual frequencies between three and five.

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 Design

class Throw

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.

Fields

Throw.outcomes
A Set of one-roll Outcomes that win with this throw.
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, d2, * outcomes)

Creates this throw, and associates the given Set of Outcomes that are winning propositions.

Parameters:
  • d1 – The value of one die
  • d2 – The value of the other die
  • outcomes – The various outcomes for this Throw

Methods

Throw.hard(self) → boolean
Returns true if d1 is equal to d2. This helps determine if hardways bets have been won or lost.
Throw.updateGame(self, game)
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.
Throw.__str__(self) → String
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 Design

class NaturalThrow

Natural Throw is a subclass of Throw for the natural number, 7.

Constructors

NaturalThrow.__init__(self, d1, d2)
Parameters:
  • d1 – The value of one die
  • d2 – The value of the other die

Creates this throw. The constraint is that d1 + d2 = 7. If the constraint is not satisfied, simply raise an exception.

This uses the superclass constructor to add appropriate Outcomes for a throw of 7.

Methods

NaturalThrow.hard(self) → boolean
A natural 7 is odd, and can never be made “the hard way”. This method always returns false.
NaturalThrow.updateGame(self, game)
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 Design

class CrapsThrow

Craps Throw is a subclass of Throw for the craps numbers 2, 3 and 12.

Constructors

CrapsThrow.__init__(self, d1, d2)
Parameters:
  • d1 – The value of one die
  • d2 – The value of the other die

Creates this throw. The constraint is that d1 + d2 \in \{ 2, 3, 12 \}. If the constraint is not satisfied, simply raise an exception.

This uses the superclass constructor to add appropriate Outcomes for a throw of craps.

Methods

CrapsThrow.hard(self) → boolean
The craps numbers are never part of “hardways” bets. This method always returns false.
CrapsThrow.updateGame(self, game)
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 Design

class ElevenThrow

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.

Constructors

ElevenThrow.__init__(self, d1, d2)
Parameters:
  • d1 – The value of one die
  • d2 – The value of the other die

Creates this throw. The constraint is that d1 + d2 = 11. If the constraint is not satisfied, simply raise an exception.

This uses the superclass constructor to add appropriate Outcomes for a throw of 11.

Methods

ElevenThrow.hard(self) → boolean
Eleven is odd and never part of “hardways” bets. This method always returns false.
ElevenThrow.updateGame(self, game)
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 Design

class PointThrow

Point Throw is a subclass of Throw for the point numbers 4, 5, 6, 8, 9 or 10.

Constructors

PointThrow.__init__(self, d1, d2)
Parameters:
  • d1 – The value of one die
  • d2 – The value of the other die

Creates this throw. The constraint is that d1 + d2 \in \{ 4, 5, 6, 8, 9, 10 \}. If the constraint is not satisfied, simply raise an exception.

This uses the superclass constructor to add appropriate Outcomes for a throw of craps.

Methods

PointThrow.hard(self) → boolean

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.

PointThrow.updateGame(self, game)
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.

Craps Game Design

class CrapsGame

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.

Fields

GrapsGame.point
The current point. This will be replaced by a proper State design pattern.

Constructors

CrapsGame.__init__(self)
Creates this Game. This will be replaced by a constructor that uses Dice and CrapsTable.

Methods

CrapsGame.craps(self)

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)

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.

CrapsGame.eleven(self)

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.

CrapsGame.point(self, point)
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.

Throw.__str__(self) → String
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.

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 the point 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, ElventThrow, PointThrow.
  • Five classes which perform unit tests on the various classes of the Throw class hierarchy.

Table Of Contents

Previous topic

Outcome Class

Next topic

Dice Class

This Page