Домашни > Работилница за отвари! > Решения > Решението на Дария Лазарова

Резултати
9 точки от тестове
0 точки от учител

9 точки общо

18 успешни теста
2 неуспешни теста
Код

  1import copy
  2import math
  3
  4class Effect:
  5    def __init__(self, name, func, intensity=1):
  6        self.name = name
  7        self.func = func
  8        self.is_used = False
  9        self.intensity = intensity
 10        self.is_active = True
 11
 12    @property
 13    def molecular_mass(self):
 14        return sum([ord(letter) for letter in self.name])
 15    
 16    def __call__(self, target, is_continuing=False):
 17        if not self.is_used or is_continuing:
 18            for _ in range(self.intensity):
 19                self.func(target)
 20            self.is_used = True
 21        else:
 22            raise TypeError("Effect is depleted.")
 23        
 24
 25class Potion:
 26    def __init__(self, effects, duration=2, intensities=None):
 27        self.effects = {}
 28        self.is_itself = True
 29        self.is_used = False
 30
 31        for effect_name in effects:
 32            effect_func = effects[effect_name]
 33            effects[effect_name].is_called = False
 34
 35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
 36
 37        self.duration = duration
 38
 39    def effect(self, target, is_continuing=False):
 40        if not is_continuing and not self.is_itself:
 41            raise TypeError("Potion is now part of something bigger than itself.")
 42        
 43        if self.is_used and not is_continuing:
 44            raise TypeError("Potion is depleted.")
 45        
 46        self.is_used = True
 47        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))
 48
 49        for effect in self.effects.values():
 50            if not effect.is_active:
 51                continue
 52            effect(target, True)
 53        
 54    def __getattr__(self, effect_name):
 55        if effect_name not in self.effects:
 56            raise AttributeError("Effect is not in potion.")
 57        
 58        if self.is_used:
 59            raise TypeError("Potion is depleted.")
 60        
 61        if not self.effects[effect_name].is_active:
 62            raise TypeError("Effect is depleted.")
 63        
 64        if not self.is_itself:
 65            raise TypeError("Potion is now part of something bigger than itself.")
 66        
 67        self.effects[effect_name].is_active = False
 68
 69        return self.effects[effect_name]
 70
 71    def __add__(self, other):
 72        """Combining two potions."""
 73        if not self.is_itself or not other.is_itself:
 74            raise TypeError("Potion is now part of something bigger than itself.")
 75        
 76        if self.is_used:
 77            raise TypeError("Potion is depleted.")
 78        
 79        effects = {}
 80        intensities = {}
 81
 82        for effect_name, effect in self.effects.items():
 83            if not effect.is_active:
 84                continue
 85            effects[effect_name] = effect.func
 86            intensities[effect_name] = effect.intensity
 87        
 88        for effect_name, effect in other.effects.items():
 89            if not effect.is_active:
 90                continue
 91
 92            if effect_name not in effects:
 93                effects[effect_name] = effect.func
 94                intensities[effect_name] = effect.intensity
 95            else:
 96                intensities[effect_name] += effect.intensity
 97    
 98        self.is_itself = False
 99        other.is_itself = False
100
101        return Potion(effects, max(self.duration, other.duration), intensities)
102    
103    def __mul__(self, number):
104        """Potentiation of two potions."""
105        if not self.is_itself:
106            raise TypeError("Potion is now part of something bigger than itself.")
107        
108        if self.is_used:
109            raise TypeError("Potion is depleted.")
110        
111        effects = {}
112        intensities = {}
113
114        for effect_name, effect in self.effects.items():
115            if not effect.is_active:
116                continue
117
118            intensities[effect_name] = effect.intensity * number
119
120            if intensities[effect_name] % 1 <= 0.5:
121                intensities[effect_name] = math.floor(intensities[effect_name])
122            else:
123                intensities[effect_name] = math.ceil(intensities[effect_name])
124
125            effects[effect_name] = effect.func
126
127        self.is_itself = False
128        return Potion(effects, self.duration, intensities)
129    
130    def __sub__(self, other):
131        """Purification of two potions."""
132        if not self.is_itself or not other.is_itself:
133            raise TypeError("Potion is now part of something bigger than itself.")
134        
135        if self.is_used:
136            raise TypeError("Potion is depleted.")
137        
138        for effect in other.effects:
139            if effect not in self.effects:
140                raise TypeError("Effect is not in potion.")
141        
142        effects = {}
143        intensities = {}
144
145        for effect_name, effect in self.effects.items():
146            intensities[effect_name] = effect.intensity
147            effects[effect_name] = effect.func
148
149            if not effect.is_active:
150                intensities[effect_name] = max(intensities[effect_name] - 1, 0)
151
152        for effect in other.effects:
153            intensities[effect] -= other.effects[effect].intensity
154
155            if not other.effects[effect].is_active and other.effects[effect].intensity > 0:
156                intensities[effect] += 1
157
158            if intensities[effect] <= 0:
159                effects.pop(effect)
160                intensities.pop(effect)
161
162        self.is_itself = False
163        other.is_itself = False
164        return Potion(effects, self.duration, intensities)
165    
166    def __truediv__(self, number:int):
167        """Dividing two potions."""
168        if not self.is_itself:
169            raise TypeError("Potion is now part of something bigger than itself.")
170        
171        if self.is_used:
172            raise TypeError("Potion is depleted.")
173        
174        effects = {}
175        intensities = {}
176
177        for effect_name, effect in self.effects.items():
178            if not effect.is_active:
179                continue
180
181            intensities[effect_name] = int(effect.intensity) / number
182            effects[effect_name] = effect.func
183
184            if intensities[effect_name] % 1 <= 0.5:
185                intensities[effect_name] = math.floor(intensities[effect_name])
186            else:
187                intensities[effect_name] = math.ceil(intensities[effect_name])
188        
189        self.is_itself = False
190        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))
191    
192    def __eq__(self, other):
193
194        if not self.is_itself or not other.is_itself:
195            raise TypeError("Potion is now part of something bigger than itself.")
196        
197        if self.is_used:
198            raise TypeError("Potion is depleted.")
199        
200        for effect in self.effects:
201            if effect not in other.effects:
202                return False
203            
204            if not self.effects[effect].is_active:
205                self.effects[effect].intensity = 0
206
207            if not other.effects[effect].is_active:
208                other.effects[effect].intensity = 0
209
210            if self.effects[effect].intensity != other.effects[effect].intensity:
211                return False
212            
213        for effect in other.effects:
214            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:
215                return False
216            
217        return True
218
219    def __lt__(self, other):
220
221        if not self.is_itself or not other.is_itself:
222            raise TypeError("Potion is now part of something bigger than itself.")
223        
224        if self.is_used:
225            raise TypeError("Potion is depleted.")
226        
227        
228        return sum(effect.intensity if effect.is_active else 0 for effect in self.effects.values()) < sum(effect.intensity if effect.is_active else 0  for effect in other.effects.values())
229    
230    def __dir__(self):
231        return list(self.effects.keys())
232
233
234class Target:
235    def __init__(self, target):
236        self.curr_target = target
237        self.original = copy.deepcopy(target.__dict__)
238
239    @property
240    def original_state(self):
241        return copy.deepcopy(self.original)
242
243    def back_to_original(self):
244        self.curr_target.__dict__ = self.original_state
245
246    def __eq__(self, other):
247        if isinstance(other, Target):
248            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__
249        return False
250
251    def __hash__(self):
252        return hash(self.curr_target.__class__.__name__)
253
254class ГоспожатаПоХимия:
255    def __init__(self):
256        self.active_potions = {}
257    
258    def apply(self, target_obj, potion):
259        target = Target(target_obj)
260        
261        if self.active_potions.get(target) is None:
262            self.active_potions[target] = []
263
264        if potion.duration > 0:
265            potion.effect(target.curr_target)
266            self.active_potions[target].append([potion.duration - 1, potion])
267    
268    def tick(self):
269        for target in self.active_potions:
270            target.back_to_original()
271            to_remove = []
272
273            for curr in self.active_potions[target]:
274                remaining_time, potion = curr
275                curr[0] -= 1
276
277                if remaining_time <= 0:
278                    to_remove.append(curr)
279                else:
280                    potion.effect(target.curr_target, True)
281
282            for curr in to_remove:
283                self.active_potions[target].remove(curr)

.................FF.
======================================================================
FAIL: test_ticking_multiple_potions (test.TestГоспожатаПоХимия)
Test ticking after applying multiple potions which affect the same attribute.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 471, in test_ticking_multiple_potions
self.assertEqual(self._target.int_attr, 5)
AssertionError: 50 != 5

======================================================================
FAIL: test_ticking_multiple_targets (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 490, in test_ticking_multiple_targets
self.assertEqual(target1.int_attr, 5)
AssertionError: 50 != 5

----------------------------------------------------------------------
Ran 20 tests in 0.002s

FAILED (failures=2)

Дискусия
История

f1import copyf1import copy
2import math2import math
33
4class Effect:4class Effect:
5    def __init__(self, name, func, intensity=1):5    def __init__(self, name, func, intensity=1):
6        self.name = name6        self.name = name
7        self.func = func7        self.func = func
8        self.is_used = False8        self.is_used = False
9        self.intensity = intensity9        self.intensity = intensity
10        self.is_active = True10        self.is_active = True
1111
12    @property12    @property
13    def molecular_mass(self):13    def molecular_mass(self):
14        return sum([ord(letter) for letter in self.name])14        return sum([ord(letter) for letter in self.name])
15    15    
16    def __call__(self, target, is_continuing=False):16    def __call__(self, target, is_continuing=False):
17        if not self.is_used or is_continuing:17        if not self.is_used or is_continuing:
18            for _ in range(self.intensity):18            for _ in range(self.intensity):
19                self.func(target)19                self.func(target)
20            self.is_used = True20            self.is_used = True
21        else:21        else:
22            raise TypeError("Effect is depleted.")22            raise TypeError("Effect is depleted.")
23        23        
2424
25class Potion:25class Potion:
26    def __init__(self, effects, duration=2, intensities=None):26    def __init__(self, effects, duration=2, intensities=None):
27        self.effects = {}27        self.effects = {}
28        self.is_itself = True28        self.is_itself = True
29        self.is_used = False29        self.is_used = False
3030
31        for effect_name in effects:31        for effect_name in effects:
32            effect_func = effects[effect_name]32            effect_func = effects[effect_name]
33            effects[effect_name].is_called = False33            effects[effect_name].is_called = False
3434
35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3636
37        self.duration = duration37        self.duration = duration
3838
39    def effect(self, target, is_continuing=False):39    def effect(self, target, is_continuing=False):
40        if not is_continuing and not self.is_itself:40        if not is_continuing and not self.is_itself:
41            raise TypeError("Potion is now part of something bigger than itself.")41            raise TypeError("Potion is now part of something bigger than itself.")
42        42        
43        if self.is_used and not is_continuing:43        if self.is_used and not is_continuing:
44            raise TypeError("Potion is depleted.")44            raise TypeError("Potion is depleted.")
45        45        
46        self.is_used = True46        self.is_used = True
47        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))47        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))
4848
49        for effect in self.effects.values():49        for effect in self.effects.values():
50            if not effect.is_active:50            if not effect.is_active:
51                continue51                continue
52            effect(target, True)52            effect(target, True)
53        53        
54    def __getattr__(self, effect_name):54    def __getattr__(self, effect_name):
55        if effect_name not in self.effects:55        if effect_name not in self.effects:
56            raise AttributeError("Effect is not in potion.")56            raise AttributeError("Effect is not in potion.")
57        57        
58        if self.is_used:58        if self.is_used:
59            raise TypeError("Potion is depleted.")59            raise TypeError("Potion is depleted.")
60        60        
61        if not self.effects[effect_name].is_active:61        if not self.effects[effect_name].is_active:
62            raise TypeError("Effect is depleted.")62            raise TypeError("Effect is depleted.")
63        63        
64        if not self.is_itself:64        if not self.is_itself:
65            raise TypeError("Potion is now part of something bigger than itself.")65            raise TypeError("Potion is now part of something bigger than itself.")
66        66        
67        self.effects[effect_name].is_active = False67        self.effects[effect_name].is_active = False
6868
69        return self.effects[effect_name]69        return self.effects[effect_name]
7070
71    def __add__(self, other):71    def __add__(self, other):
72        """Combining two potions."""72        """Combining two potions."""
73        if not self.is_itself or not other.is_itself:73        if not self.is_itself or not other.is_itself:
74            raise TypeError("Potion is now part of something bigger than itself.")74            raise TypeError("Potion is now part of something bigger than itself.")
75        75        
76        if self.is_used:76        if self.is_used:
77            raise TypeError("Potion is depleted.")77            raise TypeError("Potion is depleted.")
78        78        
79        effects = {}79        effects = {}
80        intensities = {}80        intensities = {}
8181
82        for effect_name, effect in self.effects.items():82        for effect_name, effect in self.effects.items():
83            if not effect.is_active:83            if not effect.is_active:
84                continue84                continue
85            effects[effect_name] = effect.func85            effects[effect_name] = effect.func
86            intensities[effect_name] = effect.intensity86            intensities[effect_name] = effect.intensity
87        87        
88        for effect_name, effect in other.effects.items():88        for effect_name, effect in other.effects.items():
89            if not effect.is_active:89            if not effect.is_active:
90                continue90                continue
9191
92            if effect_name not in effects:92            if effect_name not in effects:
93                effects[effect_name] = effect.func93                effects[effect_name] = effect.func
94                intensities[effect_name] = effect.intensity94                intensities[effect_name] = effect.intensity
95            else:95            else:
96                intensities[effect_name] += effect.intensity96                intensities[effect_name] += effect.intensity
97    97    
98        self.is_itself = False98        self.is_itself = False
99        other.is_itself = False99        other.is_itself = False
100100
101        return Potion(effects, max(self.duration, other.duration), intensities)101        return Potion(effects, max(self.duration, other.duration), intensities)
102    102    
103    def __mul__(self, number):103    def __mul__(self, number):
104        """Potentiation of two potions."""104        """Potentiation of two potions."""
105        if not self.is_itself:105        if not self.is_itself:
106            raise TypeError("Potion is now part of something bigger than itself.")106            raise TypeError("Potion is now part of something bigger than itself.")
107        107        
108        if self.is_used:108        if self.is_used:
109            raise TypeError("Potion is depleted.")109            raise TypeError("Potion is depleted.")
110        110        
111        effects = {}111        effects = {}
112        intensities = {}112        intensities = {}
113113
114        for effect_name, effect in self.effects.items():114        for effect_name, effect in self.effects.items():
115            if not effect.is_active:115            if not effect.is_active:
116                continue116                continue
117117
118            intensities[effect_name] = effect.intensity * number118            intensities[effect_name] = effect.intensity * number
119119
120            if intensities[effect_name] % 1 <= 0.5:120            if intensities[effect_name] % 1 <= 0.5:
121                intensities[effect_name] = math.floor(intensities[effect_name])121                intensities[effect_name] = math.floor(intensities[effect_name])
122            else:122            else:
123                intensities[effect_name] = math.ceil(intensities[effect_name])123                intensities[effect_name] = math.ceil(intensities[effect_name])
124124
125            effects[effect_name] = effect.func125            effects[effect_name] = effect.func
126126
127        self.is_itself = False127        self.is_itself = False
128        return Potion(effects, self.duration, intensities)128        return Potion(effects, self.duration, intensities)
129    129    
130    def __sub__(self, other):130    def __sub__(self, other):
131        """Purification of two potions."""131        """Purification of two potions."""
132        if not self.is_itself or not other.is_itself:132        if not self.is_itself or not other.is_itself:
133            raise TypeError("Potion is now part of something bigger than itself.")133            raise TypeError("Potion is now part of something bigger than itself.")
134        134        
135        if self.is_used:135        if self.is_used:
136            raise TypeError("Potion is depleted.")136            raise TypeError("Potion is depleted.")
137        137        
138        for effect in other.effects:138        for effect in other.effects:
139            if effect not in self.effects:139            if effect not in self.effects:
140                raise TypeError("Effect is not in potion.")140                raise TypeError("Effect is not in potion.")
141        141        
142        effects = {}142        effects = {}
143        intensities = {}143        intensities = {}
144144
145        for effect_name, effect in self.effects.items():145        for effect_name, effect in self.effects.items():
146            intensities[effect_name] = effect.intensity146            intensities[effect_name] = effect.intensity
147            effects[effect_name] = effect.func147            effects[effect_name] = effect.func
148148
149            if not effect.is_active:149            if not effect.is_active:
150                intensities[effect_name] = max(intensities[effect_name] - 1, 0)150                intensities[effect_name] = max(intensities[effect_name] - 1, 0)
151151
152        for effect in other.effects:152        for effect in other.effects:
153            intensities[effect] -= other.effects[effect].intensity153            intensities[effect] -= other.effects[effect].intensity
154154
155            if not other.effects[effect].is_active and other.effects[effect].intensity > 0:155            if not other.effects[effect].is_active and other.effects[effect].intensity > 0:
156                intensities[effect] += 1156                intensities[effect] += 1
157157
158            if intensities[effect] <= 0:158            if intensities[effect] <= 0:
159                effects.pop(effect)159                effects.pop(effect)
160                intensities.pop(effect)160                intensities.pop(effect)
161161
162        self.is_itself = False162        self.is_itself = False
163        other.is_itself = False163        other.is_itself = False
164        return Potion(effects, self.duration, intensities)164        return Potion(effects, self.duration, intensities)
165    165    
166    def __truediv__(self, number:int):166    def __truediv__(self, number:int):
167        """Dividing two potions."""167        """Dividing two potions."""
168        if not self.is_itself:168        if not self.is_itself:
169            raise TypeError("Potion is now part of something bigger than itself.")169            raise TypeError("Potion is now part of something bigger than itself.")
170        170        
171        if self.is_used:171        if self.is_used:
172            raise TypeError("Potion is depleted.")172            raise TypeError("Potion is depleted.")
173        173        
174        effects = {}174        effects = {}
175        intensities = {}175        intensities = {}
176176
177        for effect_name, effect in self.effects.items():177        for effect_name, effect in self.effects.items():
178            if not effect.is_active:178            if not effect.is_active:
179                continue179                continue
180180
181            intensities[effect_name] = int(effect.intensity) / number181            intensities[effect_name] = int(effect.intensity) / number
182            effects[effect_name] = effect.func182            effects[effect_name] = effect.func
183183
184            if intensities[effect_name] % 1 <= 0.5:184            if intensities[effect_name] % 1 <= 0.5:
185                intensities[effect_name] = math.floor(intensities[effect_name])185                intensities[effect_name] = math.floor(intensities[effect_name])
186            else:186            else:
187                intensities[effect_name] = math.ceil(intensities[effect_name])187                intensities[effect_name] = math.ceil(intensities[effect_name])
188        188        
189        self.is_itself = False189        self.is_itself = False
190        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))190        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))
191    191    
192    def __eq__(self, other):192    def __eq__(self, other):
193193
194        if not self.is_itself or not other.is_itself:194        if not self.is_itself or not other.is_itself:
195            raise TypeError("Potion is now part of something bigger than itself.")195            raise TypeError("Potion is now part of something bigger than itself.")
196        196        
197        if self.is_used:197        if self.is_used:
198            raise TypeError("Potion is depleted.")198            raise TypeError("Potion is depleted.")
199        199        
200        for effect in self.effects:200        for effect in self.effects:
201            if effect not in other.effects:201            if effect not in other.effects:
202                return False202                return False
203            203            
204            if not self.effects[effect].is_active:204            if not self.effects[effect].is_active:
205                self.effects[effect].intensity = 0205                self.effects[effect].intensity = 0
206206
207            if not other.effects[effect].is_active:207            if not other.effects[effect].is_active:
208                other.effects[effect].intensity = 0208                other.effects[effect].intensity = 0
209209
210            if self.effects[effect].intensity != other.effects[effect].intensity:210            if self.effects[effect].intensity != other.effects[effect].intensity:
211                return False211                return False
212            212            
213        for effect in other.effects:213        for effect in other.effects:
214            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:214            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:
215                return False215                return False
216            216            
217        return True217        return True
218218
219    def __lt__(self, other):219    def __lt__(self, other):
220220
221        if not self.is_itself or not other.is_itself:221        if not self.is_itself or not other.is_itself:
222            raise TypeError("Potion is now part of something bigger than itself.")222            raise TypeError("Potion is now part of something bigger than itself.")
223        223        
224        if self.is_used:224        if self.is_used:
225            raise TypeError("Potion is depleted.")225            raise TypeError("Potion is depleted.")
226        226        
tt227        
227        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])228        return sum(effect.intensity if effect.is_active else 0 for effect in self.effects.values()) < sum(effect.intensity if effect.is_active else 0  for effect in other.effects.values())
228 
229    def __gt__(self, other):
230 
231        if not self.is_itself or not other.is_itself:
232            raise TypeError("Potion is now part of something bigger than itself.")
233        
234        if self.is_used:
235            raise TypeError("Potion is depleted.")
236        
237        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])
238    229    
239    def __dir__(self):230    def __dir__(self):
240        return list(self.effects.keys())231        return list(self.effects.keys())
241232
242233
243class Target:234class Target:
244    def __init__(self, target):235    def __init__(self, target):
245        self.curr_target = target236        self.curr_target = target
246        self.original = copy.deepcopy(target.__dict__)237        self.original = copy.deepcopy(target.__dict__)
247238
248    @property239    @property
249    def original_state(self):240    def original_state(self):
250        return copy.deepcopy(self.original)241        return copy.deepcopy(self.original)
251242
252    def back_to_original(self):243    def back_to_original(self):
253        self.curr_target.__dict__ = self.original_state244        self.curr_target.__dict__ = self.original_state
254245
255    def __eq__(self, other):246    def __eq__(self, other):
256        if isinstance(other, Target):247        if isinstance(other, Target):
257            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__248            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__
258        return False249        return False
259250
260    def __hash__(self):251    def __hash__(self):
261        return hash(self.curr_target.__class__.__name__)252        return hash(self.curr_target.__class__.__name__)
262253
263class ГоспожатаПоХимия:254class ГоспожатаПоХимия:
264    def __init__(self):255    def __init__(self):
265        self.active_potions = {}256        self.active_potions = {}
266    257    
267    def apply(self, target_obj, potion):258    def apply(self, target_obj, potion):
268        target = Target(target_obj)259        target = Target(target_obj)
269        260        
270        if self.active_potions.get(target) is None:261        if self.active_potions.get(target) is None:
271            self.active_potions[target] = []262            self.active_potions[target] = []
272263
273        if potion.duration > 0:264        if potion.duration > 0:
274            potion.effect(target.curr_target)265            potion.effect(target.curr_target)
275            self.active_potions[target].append([potion.duration - 1, potion])266            self.active_potions[target].append([potion.duration - 1, potion])
276    267    
277    def tick(self):268    def tick(self):
278        for target in self.active_potions:269        for target in self.active_potions:
279            target.back_to_original()270            target.back_to_original()
280            to_remove = []271            to_remove = []
281272
282            for curr in self.active_potions[target]:273            for curr in self.active_potions[target]:
283                remaining_time, potion = curr274                remaining_time, potion = curr
284                curr[0] -= 1275                curr[0] -= 1
285276
286                if remaining_time <= 0:277                if remaining_time <= 0:
287                    to_remove.append(curr)278                    to_remove.append(curr)
288                else:279                else:
289                    potion.effect(target.curr_target, True)280                    potion.effect(target.curr_target, True)
290281
291            for curr in to_remove:282            for curr in to_remove:
292                self.active_potions[target].remove(curr)283                self.active_potions[target].remove(curr)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
2import math2import math
33
4class Effect:4class Effect:
5    def __init__(self, name, func, intensity=1):5    def __init__(self, name, func, intensity=1):
6        self.name = name6        self.name = name
7        self.func = func7        self.func = func
8        self.is_used = False8        self.is_used = False
9        self.intensity = intensity9        self.intensity = intensity
10        self.is_active = True10        self.is_active = True
1111
12    @property12    @property
13    def molecular_mass(self):13    def molecular_mass(self):
14        return sum([ord(letter) for letter in self.name])14        return sum([ord(letter) for letter in self.name])
15    15    
16    def __call__(self, target, is_continuing=False):16    def __call__(self, target, is_continuing=False):
17        if not self.is_used or is_continuing:17        if not self.is_used or is_continuing:
18            for _ in range(self.intensity):18            for _ in range(self.intensity):
19                self.func(target)19                self.func(target)
20            self.is_used = True20            self.is_used = True
21        else:21        else:
22            raise TypeError("Effect is depleted.")22            raise TypeError("Effect is depleted.")
23        23        
2424
25class Potion:25class Potion:
26    def __init__(self, effects, duration=2, intensities=None):26    def __init__(self, effects, duration=2, intensities=None):
27        self.effects = {}27        self.effects = {}
28        self.is_itself = True28        self.is_itself = True
29        self.is_used = False29        self.is_used = False
3030
31        for effect_name in effects:31        for effect_name in effects:
32            effect_func = effects[effect_name]32            effect_func = effects[effect_name]
33            effects[effect_name].is_called = False33            effects[effect_name].is_called = False
3434
35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3636
37        self.duration = duration37        self.duration = duration
3838
39    def effect(self, target, is_continuing=False):39    def effect(self, target, is_continuing=False):
40        if not is_continuing and not self.is_itself:40        if not is_continuing and not self.is_itself:
41            raise TypeError("Potion is now part of something bigger than itself.")41            raise TypeError("Potion is now part of something bigger than itself.")
nn42        
42        if self.is_used and not is_continuing:43        if self.is_used and not is_continuing:
43            raise TypeError("Potion is depleted.")44            raise TypeError("Potion is depleted.")
nn45        
44        self.is_used = True46        self.is_used = True
45        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))47        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))
4648
47        for effect in self.effects.values():49        for effect in self.effects.values():
48            if not effect.is_active:50            if not effect.is_active:
49                continue51                continue
50            effect(target, True)52            effect(target, True)
51        53        
52    def __getattr__(self, effect_name):54    def __getattr__(self, effect_name):
n53        if(effect_name not in self.effects):n55        if effect_name not in self.effects:
54            raise TypeError("Effect is not in potion.")56            raise AttributeError("Effect is not in potion.")
57        
58        if self.is_used:
59            raise TypeError("Potion is depleted.")
55        60        
56        if not self.effects[effect_name].is_active:61        if not self.effects[effect_name].is_active:
57            raise TypeError("Effect is depleted.")62            raise TypeError("Effect is depleted.")
58        63        
59        if not self.is_itself:64        if not self.is_itself:
60            raise TypeError("Potion is now part of something bigger than itself.")65            raise TypeError("Potion is now part of something bigger than itself.")
61        66        
62        self.effects[effect_name].is_active = False67        self.effects[effect_name].is_active = False
6368
64        return self.effects[effect_name]69        return self.effects[effect_name]
6570
66    def __add__(self, other):71    def __add__(self, other):
67        """Combining two potions."""72        """Combining two potions."""
68        if not self.is_itself or not other.is_itself:73        if not self.is_itself or not other.is_itself:
69            raise TypeError("Potion is now part of something bigger than itself.")74            raise TypeError("Potion is now part of something bigger than itself.")
70        75        
71        if self.is_used:76        if self.is_used:
72            raise TypeError("Potion is depleted.")77            raise TypeError("Potion is depleted.")
73        78        
74        effects = {}79        effects = {}
75        intensities = {}80        intensities = {}
7681
77        for effect_name, effect in self.effects.items():82        for effect_name, effect in self.effects.items():
nn83            if not effect.is_active:
84                continue
78            effects[effect_name] = effect.func85            effects[effect_name] = effect.func
79            intensities[effect_name] = effect.intensity86            intensities[effect_name] = effect.intensity
80        87        
81        for effect_name, effect in other.effects.items():88        for effect_name, effect in other.effects.items():
nn89            if not effect.is_active:
90                continue
91 
82            if effect_name not in effects:92            if effect_name not in effects:
83                effects[effect_name] = effect.func93                effects[effect_name] = effect.func
84                intensities[effect_name] = effect.intensity94                intensities[effect_name] = effect.intensity
85            else:95            else:
86                intensities[effect_name] += effect.intensity96                intensities[effect_name] += effect.intensity
87    97    
88        self.is_itself = False98        self.is_itself = False
89        other.is_itself = False99        other.is_itself = False
nn100 
90        return Potion(effects, max(self.duration, other.duration), intensities)101        return Potion(effects, max(self.duration, other.duration), intensities)
91    102    
92    def __mul__(self, number):103    def __mul__(self, number):
93        """Potentiation of two potions."""104        """Potentiation of two potions."""
94        if not self.is_itself:105        if not self.is_itself:
95            raise TypeError("Potion is now part of something bigger than itself.")106            raise TypeError("Potion is now part of something bigger than itself.")
96        107        
97        if self.is_used:108        if self.is_used:
98            raise TypeError("Potion is depleted.")109            raise TypeError("Potion is depleted.")
99        110        
100        effects = {}111        effects = {}
101        intensities = {}112        intensities = {}
102113
103        for effect_name, effect in self.effects.items():114        for effect_name, effect in self.effects.items():
nn115            if not effect.is_active:
116                continue
117 
104            intensities[effect_name] = effect.intensity * number118            intensities[effect_name] = effect.intensity * number
105119
106            if intensities[effect_name] % 1 <= 0.5:120            if intensities[effect_name] % 1 <= 0.5:
107                intensities[effect_name] = math.floor(intensities[effect_name])121                intensities[effect_name] = math.floor(intensities[effect_name])
108            else:122            else:
109                intensities[effect_name] = math.ceil(intensities[effect_name])123                intensities[effect_name] = math.ceil(intensities[effect_name])
110124
111            effects[effect_name] = effect.func125            effects[effect_name] = effect.func
112126
113        self.is_itself = False127        self.is_itself = False
114        return Potion(effects, self.duration, intensities)128        return Potion(effects, self.duration, intensities)
115    129    
116    def __sub__(self, other):130    def __sub__(self, other):
117        """Purification of two potions."""131        """Purification of two potions."""
118        if not self.is_itself or not other.is_itself:132        if not self.is_itself or not other.is_itself:
119            raise TypeError("Potion is now part of something bigger than itself.")133            raise TypeError("Potion is now part of something bigger than itself.")
120        134        
121        if self.is_used:135        if self.is_used:
122            raise TypeError("Potion is depleted.")136            raise TypeError("Potion is depleted.")
123        137        
124        for effect in other.effects:138        for effect in other.effects:
125            if effect not in self.effects:139            if effect not in self.effects:
126                raise TypeError("Effect is not in potion.")140                raise TypeError("Effect is not in potion.")
127        141        
128        effects = {}142        effects = {}
129        intensities = {}143        intensities = {}
130144
131        for effect_name, effect in self.effects.items():145        for effect_name, effect in self.effects.items():
132            intensities[effect_name] = effect.intensity146            intensities[effect_name] = effect.intensity
133            effects[effect_name] = effect.func147            effects[effect_name] = effect.func
134148
nn149            if not effect.is_active:
150                intensities[effect_name] = max(intensities[effect_name] - 1, 0)
151 
135        for effect in other.effects:152        for effect in other.effects:
136            intensities[effect] -= other.effects[effect].intensity153            intensities[effect] -= other.effects[effect].intensity
nn154 
155            if not other.effects[effect].is_active and other.effects[effect].intensity > 0:
156                intensities[effect] += 1
137157
138            if intensities[effect] <= 0:158            if intensities[effect] <= 0:
139                effects.pop(effect)159                effects.pop(effect)
140                intensities.pop(effect)160                intensities.pop(effect)
141161
142        self.is_itself = False162        self.is_itself = False
143        other.is_itself = False163        other.is_itself = False
144        return Potion(effects, self.duration, intensities)164        return Potion(effects, self.duration, intensities)
145    165    
146    def __truediv__(self, number:int):166    def __truediv__(self, number:int):
147        """Dividing two potions."""167        """Dividing two potions."""
148        if not self.is_itself:168        if not self.is_itself:
149            raise TypeError("Potion is now part of something bigger than itself.")169            raise TypeError("Potion is now part of something bigger than itself.")
150        170        
151        if self.is_used:171        if self.is_used:
152            raise TypeError("Potion is depleted.")172            raise TypeError("Potion is depleted.")
153        173        
154        effects = {}174        effects = {}
155        intensities = {}175        intensities = {}
156176
157        for effect_name, effect in self.effects.items():177        for effect_name, effect in self.effects.items():
nn178            if not effect.is_active:
179                continue
180 
158            intensities[effect_name] = int(effect.intensity) / number181            intensities[effect_name] = int(effect.intensity) / number
159            effects[effect_name] = effect.func182            effects[effect_name] = effect.func
160183
161            if intensities[effect_name] % 1 <= 0.5:184            if intensities[effect_name] % 1 <= 0.5:
162                intensities[effect_name] = math.floor(intensities[effect_name])185                intensities[effect_name] = math.floor(intensities[effect_name])
163            else:186            else:
164                intensities[effect_name] = math.ceil(intensities[effect_name])187                intensities[effect_name] = math.ceil(intensities[effect_name])
165        188        
166        self.is_itself = False189        self.is_itself = False
167        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))190        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))
168    191    
169    def __eq__(self, other):192    def __eq__(self, other):
nn193 
194        if not self.is_itself or not other.is_itself:
195            raise TypeError("Potion is now part of something bigger than itself.")
196        
197        if self.is_used:
198            raise TypeError("Potion is depleted.")
199        
170        for effect in self.effects:200        for effect in self.effects:
n171            if effect not in other.effects or self.effects[effect].intensity != other.effects[effect].intensity:n201            if effect not in other.effects:
172                return False202                return False
nn203            
204            if not self.effects[effect].is_active:
205                self.effects[effect].intensity = 0
206 
207            if not other.effects[effect].is_active:
208                other.effects[effect].intensity = 0
209 
210            if self.effects[effect].intensity != other.effects[effect].intensity:
211                return False
212            
173        for effect in other.effects:213        for effect in other.effects:
174            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:214            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:
175                return False215                return False
176            216            
177        return True217        return True
178218
179    def __lt__(self, other):219    def __lt__(self, other):
nn220 
221        if not self.is_itself or not other.is_itself:
222            raise TypeError("Potion is now part of something bigger than itself.")
223        
224        if self.is_used:
225            raise TypeError("Potion is depleted.")
226        
180        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])227        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])
181 228 
182    def __gt__(self, other):229    def __gt__(self, other):
nn230 
231        if not self.is_itself or not other.is_itself:
232            raise TypeError("Potion is now part of something bigger than itself.")
233        
234        if self.is_used:
235            raise TypeError("Potion is depleted.")
236        
183        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])237        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])
nn238    
239    def __dir__(self):
240        return list(self.effects.keys())
184241
185242
186class Target:243class Target:
187    def __init__(self, target):244    def __init__(self, target):
188        self.curr_target = target245        self.curr_target = target
189        self.original = copy.deepcopy(target.__dict__)246        self.original = copy.deepcopy(target.__dict__)
190247
191    @property248    @property
192    def original_state(self):249    def original_state(self):
193        return copy.deepcopy(self.original)250        return copy.deepcopy(self.original)
194251
195    def back_to_original(self):252    def back_to_original(self):
196        self.curr_target.__dict__ = self.original_state253        self.curr_target.__dict__ = self.original_state
197254
198    def __eq__(self, other):255    def __eq__(self, other):
199        if isinstance(other, Target):256        if isinstance(other, Target):
200            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__257            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__
201        return False258        return False
202259
203    def __hash__(self):260    def __hash__(self):
204        return hash(self.curr_target.__class__.__name__)261        return hash(self.curr_target.__class__.__name__)
205262
206class ГоспожатаПоХимия:263class ГоспожатаПоХимия:
207    def __init__(self):264    def __init__(self):
208        self.active_potions = {}265        self.active_potions = {}
209    266    
210    def apply(self, target_obj, potion):267    def apply(self, target_obj, potion):
211        target = Target(target_obj)268        target = Target(target_obj)
nn269        
212        if self.active_potions.get(target) is None:270        if self.active_potions.get(target) is None:
213            self.active_potions[target] = []271            self.active_potions[target] = []
214272
nn273        if potion.duration > 0:
215        potion.effect(target.curr_target)274            potion.effect(target.curr_target)
216        self.active_potions[target].append([potion.duration - 1, potion])275            self.active_potions[target].append([potion.duration - 1, potion])
217    276    
218    def tick(self):277    def tick(self):
219        for target in self.active_potions:278        for target in self.active_potions:
220            target.back_to_original()279            target.back_to_original()
221            to_remove = []280            to_remove = []
nn281 
222            for curr in self.active_potions[target]:282            for curr in self.active_potions[target]:
223                remaining_time, potion = curr283                remaining_time, potion = curr
224                curr[0] -= 1284                curr[0] -= 1
nn285 
225                if remaining_time <= 0:286                if remaining_time <= 0:
226                    to_remove.append(curr)287                    to_remove.append(curr)
227                else:288                else:
228                    potion.effect(target.curr_target, True)289                    potion.effect(target.curr_target, True)
nn290 
229            for curr in to_remove:291            for curr in to_remove:
230                self.active_potions[target].remove(curr)292                self.active_potions[target].remove(curr)
t231 t
232 
233def get_grow_potion():
234    effects = {'grow': lambda target: setattr(
235        target, 'size', target.size*2)}
236 
237    grow_potion = Potion(effects, duration=2)
238 
239    return grow_potion
240                
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
2import math2import math
33
4class Effect:4class Effect:
5    def __init__(self, name, func, intensity=1):5    def __init__(self, name, func, intensity=1):
6        self.name = name6        self.name = name
7        self.func = func7        self.func = func
8        self.is_used = False8        self.is_used = False
9        self.intensity = intensity9        self.intensity = intensity
10        self.is_active = True10        self.is_active = True
1111
12    @property12    @property
13    def molecular_mass(self):13    def molecular_mass(self):
14        return sum([ord(letter) for letter in self.name])14        return sum([ord(letter) for letter in self.name])
15    15    
16    def __call__(self, target, is_continuing=False):16    def __call__(self, target, is_continuing=False):
17        if not self.is_used or is_continuing:17        if not self.is_used or is_continuing:
18            for _ in range(self.intensity):18            for _ in range(self.intensity):
19                self.func(target)19                self.func(target)
20            self.is_used = True20            self.is_used = True
21        else:21        else:
22            raise TypeError("Effect is depleted.")22            raise TypeError("Effect is depleted.")
23        23        
2424
25class Potion:25class Potion:
26    def __init__(self, effects, duration=2, intensities=None):26    def __init__(self, effects, duration=2, intensities=None):
27        self.effects = {}27        self.effects = {}
28        self.is_itself = True28        self.is_itself = True
29        self.is_used = False29        self.is_used = False
3030
31        for effect_name in effects:31        for effect_name in effects:
32            effect_func = effects[effect_name]32            effect_func = effects[effect_name]
33            effects[effect_name].is_called = False33            effects[effect_name].is_called = False
3434
35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3636
37        self.duration = duration37        self.duration = duration
3838
39    def effect(self, target, is_continuing=False):39    def effect(self, target, is_continuing=False):
40        if not is_continuing and not self.is_itself:40        if not is_continuing and not self.is_itself:
41            raise TypeError("Potion is now part of something bigger than itself.")41            raise TypeError("Potion is now part of something bigger than itself.")
42        if self.is_used and not is_continuing:42        if self.is_used and not is_continuing:
43            raise TypeError("Potion is depleted.")43            raise TypeError("Potion is depleted.")
44        self.is_used = True44        self.is_used = True
45        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))45        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))
4646
47        for effect in self.effects.values():47        for effect in self.effects.values():
nn48            if not effect.is_active:
49                continue
48            effect(target, True)50            effect(target, True)
49        51        
50    def __getattr__(self, effect_name):52    def __getattr__(self, effect_name):
51        if(effect_name not in self.effects):53        if(effect_name not in self.effects):
52            raise TypeError("Effect is not in potion.")54            raise TypeError("Effect is not in potion.")
53        55        
54        if not self.effects[effect_name].is_active:56        if not self.effects[effect_name].is_active:
55            raise TypeError("Effect is depleted.")57            raise TypeError("Effect is depleted.")
56        58        
57        if not self.is_itself:59        if not self.is_itself:
58            raise TypeError("Potion is now part of something bigger than itself.")60            raise TypeError("Potion is now part of something bigger than itself.")
59        61        
60        self.effects[effect_name].is_active = False62        self.effects[effect_name].is_active = False
6163
62        return self.effects[effect_name]64        return self.effects[effect_name]
6365
64    def __add__(self, other):66    def __add__(self, other):
65        """Combining two potions."""67        """Combining two potions."""
66        if not self.is_itself or not other.is_itself:68        if not self.is_itself or not other.is_itself:
67            raise TypeError("Potion is now part of something bigger than itself.")69            raise TypeError("Potion is now part of something bigger than itself.")
68        70        
69        if self.is_used:71        if self.is_used:
70            raise TypeError("Potion is depleted.")72            raise TypeError("Potion is depleted.")
71        73        
72        effects = {}74        effects = {}
73        intensities = {}75        intensities = {}
7476
75        for effect_name, effect in self.effects.items():77        for effect_name, effect in self.effects.items():
76            effects[effect_name] = effect.func78            effects[effect_name] = effect.func
77            intensities[effect_name] = effect.intensity79            intensities[effect_name] = effect.intensity
78        80        
79        for effect_name, effect in other.effects.items():81        for effect_name, effect in other.effects.items():
80            if effect_name not in effects:82            if effect_name not in effects:
81                effects[effect_name] = effect.func83                effects[effect_name] = effect.func
82                intensities[effect_name] = effect.intensity84                intensities[effect_name] = effect.intensity
83            else:85            else:
84                intensities[effect_name] += effect.intensity86                intensities[effect_name] += effect.intensity
85    87    
86        self.is_itself = False88        self.is_itself = False
87        other.is_itself = False89        other.is_itself = False
88        return Potion(effects, max(self.duration, other.duration), intensities)90        return Potion(effects, max(self.duration, other.duration), intensities)
89    91    
90    def __mul__(self, number):92    def __mul__(self, number):
91        """Potentiation of two potions."""93        """Potentiation of two potions."""
92        if not self.is_itself:94        if not self.is_itself:
93            raise TypeError("Potion is now part of something bigger than itself.")95            raise TypeError("Potion is now part of something bigger than itself.")
94        96        
95        if self.is_used:97        if self.is_used:
96            raise TypeError("Potion is depleted.")98            raise TypeError("Potion is depleted.")
97        99        
98        effects = {}100        effects = {}
99        intensities = {}101        intensities = {}
100102
101        for effect_name, effect in self.effects.items():103        for effect_name, effect in self.effects.items():
102            intensities[effect_name] = effect.intensity * number104            intensities[effect_name] = effect.intensity * number
103105
104            if intensities[effect_name] % 1 <= 0.5:106            if intensities[effect_name] % 1 <= 0.5:
105                intensities[effect_name] = math.floor(intensities[effect_name])107                intensities[effect_name] = math.floor(intensities[effect_name])
106            else:108            else:
107                intensities[effect_name] = math.ceil(intensities[effect_name])109                intensities[effect_name] = math.ceil(intensities[effect_name])
108110
109            effects[effect_name] = effect.func111            effects[effect_name] = effect.func
110112
111        self.is_itself = False113        self.is_itself = False
112        return Potion(effects, self.duration, intensities)114        return Potion(effects, self.duration, intensities)
113    115    
114    def __sub__(self, other):116    def __sub__(self, other):
115        """Purification of two potions."""117        """Purification of two potions."""
116        if not self.is_itself or not other.is_itself:118        if not self.is_itself or not other.is_itself:
117            raise TypeError("Potion is now part of something bigger than itself.")119            raise TypeError("Potion is now part of something bigger than itself.")
118        120        
119        if self.is_used:121        if self.is_used:
120            raise TypeError("Potion is depleted.")122            raise TypeError("Potion is depleted.")
121        123        
122        for effect in other.effects:124        for effect in other.effects:
123            if effect not in self.effects:125            if effect not in self.effects:
124                raise TypeError("Effect is not in potion.")126                raise TypeError("Effect is not in potion.")
125        127        
126        effects = {}128        effects = {}
127        intensities = {}129        intensities = {}
128130
129        for effect_name, effect in self.effects.items():131        for effect_name, effect in self.effects.items():
130            intensities[effect_name] = effect.intensity132            intensities[effect_name] = effect.intensity
131            effects[effect_name] = effect.func133            effects[effect_name] = effect.func
132134
133        for effect in other.effects:135        for effect in other.effects:
134            intensities[effect] -= other.effects[effect].intensity136            intensities[effect] -= other.effects[effect].intensity
135137
136            if intensities[effect] <= 0:138            if intensities[effect] <= 0:
137                effects.pop(effect)139                effects.pop(effect)
138                intensities.pop(effect)140                intensities.pop(effect)
139141
140        self.is_itself = False142        self.is_itself = False
141        other.is_itself = False143        other.is_itself = False
142        return Potion(effects, self.duration, intensities)144        return Potion(effects, self.duration, intensities)
143    145    
144    def __truediv__(self, number:int):146    def __truediv__(self, number:int):
145        """Dividing two potions."""147        """Dividing two potions."""
146        if not self.is_itself:148        if not self.is_itself:
147            raise TypeError("Potion is now part of something bigger than itself.")149            raise TypeError("Potion is now part of something bigger than itself.")
148        150        
149        if self.is_used:151        if self.is_used:
150            raise TypeError("Potion is depleted.")152            raise TypeError("Potion is depleted.")
151        153        
152        effects = {}154        effects = {}
153        intensities = {}155        intensities = {}
154156
155        for effect_name, effect in self.effects.items():157        for effect_name, effect in self.effects.items():
156            intensities[effect_name] = int(effect.intensity) / number158            intensities[effect_name] = int(effect.intensity) / number
157            effects[effect_name] = effect.func159            effects[effect_name] = effect.func
158160
159            if intensities[effect_name] % 1 <= 0.5:161            if intensities[effect_name] % 1 <= 0.5:
160                intensities[effect_name] = math.floor(intensities[effect_name])162                intensities[effect_name] = math.floor(intensities[effect_name])
161            else:163            else:
162                intensities[effect_name] = math.ceil(intensities[effect_name])164                intensities[effect_name] = math.ceil(intensities[effect_name])
163        165        
164        self.is_itself = False166        self.is_itself = False
165        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))167        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))
166    168    
167    def __eq__(self, other):169    def __eq__(self, other):
168        for effect in self.effects:170        for effect in self.effects:
169            if effect not in other.effects or self.effects[effect].intensity != other.effects[effect].intensity:171            if effect not in other.effects or self.effects[effect].intensity != other.effects[effect].intensity:
170                return False172                return False
171        for effect in other.effects:173        for effect in other.effects:
172            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:174            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:
173                return False175                return False
174            176            
175        return True177        return True
176178
177    def __lt__(self, other):179    def __lt__(self, other):
n178        for effect in self.effects:n180        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])
179            if effect not in other.effects or self.effects[effect].intensity > other.effects[effect].intensity:181 
180                return False
181        return True
182 
183    def __gt__(self, other):182    def __gt__(self, other):
n184        for effect in other.effects:n183        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])
185            if effect not in self.effects or self.effects[effect].intensity < other.effects[effect].intensity:
186                return False
187184
188185
189class Target:186class Target:
190    def __init__(self, target):187    def __init__(self, target):
191        self.curr_target = target188        self.curr_target = target
192        self.original = copy.deepcopy(target.__dict__)189        self.original = copy.deepcopy(target.__dict__)
193190
194    @property191    @property
195    def original_state(self):192    def original_state(self):
196        return copy.deepcopy(self.original)193        return copy.deepcopy(self.original)
197194
198    def back_to_original(self):195    def back_to_original(self):
199        self.curr_target.__dict__ = self.original_state196        self.curr_target.__dict__ = self.original_state
200197
201    def __eq__(self, other):198    def __eq__(self, other):
202        if isinstance(other, Target):199        if isinstance(other, Target):
203            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__200            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__
204        return False201        return False
205202
206    def __hash__(self):203    def __hash__(self):
207        return hash(self.curr_target.__class__.__name__)204        return hash(self.curr_target.__class__.__name__)
208205
209class ГоспожатаПоХимия:206class ГоспожатаПоХимия:
210    def __init__(self):207    def __init__(self):
211        self.active_potions = {}208        self.active_potions = {}
212    209    
213    def apply(self, target_obj, potion):210    def apply(self, target_obj, potion):
214        target = Target(target_obj)211        target = Target(target_obj)
215        if self.active_potions.get(target) is None:212        if self.active_potions.get(target) is None:
216            self.active_potions[target] = []213            self.active_potions[target] = []
217214
218        potion.effect(target.curr_target)215        potion.effect(target.curr_target)
219        self.active_potions[target].append([potion.duration - 1, potion])216        self.active_potions[target].append([potion.duration - 1, potion])
220    217    
221    def tick(self):218    def tick(self):
222        for target in self.active_potions:219        for target in self.active_potions:
223            target.back_to_original()220            target.back_to_original()
224            to_remove = []221            to_remove = []
225            for curr in self.active_potions[target]:222            for curr in self.active_potions[target]:
226                remaining_time, potion = curr223                remaining_time, potion = curr
227                curr[0] -= 1224                curr[0] -= 1
228                if remaining_time <= 0:225                if remaining_time <= 0:
229                    to_remove.append(curr)226                    to_remove.append(curr)
230                else:227                else:
231                    potion.effect(target.curr_target, True)228                    potion.effect(target.curr_target, True)
232            for curr in to_remove:229            for curr in to_remove:
233                self.active_potions[target].remove(curr)230                self.active_potions[target].remove(curr)
234231
tt232 
233def get_grow_potion():
234    effects = {'grow': lambda target: setattr(
235        target, 'size', target.size*2)}
236 
237    grow_potion = Potion(effects, duration=2)
238 
239    return grow_potion
235                240                
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
2import math2import math
33
4class Effect:4class Effect:
5    def __init__(self, name, func, intensity=1):5    def __init__(self, name, func, intensity=1):
6        self.name = name6        self.name = name
7        self.func = func7        self.func = func
8        self.is_used = False8        self.is_used = False
9        self.intensity = intensity9        self.intensity = intensity
10        self.is_active = True10        self.is_active = True
1111
12    @property12    @property
13    def molecular_mass(self):13    def molecular_mass(self):
14        return sum([ord(letter) for letter in self.name])14        return sum([ord(letter) for letter in self.name])
15    15    
16    def __call__(self, target, is_continuing=False):16    def __call__(self, target, is_continuing=False):
17        if not self.is_used or is_continuing:17        if not self.is_used or is_continuing:
18            for _ in range(self.intensity):18            for _ in range(self.intensity):
19                self.func(target)19                self.func(target)
20            self.is_used = True20            self.is_used = True
21        else:21        else:
22            raise TypeError("Effect is depleted.")22            raise TypeError("Effect is depleted.")
23        23        
2424
25class Potion:25class Potion:
26    def __init__(self, effects, duration=2, intensities=None):26    def __init__(self, effects, duration=2, intensities=None):
27        self.effects = {}27        self.effects = {}
28        self.is_itself = True28        self.is_itself = True
29        self.is_used = False29        self.is_used = False
3030
31        for effect_name in effects:31        for effect_name in effects:
32            effect_func = effects[effect_name]32            effect_func = effects[effect_name]
33            effects[effect_name].is_called = False33            effects[effect_name].is_called = False
3434
35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3636
37        self.duration = duration37        self.duration = duration
3838
39    def effect(self, target, is_continuing=False):39    def effect(self, target, is_continuing=False):
40        if not is_continuing and not self.is_itself:40        if not is_continuing and not self.is_itself:
41            raise TypeError("Potion is now part of something bigger than itself.")41            raise TypeError("Potion is now part of something bigger than itself.")
42        if self.is_used and not is_continuing:42        if self.is_used and not is_continuing:
43            raise TypeError("Potion is depleted.")43            raise TypeError("Potion is depleted.")
44        self.is_used = True44        self.is_used = True
45        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))45        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))
4646
47        for effect in self.effects.values():47        for effect in self.effects.values():
48            effect(target, True)48            effect(target, True)
49        49        
50    def __getattr__(self, effect_name):50    def __getattr__(self, effect_name):
51        if(effect_name not in self.effects):51        if(effect_name not in self.effects):
52            raise TypeError("Effect is not in potion.")52            raise TypeError("Effect is not in potion.")
53        53        
54        if not self.effects[effect_name].is_active:54        if not self.effects[effect_name].is_active:
55            raise TypeError("Effect is depleted.")55            raise TypeError("Effect is depleted.")
56        56        
57        if not self.is_itself:57        if not self.is_itself:
58            raise TypeError("Potion is now part of something bigger than itself.")58            raise TypeError("Potion is now part of something bigger than itself.")
59        59        
60        self.effects[effect_name].is_active = False60        self.effects[effect_name].is_active = False
6161
62        return self.effects[effect_name]62        return self.effects[effect_name]
6363
64    def __add__(self, other):64    def __add__(self, other):
65        """Combining two potions."""65        """Combining two potions."""
66        if not self.is_itself or not other.is_itself:66        if not self.is_itself or not other.is_itself:
67            raise TypeError("Potion is now part of something bigger than itself.")67            raise TypeError("Potion is now part of something bigger than itself.")
68        68        
69        if self.is_used:69        if self.is_used:
70            raise TypeError("Potion is depleted.")70            raise TypeError("Potion is depleted.")
71        71        
72        effects = {}72        effects = {}
73        intensities = {}73        intensities = {}
7474
75        for effect_name, effect in self.effects.items():75        for effect_name, effect in self.effects.items():
76            effects[effect_name] = effect.func76            effects[effect_name] = effect.func
77            intensities[effect_name] = effect.intensity77            intensities[effect_name] = effect.intensity
78        78        
79        for effect_name, effect in other.effects.items():79        for effect_name, effect in other.effects.items():
80            if effect_name not in effects:80            if effect_name not in effects:
81                effects[effect_name] = effect.func81                effects[effect_name] = effect.func
82                intensities[effect_name] = effect.intensity82                intensities[effect_name] = effect.intensity
83            else:83            else:
84                intensities[effect_name] += effect.intensity84                intensities[effect_name] += effect.intensity
85    85    
86        self.is_itself = False86        self.is_itself = False
87        other.is_itself = False87        other.is_itself = False
88        return Potion(effects, max(self.duration, other.duration), intensities)88        return Potion(effects, max(self.duration, other.duration), intensities)
89    89    
90    def __mul__(self, number):90    def __mul__(self, number):
91        """Potentiation of two potions."""91        """Potentiation of two potions."""
92        if not self.is_itself:92        if not self.is_itself:
93            raise TypeError("Potion is now part of something bigger than itself.")93            raise TypeError("Potion is now part of something bigger than itself.")
94        94        
95        if self.is_used:95        if self.is_used:
96            raise TypeError("Potion is depleted.")96            raise TypeError("Potion is depleted.")
97        97        
98        effects = {}98        effects = {}
99        intensities = {}99        intensities = {}
100100
101        for effect_name, effect in self.effects.items():101        for effect_name, effect in self.effects.items():
102            intensities[effect_name] = effect.intensity * number102            intensities[effect_name] = effect.intensity * number
103103
104            if intensities[effect_name] % 1 <= 0.5:104            if intensities[effect_name] % 1 <= 0.5:
105                intensities[effect_name] = math.floor(intensities[effect_name])105                intensities[effect_name] = math.floor(intensities[effect_name])
106            else:106            else:
107                intensities[effect_name] = math.ceil(intensities[effect_name])107                intensities[effect_name] = math.ceil(intensities[effect_name])
108108
109            effects[effect_name] = effect.func109            effects[effect_name] = effect.func
110110
111        self.is_itself = False111        self.is_itself = False
112        return Potion(effects, self.duration, intensities)112        return Potion(effects, self.duration, intensities)
113    113    
114    def __sub__(self, other):114    def __sub__(self, other):
115        """Purification of two potions."""115        """Purification of two potions."""
116        if not self.is_itself or not other.is_itself:116        if not self.is_itself or not other.is_itself:
117            raise TypeError("Potion is now part of something bigger than itself.")117            raise TypeError("Potion is now part of something bigger than itself.")
118        118        
119        if self.is_used:119        if self.is_used:
120            raise TypeError("Potion is depleted.")120            raise TypeError("Potion is depleted.")
121        121        
122        for effect in other.effects:122        for effect in other.effects:
123            if effect not in self.effects:123            if effect not in self.effects:
124                raise TypeError("Effect is not in potion.")124                raise TypeError("Effect is not in potion.")
125        125        
126        effects = {}126        effects = {}
127        intensities = {}127        intensities = {}
128128
129        for effect_name, effect in self.effects.items():129        for effect_name, effect in self.effects.items():
130            intensities[effect_name] = effect.intensity130            intensities[effect_name] = effect.intensity
131            effects[effect_name] = effect.func131            effects[effect_name] = effect.func
132132
133        for effect in other.effects:133        for effect in other.effects:
134            intensities[effect] -= other.effects[effect].intensity134            intensities[effect] -= other.effects[effect].intensity
135135
136            if intensities[effect] <= 0:136            if intensities[effect] <= 0:
137                effects.pop(effect)137                effects.pop(effect)
138                intensities.pop(effect)138                intensities.pop(effect)
139139
140        self.is_itself = False140        self.is_itself = False
141        other.is_itself = False141        other.is_itself = False
142        return Potion(effects, self.duration, intensities)142        return Potion(effects, self.duration, intensities)
143    143    
144    def __truediv__(self, number:int):144    def __truediv__(self, number:int):
145        """Dividing two potions."""145        """Dividing two potions."""
146        if not self.is_itself:146        if not self.is_itself:
147            raise TypeError("Potion is now part of something bigger than itself.")147            raise TypeError("Potion is now part of something bigger than itself.")
148        148        
149        if self.is_used:149        if self.is_used:
150            raise TypeError("Potion is depleted.")150            raise TypeError("Potion is depleted.")
151        151        
152        effects = {}152        effects = {}
153        intensities = {}153        intensities = {}
154154
155        for effect_name, effect in self.effects.items():155        for effect_name, effect in self.effects.items():
156            intensities[effect_name] = int(effect.intensity) / number156            intensities[effect_name] = int(effect.intensity) / number
157            effects[effect_name] = effect.func157            effects[effect_name] = effect.func
158158
159            if intensities[effect_name] % 1 <= 0.5:159            if intensities[effect_name] % 1 <= 0.5:
160                intensities[effect_name] = math.floor(intensities[effect_name])160                intensities[effect_name] = math.floor(intensities[effect_name])
161            else:161            else:
162                intensities[effect_name] = math.ceil(intensities[effect_name])162                intensities[effect_name] = math.ceil(intensities[effect_name])
163        163        
164        self.is_itself = False164        self.is_itself = False
165        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))165        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))
166    166    
167    def __eq__(self, other):167    def __eq__(self, other):
n168        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])n168        for effect in self.effects:
169            if effect not in other.effects or self.effects[effect].intensity != other.effects[effect].intensity:
170                return False
171        for effect in other.effects:
172            if effect not in self.effects or self.effects[effect].intensity != other.effects[effect].intensity:
173                return False
174            
175        return True
169176
170    def __lt__(self, other):177    def __lt__(self, other):
n171        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])n178        for effect in self.effects:
179            if effect not in other.effects or self.effects[effect].intensity > other.effects[effect].intensity:
180                return False
181        return True
172182
173    def __gt__(self, other):183    def __gt__(self, other):
n174        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])n184        for effect in other.effects:
185            if effect not in self.effects or self.effects[effect].intensity < other.effects[effect].intensity:
186                return False
175187
176188
177class Target:189class Target:
178    def __init__(self, target):190    def __init__(self, target):
179        self.curr_target = target191        self.curr_target = target
180        self.original = copy.deepcopy(target.__dict__)192        self.original = copy.deepcopy(target.__dict__)
181193
182    @property194    @property
183    def original_state(self):195    def original_state(self):
184        return copy.deepcopy(self.original)196        return copy.deepcopy(self.original)
185197
186    def back_to_original(self):198    def back_to_original(self):
187        self.curr_target.__dict__ = self.original_state199        self.curr_target.__dict__ = self.original_state
188200
189    def __eq__(self, other):201    def __eq__(self, other):
190        if isinstance(other, Target):202        if isinstance(other, Target):
191            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__203            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__
192        return False204        return False
193205
194    def __hash__(self):206    def __hash__(self):
195        return hash(self.curr_target.__class__.__name__)207        return hash(self.curr_target.__class__.__name__)
196208
197class ГоспожатаПоХимия:209class ГоспожатаПоХимия:
198    def __init__(self):210    def __init__(self):
199        self.active_potions = {}211        self.active_potions = {}
200    212    
201    def apply(self, target_obj, potion):213    def apply(self, target_obj, potion):
202        target = Target(target_obj)214        target = Target(target_obj)
203        if self.active_potions.get(target) is None:215        if self.active_potions.get(target) is None:
204            self.active_potions[target] = []216            self.active_potions[target] = []
205217
206        potion.effect(target.curr_target)218        potion.effect(target.curr_target)
207        self.active_potions[target].append([potion.duration - 1, potion])219        self.active_potions[target].append([potion.duration - 1, potion])
208    220    
209    def tick(self):221    def tick(self):
210        for target in self.active_potions:222        for target in self.active_potions:
211            target.back_to_original()223            target.back_to_original()
212            to_remove = []224            to_remove = []
213            for curr in self.active_potions[target]:225            for curr in self.active_potions[target]:
214                remaining_time, potion = curr226                remaining_time, potion = curr
215                curr[0] -= 1227                curr[0] -= 1
216                if remaining_time <= 0:228                if remaining_time <= 0:
217                    to_remove.append(curr)229                    to_remove.append(curr)
218                else:230                else:
219                    potion.effect(target.curr_target, True)231                    potion.effect(target.curr_target, True)
220            for curr in to_remove:232            for curr in to_remove:
221                self.active_potions[target].remove(curr)233                self.active_potions[target].remove(curr)
tt234 
235                
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
nn2import math
23
3class Effect:4class Effect:
4    def __init__(self, name, func, intensity=1):5    def __init__(self, name, func, intensity=1):
5        self.name = name6        self.name = name
6        self.func = func7        self.func = func
7        self.is_used = False8        self.is_used = False
8        self.intensity = intensity9        self.intensity = intensity
nn10        self.is_active = True
911
10    @property12    @property
11    def molecular_mass(self):13    def molecular_mass(self):
12        return sum([ord(letter) for letter in self.name])14        return sum([ord(letter) for letter in self.name])
n13 n15    
14    def __call__(self, target, is_continuing=False):16    def __call__(self, target, is_continuing=False):
15        if not self.is_used or is_continuing:17        if not self.is_used or is_continuing:
16            for _ in range(self.intensity):18            for _ in range(self.intensity):
17                self.func(target)19                self.func(target)
nn20            self.is_used = True
18        else:21        else:
19            raise TypeError("Effect is depleted.")22            raise TypeError("Effect is depleted.")
n20        self.is_used = Truen
21        23        
2224
23class Potion:25class Potion:
24    def __init__(self, effects, duration=2, intensities=None):26    def __init__(self, effects, duration=2, intensities=None):
25        self.effects = {}27        self.effects = {}
26        self.is_itself = True28        self.is_itself = True
nn29        self.is_used = False
2730
28        for effect_name in effects:31        for effect_name in effects:
29            effect_func = effects[effect_name]32            effect_func = effects[effect_name]
30            effects[effect_name].is_called = False33            effects[effect_name].is_called = False
3134
32            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])35            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3336
34        self.duration = duration37        self.duration = duration
3538
36    def effect(self, target, is_continuing=False):39    def effect(self, target, is_continuing=False):
n37        if not is_continuing or not self.is_itself:n40        if not is_continuing and not self.is_itself:
38            raise TypeError("Potion is now part of something bigger than itself.")41            raise TypeError("Potion is now part of something bigger than itself.")
n39        n42        if self.is_used and not is_continuing:
43            raise TypeError("Potion is depleted.")
44        self.is_used = True
40        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass))45        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass, reverse=True))
4146
42        for effect in self.effects.values():47        for effect in self.effects.values():
43            effect(target, True)48            effect(target, True)
44        49        
45    def __getattr__(self, effect_name):50    def __getattr__(self, effect_name):
46        if(effect_name not in self.effects):51        if(effect_name not in self.effects):
47            raise TypeError("Effect is not in potion.")52            raise TypeError("Effect is not in potion.")
48        53        
n49        self.is_itself = Falsen54        if not self.effects[effect_name].is_active:
55            raise TypeError("Effect is depleted.")
56        
57        if not self.is_itself:
58            raise TypeError("Potion is now part of something bigger than itself.")
59        
60        self.effects[effect_name].is_active = False
61 
50        return self.effects[effect_name]62        return self.effects[effect_name]
5163
52    def __add__(self, other):64    def __add__(self, other):
53        """Combining two potions."""65        """Combining two potions."""
n54 n66        if not self.is_itself or not other.is_itself:
67            raise TypeError("Potion is now part of something bigger than itself.")
68        
69        if self.is_used:
70            raise TypeError("Potion is depleted.")
71        
55        effects = {}72        effects = {}
56        intensities = {}73        intensities = {}
5774
58        for effect_name, effect in self.effects.items():75        for effect_name, effect in self.effects.items():
n59            effects[effect_name] = copy.deepcopy(effect)n76            effects[effect_name] = effect.func
60            intensities[effect_name] = 177            intensities[effect_name] = effect.intensity
61        78        
62        for effect_name, effect in other.effects.items():79        for effect_name, effect in other.effects.items():
63            if effect_name not in effects:80            if effect_name not in effects:
n64                effects[effect_name] = copy.deepcopy(effectn81                effects[effect_name] = effect.func
65                intensities[effect_name] = 182                intensities[effect_name] = effect.intensity
66            else:83            else:
67                intensities[effect_name] += effect.intensity84                intensities[effect_name] += effect.intensity
68    85    
69        self.is_itself = False86        self.is_itself = False
nn87        other.is_itself = False
70        return Potion(effects, self.duration + other.duration, intensities)88        return Potion(effects, max(self.duration, other.duration), intensities)
71    89    
n72    #Потенцииране и Разрежданеn
73    def __mul__(self, number):90    def __mul__(self, number):
74        """Potentiation of two potions."""91        """Potentiation of two potions."""
n75 n92        if not self.is_itself:
93            raise TypeError("Potion is now part of something bigger than itself.")
94        
95        if self.is_used:
96            raise TypeError("Potion is depleted.")
97        
76        effects = {}98        effects = {}
77        intensities = {}99        intensities = {}
78100
79        for effect_name, effect in self.effects.items():101        for effect_name, effect in self.effects.items():
n80            intensities[effect_name] = round(effect.intensity * number)n102            intensities[effect_name] = effect.intensity * number
103 
104            if intensities[effect_name] % 1 <= 0.5:
105                intensities[effect_name] = math.floor(intensities[effect_name])
106            else:
107                intensities[effect_name] = math.ceil(intensities[effect_name])
108 
81            effects[effect_name] = effect.func109            effects[effect_name] = effect.func
n82        n110 
111        self.is_itself = False
83        return Potion(effects, self.duration, intensities)112        return Potion(effects, self.duration, intensities)
84    113    
85    def __sub__(self, other):114    def __sub__(self, other):
86        """Purification of two potions."""115        """Purification of two potions."""
n87 n116        if not self.is_itself or not other.is_itself:
117            raise TypeError("Potion is now part of something bigger than itself.")
118        
119        if self.is_used:
120            raise TypeError("Potion is depleted.")
121        
88        for effect in other.effects:122        for effect in other.effects:
89            if effect not in self.effects:123            if effect not in self.effects:
90                raise TypeError("Effect is not in potion.")124                raise TypeError("Effect is not in potion.")
91        125        
nn126        effects = {}
127        intensities = {}
128 
129        for effect_name, effect in self.effects.items():
130            intensities[effect_name] = effect.intensity
131            effects[effect_name] = effect.func
132 
92        for effect in other.effects:133        for effect in other.effects:
n93            self.effects[effect].intensity -= other.effects[effect].intensityn134            intensities[effect] -= other.effects[effect].intensity
94            self.effects.pop(effect) if self.effects[effect].intensity < 0 else None
95135
nn136            if intensities[effect] <= 0:
137                effects.pop(effect)
138                intensities.pop(effect)
139 
140        self.is_itself = False
96        self.is_itself = False141        other.is_itself = False
97        return self142        return Potion(effects, self.duration, intensities)
98    143    
99    def __truediv__(self, number:int):144    def __truediv__(self, number:int):
100        """Dividing two potions."""145        """Dividing two potions."""
n101 n146        if not self.is_itself:
147            raise TypeError("Potion is now part of something bigger than itself.")
148        
149        if self.is_used:
150            raise TypeError("Potion is depleted.")
151        
102        effects = {}152        effects = {}
103        intensities = {}153        intensities = {}
104154
105        for effect_name, effect in self.effects.items():155        for effect_name, effect in self.effects.items():
n106            intensities[effect_name] = round(int(effect.intensity) / number)n156            intensities[effect_name] = int(effect.intensity) / number
107            effects[effect_name] = effect.func157            effects[effect_name] = effect.func
n108        n
109        potion = Potion(effects, self.duration, intensities)
110158
n111        return tuple(potion for _ in range(number))n159            if intensities[effect_name] % 1 <= 0.5:
160                intensities[effect_name] = math.floor(intensities[effect_name])
161            else:
162                intensities[effect_name] = math.ceil(intensities[effect_name])
163        
164        self.is_itself = False
165        return tuple(Potion(effects, self.duration, intensities) for _ in range(number))
112    166    
113    def __eq__(self, other):167    def __eq__(self, other):
114        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])168        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])
115169
116    def __lt__(self, other):170    def __lt__(self, other):
117        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])171        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])
118172
119    def __gt__(self, other):173    def __gt__(self, other):
120        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])174        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])
121175
122176
123class Target:177class Target:
124    def __init__(self, target):178    def __init__(self, target):
125        self.curr_target = target179        self.curr_target = target
126        self.original = copy.deepcopy(target.__dict__)180        self.original = copy.deepcopy(target.__dict__)
127181
128    @property182    @property
129    def original_state(self):183    def original_state(self):
130        return copy.deepcopy(self.original)184        return copy.deepcopy(self.original)
131185
132    def back_to_original(self):186    def back_to_original(self):
133        self.curr_target.__dict__ = self.original_state187        self.curr_target.__dict__ = self.original_state
134188
nn189    def __eq__(self, other):
190        if isinstance(other, Target):
191            return self.curr_target.__class__.__name__ == other.curr_target.__class__.__name__
192        return False
193 
194    def __hash__(self):
195        return hash(self.curr_target.__class__.__name__)
135196
136class ГоспожатаПоХимия:197class ГоспожатаПоХимия:
137    def __init__(self):198    def __init__(self):
138        self.active_potions = {}199        self.active_potions = {}
139    200    
140    def apply(self, target_obj, potion):201    def apply(self, target_obj, potion):
141        target = Target(target_obj)202        target = Target(target_obj)
142        if self.active_potions.get(target) is None:203        if self.active_potions.get(target) is None:
143            self.active_potions[target] = []204            self.active_potions[target] = []
144205
n145        potion.effect(target.curr_target, True)n206        potion.effect(target.curr_target)
146        self.active_potions[target].append([potion.duration - 1, potion])207        self.active_potions[target].append([potion.duration - 1, potion])
147    208    
148    def tick(self):209    def tick(self):
149        for target in self.active_potions:210        for target in self.active_potions:
150            target.back_to_original()211            target.back_to_original()
nn212            to_remove = []
151            for curr in self.active_potions[target]:213            for curr in self.active_potions[target]:
152                remaining_time, potion = curr214                remaining_time, potion = curr
153                curr[0] -= 1215                curr[0] -= 1
154                if remaining_time <= 0:216                if remaining_time <= 0:
n155                    self.active_potions[target].remove(curr) n217                    to_remove.append(curr)
156                else:218                else:
157                    potion.effect(target.curr_target, True)219                    potion.effect(target.curr_target, True)
tt220            for curr in to_remove:
221                self.active_potions[target].remove(curr)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
22
3class Effect:3class Effect:
4    def __init__(self, name, func, intensity=1):4    def __init__(self, name, func, intensity=1):
5        self.name = name5        self.name = name
6        self.func = func6        self.func = func
7        self.is_used = False7        self.is_used = False
8        self.intensity = intensity8        self.intensity = intensity
99
10    @property10    @property
11    def molecular_mass(self):11    def molecular_mass(self):
12        return sum([ord(letter) for letter in self.name])12        return sum([ord(letter) for letter in self.name])
1313
14    def __call__(self, target, is_continuing=False):14    def __call__(self, target, is_continuing=False):
15        if not self.is_used or is_continuing:15        if not self.is_used or is_continuing:
16            for _ in range(self.intensity):16            for _ in range(self.intensity):
17                self.func(target)17                self.func(target)
18        else:18        else:
19            raise TypeError("Effect is depleted.")19            raise TypeError("Effect is depleted.")
20        self.is_used = True20        self.is_used = True
21        21        
2222
23class Potion:23class Potion:
24    def __init__(self, effects, duration=2, intensities=None):24    def __init__(self, effects, duration=2, intensities=None):
25        self.effects = {}25        self.effects = {}
26        self.is_itself = True26        self.is_itself = True
2727
28        for effect_name in effects:28        for effect_name in effects:
29            effect_func = effects[effect_name]29            effect_func = effects[effect_name]
30            effects[effect_name].is_called = False30            effects[effect_name].is_called = False
3131
32            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])32            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3333
34        self.duration = duration34        self.duration = duration
3535
36    def effect(self, target, is_continuing=False):36    def effect(self, target, is_continuing=False):
37        if not is_continuing or not self.is_itself:37        if not is_continuing or not self.is_itself:
38            raise TypeError("Potion is now part of something bigger than itself.")38            raise TypeError("Potion is now part of something bigger than itself.")
39        39        
40        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass))40        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass))
4141
42        for effect in self.effects.values():42        for effect in self.effects.values():
43            effect(target, True)43            effect(target, True)
44        44        
45    def __getattr__(self, effect_name):45    def __getattr__(self, effect_name):
46        if(effect_name not in self.effects):46        if(effect_name not in self.effects):
t47            raise TypeError ("Effect is not in potion.")t47            raise TypeError("Effect is not in potion.")
48        48        
49        self.is_itself = False49        self.is_itself = False
50        return self.effects[effect_name]50        return self.effects[effect_name]
5151
52    def __add__(self, other):52    def __add__(self, other):
53        """Combining two potions."""53        """Combining two potions."""
5454
55        effects = {}55        effects = {}
56        intensities = {}56        intensities = {}
5757
58        for effect_name, effect in self.effects.items():58        for effect_name, effect in self.effects.items():
59            effects[effect_name] = copy.deepcopy(effect)59            effects[effect_name] = copy.deepcopy(effect)
60            intensities[effect_name] = 160            intensities[effect_name] = 1
61        61        
62        for effect_name, effect in other.effects.items():62        for effect_name, effect in other.effects.items():
63            if effect_name not in effects:63            if effect_name not in effects:
64                effects[effect_name] = copy.deepcopy(effect) 64                effects[effect_name] = copy.deepcopy(effect) 
65                intensities[effect_name] = 165                intensities[effect_name] = 1
66            else:66            else:
67                intensities[effect_name] += effect.intensity67                intensities[effect_name] += effect.intensity
68    68    
69        self.is_itself = False69        self.is_itself = False
70        return Potion(effects, self.duration + other.duration, intensities)70        return Potion(effects, self.duration + other.duration, intensities)
71    71    
72    #Потенцииране и Разреждане72    #Потенцииране и Разреждане
73    def __mul__(self, number):73    def __mul__(self, number):
74        """Potentiation of two potions."""74        """Potentiation of two potions."""
7575
76        effects = {}76        effects = {}
77        intensities = {}77        intensities = {}
7878
79        for effect_name, effect in self.effects.items():79        for effect_name, effect in self.effects.items():
80            intensities[effect_name] = round(effect.intensity * number)80            intensities[effect_name] = round(effect.intensity * number)
81            effects[effect_name] = effect.func81            effects[effect_name] = effect.func
82        82        
83        return Potion(effects, self.duration, intensities)83        return Potion(effects, self.duration, intensities)
84    84    
85    def __sub__(self, other):85    def __sub__(self, other):
86        """Purification of two potions."""86        """Purification of two potions."""
8787
88        for effect in other.effects:88        for effect in other.effects:
89            if effect not in self.effects:89            if effect not in self.effects:
90                raise TypeError("Effect is not in potion.")90                raise TypeError("Effect is not in potion.")
91        91        
92        for effect in other.effects:92        for effect in other.effects:
93            self.effects[effect].intensity -= other.effects[effect].intensity93            self.effects[effect].intensity -= other.effects[effect].intensity
94            self.effects.pop(effect) if self.effects[effect].intensity < 0 else None94            self.effects.pop(effect) if self.effects[effect].intensity < 0 else None
9595
96        self.is_itself = False96        self.is_itself = False
97        return self97        return self
98    98    
99    def __truediv__(self, number:int):99    def __truediv__(self, number:int):
100        """Dividing two potions."""100        """Dividing two potions."""
101101
102        effects = {}102        effects = {}
103        intensities = {}103        intensities = {}
104104
105        for effect_name, effect in self.effects.items():105        for effect_name, effect in self.effects.items():
106            intensities[effect_name] = round(int(effect.intensity) / number)106            intensities[effect_name] = round(int(effect.intensity) / number)
107            effects[effect_name] = effect.func107            effects[effect_name] = effect.func
108        108        
109        potion = Potion(effects, self.duration, intensities)109        potion = Potion(effects, self.duration, intensities)
110110
111        return tuple(potion for _ in range(number))111        return tuple(potion for _ in range(number))
112    112    
113    def __eq__(self, other):113    def __eq__(self, other):
114        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])114        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])
115115
116    def __lt__(self, other):116    def __lt__(self, other):
117        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])117        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])
118118
119    def __gt__(self, other):119    def __gt__(self, other):
120        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])120        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])
121121
122122
123class Target:123class Target:
124    def __init__(self, target):124    def __init__(self, target):
125        self.curr_target = target125        self.curr_target = target
126        self.original = copy.deepcopy(target.__dict__)126        self.original = copy.deepcopy(target.__dict__)
127127
128    @property128    @property
129    def original_state(self):129    def original_state(self):
130        return copy.deepcopy(self.original)130        return copy.deepcopy(self.original)
131131
132    def back_to_original(self):132    def back_to_original(self):
133        self.curr_target.__dict__ = self.original_state133        self.curr_target.__dict__ = self.original_state
134134
135135
136class ГоспожатаПоХимия:136class ГоспожатаПоХимия:
137    def __init__(self):137    def __init__(self):
138        self.active_potions = {}138        self.active_potions = {}
139    139    
140    def apply(self, target_obj, potion):140    def apply(self, target_obj, potion):
141        target = Target(target_obj)141        target = Target(target_obj)
142        if self.active_potions.get(target) is None:142        if self.active_potions.get(target) is None:
143            self.active_potions[target] = []143            self.active_potions[target] = []
144144
145        potion.effect(target.curr_target, True)145        potion.effect(target.curr_target, True)
146        self.active_potions[target].append([potion.duration - 1, potion])146        self.active_potions[target].append([potion.duration - 1, potion])
147    147    
148    def tick(self):148    def tick(self):
149        for target in self.active_potions:149        for target in self.active_potions:
150            target.back_to_original()150            target.back_to_original()
151            for curr in self.active_potions[target]:151            for curr in self.active_potions[target]:
152                remaining_time, potion = curr152                remaining_time, potion = curr
153                curr[0] -= 1153                curr[0] -= 1
154                if remaining_time <= 0:154                if remaining_time <= 0:
155                    self.active_potions[target].remove(curr) 155                    self.active_potions[target].remove(curr) 
156                else:156                else:
157                    potion.effect(target.curr_target, True)157                    potion.effect(target.curr_target, True)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
22
3class Effect:3class Effect:
4    def __init__(self, name, func, intensity=1):4    def __init__(self, name, func, intensity=1):
5        self.name = name5        self.name = name
6        self.func = func6        self.func = func
7        self.is_used = False7        self.is_used = False
8        self.intensity = intensity8        self.intensity = intensity
99
10    @property10    @property
11    def molecular_mass(self):11    def molecular_mass(self):
12        return sum([ord(letter) for letter in self.name])12        return sum([ord(letter) for letter in self.name])
1313
n14    def __call__(self, target, is_continuing = False):n14    def __call__(self, target, is_continuing=False):
15        if not self.is_used or is_continuing:15        if not self.is_used or is_continuing:
16            for _ in range(self.intensity):16            for _ in range(self.intensity):
17                self.func(target)17                self.func(target)
18        else:18        else:
19            raise TypeError("Effect is depleted.")19            raise TypeError("Effect is depleted.")
20        self.is_used = True20        self.is_used = True
21        21        
2222
23class Potion:23class Potion:
n24    def __init__(self, effects, duration = 2, intensities = None):n24    def __init__(self, effects, duration=2, intensities=None):
25        self.effects = {}25        self.effects = {}
26        self.is_itself = True26        self.is_itself = True
2727
n28        for effect_name in effects.keys():n28        for effect_name in effects:
29            effect_func = effects[effect_name]29            effect_func = effects[effect_name]
30            effects[effect_name].is_called = False30            effects[effect_name].is_called = False
3131
32            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])32            self.effects[effect_name] = Effect(effect_name, effect_func, 1 if intensities is None else intensities[effect_name])
3333
34        self.duration = duration34        self.duration = duration
3535
n36    def effect(self, target, is_continuing = False):n36    def effect(self, target, is_continuing=False):
37        if(not is_continuing or not self.is_itself):37        if not is_continuing or not self.is_itself:
38            raise TypeError("Potion is now part of something bigger than itself.")38            raise TypeError("Potion is now part of something bigger than itself.")
39        39        
n40        dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass))n40        self.effects = dict(sorted(self.effects.items(), key=lambda x: x[1].molecular_mass))
4141
42        for effect in self.effects.values():42        for effect in self.effects.values():
43            effect(target, True)43            effect(target, True)
44        44        
45    def __getattr__(self, effect_name):45    def __getattr__(self, effect_name):
46        if(effect_name not in self.effects):46        if(effect_name not in self.effects):
47            raise TypeError ("Effect is not in potion.")47            raise TypeError ("Effect is not in potion.")
48        48        
49        self.is_itself = False49        self.is_itself = False
50        return self.effects[effect_name]50        return self.effects[effect_name]
5151
n52    #Комбиниранеn
53    def __add__(self, other):52    def __add__(self, other):
nn53        """Combining two potions."""
54 
54        effects = {}55        effects = {}
55        intensities = {}56        intensities = {}
5657
57        for effect_name, effect in self.effects.items():58        for effect_name, effect in self.effects.items():
58            effects[effect_name] = copy.deepcopy(effect)59            effects[effect_name] = copy.deepcopy(effect)
59            intensities[effect_name] = 160            intensities[effect_name] = 1
60        61        
61        for effect_name, effect in other.effects.items():62        for effect_name, effect in other.effects.items():
62            if effect_name not in effects:63            if effect_name not in effects:
63                effects[effect_name] = copy.deepcopy(effect) 64                effects[effect_name] = copy.deepcopy(effect) 
64                intensities[effect_name] = 165                intensities[effect_name] = 1
65            else:66            else:
66                intensities[effect_name] += effect.intensity67                intensities[effect_name] += effect.intensity
67    68    
68        self.is_itself = False69        self.is_itself = False
69        return Potion(effects, self.duration + other.duration, intensities)70        return Potion(effects, self.duration + other.duration, intensities)
70    71    
71    #Потенцииране и Разреждане72    #Потенцииране и Разреждане
72    def __mul__(self, number):73    def __mul__(self, number):
nn74        """Potentiation of two potions."""
75 
73        effects = {}76        effects = {}
74        intensities = {}77        intensities = {}
7578
76        for effect_name, effect in self.effects.items():79        for effect_name, effect in self.effects.items():
77            intensities[effect_name] = round(effect.intensity * number)80            intensities[effect_name] = round(effect.intensity * number)
78            effects[effect_name] = effect.func81            effects[effect_name] = effect.func
79        82        
80        return Potion(effects, self.duration, intensities)83        return Potion(effects, self.duration, intensities)
81    84    
n82    #Пречистванеn
83    def __sub__(self, other):85    def __sub__(self, other):
nn86        """Purification of two potions."""
87 
84        for effect in other.effects:88        for effect in other.effects:
85            if effect not in self.effects:89            if effect not in self.effects:
n86                raise TypeError ("Effect is not in potion.")n90                raise TypeError("Effect is not in potion.")
87        91        
88        for effect in other.effects:92        for effect in other.effects:
89            self.effects[effect].intensity -= other.effects[effect].intensity93            self.effects[effect].intensity -= other.effects[effect].intensity
90            self.effects.pop(effect) if self.effects[effect].intensity < 0 else None94            self.effects.pop(effect) if self.effects[effect].intensity < 0 else None
9195
92        self.is_itself = False96        self.is_itself = False
93        return self97        return self
94    98    
n95    #Разделянеn
96    def __truediv__(self, number:int):99    def __truediv__(self, number:int):
nn100        """Dividing two potions."""
101 
97        effects = {}102        effects = {}
98        intensities = {}103        intensities = {}
99104
100        for effect_name, effect in self.effects.items():105        for effect_name, effect in self.effects.items():
101            intensities[effect_name] = round(int(effect.intensity) / number)106            intensities[effect_name] = round(int(effect.intensity) / number)
102            effects[effect_name] = effect.func107            effects[effect_name] = effect.func
103        108        
104        potion = Potion(effects, self.duration, intensities)109        potion = Potion(effects, self.duration, intensities)
105110
n106        return ([potion for _ in range(number)])n111        return tuple(potion for _ in range(number))
107    112    
108    def __eq__(self, other):113    def __eq__(self, other):
109        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])114        return sum([effect.intensity for effect in self.effects.values()]) == sum([effect.intensity for effect in other.effects.values()])
110115
111    def __lt__(self, other):116    def __lt__(self, other):
112        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])117        return sum([effect.intensity for effect in self.effects.values()]) < sum([effect.intensity for effect in other.effects.values()])
113118
114    def __gt__(self, other):119    def __gt__(self, other):
115        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])120        return sum([effect.intensity for effect in self.effects.values()]) > sum([effect.intensity for effect in other.effects.values()])
116121
nn122 
117class Target:123class Target:
n118    id_counter = 0n
119    originals = {}
120 
121    def __init__(self, target):124    def __init__(self, target):
n122        self.id = Target.id_countern
123        self.curr_target = target125        self.curr_target = target
n124        if Target.originals.get(self.id) is None:n
125            Target.originals[self.id] = copy.deepcopy(target.__dict__)126        self.original = copy.deepcopy(target.__dict__)
126        Target.id_counter += 1
127127
128    @property128    @property
129    def original_state(self):129    def original_state(self):
n130        return copy.deepcopy(Target.originals[self.id])n130        return copy.deepcopy(self.original)
131131
132    def back_to_original(self):132    def back_to_original(self):
133        self.curr_target.__dict__ = self.original_state133        self.curr_target.__dict__ = self.original_state
tt134 
134135
135class ГоспожатаПоХимия:136class ГоспожатаПоХимия:
136    def __init__(self):137    def __init__(self):
137        self.active_potions = {}138        self.active_potions = {}
138    139    
139    def apply(self, target_obj, potion):140    def apply(self, target_obj, potion):
140        target = Target(target_obj)141        target = Target(target_obj)
141        if self.active_potions.get(target) is None:142        if self.active_potions.get(target) is None:
142            self.active_potions[target] = []143            self.active_potions[target] = []
143144
144        potion.effect(target.curr_target, True)145        potion.effect(target.curr_target, True)
145        self.active_potions[target].append([potion.duration - 1, potion])146        self.active_potions[target].append([potion.duration - 1, potion])
146    147    
147    def tick(self):148    def tick(self):
148        for target in self.active_potions:149        for target in self.active_potions:
149            target.back_to_original()150            target.back_to_original()
150            for curr in self.active_potions[target]:151            for curr in self.active_potions[target]:
151                remaining_time, potion = curr152                remaining_time, potion = curr
152                curr[0] -= 1153                curr[0] -= 1
153                if remaining_time <= 0:154                if remaining_time <= 0:
154                    self.active_potions[target].remove(curr) 155                    self.active_potions[target].remove(curr) 
155                else:156                else:
156                    potion.effect(target.curr_target, True)157                    potion.effect(target.curr_target, True)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op