#!/usr/bin/env python class RegisterableParent: def __init__(self): self._updates = [] self.value = 0 def calculate(self): self._set(self.formula()) def _set(self, val): self.value = val for stat in self._updates: stat.calculate() def get(self): return self.value class PrimitiveStat(RegisterableParent): def __init__(self): RegisterableParent.__init__(self) self.set = self._set class CompoundStat(RegisterableParent): def __init__(self, base=PrimitiveStat()): RegisterableParent.__init__(self) self.multipliers = MultiplyingCollection() self.bonuses = AddingCollection() self.base = base for stat in [self.multipliers, self.bonuses, self.base]: stat._updates.append(self) def formula(self): return (self.multipliers.value * self.base.value) + self.bonuses.value class CalculatedStat(RegisterableParent): def __init__(self, **kwargs): RegisterableParent.__init__(self) self._toolbox = {} for arg in kwargs: self._toolbox[arg] = kwargs[arg] for stat in self._toolbox: self._toolbox[stat]._updates.append(self) def getStat(self, stat): return self._toolbox[stat].value class Bonus: def __init__(self, value): self.value = value self._updates = [] class BonusCollectionParent(RegisterableParent): def __init__(self): RegisterableParent.__init__(self) self.bonuses = set() def register(self, item): self.bonuses.add(item) self.calculate() def unregister(self, item): self.bonuses.remove(item) self.calculate() class AddingCollection(BonusCollectionParent): def formula(self): x = 0 for bonus in self.bonuses: x += bonus.value return x class MultiplyingCollection(BonusCollectionParent): def formula(self): x = 1 for bonus in self.bonuses: x *= (1 + bonus) return x level = PrimitiveStat() strength = CompoundStat() strength.base.set(13) bonus_attack_power = PrimitiveStat() bonus_attack_power.set(5) attack_power = CalculatedStat(level=level, strength=strength, bonus_attack_power = bonus_attack_power) attack_power.formula = lambda: attack_power.getStat('level') + attack_power.getStat('strength') * 2 + attack_power.getStat('bonus_attack_power') hp = CalculatedStat(level=level) hp.formula = lambda: hp.getStat('level') * 10 level.set(4) print level.value print hp.value print attack_power.value level.set(level.value + 1) print attack_power.value bonus_attack_power.set(0) print attack_power.value test = AddingCollection() g = Bonus(3) test.register(g) print test.value test.register(Bonus(4)) print test.value test.unregister(g) print test.value