def on_before_move(self, user, move, battle): assert user.status is Status.FRZ if random.randrange(5) == 0 or move.thaw_user: user.cure_status() else: if __debug__: log.i("%s is frozen!", user) return FAIL
def on_try_hit(self, user, move, target, battle): if (not self.suppressed and move.category is not MoveCategory.STATUS and move.type is Type.FIRE ): if __debug__: log.i('But the fire move fizzled out!') return FAIL
def on_modify_base_power(self, user, move, target, battle, base_power): if (user.status in (Status.PSN, Status.TOX) and move.category is MoveCategory.PHYSICAL ): if __debug__: log.i("%s's power was boosted by ToxicBoost!", move) return base_power * 1.5 return base_power
def on_modify_effectiveness(self, user, move, target, effectiveness): if not self.suppressed: if Type.FLYING in target.types and type_effectiveness(move.type, Type.FLYING) == 2: if __debug__: log.i("DeltaStream suppressed %s's %s type move", user, move.type) return effectiveness * 0.5 return effectiveness
def set_status(self, pokemon, status, setter): """ Set `status` (enums.Status) on `pokemon`. Fails if the pokemon is already statused, Sleep Clause activates, or if an effect or immunity prevents it. `setter` should be the pokemon causing the status (usually the foe). `setter` == `pokemon` in the case of rest, toxicorb, etc., or None in the case of toxicspikes, etc. """ assert not pokemon.is_fainted() assert setter is None or isinstance(setter, BattlePokemon) if status is Status.SLP and any(teammate.status is Status.SLP and not teammate.is_resting for teammate in pokemon.side.team if teammate is not pokemon): if __debug__: log.i('Sleep Clause Mod!') return FAIL if pokemon.status is not None or pokemon.is_immune_to(status): if __debug__: log.i('Failed to set status %s: ' % status + ('%%s is already statused (%s)' % pokemon.status if pokemon.status is not None else '%s is immune') % pokemon) return FAIL for effector in (pokemon, pokemon.side, self.battlefield): if effector.activate_effect('on_set_status', status, pokemon, setter, self, failfast=True) is FAIL: return FAIL pokemon.status = status pokemon.set_effect(STATUS_EFFECTS[status](pokemon)) pokemon.activate_effect('on_after_set_status', status, pokemon, setter, self)
def check_accuracy(self, user, move, target): """ Return FAIL if the move misses. An accuracy value of None means to skip the accuracy check, i.e. it always hits. """ accuracy = move.accuracy accuracy = user.accumulate_effect('on_accuracy', user, move, target, self, accuracy) accuracy = target.accumulate_effect('on_foe_accuracy', user, move, target, self, accuracy) if accuracy is None: return boost_factor = (1.0, 4.0/3.0, 5.0/3.0, 2.0, 7.0/3.0, 8.0/3.0, 3.0) if not move.ignore_accuracy_boosts: acc_boost = user.boosts['acc'] if acc_boost > 0: accuracy *= boost_factor[acc_boost] elif acc_boost < 0: accuracy /= boost_factor[-acc_boost] if not move.ignore_evasion_boosts: evn_boost = target.boosts['evn'] if evn_boost > 0: accuracy /= boost_factor[evn_boost] elif evn_boost < 0: accuracy *= boost_factor[-evn_boost] if __debug__: log.d('Using accuracy of %s', accuracy) if random.randrange(100) >= int(accuracy): if __debug__: log.i('But it missed!') return FAIL
def set_effect(self, effect): if effect.source in self._effect_index: if __debug__: log.i('Tried to set effect %s but it is already on the field', effect) return FAIL self._effect_index[effect.source] = effect self._set_handlers(effect)
def reveal(self, pokemon): for i, foe in enumerate(self.team): if foe.name == UNREVEALED: self.team[i] = pokemon return # all 6 slots are filled; zoroark shenanigans can cause this log.i("All 6 slots on foe's side are full... attempting to resolve") for i in range(len(self.team)): # remove revealed zoroark if self.team[i].name == 'zoroark': self.team[i] = UnrevealedPokemon() else: # remove duplicate pokemon for j in range(i+1, len(self.team)): if self.team[j].base_species == self.team[i].base_species != UNREVEALED: self.team[j] = UnrevealedPokemon() # try again, if there's still no available slots then something else is wrong for i, foe in enumerate(self.team): if foe.name == UNREVEALED: self.team[i] = pokemon return raise AssertionError("Tried to reveal a 7th pokemon on a fully revealed foe's team?!" "\nTeam=\n%r\n\npokemon=\n%r" % (self, pokemon))
def on_foe_accuracy(self, foe, move, target, battle, accuracy): if accuracy is None: return accuracy if target.has_effect(Volatile.CONFUSE): if __debug__: log.i("%s's TangledFeet raised its evasion!", target) return accuracy * 0.5 return accuracy
def on_foe_accuracy(self, foe, move, target, battle, accuracy): if accuracy is None: return accuracy if move.category is MoveCategory.STATUS and accuracy is not None: if __debug__: log.i("%s's accuracy is reduced by WonderSkin", move) return accuracy * 0.5 return accuracy
def on_boost(self, pokemon, boosts, self_induced): if not self_induced: for stat, val in boosts.items(): if val < 0: boosts['spa'] += 2 if __debug__: log.i('Competitive boost! (from %s %s)', stat, val) return boosts
def on_after_move_damage(self, battle, pokemon, damage, move, foe): if (move.makes_contact and not foe.is_fainted() and random.randrange(10) < 3 ): if __debug__: log.i("%s was burned by %s's FlameBody", foe, pokemon) battle.set_status(foe, Status.BRN, pokemon)
def on_boost(self, pokemon, boosts, self_induced): if not self_induced: for stat, val in boosts.items(): if val < 0: boosts['atk'] += 2 if __debug__: log.i('Defiant boost! (from %s %s)', stat, val) return boosts
def on_try_hit(self, user, move, target, battle): if (not self.suppressed and move.category is not MoveCategory.STATUS and move.type is Type.WATER ): if __debug__: log.i('But the water move evaporated!') return FAIL
def on_boost(self, pokemon, boosts, self_induced): if not self_induced: for stat, val in boosts.items(): if val < 0: boosts[stat] = 0 if __debug__: log.i("%s's %s drop was blocked by ClearBody!", pokemon, stat) return boosts
def set_effect(self, effect): if effect.source in self._effect_index: if __debug__: log.i('Tried to set condition %s but it %s already has it', effect, self) return FAIL self._effect_index[effect.source] = effect self._set_handlers(effect)
def on_residual(self, pokemon, foe, battle): if pokemon.is_fainted() or foe is None: return if foe.status is Status.SLP: if __debug__: log.i("%s is hurt by %s's BadDreams", foe, pokemon) battle.damage(foe, foe.max_hp / 8.0, Cause.OTHER)
def on_residual(self, pokemon, foe, battle): if (pokemon.item is None and pokemon.last_berry_used is not None and (battle.battlefield.weather in (Weather.SUNNYDAY, Weather.DESOLATELAND) or random.randrange(2) == 0) ): if __debug__: log.i("%s harvested a %s!", pokemon, pokemon.last_berry_used) pokemon.set_item(pokemon.last_berry_used)
def on_start(self, pokemon, battle): foe = battle.get_foe(pokemon) if foe is not None: # foe stat calculation: boosted but not modified boosts = (Boosts(spa=1) if foe.calculate_stat('def') >= foe.calculate_stat('spd') else Boosts(atk=1)) if __debug__: log.i("%s is boosted by its Download!", pokemon) pokemon.apply_boosts(boosts, self_induced=True)
def on_modify_base_power(self, user, move, target, battle, base_power): if move.type is self.aura_type: if __debug__: log.i("%s boosted %s's power!", self.source, move) if battle.battlefield.has_effect(PseudoWeather.AURABREAK): if __debug__: log.i('Aura Break broke the aura!') return 0.75 * base_power return float(0x1547) / 0x1000 * base_power return base_power
def on_foe_try_hit(self, foe, move, target, battle): if (move.category is not MoveCategory.STATUS and battle.get_effectiveness(foe, move, target) <= 1 and move.type is not Type.NOTYPE and foe is not target ): if __debug__: log.i("WonderGuard makes %s immune to %s!", target, move) return FAIL
def on_after_set_status(self, status, pokemon, setter, battle): if (setter is not None and setter != pokemon and status not in (Status.FRZ, Status.SLP) and setter.hp > 0 ): if __debug__: log.i("%s's Synchronize activated!", pokemon) battle.set_status(setter, status, pokemon)
def on_damage(self, pokemon, cause, source, battle, damage): if (pokemon.hp == pokemon.max_hp and damage >= pokemon.hp and cause is Cause.MOVE ): if __debug__: log.i("%s held on with Sturdy!", pokemon) return pokemon.hp - 1 return damage
def on_after_move_damage(self, battle, pokemon, damage, move, foe): if (move.makes_contact and foe is not None and not foe.is_fainted() and random.randrange(10) < 3 ): if __debug__: log.i("%s's Static activated!", pokemon) battle.set_status(foe, Status.PAR, pokemon)
def on_before_move(self, user, move, battle): if not self.mate == battle.get_foe(user): user.remove_effect(Volatile.ATTRACT) return if random.randrange(2): if __debug__: log.i('%s was immobolized by Attract!', user) return FAIL
def __getitem__(self, index): if index in self: return dict.__getitem__(self, index) elif index[-3:].startswith('L') and index[:-3] in self: # strip off level if pokemon at that level is not found if __debug__: log.i('%s not found: stripping "%s"', index, index[-3:]) return dict.__getitem__(self, index[:-3]) else: dict.__getitem__(self, index) # raise KeyError
def get_instaswitches(self, sides): switch_queue = [] for i, side in enumerate(sides): if side is not None: if __debug__: log.i('No active pokemon on side %d; requesting switch' % i) event = InstaSwitchEvent(None, 0, self.get_switch_decision(side, forced=True)) insort(switch_queue, event) assert switch_queue return switch_queue
def on_after_foe_move_secondary(self, foe, move, target, battle): if (move.makes_contact and target.item is None and foe.item is not None ): item = foe.take_item() if item is not FAIL: if __debug__: log.i("%s stole %s's item!", target, foe) target.set_item(item)
def remove_effect(self, source, _=None): effect = self._effect_index.pop(source, None) if effect is None: if __debug__: log.d("Tried to remove nonexistent %s from side %d", source, self.index) return self._remove_handlers(effect) if __debug__: log.i('Removed %s from side %d', effect, self.index)
def on_damage(self, pokemon, cause, source, battle, damage): if (pokemon.hp == pokemon.max_hp and damage >= pokemon.hp and cause in (Cause.MOVE, Cause.CONFUSE) and pokemon.use_item(battle) is not FAIL ): if __debug__: log.i("%s held on with FocusSash!", pokemon) return pokemon.hp - 1 return damage