What you'd generally do is make a system that optimizes along the following criteria:
- Easy to implement
- Easy to debug
- Fast enough
To make it easy to maintain, put it in a class:
class Upgrades
{
void Add(Upgrade u)
void Remove(Upgrade u)
float GetSpeedBonus()
float GetProductionBonus()
float GetIncomeBonus()
}
As you can see from the class interface, there's never a need to iterate through all possible updates. You need to tell the code if a new update applies, and telling the code means telling the Upgrades
class (if you don't want to create a mess of spaghetti code). You do not "enable" an upgrade by setting a magic flag on an achievement. You enable an upgrade by telling the Upgrades
class that the upgrade is enabled.
How you optimize the code inside the class is then pretty much irrelevant: it's a problem you can solve when it becomes a problem. If you want solve it, you solve it by caching values for speed, production, income, etc.
A possible pseudocode implementation looks somewhat like this:
public class Upgrades
{
public void Add(Upgrade u)
{
// toDo: if some kind of update can or cannot
// be added multiple times, implement that here
_container.Add(u);
RecalculateCache();
}
public void Remove(Upgrade u)
{
_container.Remove(u);
RecalculateCache();
}
public float SpeedBonus() { get { return _speed; } }
public float ProductionBonus() { get { return _production; } }
public float IncomeBonus() { get { return _income; } }
void RecalculateCache
{
// this can be a very complicated function depending on
// the rules you have for combining different upgrade types
}
}
A tempting optimization is to change the code to only do a partial recalculation of the cache on adding or removing a update. The downside of such an optimization is that changing the formula for aggregating updates will become much more challenging. It is likely that the formula will be changed at some point, e.g. to ensure the effects of upgrade "foo" and upgrade "bar" don't stack. So I advise against this particular optimization, unless updates change excessively often (multiple times per frame). A more worthwhile optimization may be a way that enables/disables the recalculation of the cache while multiple updates are being added.