From 380fd8cab41bce0954bcd38eba5befe7057c8fa2 Mon Sep 17 00:00:00 2001 From: dP Date: Mon, 18 May 2020 16:12:20 +0300 Subject: Fix: Make subsidies scan tiles for town acceptance and production instead of using desync-prone town caches --- src/subsidy.cpp | 28 ++++++++++++++++++---------- src/subsidy_base.h | 1 + 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/subsidy.cpp b/src/subsidy.cpp index e3913a289..25651a91e 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -328,20 +328,27 @@ bool FindSubsidyTownCargoRoute() const Town *src_town = Town::GetRandom(); if (src_town->cache.population < SUBSIDY_CARGO_MIN_POPULATION) return false; - CargoTypes town_cargo_produced = src_town->cargo_produced; + CargoArray town_cargo_produced = GetProductionAroundTiles(src_town->xy, 1, 1, SUBSIDY_TOWN_CARGO_RADIUS); /* Passenger subsidies are not handled here. */ - ClrBit(town_cargo_produced, CT_PASSENGERS); + town_cargo_produced[CT_PASSENGERS] = 0; + + uint8 cargo_count = 0; + for (CargoID i = 0; i < NUM_CARGO; i++) { + if (town_cargo_produced[i] > 0) cargo_count++; + } /* No cargo produced at all? */ - if (town_cargo_produced == 0) return false; + if (cargo_count == 0) return false; /* Choose a random cargo that is produced in the town. */ - uint8 cargo_number = RandomRange(CountBits(town_cargo_produced)); + uint8 cargo_number = RandomRange(cargo_count); CargoID cid; - FOR_EACH_SET_CARGO_ID(cid, town_cargo_produced) { - if (cargo_number == 0) break; - cargo_number--; + for (cid = 0; cid < NUM_CARGO; cid++) { + if (town_cargo_produced[cid] > 0) { + if (cargo_number == 0) break; + cargo_number--; + } } /* Avoid using invalid NewGRF cargoes. */ @@ -416,17 +423,18 @@ bool FindSubsidyIndustryCargoRoute() */ bool FindSubsidyCargoDestination(CargoID cid, SourceType src_type, SourceID src) { - /* Choose a random destination. Only consider towns if they can accept the cargo. */ - SourceType dst_type = (HasBit(_town_cargoes_accepted, cid) && Chance16(1, 2)) ? ST_TOWN : ST_INDUSTRY; + /* Choose a random destination. */ + SourceType dst_type = Chance16(1, 2) ? ST_TOWN : ST_INDUSTRY; SourceID dst; switch (dst_type) { case ST_TOWN: { /* Select a random town. */ const Town *dst_town = Town::GetRandom(); + CargoArray town_cargo_accepted = GetAcceptanceAroundTiles(dst_town->xy, 1, 1, SUBSIDY_TOWN_CARGO_RADIUS); /* Check if the town can accept this cargo. */ - if (!HasBit(dst_town->cargo_accepted_total, cid)) return false; + if (town_cargo_accepted[cid] >= 8) return false; dst = dst_town->index; break; diff --git a/src/subsidy_base.h b/src/subsidy_base.h index ef26f6416..ef9276433 100644 --- a/src/subsidy_base.h +++ b/src/subsidy_base.h @@ -57,5 +57,6 @@ static const uint SUBSIDY_PAX_MIN_POPULATION = 400; ///< Min. population of to static const uint SUBSIDY_CARGO_MIN_POPULATION = 900; ///< Min. population of destination town for cargo route static const uint SUBSIDY_MAX_PCT_TRANSPORTED = 42; ///< Subsidy will be created only for towns/industries with less % transported static const uint SUBSIDY_MAX_DISTANCE = 70; ///< Max. length of subsidised route (DistanceManhattan) +static const uint SUBSIDY_TOWN_CARGO_RADIUS = 6; ///< Extent of a tile area around town center when scanning for town cargo acceptance and production (6 ~= min catchmement + min station / 2) #endif /* SUBSIDY_BASE_H */ -- cgit v1.2.3-54-g00ecf