//
// CalculateFrequencies1.cpp
//
#include
#include
#include "Constants.h"
#include "CalculateFrequencies.h"
using namespace std;
namespace
{
const bool DEBUGGING_ROLL_1 = false;
}
//
// Helper Function: calculateFrequencies10
//
// This function is used to pseudo-recursively find all the
// roll combinations. At each level, it calls the next-level
// function once for each possible roll. If a value imust be
// rerolled because of a fighter, the next-level function is
// called for each valid roll (i.e. a roll that is not
// rerolled). The rerolled calls are made with the specified
// weight distributed equally amoung the valid rolls.
//
// The function for the final die roll calls the
// addFrequencies1 function. All functions for non-final die
// rolls call the function for the next die. As the
// calculateFrequencies10 function is for when only one die
// is rolled, the first pseudo-recursive level calls
// addFrequencies1.
//
// The following functions are adapted variants of this one:
// -> in CalculateFrequencies2.cpp
// -> calculateFrequencies20
// -> calculateFrequencies21
// -> in CalculateFrequencies3.cpp
// -> calculateFrequencies30
// -> calculateFrequencies31
// -> calculateFrequencies32
//
// The variant functions have approximately the same logic, but
// use 2D and 3D arrays. They also call the appropriate
// addFrequencies? function for the number of dimensions.
// The first digit in the name indicates how many dice will
// be rolled. This is also the number of dimensions in the
// frequency arry. The second digit indicates how many dice
// have already been rolled. This is also the number of
// pseudo-recursive levels deep we currently are.
//
// A bit of work could probably turn these into real recursion.
// This would be cleaner and probably slower. Combining the
// versions for different-dimensioned arrays would be very
// difficult. They would all have to be converted to 1D
// arrays with unpacking information associated with them.
// It would also make the code much harder to read.
//
// Purpose: As explained above.
// Parameter(s):
// <1> a_frequencies: The array to fill with the roll
// frequencies
// <2> a_dimensions: The array containing the number of
// sides on each die to be rolled
// <3> a_small_dimensions: The array containing the number
// of die sides that are legal with
// a fighter
// <4> fighters_remaining: The number of unused fighters
// <5> bomber_count: The number of support bombers
// <6> weight: The value to increase the frequency table by
// Precondition(s):
// <1> a_frequencies != NULL
// <1> aa_frequencies != NULL
// <1> aaa_frequencies != NULL
// <2> a_dimensions != NULL
// <3> a_small_dimensions != NULL
// <4> weight >= 1
// Returns: N/A
// Side Effect: The appropriate values in the frequency table
// are increased by the appropriate amounts.
//
void calculateFrequencies10 (unsigned int a_frequencies[POSSIBLE_VALUE_COUNT],
const unsigned int a_dimensions[1],
const unsigned int a_small_dimensions[1],
unsigned int fighters_remaining,
unsigned int bomber_count,
unsigned int weight);
//
// addFrequencies1
//
// Purpose: To increase the frequency in the specified
// frequency table for the specified roll. The
// frequency is increased by the specified weight.
// The number of bombers is taken into account.
// Parameter(s):
// <1> a_frequencies: The table of frequencies to update
// <2> bomber_count: The number of support bombers
// available to increase rolls
// <3> roll1: The value rolled
// <4> weight: The amount to increase the frequency by
// Preciondition(s):
// <1> a_frequencies != NULL
// <2> weight >= 1
// Returns: N/A
// Side Effect: The element of a_frequencies indicated by roll1
// and bomber_count is increased by weight.
//
void addFrequencies1 (unsigned int a_frequencies[POSSIBLE_VALUE_COUNT],
unsigned int bomber_count,
unsigned int roll1,
unsigned int weight);
//
// Forms of this function adapted to use 2D and 3D frequency
// arrays appear in CalculateFrequencies1.cpp and
// CalculateFrequencies1.cpp.
//
void calculateFrequencies1 (unsigned int a_frequencies[POSSIBLE_VALUE_COUNT],
unsigned int a_value_count[1],
unsigned int fighter_count,
unsigned int bomber_count,
unsigned int capital_count)
{
assert(a_frequencies != NULL);
assert(a_value_count != NULL);
unsigned int weight_base = 1;
unsigned int a_dimensions[1];
unsigned int a_small_dimensions[1];
//
// Calculate the sides for the dice we roll.
// -> These will determine the size of the array we
// store our results in
// -> The actually is full-size every time, but we
// only use part of it
//
// We also calculate the original weight for the values
// we add. We need it to be large enough that we can
// divide it up if there are fighters to make us
// reroll dice.
//
a_dimensions[0] = (capital_count > 0) ? SIDES_CAPTIAL : SIDES_BASIC;
assert(a_dimensions[0] >= FIGHTER_MAX_EXCLUDED);
a_small_dimensions[0] = a_dimensions[0] - FIGHTER_MAX_EXCLUDED;
assert(a_dimensions[0] > 1);
assert(a_small_dimensions[0] > 1);
weight_base *= a_small_dimensions[0];
// zero the frequency array
for(unsigned int x = 0; x < POSSIBLE_VALUE_COUNT; x++)
a_frequencies[x] = 0;
//
// Go through every possible roll and increment the
// correct array element. This is handled
// pseudo-recursively using the appropriate
// calculateFrequencies?? functions.
//
assert(weight_base >= 1);
calculateFrequencies10(a_frequencies,
a_dimensions,
a_small_dimensions,
fighter_count,
bomber_count,
weight_base);
// calculate the size of the results array
a_value_count[0] = a_dimensions[0];
if(bomber_count > 0)
a_value_count[0] += BOMBER_INCREASE;
}
void calculateFrequencies10 (unsigned int a_frequencies[POSSIBLE_VALUE_COUNT],
const unsigned int a_dimensions[1],
const unsigned int a_small_dimensions[1],
unsigned int fighters_remaining,
unsigned int bomber_count,
unsigned int weight)
{
assert(a_frequencies != NULL);
assert(a_dimensions != NULL);
assert(a_small_dimensions != NULL);
assert(weight >= 1);
for(unsigned int x = 0; x < a_dimensions[0]; x++)
{
if(DEBUGGING_ROLL_1)
cout << "x = " << x << endl;
// if we used a fighter, reroll
if(fighters_remaining > 0 && x < FIGHTER_MAX_EXCLUDED)
{
assert(weight / a_small_dimensions[0] >= 1);
assert(weight % a_small_dimensions[0] == 0);
unsigned int new_weight = weight / a_small_dimensions[0];
for(unsigned int x2 = 0; x2 < a_small_dimensions[0]; x2++)
{
if(DEBUGGING_ROLL_1)
cout << " x2 = " << x2 << " ==> " << (x2 + FIGHTER_MAX_EXCLUDED) << endl;
addFrequencies1(a_frequencies, bomber_count, x2 + FIGHTER_MAX_EXCLUDED, new_weight);
}
}
else
addFrequencies1(a_frequencies, bomber_count, x, weight);
}
}
void addFrequencies1 (unsigned int a_frequencies[POSSIBLE_VALUE_COUNT],
unsigned int bomber_count,
unsigned int roll1,
unsigned int weight)
{
assert(a_frequencies != NULL);
assert(weight >= 1);
unsigned int a_sorted[1];
a_sorted[0] = roll1;
if(bomber_count >= 1)
a_sorted[0] += BOMBER_INCREASE;
assert(a_sorted[0] < POSSIBLE_VALUE_COUNT);
a_frequencies[a_sorted[0]] += weight;
}