def execute_miss(self, battle, user_id, target_id, message=None): message = message or 'But it missed!' if 'miss_penalty' in self.extra: user = battle.get_pokemon(user_id) (damage, _) = self.compute_damage(battle, user, battle.get_pokemon(target_id)) damage = int(damage*self.extra['miss_penalty']) return (Callbacks.do_damage(battle, user_id, damage, message, special=' instead'), False) return (Callbacks.chain({'menu': [message or 'But it missed!']}), False)
def post_move_hook(self, battle, user_id, outcome, callback=None): if 'post_move_hook' in self.extra: hook = self.extra.get('post_move_hook') if hook['type'] == 'buff': if uniform(0, 1) < hook['rate']: (stat, stages) = (hook['stat'], hook['stages']) return Callbacks.do_buff(battle, user_id, stat, stages, callback=callback) elif hook['type'] == 'recoil': assert('damage' in outcome), 'Unexpected outcome %s for %s' % (outcome, self.name) damage = max(int(hook['ratio']*outcome['damage']), 1) message = "%s's hit by the recoil!" % (battle.get_name(user_id),) return Callbacks.do_damage(battle, user_id, damage, message, callback=callback) else: assert(False), 'Unexpected hook: %s' % (hook,) return callback
def get_secondary_effect(self, battle, target_id, target, callback=None): total_mass = 1.0 stat_rate = self.extra.get('stat_rate') if stat_rate: if uniform(0, total_mass) < stat_rate: (stat, stages) = (self.extra['stat'], self.extra['stages']) assert(stages < 0), 'Unexpect stat buff: %s' % (self.name,) return Callbacks.do_buff(battle, target_id, stat, stages, callback=callback) total_mass -= stat_rate for status in Status.OPTIONS: rate = self.extra.get(status + '_rate') if rate: if uniform(0, total_mass) < rate: return Callbacks.set_status(battle, target_id, status, self, callback=callback) total_mass -= rate return callback
def execute_status(self, battle, user_id, target_id): status = self.extra['status'] assert(status in Status.OPTIONS), 'Unexpected status: %s' % (status,) user = battle.get_pokemon(user_id) target = battle.get_pokemon(target_id) if self.hits(battle, user, target): return (Callbacks.set_status(battle, target_id, status, self, noisy_failure=True), True) return self.execute_miss(battle, user_id, target_id)
def execute_buff(self, battle, user_id, target_id): (stat, stages) = (self.extra['stat'], self.extra['stages']) user = battle.get_pokemon(user_id) if self.extra.get('target') == 'self': target_id = user_id target = user else: target = battle.get_pokemon(target_id) if not self.hits(battle, user, target): return self.execute_miss(battle, user_id, target_id) callback = self.get_secondary_effect(battle, target_id, target) return (Callbacks.do_buff(battle, target_id, stat, stages, callback=callback), True)
def execute_default(self, battle, user_id, target_id, cur_hit=0, num_hits=0): ''' An implementation of a damaging, single-target move. ''' user = battle.get_pokemon(user_id) target = battle.get_pokemon(target_id) if self.get_type_advantage(target): if num_hits or self.hits(battle, user, target): (damage, message) = self.compute_damage(battle, user, target, cur_hit) callback = None if num_hits: (callback, _) = self.execute_multihit(battle, user_id, target_id, cur_hit, num_hits) callback = self.get_secondary_effect(battle, target_id, target, callback=callback) return (Callbacks.do_damage(battle, target_id, damage, message, callback=callback), { 'damage': min(damage, target.cur_hp), }) else: return self.execute_miss(battle, user_id, target_id) else: message = "It didn't affect %s!" % (battle.get_name(target_id, lower=True),) return self.execute_miss(battle, user_id, target_id, message=message)
def execute_multihit(self, battle, user_id, target_id, cur_hit=0, num_hits=0): ''' A move that, if it hits, strikes the target 2-5 times. ''' if not num_hits: user = battle.get_pokemon(user_id) target = battle.get_pokemon(target_id) if self.get_type_advantage(target): if self.hits(battle, user, target): if 'num_hits' in self.extra: num_hits = self.extra['num_hits'] else: hits_map = {0: 2, 1: 2, 2: 2, 3: 3, 4: 3, 5: 3, 6: 4, 7: 5} num_hits = hits_map[randrange(8)] else: return self.execute_miss(battle, user_id, target_id) else: message = "It didn't affect %s!" % (battle.get_name(target_id, lower=True),) return self.execute_miss(battle, user_id, target_id, message=message) if cur_hit < num_hits: return self.execute_default(battle, user_id, target_id, cur_hit + 1, num_hits) return (Callbacks.chain({'menu': ['Hit %s times!' % (num_hits,)]}), True)
def execute_failure(self, battle, user_id, target_id): return (Callbacks.chain({'menu': ['Nothing happened...']}), False)