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

pull/155/head
alberth 14 years ago
parent 6d73213ab7
commit a9009b2acb

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

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

Loading…
Cancel
Save