From 19e4895ffdc4746faeeafc8887d66f56cbfb4e5b Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 19 Feb 2024 03:49:35 +0000 Subject: [PATCH] Add cargo mask of town production cargoes Use for all non-GUI cases (where display sort order is not required) --- src/cargotype.cpp | 3 +++ src/cargotype.h | 3 +++ src/subsidy.cpp | 17 +++++++++++++---- src/town_cmd.cpp | 27 ++++++++++++++------------- src/town_gui.cpp | 2 +- src/zoning_cmd.cpp | 6 ++---- 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/cargotype.cpp b/src/cargotype.cpp index 8160196b4c..0a07138e7d 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -25,6 +25,7 @@ CargoSpec CargoSpec::array[NUM_CARGO]; std::array, NUM_TPE> CargoSpec::town_production_cargoes{}; +std::array CargoSpec::town_production_cargo_mask{}; /** * Bitmask of cargo types available. This includes phony cargoes like regearing cargoes. @@ -216,6 +217,7 @@ static bool CargoSpecClassSorter(const CargoSpec * const &a, const CargoSpec * c void InitializeSortedCargoSpecs() { for (auto &tpc : CargoSpec::town_production_cargoes) tpc.clear(); + for (auto &tpc : CargoSpec::town_production_cargo_mask) tpc = 0; _sorted_cargo_specs.clear(); /* Add each cargo spec to the list, and determine the largest cargo icon size. */ for (const CargoSpec *cargo : CargoSpec::Iterate()) { @@ -236,6 +238,7 @@ void InitializeSortedCargoSpecs() for (const auto &cargo : _sorted_cargo_specs) { assert(cargo->town_production_effect != INVALID_TPE); CargoSpec::town_production_cargoes[cargo->town_production_effect].push_back(cargo); + SetBit(CargoSpec::town_production_cargo_mask[cargo->town_production_effect], cargo->Index()); if (cargo->classes & CC_SPECIAL) break; nb_standard_cargo++; SetBit(_standard_cargo_mask, cargo->Index()); diff --git a/src/cargotype.h b/src/cargotype.h index 7381c16e25..c5f7bce8b0 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -199,6 +199,9 @@ struct CargoSpec { /** List of cargo specs for each Town Product Effect. */ static std::array, NUM_TPE> town_production_cargoes; + /** Mask of cargo IDs for each Town Product Effect. */ + static std::array town_production_cargo_mask; + private: static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs diff --git a/src/subsidy.cpp b/src/subsidy.cpp index fd3c37ae93..89d6e77e94 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -293,9 +293,18 @@ bool FindSubsidyPassengerRoute() { if (!Subsidy::CanAllocateItem()) return false; + if (CargoSpec::town_production_cargo_mask[TPE_PASSENGERS] == 0) return false; + /* Pick a random TPE_PASSENGER type */ - uint32_t r = RandomRange(static_cast(CargoSpec::town_production_cargoes[TPE_PASSENGERS].size())); - CargoID cid = CargoSpec::town_production_cargoes[TPE_PASSENGERS][r]->Index(); + uint32_t r = RandomRange(CountBits(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS])); + CargoID cid{}; + for (CargoID cargo_id : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS])) { + if (r == 0) { + cid = cargo_id; + break; + } + r--; + } const Town *src = Town::GetRandom(); if (src->cache.population < SUBSIDY_PAX_MIN_POPULATION || @@ -343,8 +352,8 @@ bool FindSubsidyTownCargoRoute() } /* Passenger subsidies are not handled here. */ - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) { - town_cargo_produced[cs->Index()] = 0; + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS])) { + town_cargo_produced[cid] = 0; } uint8_t cargo_count = town_cargo_produced.GetCount(); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 8c01f4d0ee..52c41367dd 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -688,7 +688,8 @@ static void TownGenerateCargo(Town *t, CargoID ct, uint amount, StationFinder &s */ static void TownGenerateCargoOriginal(Town *t, TownProductionEffect tpe, uint8_t rate, StationFinder &stations) { - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[tpe])) { + const CargoSpec *cs = CargoSpec::Get(cid); uint32_t r = Random(); if (GB(r, 0, 8) < rate) { CargoID cid = cs->Index(); @@ -708,8 +709,8 @@ static void TownGenerateCargoOriginal(Town *t, TownProductionEffect tpe, uint8_t */ static void TownGenerateCargoBinominal(Town *t, TownProductionEffect tpe, uint8_t rate, StationFinder &stations) { - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { - CargoID cid = cs->Index(); + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[tpe])) { + const CargoSpec *cs = CargoSpec::Get(cid); uint32_t r = Random(); /* Make a bitmask with up to 32 bits set, one for each potential pax. */ @@ -891,13 +892,13 @@ void AddProducedHouseCargo(HouseID house_id, TileIndex tile, CargoArray &produce } } else { if (hs->population > 0) { - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) { - produced[cs->Index()]++; + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS])) { + produced[cid]++; } } if (hs->mail_generation > 0) { - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) { - produced[cs->Index()]++; + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_MAIL])) { + produced[cid]++; } } } @@ -2184,11 +2185,11 @@ void UpdateTownRadii() void UpdateTownMaxPass(Town *t) { - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) { - t->supplied[cs->Index()].old_max = _town_cargo_scaler.Scale(t->cache.population >> 3); + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS])) { + t->supplied[cid].old_max = _town_cargo_scaler.Scale(t->cache.population >> 3); } - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) { - t->supplied[cs->Index()].old_max = _town_cargo_scaler.Scale(t->cache.population >> 4); + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_MAIL])) { + t->supplied[cid].old_max = _town_cargo_scaler.Scale(t->cache.population >> 4); } } @@ -4180,8 +4181,8 @@ static uint GetNormalGrowthRate(Town *t) for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) { uint32_t old_max = 0; uint32_t old_act = 0; - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { - const TransportedCargoStat &stat = t->supplied[cs->Index()]; + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[tpe])) { + const TransportedCargoStat &stat = t->supplied[cid]; old_max += stat.old_max; old_act += stat.old_act; } diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 164f13e526..d97b23ee9e 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -725,7 +725,7 @@ public: */ uint GetDesiredInfoHeight(int width) const { - uint aimed_height = static_cast(1 + CargoSpec::town_production_cargoes[TPE_PASSENGERS].size() + CargoSpec::town_production_cargoes[TPE_MAIL].size()) * GetCharacterHeight(FS_NORMAL); + uint aimed_height = static_cast(1 + CountBits(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS] | CargoSpec::town_production_cargo_mask[TPE_MAIL])) * GetCharacterHeight(FS_NORMAL); bool first = true; for (int i = TAE_BEGIN; i < TAE_END; i++) { diff --git a/src/zoning_cmd.cpp b/src/zoning_cmd.cpp index c2f3d6f6bc..4ce2aae7b0 100644 --- a/src/zoning_cmd.cpp +++ b/src/zoning_cmd.cpp @@ -194,10 +194,8 @@ SpriteID TileZoneCheckUnservedBuildingsEvaluation(TileIndex tile, Owner owner) } auto has_town_cargo = [&](const CargoArray &dat) { - for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) { - for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { - if (dat[cs->Index()] > 0) return true; - } + for (CargoID cid : SetCargoBitIterator(CargoSpec::town_production_cargo_mask[TPE_PASSENGERS] | CargoSpec::town_production_cargo_mask[TPE_MAIL])) { + if (dat[cid] > 0) return true; } return false; };