Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
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
Exemplo n.º 3
0
 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)
Exemplo n.º 4
0
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]))
Exemplo n.º 5
0
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()
Exemplo n.º 6
0
    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