Game Development Reference
In-Depth Information
// 6..8 = 3
if ( index <= 8 ) return GUESS_22;
// 9..38 = 30
if ( index <= 38 ) return GUESS_RANDOM;
// 39..100 = 62
return GUESS_SEMI;
}
As we can see above, we had to change all three
if
statements, increasing the
test number by one in each case. It is easy to see that this is
not
a very flexible way
of laying out code. Trust me: As I was fine-tuning this example in the last chapter,
I changed those numbers a few times… it's not fun. (The process was made even
more annoying by the fact that I had to change my comments as well.)
There are a few considerations over and above the time consumption argu-
ment. First, it is ridiculously prone to errors. For example, if we forget to change
one of those numbers, we are going to skew the probability of
two
occurrences
rather than just the one that we are changing. Second, the difficulty in keeping
track of our problems increases with the number of possibilities. The above exam-
ple had only four selections (which gives us three
if
statements. If we have
dozens… or even
scores
of possible actions, managing the bucket edges efficiently
gets prohibitive quickly.
Perhaps the most problematic issue in constructing the probabilities in this
manner is the fact that it is hard-coded, however. We have no way of changing the
edges during run time. This goes beyond the ability to have data-driven code such
as probabilities based on a difficulty setting that a designer sets beforehand. We
have no way of efficiently changing these values
on the fly.
We will address the myr-
iad uses for this later on in the topic.
The solution to this is to store the edge values in a data structure. For example,
we will create a
struct
named
sGUESSER_BUCKET
in our project that represents
a bucket. Each bucket represents one type of guesser. The components of
sGUESSER_BUCKET
are simple: a width, an edge (both of type
USHORT
), and a
GUESS_TYPE
.
typedef enum {
GUESS_33,
GUESS_22,