Facebook
From miro, 5 Months ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 166
  1. def multiple_calls_wrapper(func, count):
  2.     def wrapper(*args, **kwargs):
  3.         for _ in range(count):
  4.             func(*args, **kwargs)
  5.     return wrapper
  6.  
  7. custom_round = lambda x: int(x) + 1 if x % 1 > 0.5 else int(x)
  8.  
  9. class Potion:
  10.     def __init__(self, effects, duration):
  11.         self.effects = effects
  12.         self.intensities = {effect : 1 for effect in self.effects.keys()}
  13.         self.depleted_effects = set()
  14.         self.is_depleted = False
  15.         self.is_applied = False
  16.         self.duration = duration
  17.  
  18.     def __getattr__(self, name):
  19.         if self.is_depleted:
  20.             raise TypeError("Potion is now part of something bigger than itself.")
  21.         elif self.is_applied or name in self.effects and name in self.depleted_effects:
  22.             raise TypeError("Effect is depleted.")
  23.         elif name in self.effects and name not in self.depleted_effects:
  24.             self.depleted_effects.add(name)
  25.             self.is_applied = self.depleted_effects == set(self.effects)
  26.             return multiple_calls_wrapper(self.effects[name], self.intensities[name])
  27.         else:
  28.             raise AttributeError(f"Couldn't find {name} attribute")
  29.  
  30.     def __add__(self, other_potion):
  31.         if self.is_depleted or other_potion.is_depleted:
  32.             raise TypeError("Potion is now part of something bigger than itself.")
  33.         if self.is_applied or other_potion.is_applied:
  34.             raise TypeError("Potion is depleted.")
  35.         self.is_depleted = True
  36.         other_potion.is_depleted = True
  37.  
  38.         new_duration = max(self.duration, other_potion.duration)
  39.         new_effects = {**self.effects, **other_potion.effects}
  40.         #union of intensities, where intensities are summed for common effects  
  41.         new_intensities = {key : self.intensities.get(key) for key in set(self.intensities.keys()) - self.depleted_effects}
  42.         for key in set(other_potion.intensities.keys()) - other_potion.depleted_effects:
  43.             if key in new_intensities:
  44.                 new_intensities[key] += other_potion.intensities[key]
  45.             else:
  46.                 new_intensities[key] = other_potion.intensities[key]
  47.  
  48.         result = Potion(new_effects, new_duration)
  49.         result.intensities = new_intensities
  50.         return result
  51.    
  52.     def __mul__(self, times):
  53.         if self.is_depleted:
  54.             raise TypeError("Potion is now part of something bigger than itself.")
  55.         if self.is_applied:
  56.             raise TypeError("Potion is depleted.")
  57.         self.is_depleted = True
  58.  
  59.         #dict comprehension with custom rounding criteria
  60.         #(>x.5 is rounded to x + 1; <=x.5 is rounded to x)
  61.         new_intensities = {key: custom_round(times * val)
  62.                             for (key, val) in self.intensities.items()}
  63.         result = Potion(self.effects, self.duration)
  64.         result.intensities = new_intensities
  65.         result.depleted_effects = self.depleted_effects
  66.         return result
  67.    
  68.    
  69.     def __rmul__(self, times):
  70.         return self.__mul__(times)
  71.    
  72.     def __imul__(self, times):
  73.         self = self.__mul__(times)
  74.         return self
  75.    
  76.     def __sub__(self, other_potion):
  77.         if self.is_depleted or other_potion.is_depleted:
  78.             raise TypeError("Potion is now part of something bigger than itself.")
  79.         if self.is_applied or other_potion.is_applied:
  80.             raise TypeError("Potion is depleted.")
  81.         self.is_depleted = True
  82.         other_potion.is_depleted = True
  83.  
  84.         if  not (set(other_potion.effects.keys()) <= set(self.effects.keys())):
  85.             raise TypeError("Invalid subtract")
  86.        
  87.         new_intensities = self.intensities
  88.         for effect in other_potion.intensities:
  89.             new_intensities[effect] -= other_potion.intensities[effect]
  90.             if new_intensities[effect] < 0:
  91.                 del new_intensities[effect]
  92.         new_effects = {key : val for (key, val) in self.effects.items() if key in new_intensities}
  93.         result = Potion(new_effects, self.duration)
  94.         result.intensities = new_intensities
  95.         result.depleted_effects = self.depleted_effects & set(new_effects.keys())
  96.         return result
  97.    
  98.     def __truediv__(self, times):
  99.         if self.is_depleted:
  100.              raise TypeError("Potion is now part of something bigger than itself.")
  101.         if self.is_applied:
  102.             raise TypeError("Potion is depleted.")
  103.         self.is_depleted = True
  104.  
  105.         new_intensities = {key : custom_round(val / times) for (key, val) in self.intensities.items()}
  106.         result = Potion(self.effects, self.duration)
  107.         result.intensities = new_intensities
  108.         return tuple([result for _ in range(times)])
  109.    
  110.     def __eq__(self, other_potion):
  111.         first_effects = set(self.intensities) - set(self.depleted_effects)
  112.          sec - set(other_potion.depleted_effects)
  113.         if first_effects != second_effects:
  114.             return False
  115.         for effect in first_effects:
  116.             if other_potion.intensities[effect] != self.intensities[effect]:
  117.                 return False
  118.         return True
  119.    
  120.     def __gt__(self, other_potion):
  121.         first_sum = sum([self.intensities[effect] for effect in self.effects if effect not in self.depleted_effects])
  122.          sec for effect in other_potion.effects
  123.                            if effect not in other_potion.depleted_effects])
  124.         return first_sum > second_sum
  125.  
  126. class ГоспожатаПоХимия:
  127.     def __init__(self):
  128.         pass
  129.         #history = {}
  130.     def apply(self, target, potion):
  131.         if potion.is_applied:
  132.             raise TypeError("Potion is depleted.")
  133.         if potion.is_depleted:
  134.              raise TypeError("Potion is now part of something bigger than itself.")
  135.        
  136.        # if not target in self.history.keys():
  137.         #    self.history[target] = [target.__dict__.copy()]
  138.         #self.history[target].extend([potion.__dict__.copy(), potion.duration])
  139.  
  140.         inorder_effects = [effect for effect in potion.effects.keys() if not effect in potion.depleted_effects]
  141.         inorder_effects.sort(key = lambda x : sum([ord(ch) for ch in x]), reverse = True)
  142.         for effect in inorder_effects:
  143.             potion.__getattr__(effect)(target)
  144.  
  145.         potion.is_applied = True
  146.  
  147.     def tick(self):
  148.         pass
  149.         #for key, val in self.history.items():
  150.  
  151. #testing:
  152.  
  153. class Target:
  154.     def __init__(self):
  155.         self.size = 5
  156.  
  157. target = Target()
  158.  
  159. effects = {'grow': lambda target: setattr(target, 'size', target.size*2)}
  160. grow_potion=Potion(effects,duration=2)
  161.  
  162. def elemental_dmg_immunity(target):
  163.     target.fire_dmg_resistance = 1.0 # Percentage value between 0 and 1
  164.     target.water_dmg_resistance = 1.0
  165.     target.earth_dmg_resistance = 1.0
  166.     target.air_dmg_resistance = 1.0
  167.  
  168. def physical_dmg_immunity(target):
  169.     target.bludgeoning_dmg_resistance = 1.0
  170.     target.slashing_dmg_resistance = 1.0
  171.     target.piercing_dmg_resistance = 1.0
  172.  
  173. immunity_potion = Potion({'make_elemental_immune': elemental_dmg_immunity,
  174.                           'make_physical_immune': physical_dmg_immunity},
  175.                          duration=1)
  176.  
  177. dimitrichka = ГоспожатаПоХимия()
  178. # grow_potion и immunity_potion са отварите от горния пример
  179. grow_and_immunity_potion = grow_potion + immunity_potion
  180.  
  181. # target.size = 5
  182. print(target.__dict__)
  183. print('----------------------------')
  184. dimitrichka.apply(target, grow_and_immunity_potion)
  185. print(target.__dict__)
  186. # target.size = 10
  187. # target.*_resistance = 1.0 (* за да не ги изброяваме)
  188.  
  189.  
  190.  
  191.