Table of Contents
This section starts to address the overall “main program” that pulls the various classes together to create a finished application. Additionally, we'll also address some issues in how Java handles collections of primitive data types like integers.
We can now use our application to generate some more usable results. We can perform a number of simulation runs and evaluate the long-term prospects for the Martingale betting system. We want to know a few things about the game:
How long can we play with a given budget? In other words, how many spins before we've lost our stake.
How much we can realistically hope to win? How large a streak can we hope for? How far ahead can we hope to get before we should quit?
The Simulator will be an active class
with a number of responsibilities
Create the Wheel,
Table and Game
objects.
Simulate a number of sessions (typically 100), saving the maximum stake and length of each session.
For each session: initialize the
Player and Game,
cycle the game a number of times, collect the size of the
Player's stake after each cycle.
Write a final summary of the results.
At this point, we'll need for formalize some definitions, just to be crystal clear on the responisbility allocation.
Simulation Terms
A single cycle of betting and bet resolution. This depends on a single random event: a spin of the wheel or a throw of the dice. Also known as a round of play.
One or more cycles. The session begins with a player having their full stake. A session ends when the play elects to leave or can no longer participate. A player may elect to leave because of elapsed time (typically 250 cycles), or they have won a statistically significant amount. A player can no longer participate when their stake is too small to make the minimum bet for the table.
Some games have intermediate groupings of events between an individual cycles and an entire session. Blackjack has hands, where a number of player decisions and a number of random events contribute to the payoff. Craps has a game, which starts with the dice roll when the point is off, and ends when the point is made or the shooter gets Craps; consequently, any number of individual dice rolls can make up a game. Some bets are placed on the overall game, while others are placed on individual dice rolls.
The sequence of operations for the simulator looks like this.
Procedure 13.1. Controlling the Simulation
Empty List of Maxima. Create an empty maxima list. This is the maximum stake at the end of each session.
Empty List of Durations. Create an empty durations list. This is the duration of each session, measured in the number of cycles of play before the player withdrew or ran out of money.
For All Sessions. For each of 100 sessions:
Empty List of Stake Details. Create an empty list to hold the history of stake values for this session. This is raw data that we will summarize into two metrics for the session: maximum stake and duration. We could also have two simple variables to record the maximum stake and count the number of spins for the duratioon. However, the list allows us to gather other statistics, like maximum win or maximum loss.
While The Player Is Active
One Cycle. Play one cycle of the game. See the definition in Roulette Game Class.
Save Detail. Save the player's current stake in the list of stake values for this session. The alternative is to update the maximum to be the larger of the current stake and the maximum, and increment the duration.
Get Maximum. Get the maximum stake from the list of stake values. Save the maximum stake metric in the maxima list.
Get Duration. Get the length of the list of stake values. Save the duration metric in the durations list.
Statistical Description of Maxima. Compute the average and standard deviation of the values in the maxima list.
Statistical Description of Durations. Compute the average and standard deviation of values in the durations list.
Both this overall Simulator and the
Game collaborate with the
Player. The Simulator's
collaboration, however, initalizes the Player
and then monitor's the changes to the Player's
stake. We have to design two interfaces for this collaboration.
Player Initialization. The Simulator will initialize a
Player for 250 cycles of play, assuming about
one cycle each minute, and about four hours of patience. We will
also initialize the player with a generous budget of the table
limit, 100 betting units. For a $10 table, this is $1,000
bankroll.
Currently, the Player class is designed
to play one session and stop when their duration is reached or their
stake is reduced to zero. We have two alternatives for reinitializing
the Player at the beginning of each
session.
Provide some setters that allow a
client class like this overall simulator control to reset the
stake and roundsToGo values
of a Player.
Provide a Factory that
allows a client class to create new, freshly initialized instances
of Player.
While the first solution is quite simple, there are some
advantages to creating a PlayerFactory. If we
create an Abstract Factory, we have a
single place that creates all Players. Further,
when we add new player subclasses, we introduce these new subclasses
by creating a new subclass of the factory. In this case, however, only
the main program creates instances of Player,
reducing the value of the factory. While design of the factory is a
good exercise, we can scrape by with adding setter methods to the
Player class.
Player Interrogation. The Simulator will interrogate the
Player after each cycle and capture the
current stake. An easy way to manage this detailed data is to create
a List that contains the stake at the
end of each cycle. The length of this list and the maximum value in
this list are the two metrics the Simulator
gathers for each session.
Our list of maxima and durations are created sequentially during
the session and summarized sequentially at the end of the session. A
Java LinkedList will do everything we need. For
a deeper discussion on the alternatives available in the collections
framework, see Java Collections.
Statistical Summary. The Simulator will interrogate the
Player after each cycle and capture the
current stake. We don't want the sequence of stakes for each cycle,
however, we want a summary of all the cycles in the session. We can
save the length of the sequence as well as the maximum of the
sequence to determine these two aggregate performance parameters for
each session. Our objective is to run several session simulations to
get averages and a standard deviations for duration and maximum
stake. This means that the Simulator needs to
retain these statistical samples. We will defer the detailed design
of the statistical processing, and simply keep the duration and
maximum values in Lists for this first round of design.