From 8930337aaec29771b991f2f89f7b7279466278a8 Mon Sep 17 00:00:00 2001 From: frosch Date: Mon, 4 Jul 2011 20:37:20 +0000 Subject: [PATCH] (svn r22635) -Fix: Correctly reseed random bits of industries and industry tiles. --- src/newgrf_engine.cpp | 5 ++-- src/newgrf_house.cpp | 5 ++-- src/newgrf_industrytiles.cpp | 48 ++++++++++++++++++++++++++++++++---- src/newgrf_spritegroup.cpp | 2 +- src/newgrf_spritegroup.h | 31 +++++++++++++++++------ 5 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 0491ec7622..f2f28883a1 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -1070,8 +1070,9 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando if (group == NULL) return; new_random_bits = Random(); - v->random_bits &= ~object.reseed; - v->random_bits |= (first ? new_random_bits : base_random_bits) & object.reseed; + uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding + v->random_bits &= ~reseed; + v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed; switch (trigger) { case VEHICLE_TRIGGER_NEW_CARGO: diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index f6e1d3790f..04a0d8617c 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -606,8 +606,9 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando byte new_random_bits = Random(); byte random_bits = GetHouseRandomBits(tile); - random_bits &= ~object.reseed; - random_bits |= (first ? new_random_bits : base_random) & object.reseed; + uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding + random_bits &= ~reseed; + random_bits |= (first ? new_random_bits : base_random) & reseed; SetHouseRandomBits(tile, random_bits); switch (trigger) { diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 74a48cd3b3..1191f3162d 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -369,7 +369,14 @@ bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigge return ret; } -static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, Industry *ind) +/** + * Trigger random triggers for an industry tile and reseed its random bits. + * @param tile Industry tile to trigger. + * @param trigger Trigger to trigger. + * @param ind Industry of the tile. + * @param [in,out] reseed_industry Collects bits to reseed for the industry. + */ +static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, Industry *ind, uint32 &reseed_industry) { ResolverObject object; @@ -390,24 +397,55 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I byte new_random_bits = Random(); byte random_bits = GetIndustryRandomBits(tile); - random_bits &= ~object.reseed; - random_bits |= new_random_bits & object.reseed; + random_bits &= ~object.reseed[VSG_SCOPE_SELF]; + random_bits |= new_random_bits & object.reseed[VSG_SCOPE_SELF]; SetIndustryRandomBits(tile, random_bits); MarkTileDirtyByTile(tile); + + reseed_industry |= object.reseed[VSG_SCOPE_PARENT]; } +/** + * Reseeds the random bits of an industry. + * @param ind Industry. + * @param reseed Bits to reseed. + */ +static void DoReseedIndustry(Industry *ind, uint32 reseed) +{ + if (reseed == 0 || ind == NULL) return; + + uint16 random_bits = Random(); + ind->random &= reseed; + ind->random |= random_bits & reseed; +} + +/** + * Trigger a random trigger for a single industry tile. + * @param tile Industry tile to trigger. + * @param trigger Trigger to trigger. + */ void TriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger) { - DoTriggerIndustryTile(tile, trigger, Industry::GetByTile(tile)); + uint32 reseed_industry = 0; + Industry *ind = Industry::GetByTile(tile); + DoTriggerIndustryTile(tile, trigger, ind, reseed_industry); + DoReseedIndustry(ind, reseed_industry); } +/** + * Trigger a random trigger for all industry tiles. + * @param ind Industry to trigger. + * @param trigger Trigger to trigger. + */ void TriggerIndustry(Industry *ind, IndustryTileTrigger trigger) { + uint32 reseed_industry = 0; TILE_AREA_LOOP(tile, ind->location) { if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) { - DoTriggerIndustryTile(tile, trigger, ind); + DoTriggerIndustryTile(tile, trigger, ind, reseed_industry); } } + DoReseedIndustry(ind, reseed_industry); } /** diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index a327a3be13..387366352c 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -207,7 +207,7 @@ const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject *object) const if (res) { waiting_triggers &= ~match; - object->reseed |= (this->num_groups - 1) << this->lowest_randbit; + object->reseed[this->var_scope] |= (this->num_groups - 1) << this->lowest_randbit; } else { waiting_triggers |= object->trigger; } diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index bf72e96cec..d18ad643fa 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -122,12 +122,15 @@ protected: /* Shared by deterministic and random groups. */ enum VarSpriteGroupScope { - VSG_SCOPE_SELF, - /* Engine of consists for vehicles, city for stations. */ - VSG_SCOPE_PARENT, - /* Any vehicle in the consist (vehicles only) */ - VSG_SCOPE_RELATIVE, + VSG_BEGIN, + + VSG_SCOPE_SELF = VSG_BEGIN, ///< Resolved object itself + VSG_SCOPE_PARENT, ///< Related object of the resolved one + VSG_SCOPE_RELATIVE, ///< Relative position (vehicles only) + + VSG_END }; +DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope) enum DeterministicSpriteGroupSize { DSG_SIZE_BYTE, @@ -309,7 +312,7 @@ struct ResolverObject { byte trigger; uint32 last_value; ///< Result of most recent DeterministicSpriteGroup (including procedure calls) - uint32 reseed; ///< Collects bits to rerandomise while triggering triggers. + uint32 reseed[VSG_END]; ///< Collects bits to rerandomise while triggering triggers. VarSpriteGroupScope scope; ///< Scope of currently resolved DeterministicSpriteGroup resp. RandomizedSpriteGroup byte count; ///< Additional scope for RandomizedSpriteGroup @@ -382,6 +385,20 @@ struct ResolverObject { const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const RealSpriteGroup*); void (*StorePSA)(struct ResolverObject*, uint, int32); + /** + * Returns the OR-sum of all bits that need reseeding + * independent of the scope they were accessed with. + * @return OR-sum of the bits. + */ + uint32 GetReseedSum() const + { + uint32 sum = 0; + for (VarSpriteGroupScope vsg = VSG_BEGIN; vsg < VSG_END; vsg++) { + sum |= this->reseed[vsg]; + } + return sum; + } + /** * Resets the dynamic state of the resolver object. * To be called before resolving an Action-1-2-3 chain. @@ -390,7 +407,7 @@ struct ResolverObject { { this->last_value = 0; this->trigger = 0; - this->reseed = 0; + memset(this->reseed, 0, sizeof(this->reseed)); } };