Started to address comments from the reviewer.

This commit is contained in:
hiker 2018-06-17 23:48:47 +10:00
parent 8cf52b4c7c
commit 48aca2f70f
3 changed files with 80 additions and 58 deletions

View File

@ -79,9 +79,16 @@
For each race mode (race, time-trial, soccer etc) there is one For each race mode (race, time-trial, soccer etc) there is one
weight-list entry (e.g. race-weight-list etc). Each of those lists weight-list entry (e.g. race-weight-list etc). Each of those lists
contains a list (1 or more entries) of weights for a certain number contains a list (1 or more entries) of weights for a certain number
of karts in the race (which is used to reduce the frequency of of karts in the race. This offers two advantages:
'global' items). Each of those weight tagsis stored into a 1) the frequency of global items (like switch) can be reduced for
WeightsData object. higher number of karts (so that game play does not get dominated
by frequent global items)
2) to take into account the balance changes when the number of karts
is different. Typically, the higher the number of karts, the
stronger the difference in "powerup quality" between the first and
the last.
Each of those weight tags is stored into a WeightsData object.
At race time, a new WeightsData object is created from the list for At race time, a new WeightsData object is created from the list for
the current race type depending on number of karts in the race. the current race type depending on number of karts in the race.
If there is a WeightsData object for the same kart number, it is If there is a WeightsData object for the same kart number, it is
@ -111,7 +118,7 @@
corresponds to the weights of getting one specific item, corresponds to the weights of getting one specific item,
the second line (multi) to the weight at which it will yeld the second line (multi) to the weight at which it will yeld
a triple item rather than a single one. The probability to get a triple item rather than a single one. The probability to get
an item is its weight divided by sum of weights of all items an item is its weight divided by the sum of weights of all items
(single AND multi). It is recommended to keep that sum equal (single AND multi). It is recommended to keep that sum equal
to 200 to easily keep track of probabilities. to 200 to easily keep track of probabilities.
@ -126,7 +133,7 @@
there are more karts. --> there are more karts. -->
<race-weight-list> <race-weight-list>
<!-- The entry for '0' karts is special and means 'first kart' --> <!-- The entry for '1' karts is special and means 'first kart' -->
<weights num-karts="1"> <weights num-karts="1">
<!-- bubble cake bowl zipper plunger switch swattr rubber para anvil --> <!-- bubble cake bowl zipper plunger switch swattr rubber para anvil -->
<weight single ="28 0 60 20 45 15 32 0 0 0" <weight single ="28 0 60 20 45 15 32 0 0 0"

View File

@ -220,7 +220,13 @@ void PowerupManager::WeightsData::readData(int num_karts, const XMLNode *node)
l.push_back(n); l.push_back(n);
} }
// Make sure we have the right number of entries // Make sure we have the right number of entries
while(l.size()<2*(int)POWERUP_LAST) l.push_back(0); if (l.size() < 2 * (int)POWERUP_LAST)
{
Log::error("PowerupManager",
"Not enough entries for '%s' in powerup.xml",
node->getName().c_str());
while (l.size() < 2 * (int)POWERUP_LAST) l.push_back(0);
}
if(l.size()>2*(int)POWERUP_LAST) if(l.size()>2*(int)POWERUP_LAST)
{ {
Log::error("PowerupManager", Log::error("PowerupManager",
@ -265,7 +271,7 @@ void PowerupManager::WeightsData::interpolate(WeightsData *prev,
} // WeightsData::interpolate } // WeightsData::interpolate
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** For a given rank in the current race this computed the previous and /** For a given rank in the current race this computes the previous and
* next entry in the weight list, and the weight necessary to interpolate * next entry in the weight list, and the weight necessary to interpolate
* between these two values. If the requested rank should exactly match * between these two values. If the requested rank should exactly match
* one entries, previous and next entry will be identical, and weight set * one entries, previous and next entry will be identical, and weight set
@ -276,9 +282,10 @@ void PowerupManager::WeightsData::interpolate(WeightsData *prev,
* \param next On return contains the index of the closest weight field * \param next On return contains the index of the closest weight field
* bigger than the given rank. * bigger than the given rank.
* \param weight On return contains the weight to use to interpolate between * \param weight On return contains the weight to use to interpolate between
* next and previous. * next and previous. The weight is for 'next', so (1-weight) is the
* weight that needs to be applied to the previous data.
*/ */
int PowerupManager::WeightsData::convertRankToSection(int rank, int *prev, void PowerupManager::WeightsData::convertRankToSection(int rank, int *prev,
int *next, float *weight) int *next, float *weight)
{ {
// If there is only one section (e.g. in soccer mode etc), use it. // If there is only one section (e.g. in soccer mode etc), use it.
@ -287,7 +294,7 @@ int PowerupManager::WeightsData::convertRankToSection(int rank, int *prev,
{ {
*prev = *next = 0; *prev = *next = 0;
*weight = 1.0f; *weight = 1.0f;
return 1; return;
} }
// The last kart always uses the data for the last section // The last kart always uses the data for the last section
@ -295,7 +302,7 @@ int PowerupManager::WeightsData::convertRankToSection(int rank, int *prev,
{ {
*prev = *next = m_weights_for_section.size() - 1; *prev = *next = m_weights_for_section.size() - 1;
*weight = 1.0f; *weight = 1.0f;
return 1; return;
} }
// In FTL mode the first section is for the leader, the // In FTL mode the first section is for the leader, the
@ -304,7 +311,7 @@ int PowerupManager::WeightsData::convertRankToSection(int rank, int *prev,
{ {
*prev = *next = 1; *prev = *next = 1;
*weight = 1.0f; *weight = 1.0f;
return 1; return;
} }
// Now we have a rank that needs to be interpolated between // Now we have a rank that needs to be interpolated between
@ -314,25 +321,33 @@ int PowerupManager::WeightsData::convertRankToSection(int rank, int *prev,
// special since index 2 is for the first non-leader kart): // special since index 2 is for the first non-leader kart):
int first_section_index = race_manager->isFollowMode() ? 2 : 1; int first_section_index = race_manager->isFollowMode() ? 2 : 1;
// Get the lowest rank for which the grouping applies: // If we have five points, the first and last assigned to the first
int first_section_rank = race_manager->isFollowMode() ? 3 : 2; // and last kart, leaving 3 points 'inside' this interval, which define
// 4 'sections'. So the number of sections is number_of_points - 2 + 1.
// If we have three points, we get 4 sections etc. // If the first two points are assigned to rank 1 and 2 in a FTL race
// and the last to the last kart, leaving two inner points defining
// 3 sections, i.e. number_of_points - 3 + 1
// In both cases the number of sections is:
int num_sections = (m_weights_for_section.size() - first_section_index); int num_sections = (m_weights_for_section.size() - first_section_index);
float karts_per_fraction = (m_num_karts - first_section_index) float karts_per_fraction = (m_num_karts - first_section_index)
/ float(num_sections); / float(num_sections);
int count = 0;
while (rank - 1 > (count + 1) * karts_per_fraction) // Now check in which section the current rank is: Test from the first
// section (section 0) and see if the rank is still greater than the
// next section. If not, the current section is the section to which
// this rank belongs. Otherwise increase section and try again:
int section = 0;
while (rank - first_section_index > (section + 1) * karts_per_fraction)
{ {
count++; section++;
} }
*prev = first_section_index + count - 1; *prev = first_section_index + section - 1;
*next = *prev + 1; *next = *prev + 1;
*weight = (rank - first_section_index - count * karts_per_fraction) *weight = (rank - first_section_index - section * karts_per_fraction)
/ karts_per_fraction; / karts_per_fraction;
return 1; return;
} // WeightsData::convertRankToSection } // WeightsData::convertRankToSection
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -101,7 +101,7 @@ private:
void reset(); void reset();
void readData(int num_karts, const XMLNode *node); void readData(int num_karts, const XMLNode *node);
void interpolate(WeightsData *prev, WeightsData *next, int num_karts); void interpolate(WeightsData *prev, WeightsData *next, int num_karts);
int convertRankToSection(int rank, int *prev, int *next, void convertRankToSection(int rank, int *prev, int *next,
float *weight); float *weight);
void precomputeWeights(); void precomputeWeights();
int getRandomItem(int rank, int random_number); int getRandomItem(int rank, int random_number);