def get_statuses(pkmn: Pokemon): statuses = [] if pkmn.get_status() is not None: statuses.append(pkmn.get_status().name) if pkmn.get_other_status() is not None: statuses.append(pkmn.get_other_status().name) return ', '.join(statuses)
def calculate_damage(move: Move, pokemon: Pokemon, on_pokemon: Pokemon) -> (int, Effectiveness, Criticality): """ Calculates a slightly random (due to critical hit, etc.) damage from the pokemon to the on_pokemon. :param move: The move pokemon attacks on_pokemon with. :param pokemon: The attacking Pokemon. :param on_pokemon: The defending Pokemon. :return: A tuple containing damage dealt, the level of effectiveness of the move, and a critical hit value (2 for critical hit, 1 for regular). """ critical = chance(.0625, lambda: Criticality.CRITICAL, lambda: Criticality.NOT_CRITICAL) random = random_pct(85, 100) effectiveness = is_effective(move.get_type(), on_pokemon.get_type()) modifier = critical.value * random * effectiveness.value attack = pokemon.get_stats().get_special_attack() if move.is_special( ) else pokemon.get_stats().get_attack() attack *= 1.5 if move.get_type() == pokemon.get_type() else 1 # STAB defense = on_pokemon.get_stats().get_special_defense() if move.is_special( ) else on_pokemon.get_stats().get_defense() damage = max( 0, int(((((((2 * pokemon.get_level()) / 5) + 2) * move.get_base_damage() * (attack / defense)) / 50) + 2) * modifier)) damage = damage if damage < on_pokemon.get_hp() else on_pokemon.get_hp() return damage, effectiveness, critical
def _tokenize_child(pokemon: Pokemon, action_type: MonteCarloActionType) -> str: """ Tokenizes a pokemon and action type for keeping track of nodes. :param pokemon: A Pokemon. :param action_type: A MonteCarloActionType. :return: A tokenized string. """ return "%d-%s" % (pokemon.get_id(), action_type.name)
def get_pokemon(name_or_id: Union[int, str]) -> Pokemon: script_dir = os.path.dirname(__file__) rel_path = "pokemon.csv" abs_file_path = os.path.join(script_dir, rel_path) with open(abs_file_path, 'r') as csv_file: reader = csv.reader(csv_file) pokemon = {} pokemon_names = [] for row in reader: if len(row) != 0: pokemon[row[0]] = row pokemon_names.append(row[0]) info = pokemon[name_or_id.lower().capitalize()] if isinstance( name_or_id, str) else pokemon[pokemon_names[name_or_id]] type_map = { "normal": 0, "fighting": 1, "flying": 2, "poison": 3, "ground": 4, "rock": 5, "bug": 6, "ghost": 7, "steel": 8, "fire": 9, "water": 10, "grass": 11, "electric": 12, "psychic": 13, "ice": 14, "dragon": 15, "dark": 16, "fairy": 17 } status_map = { "infatuation": 0, "confusion": 1, "sleep": 2, "poison": 3, "bad_poison": 4, "paralysis": 5, "freeze": 6, "burn": 7, } move_bank = [] i = 9 while i < 35: if info[i] != '': status = Status( status_map[info[i + 5]]) if info[i + 5] != "none" else None move_bank.append( Move(info[i], int(info[i + 1]), int(info[i + 2]), PokemonType(type_map[info[i + 3]]), info[i + 4] == "special", int(info[i + 6]), status)) i += 7 return Pokemon( PokemonType(type_map[info[1]]), info[0], int(info[2]), Stats(int(info[4]), int(info[6]), int(info[5]), int(info[7]), int(info[8])), MoveBank(move_bank), int(info[3]))
import sys from os.path import join, dirname sys.path.append(join(dirname(__file__), '../..')) from pokemon_ai.battle import Battle from pokemon_ai.classes import Bag, Party, Player, Move, MoveBank, Pokemon, Stats, PokemonType party1 = Party([ Pokemon(PokemonType.FIRE, "Charizard", 100, Stats(300, 300, 300, 300, 300), MoveBank([Move("Flamethrower", 100, 0, PokemonType.FIRE, True)]), 300), Pokemon(PokemonType.WATER, "Piplup", 100, Stats(300, 300, 300, 300, 300), MoveBank([Move("Water Squirt", 100, 3, PokemonType.WATER, True)]), 300) ]) party2 = Party([ Pokemon(PokemonType.FIRE, "Blaziken", 100, Stats(300, 300, 300, 300, 300), MoveBank([Move("Flamethrower", 100, 3, PokemonType.FIRE, True)]), 300), Pokemon(PokemonType.WATER, "Squirtle", 100, Stats(300, 300, 300, 300, 300), MoveBank([Move("Water Squirt", 100, 3, PokemonType.WATER, True)]), 300) ]) player1 = Player("Player 1", party1, Bag()) player2 = Player("Player 2", party2, Bag()) battle = Battle(player1, player2, 2) battle.play()
def _perform_attack(self, move: Move, player: Player, on_player: Player, pokemon: Pokemon): """ Performs a move by the starting Pokemon of player against the starting pokemon of on_player. :param move: The move player's Pokemon is performing. :param player: The player whose Pokemon is attacking. :param on_player: The player whose Pokemon is defending. :param pokemon: The attacking Pokemon. :return: Returns True if player wins, False otherwise. """ if pokemon.is_fainted(): return False on_pokemon = on_player.get_party().get_starting() def confusion(): base_damage = 40 damage = int(pokemon.get_stats().get_attack() / base_damage) defense = int(pokemon.get_stats().get_defense() / base_damage * 1 / 10) total_damage = max(1, damage - defense) pokemon.take_damage(total_damage) self._alert(pokemon.get_name() + ' hurt itself in its confusion.', player, on_player) if pokemon.is_fainted(): self._alert(pokemon.get_name() + ' fainted!', player) return not self._turn_switch_pokemon(player, False) return False def paralysis(): self._alert(pokemon.get_name() + ' is unable to move.', player, on_player) def infatuation(): self._alert( pokemon.get_name() + ' is infatuated and is unable to move.', player, on_player) def freeze(): self._alert(pokemon.get_name() + ' is frozen solid.', player, on_player) def sleep(): self._alert(pokemon.get_name() + ' is fast asleep.', player, on_player) def try_attack(): # Decrease the PP on the move move.dec_pp() move.reveal() # Checks to see if the attack hit change_of_hit = pokemon.get_stats().get_accuracy( ) / 100 * on_pokemon.get_stats().get_evasiveness() / 100 did_hit = chance(change_of_hit, True, False) if not did_hit: self._alert(pokemon.get_name() + '\'s attack missed.', player, on_player) return False self._alert( player.get_name() + "'s " + pokemon.get_name() + ' used ' + move.get_name() + '!', player, on_player) if move.is_damaging(): # Calculate damage damage, effectiveness, critical = calculate_damage( move, pokemon, on_pokemon) # Describe the effectiveness if critical == Criticality.CRITICAL and effectiveness != Effectiveness.NO_EFFECT: self._alert('A critical hit!', player, on_player) if effectiveness == Effectiveness.NO_EFFECT: self._alert( 'It has no effect on ' + on_pokemon.get_name() + '.', player, on_player) if effectiveness == Effectiveness.SUPER_EFFECTIVE: self._alert('It\'s super effective!', player, on_player) if effectiveness == Effectiveness.NOT_EFFECTIVE: self._alert('It\'s not very effective...', player, on_player) self._alert( on_pokemon.get_name() + ' took ' + str(damage) + ' damage.', player, on_player) # Lower the opposing Pokemon's HP on_pokemon._hp = max(0, on_pokemon.get_hp() - damage) # If the move inflicts a status, perform the status effect if move.get_status_inflict(): if move.get_status_inflict() in [ Status.POISON, Status.BAD_POISON, Status.BURN ]: # Unlike status turns, other status turns increase in length because they don't end on_pokemon.set_other_status(move.get_status_inflict()) else: on_pokemon.set_status(move.get_status_inflict()) self._alert( on_pokemon.get_name() + ' was ' + status_names[move.get_status_inflict()], player, on_player) # Heal the pokemon if move.get_base_heal() > 0: on_pokemon.heal(move.get_base_heal()) self._alert( pokemon.get_name() + ' gained ' + str(move.get_base_heal()) + ' HP.', player) # Check if the Pokemon fainted if on_pokemon.is_fainted(): self._alert(on_pokemon.get_name() + ' fainted!', player, on_player) return not self._turn_switch_pokemon(on_player, False) return False if pokemon.get_status() not in [ None, Status.POISON, Status.BAD_POISON, Status.BURN ]: # If the Pokemon is inflicted by a status effect that impacts the chance of landing the attack, # perform the calculations. status = pokemon.get_status() pokemon._status_turns = max(0, pokemon.get_status_turns() - 1) if pokemon.get_status_turns() == 0: pokemon._status = None self._alert( pokemon.get_name() + ' is ' + status_names[status] + '.', player, on_player) if status is Status.CONFUSION: chance(1 / 3, lambda: confusion(), try_attack) elif status is Status.PARALYSIS: chance(0.25, lambda: paralysis(), try_attack) elif status is Status.INFATUATION: chance(0.5, lambda: infatuation(), try_attack) elif status is Status.FREEZE: freeze() elif status is Status.SLEEP: sleep() elif pokemon.get_status() is None: # No status effect, attempt to attack return try_attack() return False