194 lines
7.0 KiB
Python
194 lines
7.0 KiB
Python
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):
|
|
win_flag = False
|
|
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 or opponent.curr_hp == 0:
|
|
opponent.curr_hp = 0
|
|
win_flag = True
|
|
print(f"{opponent.name} has fainted!")
|
|
print(f"{self.name} used {move['name']} and dealt {damage} damage to {opponent.name}!")
|
|
print("CPU's Pokemon current HP: ", opponent.curr_hp)
|
|
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']}!")
|
|
return win_flag
|
|
|
|
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:
|
|
return 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 = {}, 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 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 the 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() |