This simulation is still under development. There are a few missing pieces, and may be some small inconsitancies between documentation and actual code.
If you are still working on an assignment like this, you should not delve into my code, and I'd prefer that you only glance at the documentation for all but the simulation classes.
The files in this subsite illustrate the design and implementation of a few simple game simulations that are fairly closely related. The initial motivation for this system was the design of a simple simulator for Racquetball. The simplest simulator simply reads in the probability of each player winning when that player serves, and simulates a game. A more advanced simulator uses three values to simulate the game. Two simulators for ping pong (similar setting, different rules) are also included.
In attempting to develop these simulation, I have attempted to segment each core piece of functionality into a separate class. I've also subclassed where appropriate to permit better or different simulations.
Various design decisions led to the following classes. In this document, their purpose is summarized. More information can be found in the documentation for the individual classes.
Score
,
which keeps track of the score and service
in a two player game.
ScoreBoard
,
which keeps track of not only score and
service, but also the rules of the game. The ScoreBoard
can report when a game is over or when a shutout occurs.
The ScoreBoard also alternates service when appropriate.
Player
Keeps track of basic information on players. Also used
to determine the winner of a volley (a player is told to
serve, and returns a boolean that indicates whether or not
the server won the volley).
Game
Ties together the ScoreBoard
and the
two Player
s and runs a game.
RecordTable
Records the scores for each game, and presents summary
statistics.
+--------------+ +---------+ | ScoreBoard | <---> | Score | +--------------+ +---------+ ^ | | +-----------+ v +> | PlayerA | <--+ +--------+ / +-----------+ | | Game | <--+ | +--------+ \ +-----------+ | ^ +> | PlayerB | <--+ | +-----------+ | v +-------+ +-------------+ | Sim | <----> | RecordTable | +-------+ +-------------+
Sim
) is the heart of the simulation.
It
There are a number of simulations (all of which fit under the Sim in the diagram). Here is basic information about their purpose. You can determine calling strategy by looking at their documentation.
RBsim1
Simulates one game of racquetball
when all we
know is each player's likelihood of winning a volley when (s)he
serves.
RBsim2
Simulates racquetball when we
know three things about each player: likelihood serves are in,
likelihood serve returns are in, and likelihood that other shots are in.
RBstats1
Computes statistics over some
number of games.
PPsim1
Simulates ping pong when all we
know is each player's likelihood of winning a volley when (s)he
serves.
PPsim2
Simulates ping pong when we
know three things about each player: likelihood serves are in,
likelihood serve returns are in, and likelihood that other shots are in.
For each new simulation, I generally
I was able to provide the alternative simulation (with three
values, rather than one) by subclassing the Player
class. The choice to have the game tell players to serve and
ask them what happened meant that I did not have to change the
Game
class at all. However, I will admit that my
current simulation is somewhat inefficient, since the computation
of the winner of a volley is done with a series of function calls.
My greatest hurdle in building this extension was ensuring that the overridden methods in the subclass were, in fact, called instead of those in the superclass.
My original design accomodated the change in rules by encapsulating
them in a generic ScoreBoard
superclass that I had
already had to subclass for the rules to racquetball. The
PingPongSB
subclass was slightly more complicated to
design, because (1) I needed to add another field to keep track
of how many consecutive serves each player had made, so that I could
switch service after every five serves; and (2) an earlier assumption
that "the last server is the winner" no longer held.
Most modifications were reasonably quick. Compound modifications that
could draw upon earlier work were astoundingly quick. For example, I
was able to create PPsim2
in less than five minutes, since
it required only five small modifications from RBsim2
and no
new classes (the simulation extensions were done as part of the development
of RBsim2
, the rules extensions as part of PPsim1
).
For both debugging and to keep it interested, I included an option for
players and games to report on what was happening as it happened. The
various play()
and serve()
routines take
an optional boolean parameter that, when true, asks them to be verbose
about what is happening. There are certainly other output-based debugging
strategies, but this seemed to give a good balance of simplicity and
usefulness. It is, however, somewhat computationally expensive, as it
adds a number of tests on the value of that variable.
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
Source text written by Samuel A. Rebelsky.
Source text last modified Fri Sep 12 11:20:18 1997.
This page generated on Fri Sep 12 11:23:26 1997 by SamR's Site Suite.
Contact our webmaster at rebelsky@math.grin.edu