(svn r17128) -Codechange: make code used for generating new subsidies nicer

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
smatz 15 years ago
parent e2c404958d
commit e6bc51ab06

@ -150,44 +150,58 @@ void DeleteSubsidyWith(SourceType type, SourceID index)
}
}
struct FoundRoute {
uint distance;
CargoID cargo;
void *from;
void *to;
};
static bool CheckSubsidyDuplicate(CargoID cargo, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
{
const Subsidy *s;
FOR_ALL_SUBSIDIES(s) {
if (s->cargo_type == cargo &&
s->src_type == src_type && s->src == src &&
s->dst_type == dst_type && s->dst == dst) {
return true;
}
}
return false;
}
static void FindSubsidyPassengerRoute(FoundRoute *fr)
static Subsidy *FindSubsidyPassengerRoute()
{
Town *from, *to;
assert(Subsidy::CanAllocateItem());
fr->distance = UINT_MAX;
const Town *src = Town::GetRandom();
if (src->population < SUBSIDY_PAX_MIN_POPULATION ||
src->pct_pass_transported > SUBSIDY_MAX_PCT_TRANSPORTED) {
return NULL;
}
fr->from = from = Town::GetRandom();
if (from == NULL || from->population < SUBSIDY_PAX_MIN_POPULATION ||
from->pct_pass_transported > SUBSIDY_MAX_PCT_TRANSPORTED) {
return;
const Town *dst = Town::GetRandom();
if (dst->population < SUBSIDY_PAX_MIN_POPULATION || src == dst) {
return NULL;
}
fr->to = to = Town::GetRandom();
if (from == to || to == NULL || to->population < SUBSIDY_PAX_MIN_POPULATION) return;
if (DistanceManhattan(src->xy, src->xy) > SUBSIDY_MAX_DISTANCE) return NULL;
if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return NULL;
Subsidy *s = new Subsidy();
s->cargo_type = CT_PASSENGERS;
s->src_type = s->dst_type = ST_TOWN;
s->src = src->index;
s->dst = dst->index;
fr->distance = DistanceManhattan(from->xy, to->xy);
return s;
}
static void FindSubsidyCargoRoute(FoundRoute *fr)
static Subsidy *FindSubsidyCargoRoute()
{
Industry *i;
int trans, total;
CargoID cargo;
assert(Subsidy::CanAllocateItem());
fr->distance = UINT_MAX;
const Industry *i = Industry::GetRandom();
if (i == NULL) return NULL;
fr->from = i = Industry::GetRandom();
if (i == NULL) return;
CargoID cargo;
int trans, total;
/* Randomize cargo type */
if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) {
if (i->produced_cargo[1] != CT_INVALID && HasBit(Random(), 0)) {
cargo = i->produced_cargo[1];
trans = i->last_month_pct_transported[1];
total = i->last_month_production[1];
@ -198,54 +212,56 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
}
/* Quit if no production in this industry
* or if the cargo type is passengers
* or if the pct transported is already large enough */
if (total == 0 || trans > SUBSIDY_MAX_PCT_TRANSPORTED || cargo == CT_INVALID) return;
if (total == 0 || trans > SUBSIDY_MAX_PCT_TRANSPORTED || cargo == CT_INVALID) return NULL;
/* Don't allow passengers subsidies from industry */
const CargoSpec *cs = CargoSpec::Get(cargo);
if (cs->town_effect == TE_PASSENGERS) return;
if (cs->town_effect == TE_PASSENGERS) return NULL;
fr->cargo = cargo;
SourceType dst_type;
SourceID dst;
if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
/* The destination is a town */
Town *t = Town::GetRandom();
dst_type = ST_TOWN;
const Town *t = Town::GetRandom();
/* Only want big towns */
if (t == NULL || t->population < SUBSIDY_CARGO_MIN_POPULATION) return;
if (t->population < SUBSIDY_CARGO_MIN_POPULATION) return NULL;
if (DistanceManhattan(i->xy, t->xy) > SUBSIDY_MAX_DISTANCE) return NULL;
fr->distance = DistanceManhattan(i->xy, t->xy);
fr->to = t;
dst = t->index;
} else {
/* The destination is an industry */
Industry *i2 = Industry::GetRandom();
dst_type = ST_INDUSTRY;
const Industry *i2 = Industry::GetRandom();
/* The industry must accept the cargo */
if (i2 == NULL || i == i2 ||
(cargo != i2->accepts_cargo[0] &&
cargo != i2->accepts_cargo[1] &&
cargo != i2->accepts_cargo[2])) {
return;
cargo != i2->accepts_cargo[1] &&
cargo != i2->accepts_cargo[2])) {
return NULL;
}
fr->distance = DistanceManhattan(i->xy, i2->xy);
fr->to = i2;
}
}
static bool CheckSubsidyDuplicate(Subsidy *s)
{
const Subsidy *ss;
FOR_ALL_SUBSIDIES(ss) {
if (s != ss && ss->cargo_type == s->cargo_type &&
ss->src_type == s->src_type && ss->src == s->src &&
ss->dst_type == s->dst_type && ss->dst == s->dst) {
delete s;
return true;
}
if (DistanceManhattan(i->xy, i2->xy) > SUBSIDY_MAX_DISTANCE) return NULL;
dst = i2->index;
}
return false;
}
if (CheckSubsidyDuplicate(cargo, ST_INDUSTRY, i->index, dst_type, dst)) return NULL;
Subsidy *s = new Subsidy();
s->cargo_type = cargo;
s->src_type = ST_INDUSTRY;
s->src = i->index;
s->dst_type = dst_type;
s->dst = dst;
return s;
}
void SubsidyMonthlyLoop()
{
@ -276,44 +292,18 @@ void SubsidyMonthlyLoop()
if (Subsidy::CanAllocateItem() && Chance16(1, 4)) {
uint n = 1000;
do {
FoundRoute fr;
FindSubsidyPassengerRoute(&fr);
if (fr.distance <= SUBSIDY_MAX_DISTANCE) {
s = new Subsidy();
s->cargo_type = CT_PASSENGERS;
s->src_type = s->dst_type = ST_TOWN;
s->src = ((Town *)fr.from)->index;
s->dst = ((Town *)fr.to)->index;
goto add_subsidy;
}
FindSubsidyCargoRoute(&fr);
if (fr.distance <= SUBSIDY_MAX_DISTANCE) {
s = new Subsidy();
s->cargo_type = fr.cargo;
s->src_type = ST_INDUSTRY;
s->src = ((Industry *)fr.from)->index;
{
const CargoSpec *cs = CargoSpec::Get(fr.cargo);
if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
s->dst_type = ST_TOWN;
s->dst = ((Town *)fr.to)->index;
} else {
s->dst_type = ST_INDUSTRY;
s->dst = ((Industry *)fr.to)->index;
}
}
add_subsidy:
if (!CheckSubsidyDuplicate(s)) {
s->remaining = SUBSIDY_OFFER_MONTHS;
s->awarded = INVALID_COMPANY;
Pair reftype = SetupSubsidyDecodeParam(s, 0);
AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC);
SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST);
AI::BroadcastNewEvent(new AIEventSubsidyOffer(s->index));
modified = true;
break;
}
Subsidy *s = FindSubsidyPassengerRoute();
if (s == NULL) s = FindSubsidyCargoRoute();
if (s != NULL) {
s->remaining = SUBSIDY_OFFER_MONTHS;
s->awarded = INVALID_COMPANY;
Pair reftype = SetupSubsidyDecodeParam(s, 0);
AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC);
SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST);
AI::BroadcastNewEvent(new AIEventSubsidyOffer(s->index));
modified = true;
break;
}
} while (n--);
}

Loading…
Cancel
Save