(svn r21168) -Feature: Use desired industry counts rather than relative probability to decide which industry to build.

This commit is contained in:
alberth 2010-11-13 15:07:34 +00:00
parent 6d73213ab7
commit a9009b2acb
2 changed files with 44 additions and 12 deletions

View File

@ -146,6 +146,7 @@ void ReleaseDisastersTargetingIndustry(IndustryID);
/** Data for managing the number of industries of a single industry type. */
struct IndustryTypeBuildData {
uint32 probability; ///< Relative probability of building this industry.
uint16 target_count; ///< Desired number of industries of this type.
void GetIndustryTypeData(IndustryType it);
};
@ -156,6 +157,7 @@ struct IndustryTypeBuildData {
struct IndustryBuildData {
IndustryTypeBuildData builddata[NUM_INDUSTRYTYPES]; ///< Industry build data for every industry type.
void SetupTargetCount();
void TryBuildNewIndustry();
};

View File

@ -2055,26 +2055,56 @@ void IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
this->probability = GetIndustryGamePlayProbability(it);
}
/** Decide how many industries of each type are needed. */
void IndustryBuildData::SetupTargetCount()
{
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
this->builddata[it].GetIndustryTypeData(it);
}
uint total_amount = GetNumberOfIndustries(); // Desired number of industries.
uint32 total_prob = 0; // Sum of probabilities.
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
this->builddata[it].target_count = 0;
total_prob += this->builddata[it].probability;
}
/* Assign number of industries that should be aimed for, by using the probability as a weight. */
while (total_amount > 0) {
uint32 r = RandomRange(total_prob);
IndustryType it = 0;
while (r >= this->builddata[it].probability) {
r -= this->builddata[it].probability;
it++;
assert(it < NUM_INDUSTRYTYPES);
}
assert(this->builddata[it].probability > 0);
this->builddata[it].target_count++;
total_amount--;
}
}
/**
* Try to create a random industry, during gameplay
*/
void IndustryBuildData::TryBuildNewIndustry()
{
/* Generate a list of all possible industries that can be built. */
for (IndustryType j = 0; j < NUM_INDUSTRYTYPES; j++) {
this->builddata[j].GetIndustryTypeData(j);
}
this->SetupTargetCount();
int missing = 0; // Number of industries that need to be build.
uint count = 0; // Number of industry types eligible for build.
uint32 total_prob = 0; // Sum of probabilities.
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
uint32 chance = this->builddata[it].probability;
if (chance > 0) {
total_prob += chance;
int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
missing += difference;
if (difference > 0) {
total_prob += difference;
count++;
}
}
if (missing <= 0 || total_prob == 0) count = 0; // Skip creation of an industry.
if (count >= 1) {
/* Pick a weighted random industry to build.
* For the case that count == 1, there is no need to draw a random number. */
@ -2083,13 +2113,13 @@ void IndustryBuildData::TryBuildNewIndustry()
uint32 r = 0; // Initialized to silence the compiler.
if (count > 1) r = RandomRange(total_prob);
for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
uint32 chance = this->builddata[it].probability;
if (chance == 0) continue;
int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
if (difference <= 0) continue; // Too many of this kind.
if (count == 1) break;
if (r < chance) break;
r -= chance;
if (r < (uint)difference) break;
r -= difference;
}
assert(it < NUM_INDUSTRYTYPES);
assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
/* Try to create the industry. */
const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);