import random import math import game_data as gd import copy class Pokemon: def __init__(self, national_pokedex_number, name, level = 1, types = [], baseStats = {}, moves = [], curr_hp = 0): self.national_pokedex_number = national_pokedex_number self.name = name self.level = level self.types = types self.baseStats = baseStats self.moves_dict = {} if len(self.moves_dict) > 4: raise ValueError("A Pokemon can only have 4 moves.") else: for move in moves: if move not in gd.available_moves: raise ValueError(f"{move} is not an available move.") else: self.moves_dict[move] = copy.deepcopy(gd.available_moves[move]) self.curr_hp = self.baseStats['hp'] def _get_baseStats(self): return self.baseStats def get_current_hp(self): return self.curr_hp def can_battle(self): condition1 = self.curr_hp > 0 condition2 = False for move in self.moves_dict: move_usage_avail = self.moves_dict[move]['PP'] > 0 if move_usage_avail: condition2 = True break else: condition2 = False return condition1 and condition2 def learnMove(self, move): if len(self.moves_dict) >= 4: raise ValueError("A Pokemon can only have 4 moves.") else: self.moves_dict[move] = gd.available_moves[move] def _useMove(self, move, opponent): if move['PP'] > 0: if random.random() < move['accuracy']: if move['category'] == 'physical': attack = self.baseStats['attack'] defense = opponent.baseStats['defense'] else: attack = self.baseStats['special'] defense = opponent.baseStats['special'] stability = 1.5 if move['type'] in self.types else 1 effect = 1 critical = 2 if random.random() < self.baseStats['speed']/512 else 1 luck = random.uniform(0.85, 1.0) modifier = stability * effect * critical * luck damage = math.floor(((2*self.level+10)/250 * (attack/defense) * move['power'] + 2) * modifier) opponent.curr_hp -= damage if opponent.curr_hp < 0: opponent.curr_hp = 0 print(f"{self.name} used {move['name']} and dealt {damage} damage to {opponent.name}!") move['PP'] = move['PP'] - 1 else: print(f"{self.name}'s attack missed!") move['PP'] = move['PP'] - 1 else: print(f"{self.name} has no PP left for {move['name']}!") pass def useMove(self, move_name, opponent): if move_name not in self.moves_dict: raise ValueError(f"{self.name} does not know the move {move_name}.") else: self._useMove(self.moves_dict[move_name], opponent) def print_move(self,move): print(f"Move: {self.moves_dict[move]['name']}") print(f"Type: {self.moves_dict[move]['type']}") print(f"Category: {self.moves_dict[move]['category']}") print(f"Power: {self.moves_dict[move]['power']}") print(f"Accuracy: {self.moves_dict[move]['accuracy']}") print(f"PP: {self.moves_dict[move]['PP']}") def get_moves(self): return list(self.moves_dict.keys()) def checkout_move(self, move_name): if move_name not in self.moves_dict: raise ValueError(f"{self.name} does not know the move {move_name}.") else: self.print_move(move_name) def _status(self): print(f"Pokemon: {self.name}") print(f"Level: {self.level}") print(f"Types: {self.types}") print(f"Base Stats: {self.baseStats}") print(f"Current HP: {self.curr_hp}") print(f"Moves: {self.moves_dict}") def print_pokemon_info(self): self._status() class Trainer: def __init__(self, name, starter_name, items = {"potions": 0, "pokeball": 0}, is_CPU = False): self.name = name if is_CPU: if starter_name not in gd.available_wild_pokemons: raise ValueError(f"{starter_name} is not an available wild Pokemon.") else: self.starter = starter_name self.active_pokemon = Pokemon(**gd.available_wild_pokemons[starter_name]) self.pokemon_list = [] self.add_pokemon(self.active_pokemon) else: if starter_name not in gd.available_starters: raise ValueError(f"{starter_name} is not an available starter Pokemon.") else: self.starter = starter_name self.active_pokemon = Pokemon(**gd.available_starters[starter_name]) self.pokemon_list = [] self.add_pokemon(self.active_pokemon) self.items = items self.is_CPU = is_CPU def add_pokemon(self, pokemon): if len(self.pokemon_list) >= 6: raise ValueError("A trainer can only have 6 Pokemon.") else: self.pokemon_list.append(pokemon) def get_pokemon_list(self): return [pok.name for pok in self.pokemon_list] def get_pokemon(self, name): for pokemon in self.pokemon_list: if pokemon.name == name: return pokemon raise ValueError(f"{name} is not in the trainer's Pokemon list.") def can_battle(self): for pokemon in self.pokemon_list: if pokemon.can_battle(): return True return False def active_pokemon_can_battle(self): return self.active_pokemon.can_battle() def _change_active_pokemon(self,new_pokemon): self.active_pokemon = new_pokemon def get_active_pokemon(self): return self.active_pokemon def change_active_pokemon(self,pokemon_name): try: new_pokemon = self.get_pokemon(pokemon_name) self._change_active_pokemon(new_pokemon) print("Pokemon change successfull!") except ValueError as e: raise e def print_items(self): print(f"1) Potions: {self.items['potions']}") print(f"2) Pokeballs: {self.items['pokeball']}") def use_item(self, item_name): if item_name not in self.items: raise ValueError(f"{item_name} is not an available item.") else: if self.items[item_name] > 0: self.items[item_name] -= 1 print(f"Used {item_name}. Remaining: {self.items[item_name]}") if item_name == "potions": self.active_pokemon.curr_hp += 20 if self.active_pokemon.curr_hp > self.active_pokemon.baseStats['hp']: self.active_pokemon.curr_hp = self.active_pokemon.baseStats['hp'] print(f"{self.active_pokemon.name} has been healed by 20 HP!") return False elif item_name == "pokeball": return True else: raise ValueError(f"You have no {item_name} left.") def update_pokemon_list(self, pokemon): pass def _status(self): print('='*30) print(f"Trainer name: {self.name}") print(f"Starter Pokemon: {self.starter}") print(f"Pokemon List: {[pok.name for pok in self.pokemon_list]}") print("Active Pokemon info:") self.active_pokemon.print_pokemon_info() print("Detailed info of Pokemons in your list:") print("-"*30) for pokemon in self.pokemon_list: pokemon.print_pokemon_info() print("-"*30) print(f"Items: {self.items}") print('='*30) def print_trainer_info(self): self._status()