Compare commits

..
5 Commits
Author SHA1 Message Date
Edoardo Vergerio f046d06e21 final corrections before submission 2026-09-06 17:42:44 +02:00
Edoardo Vergerio 268fda0a6b added HW5_final with suggestion system and repo cleanup 2026-08-25 11:08:53 +02:00
Edoardo Vergerio 10a1a632fe repo setup 2026-08-24 21:28:41 +02:00
Edoardo Vergerio 66fe741539 added .gitignore 2026-08-24 13:51:40 +02:00
Edoardo Vergerio 5100d055be homework commit 2026-08-24 13:49:19 +02:00
5551 changed files with 5321 additions and 1 deletions
+10
View File
@@ -0,0 +1,10 @@
HW3/results/*
HW3/results
HW3/plots
HW4/results
HW4/plots
HW5/results
HW5/plots
HW5/plots/*
HW5/dataset.csv
HW5/trained_model.joblib
Binary file not shown.
Binary file not shown.
+194
View File
@@ -0,0 +1,194 @@
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()
+120
View File
@@ -0,0 +1,120 @@
##########################
#known moves
##########################
tackle = {
'name': 'tackle',
'type': 'normal',
'category': 'physical',
'power': 35,
'accuracy': 0.95,
'PP': 35
}
razor_leaf = {
'name': 'razor leaf',
'type': 'grass',
'category': 'physical',
'power': 55,
'accuracy': 0.95,
'PP': 25
}
ember = {
'name': 'ember',
'type': 'fire',
'category': 'special',
'power': 40,
'accuracy': 1.0,
'PP': 25
}
water_gun = {
'name': 'water gun',
'type': 'water',
'category': 'special',
'power': 40,
'accuracy': 1.0,
'PP': 25
}
peck = {
"name": "peck",
"type": "flying",
"category": "physical",
"power": 35,
"accuracy": 1.0,
"PP": 35
}
twineedle = {
"name": "twineedle",
"type": "bug",
"category": "physical",
"power": 25,
"accuracy": 1.0,
"PP": 20
}
available_moves = {'tackle': tackle, 'razor leaf': razor_leaf, 'ember': ember, 'water gun': water_gun, 'peck': peck, 'twineedle': twineedle}
###########################
#starter pokemon
###########################
bulbasaur = {
'national_pokedex_number': 1,
'name': "bulbasaur",
'types': ["grass", "poison"],
'baseStats': {"hp": 45, "attack": 49, "defense": 49, "speed": 45, "special": 65},
'moves': ["tackle", "razor leaf"]
}
charmender = {
'national_pokedex_number': 4,
'name': "charmander",
'types': ["fire"],
'baseStats': {"hp": 39, "attack": 52, "defense": 43, "speed": 65, "special": 50},
'moves': ["tackle", "ember"]
}
squirtle = {
'national_pokedex_number': 7,
'name': "squirtle",
'types': ["water"],
'baseStats': {"hp": 44, "attack": 48, "defense": 65, "speed": 43, "special": 50},
'moves': ["tackle", "water gun"]
}
available_starters = {'bulbasaur': bulbasaur, 'charmander': charmender, 'squirtle': squirtle}
available_starter_names = list(available_starters.keys())
############################
############################
#wild pokemons
############################
caterpie = {
"national_pokedex_number": 10,
"name": "caterpie",
"types": ["bug"],
"baseStats": {"hp": 45, "attack": 30, "defense": 35, "speed": 45, "special": 20},
"moves" : ["twineedle"]
}
pidgey = {
"national_pokedex_number": 16,
"name": "pidgey",
"types": ["normal", "flying"],
"baseStats": {"hp": 40, "attack": 45, "defense": 40, "speed": 56, "special": 35},
"moves" : ["tackle", "peck"]
}
rattata = {
"national_pokedex_number": 19,
"name": "rattata",
"types": ["normal"],
"baseStats": {"hp": 30, "attack": 56, "defense": 35, "speed": 72, "special": 25},
"moves" : ["tackle"]
}
available_wild_pokemons = {'caterpie':caterpie, 'pidgey':pidgey, 'rattata':rattata}
available_wild_pokemon_names = list(available_wild_pokemons.keys())
+70
View File
@@ -0,0 +1,70 @@
import random
import game_data as gd
from core import Trainer
def Main():
setup_complete = False
trainer_name = input("Enter your trainer name: ")
while not setup_complete:
try:
print("Available starter Pokemon: ", gd.available_starter_names)
starter_name = input("Choose your starter Pokemon: ")
trainer = Trainer(name=trainer_name, starter_name=starter_name)
print(f"{trainer.name} has chosen {trainer.get_active_pokemon().name} as their starter Pokemon!")
setup_complete = True
except ValueError as e:
print(e)
print("Please try again...")
continue
#trainer.print_trainer_info()
cpu_trainer = Trainer(name="CPU", starter_name=random.choice(gd.available_wild_pokemon_names), is_CPU=True)
print(f"CPU has chosen {cpu_trainer.get_active_pokemon().name} as their starter Pokemon!")
#cpu_trainer.print_trainer_info()
continue_playing = True
while continue_playing:
selected_pokemon_combat_flag = False
while not selected_pokemon_combat_flag:
print("Choose a Pokemon from your list to battle with:\n", trainer.get_pokemon_list())
player_pokemon = input("Choose:")
try:
player_pokemon = trainer.get_pokemon(player_pokemon)
selected_pokemon_combat_flag = True
except ValueError as e:
print(e)
print("Please try again...")
selected_combat_move_flag = False
while not selected_combat_move_flag:
print(f"Choose a move for {player_pokemon.name} to use against {cpu_trainer.get_active_pokemon().name}:\n", player_pokemon.get_moves())
player_move_name = input("Choose:")
try:
print("Your selected move: ")
player_pokemon.checkout_move(player_move_name)
selected_combat_move_flag = True
except ValueError as e:
print(e)
print("Please try again...")
#combat
print('='*30)
print("BATTLE RESULTS:")
print("Your move:")
opponent_fainted = player_pokemon.useMove(player_move_name, cpu_trainer.get_active_pokemon())
#player_pokemon.checkout_move(player_move_name)
#print('-'*30)
#print("CPU's pokemon")
#cpu_trainer.get_active_pokemon().print_pokemon_info()
#print('='*30)
if opponent_fainted:
print("You won the battle!")
continue_playing = False
else:
print("Continue playing? (yes/no)")
response = input().strip().lower()
if response != "yes":
continue_playing = False
if __name__ == "__main__":
Main()
Binary file not shown.
Binary file not shown.
+213
View File
@@ -0,0 +1,213 @@
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()
+120
View File
@@ -0,0 +1,120 @@
##########################
#known moves
##########################
tackle = {
'name': 'tackle',
'type': 'normal',
'category': 'physical',
'power': 35,
'accuracy': 0.95,
'PP': 35
}
razor_leaf = {
'name': 'razor leaf',
'type': 'grass',
'category': 'physical',
'power': 55,
'accuracy': 0.95,
'PP': 25
}
ember = {
'name': 'ember',
'type': 'fire',
'category': 'special',
'power': 40,
'accuracy': 1.0,
'PP': 25
}
water_gun = {
'name': 'water gun',
'type': 'water',
'category': 'special',
'power': 40,
'accuracy': 1.0,
'PP': 25
}
peck = {
"name": "peck",
"type": "flying",
"category": "physical",
"power": 35,
"accuracy": 1.0,
"PP": 35
}
twineedle = {
"name": "twineedle",
"type": "bug",
"category": "physical",
"power": 25,
"accuracy": 1.0,
"PP": 20
}
available_moves = {'tackle': tackle, 'razor leaf': razor_leaf, 'ember': ember, 'water gun': water_gun, 'peck': peck, 'twineedle': twineedle}
###########################
#starter pokemon
###########################
bulbasaur = {
'national_pokedex_number': 1,
'name': "bulbasaur",
'types': ["grass", "poison"],
'baseStats': {"hp": 45, "attack": 49, "defense": 49, "speed": 45, "special": 65},
'moves': ["tackle", "razor leaf"]
}
charmender = {
'national_pokedex_number': 4,
'name': "charmander",
'types': ["fire"],
'baseStats': {"hp": 39, "attack": 52, "defense": 43, "speed": 65, "special": 50},
'moves': ["tackle", "ember"]
}
squirtle = {
'national_pokedex_number': 7,
'name': "squirtle",
'types': ["water"],
'baseStats': {"hp": 44, "attack": 48, "defense": 65, "speed": 43, "special": 50},
'moves': ["tackle", "water gun"]
}
available_starters = {'bulbasaur': bulbasaur, 'charmander': charmender, 'squirtle': squirtle}
available_starter_names = list(available_starters.keys())
############################
############################
#wild pokemons
############################
caterpie = {
"national_pokedex_number": 10,
"name": "caterpie",
"types": ["bug"],
"baseStats": {"hp": 45, "attack": 30, "defense": 35, "speed": 45, "special": 20},
"moves" : ["twineedle"]
}
pidgey = {
"national_pokedex_number": 16,
"name": "pidgey",
"types": ["normal", "flying"],
"baseStats": {"hp": 40, "attack": 45, "defense": 40, "speed": 56, "special": 35},
"moves" : ["tackle", "peck"]
}
rattata = {
"national_pokedex_number": 19,
"name": "rattata",
"types": ["normal"],
"baseStats": {"hp": 30, "attack": 56, "defense": 35, "speed": 72, "special": 25},
"moves" : ["tackle"]
}
available_wild_pokemons = {'caterpie':caterpie, 'pidgey':pidgey, 'rattata':rattata}
available_wild_pokemon_names = list(available_wild_pokemons.keys())
+241
View File
@@ -0,0 +1,241 @@
from core import Trainer
import game_data as gd
import random
import copy
game_status = 'story'
game_active_flag = True
def Battle(trainer,cpu_trainer):
global game_status
global game_active_flag
print("You are in battle!")
battle_active = True
while battle_active:
player_battle_action_selected = False
while not player_battle_action_selected:
print("Type the number of one of the following actions:")
print(f"1) Attack - [Your active Pokemon - {trainer.get_active_pokemon().name}]")
print("2) Change pokemon")
print("3) Use item")
print("4) Run away")
print('5) Check status')
try:
action = int(input("Choose an action (1-5): ").strip())
player_battle_action_selected = True
except ValueError:
print("Invalid input. Please enter a number between 1 and 5.")
continue
if action == 1:
#check if the player can sustain a battle: first check the active pokemon,
#then check the pokemons in the list
if not trainer.active_pokemon_can_battle():
print("Your active pokemon cannot battle!")
if not trainer.can_battle():
print("You have no more pokemon that can battle! You lost the battle!")
battle_active = False
game_status = 'pokemon_center'
break
else:
print("You have other pokemon that can battle! Please change your active pokemon!")
continue
selected_combat_move_flag = False
while not selected_combat_move_flag:
active_pokemon = trainer.get_active_pokemon()
cpu_active_pokemon = cpu_trainer.get_active_pokemon()
print(f"Choose a move for {active_pokemon.name} to use against {cpu_active_pokemon.name}:\n", active_pokemon.get_moves())
player_move_name = input("Choose:")
try:
active_pokemon.useMove(player_move_name,cpu_active_pokemon)
selected_combat_move_flag = True
#check if the opponent has been defeated
if not cpu_trainer.active_pokemon_can_battle():
print(f"{cpu_trainer.get_active_pokemon().name} has been defeated!")
battle_active = False
game_status = 'story'
break
#if the opponent has not been defeated, then its the CPU turn to play
cpu_active_pokemon_selected_move_name = random.choice(cpu_active_pokemon.get_moves())
print(f"CPU's {cpu_active_pokemon.name} is using {cpu_active_pokemon_selected_move_name} against your {active_pokemon.name}!")
cpu_active_pokemon.useMove(cpu_active_pokemon_selected_move_name, active_pokemon)
#update the player pokemon list
trainer.update_pokemon_list(active_pokemon)
#check if the player has been defeated
if not trainer.active_pokemon_can_battle():
print(f"Your {active_pokemon.name} has been defeated!")
if not trainer.can_battle():
print("You have no more Pokemons that can battle! You lost!")
battle_active = False
game_status = 'pokemon_center'
break
else:
print("You have other Pokemons that can battle!")
continue
except ValueError as e:
print(e)
print("Please try again...")
elif action == 2:
print('='*30)
print("Change active pokemon")
print('-'*30)
change_pokemon_success = False
while not change_pokemon_success:
try:
print("Select the name of a pokemon in your list:")
print(trainer.get_pokemon_list())
chosen_new_pokemon_name = input('Choose...')
trainer.change_active_pokemon(chosen_new_pokemon_name)
change_pokemon_success = True
except ValueError as e:
print(e)
elif action == 3:
print("Select the item index to use:")
trainer.print_items()
item_selected_flag = False
while not item_selected_flag:
try:
avail_items = list(trainer.items.keys())
item_index = int(input("Choose an item index (1-2): ").strip())
item_selected_flag = True
is_pokeball = trainer.use_item(item_name=avail_items[item_index - 1])
if is_pokeball:
catch_prob = 1 - (cpu_trainer.get_active_pokemon().get_current_hp() / cpu_trainer.get_active_pokemon().baseStats['hp'])
random_value = random.uniform(0, 1)
if random_value < catch_prob:
print(f"You caught {cpu_trainer.get_active_pokemon().name}!")
trainer.add_pokemon(cpu_trainer.get_active_pokemon())
battle_active = False
game_status = 'story'
else:
print(f"{cpu_trainer.get_active_pokemon().name} escaped your pokeball!")
except ValueError:
print("Please enter a number between 1 and 2.")
continue
elif action == 4:
runaway_prob = 0.6
random_value = random.uniform(0, 1)
if random_value < runaway_prob:
print("You successfully ran away from the battle!")
battle_active = False
game_status = 'story'
else:
print("You could not run away from the battle!")
elif action == 5:
print('='*30)
print("BATTLE INFO")
print('-'*30)
print("Your items:")
trainer.print_items()
print("Your pokemon list info:")
for pokemon in trainer.pokemon_list:
pokemon.print_pokemon_info()
print("-"*30)
print("CPU active pokemon info:")
cpu_trainer.get_active_pokemon().print_pokemon_info()
print('='*30)
else:
print("Invalid action. Please choose again.")
def Main():
global game_status
global game_active_flag
player_created_flag = False
while not player_created_flag:
try:
trainer_name = input("Enter your trainer name: ")
print("Available starter Pokemon: ", gd.available_starter_names)
starter_name = input("Choose your starter Pokemon: ")
trainer = Trainer(name=trainer_name, starter_name=starter_name)
print(f"{trainer.name} has chosen {trainer.starter} as their starter Pokemon!")
print("Adding potions and pokeballs to your inventory...")
trainer.items = {"potions": 10, "pokeball": 10}
print("Your character is ready!")
#trainer.print_trainer_info()
player_created_flag = True
print(f"Welcome {trainer.name}! Your adventure begins now!")
except ValueError as e:
print(e)
print("Please try again...")
continue
while game_active_flag:
if game_status == 'story':
print("Type the number of one of the following actions:")
print("1) Explore ")
print("2) Pokemon Center")
print("3) Pokemon Store")
print("4) Show trainer data")
print("5) Exit")
try:
action = int(input("Choose an action (1-5): ").strip())
except ValueError:
print("Invalid input. Please enter a number between 1 and 5.")
continue
if action == 1:
game_status = 'explore'
elif action == 2:
game_status = 'pokemon_center'
elif action == 3:
game_status = 'pokemon_store'
elif action == 4:
print("Showing trainer data:")
trainer.print_trainer_info()
elif action == 5:
print("Exiting the game. Goodbye!")
game_active_flag = False
else:
print("Invalid action. Please choose again.")
elif game_status == 'explore':
print("You are exploring")
battle_prob = random.uniform(0, 1)
print(f"Battle probability: {battle_prob:.2f}")
if battle_prob < 0.8:
cpu_trainer = Trainer(name='CPU',starter_name=gd.available_wild_pokemon_names[random.randint(0,len(gd.available_wild_pokemon_names)-1)],is_CPU=True)
print(f"A wild {cpu_trainer.get_active_pokemon().name} appeared!")
#print(cpu_trainer.get_active_pokemon().print_pokemon_info())
game_status = 'battle'
Battle(trainer,cpu_trainer)
else:
print('-'*30)
print("No wild Pokemon appeared.")
game_status = 'story'
elif game_status == 'pokemon_center':
print("You are at the Pokemon Center. You can heal your Pokemon here.")
heal_flag = input("Type 'yes' to heal your Pokemons: ").strip().lower()
if heal_flag == 'yes':
for pokemon in trainer.pokemon_list:
pokemon.curr_hp = pokemon.baseStats['hp']
for move in pokemon.moves_dict.keys():
pokemon.moves_dict[move]['PP'] = copy.deepcopy(gd.available_moves[move]['PP'])
print("All your Pokemon have been healed!")
game_status = 'story'
else:
print("You exited the Pokemon Center.")
game_status = 'story'
elif game_status == 'pokemon_store':
print("You are in the Pokemon Store. You can buy items here.")
restore_items_flag = input("Type 'yes' to restore your items: ").strip().lower()
if restore_items_flag == 'yes':
trainer.items = {"potions": 10, "pokeball": 10}
print("Your items have been restored!")
game_status = 'story'
else:
print("You exited the Pokemon Store.")
game_status = 'story'
else:
print("Unknown game status. Try again.")
if __name__ == "__main__":
Main()
+4
View File
@@ -0,0 +1,4 @@
{
"python-envs.defaultEnvManager": "ms-python.python:conda",
"python-envs.defaultPackageManager": "ms-python.python:conda"
}
Binary file not shown.
Binary file not shown.
+216
View File
@@ -0,0 +1,216 @@
import random
import math
import copy
import game_data as gd
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.keys():
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 get_current_hp_percent(self):
return self.curr_hp / self.baseStats['hp']
def can_battle(self):
condition1 = self.curr_hp > 0
condition2 = False
for move in self.moves_dict:
move_usage_avail = True #disregard pp in random battle
#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] = copy.deepcopy(gd.available_moves[move])
def _compute_effect(self, move, opponent):
attack_move_type = move['type']
defending_types = opponent.get_types()
effect = 1
for def_t in defending_types:
for effectiveness_dataset in gd.type_effectiveness:
if effectiveness_dataset['attack'] == attack_move_type and effectiveness_dataset['defend'] == def_t:
effect = effect * effectiveness_dataset['effectiveness']
break
return effect
def _useMove(self, move, opponent):
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 = self._compute_effect(move,opponent)
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}!")
else:
pass
#print(f"{self.name}'s attack missed!")
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 get_types(self):
return self.types
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
self.starter = starter_name
self.active_pokemon = Pokemon(**gd.pokemons_dict[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 #use the item
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()
+48
View File
@@ -0,0 +1,48 @@
import json
import random
#exclude moves with power equal to null,
#do not consider the effect,effects or changes fields
available_moves = dict()
keys_to_skip = ['effect','effects','changes']
with open('moves.json', 'r') as file:
for line in file:
m = json.loads(line)
if m['power'] == None or m['accuracy'] == None:
continue
else:
available_moves[m['name']] = {}
m_keys = list(m.keys())
for k in m_keys:
if k in keys_to_skip:
continue
else:
available_moves[m['name']][k] = m[k]
#loading pokemons from json file
#assume levell = 1 for all
pokemons_dict = dict()
with open('pokemons.json', 'r') as file:
for line in file:
p = json.loads(line)
pokemons_dict[p['name']] = p
pokemons_dict[p['name']]['level'] = 1
current_pokemon_types = p['types'] + ['normal']
compatible_moves = []
for m in available_moves.keys():
if available_moves[m]['type'] in current_pokemon_types:
compatible_moves.append(m)
#select two (compatible) random moves
selected_moves = [random.choice(compatible_moves) for _ in range(2)]
pokemons_dict[p['name']]['moves'] = selected_moves
available_pokemon_names = list(pokemons_dict.keys())
available_starters = ['bulbasaur', 'charmander', 'squirtle']
#type effectiveness
type_effectiveness = []
with open('type_effectiveness.json', 'r') as file:
for line in file:
type_effectiveness.append(json.loads(line))
+185
View File
@@ -0,0 +1,185 @@
import os
from core import Trainer
import random
import copy
import game_data as gd
import pickle
import matplotlib.pyplot as plt
import numpy as np
def RandomBattle(trainer,cpu_trainer):
#print(f"You are in battle against {cpu_trainer.name}!")
battle_active = True
active_pokemon = trainer.get_active_pokemon()
cpu_active_pokemon = cpu_trainer.get_active_pokemon()
did_player_won = False
battle_turns_num = 0
while battle_active:
player_move_name = random.choice(active_pokemon.get_moves())
#print(f"{active_pokemon.name} selected {player_move_name} to use against {cpu_active_pokemon.name}:\n")
try:
active_pokemon.useMove(player_move_name,cpu_active_pokemon)
battle_turns_num += 1
#check if the opponent has been defeated
if not cpu_trainer.active_pokemon_can_battle():
#print(f"{cpu_trainer.get_active_pokemon().name} has been defeated! You win!")
did_player_won = True
battle_active = False
break
#if the opponent has not been defeated, then its the CPU turn to play
cpu_active_pokemon_selected_move_name = random.choice(cpu_active_pokemon.get_moves())
#print(f"CPU's {cpu_active_pokemon.name} is using {cpu_active_pokemon_selected_move_name} against your {active_pokemon.name}!")
cpu_active_pokemon.useMove(cpu_active_pokemon_selected_move_name, active_pokemon)
battle_turns_num += 1
#update the player pokemon list
trainer.update_pokemon_list(active_pokemon)
#check if the player has been defeated
if not trainer.active_pokemon_can_battle():
#print(f"Your {active_pokemon.name} has been defeated!")
if not trainer.can_battle():
#print("You have no more Pokemons that can battle! You lose!")
did_player_won=False
battle_active = False
break
else:
#print("You have other Pokemons that can battle!")
continue
except ValueError as e:
print(e)
player_residual_hp_percent = trainer.get_active_pokemon().get_current_hp_percent()
battle_results = {
'encountered_pokemon':cpu_trainer.get_active_pokemon().name,
'result':did_player_won,
'battle_turns_num':battle_turns_num,
'player_residual_hp_percent':player_residual_hp_percent
}
return battle_results
def Main(starter_choice,Nbattles):
try:
starter_name = starter_choice
trainer = Trainer(name='edo', starter_name=starter_name)
trainer.items = {"potions": 10, "pokeball": 10}
except ValueError as e:
print(e)
print("Something went wrong!")
game_active_flag = True
while game_active_flag:
all_battle_results = []
for i in range(0,Nbattles):
#print("You entered the Random Battle mode")
#print("Battle #",i)
cpu_trainer = Trainer(name='CPU',starter_name=gd.available_pokemon_names[random.randint(0,len(gd.available_pokemon_names)-1)],is_CPU=True)
battle_results = RandomBattle(trainer,cpu_trainer)
all_battle_results.append(battle_results)
heal_flag = 'yes'
if heal_flag == 'yes':
for pokemon in trainer.pokemon_list:
pokemon.curr_hp = pokemon.baseStats['hp']
#print("All your Pokemon have been healed!")
game_active_flag = False
#save all battle results
return all_battle_results
def make_plots(Ngames,Nbattles):
#SIMPLE PLOT
if os.path.exists('plots') == False:
os.makedirs('plots')
cumulative_victories = np.zeros((Ngames,Nbattles))
plt.figure(figsize=(10, 6))
for starter_choice in gd.available_starters:
for ng in range(Ngames):
pickle_in = open(f"results/{starter_choice}_game_{ng}_{Nbattles}_battles.pickle",'rb')
all_battle_results = pickle.load(pickle_in)
pickle_in.close()
this_game_victory_number = 0
for j, battle_result in enumerate(all_battle_results):
if battle_result['result'] == True:
this_game_victory_number += 1
cumulative_victories[ng,j] = this_game_victory_number
avg_cumulative_victories = np.mean(cumulative_victories,axis=0)
plt.plot(avg_cumulative_victories, label=f"{starter_choice}")
plt.xlabel("Battle number")
plt.ylabel("Average number of victories")
plt.title(f"Cumulative number of victories over {Nbattles} battles average over {Ngames} games")
plt.legend()
plt.savefig(f'plots/battle_victories_plot.pdf')
#BOX PLOT - turns
plt.figure(figsize=(10, 6))
boxes_to_plot = []
for m,starter_choice in enumerate(gd.available_starters):
all_battle_turns = np.zeros((Ngames,Nbattles))
for i in range(Ngames):
pickle_in = open(f"results/{starter_choice}_game_{i}_{Nbattles}_battles.pickle",'rb')
all_battle_results = pickle.load(pickle_in)
pickle_in.close()
for j in range(Nbattles):
all_battle_turns[i,j] = all_battle_results[j]['battle_turns_num']
boxes_to_plot.append(all_battle_turns.flatten())
plt.boxplot(boxes_to_plot)
plt.xticks(np.arange(1,len(gd.available_starters)+1), gd.available_starters, fontsize=15)
plt.xlabel("Starter names", fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel("Number of turns", fontsize=15)
plt.tight_layout()
plt.savefig(f'plots/battle_turns_boxplot.pdf')
plt.close()
#BOX PLOT - health
boxes_to_plot = []
plt.figure(figsize=(10, 6))
for m,starter_choice in enumerate(gd.available_starters):
all_battle_health = np.zeros((Ngames,Nbattles))
for i in range(Ngames):
pickle_in = open(f"results/{starter_choice}_game_{i}_{Nbattles}_battles.pickle",'rb')
all_battle_results = pickle.load(pickle_in)
pickle_in.close()
for j in range(Nbattles):
all_battle_health[i,j] = all_battle_results[j]['player_residual_hp_percent']*100
boxes_to_plot.append(all_battle_health.flatten())
plt.boxplot(boxes_to_plot)
plt.xlabel("Starter names", fontsize=15)
plt.xticks(np.arange(1,len(gd.available_starters)+1), gd.available_starters,fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel("Player residual HP (%)", fontsize=15)
plt.tight_layout()
plt.savefig(f'plots/battle_health_boxplot.pdf')
plt.close()
if __name__ == "__main__":
Ngames = 500
Nbattles = 100
if os.path.exists('results') == False:
os.makedirs('results')
if os.path.exists('plots') == False:
os.makedirs('plots')
for starter_choice in gd.available_starters:
for i in range(Ngames):
print(f"Generating data for {starter_choice}, game {i}...")
results = Main(starter_choice = starter_choice, Nbattles=Nbattles)
pickle_out = open(f"results/{starter_choice}_game_{i}_{Nbattles}_battles.pickle",'wb')
pickle.dump(results,pickle_out)
pickle_out.close()
make_plots(Ngames, Nbattles)
+165
View File
@@ -0,0 +1,165 @@
{"name": "absorb", "type": "grass", "category": "special", "power": 20, "accuracy": 1.0, "pp": 20, "effects": ["Absorb deals damage and the user will recover 50% of the HP drained."]}
{"name": "acid", "type": "poison", "category": "physical", "power": 40, "accuracy": 1.0, "pp": 30, "effect": {"chance": 0.1, "stat": "defense", "stages": -1}}
{"name": "acid armor", "type": "poison", "category": "status", "power": null, "accuracy": null, "pp": 40, "effect": {"stat": "defense", "stages": 2}}
{"name": "agility", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 30, "effect": {"stat": "speed", "stages": 2}}
{"name": "amnesia", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 20, "effect": {"stat": "special", "stages": 2}}
{"name": "aurora beam", "type": "ice", "category": "special", "power": 65, "accuracy": 1.0, "pp": 20, "effect": {"chance": 0.1, "stat": "attack", "stages": -1}}
{"name": "barrage", "type": "normal", "category": "physical", "power": 15, "accuracy": 0.85, "pp": 20, "changes": ["In Generations 1-3, Barrage ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "barrier", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 30, "effect": {"stat": "defense", "stages": 2}}
{"name": "bide", "type": "normal", "category": "physical", "power": null, "accuracy": null, "pp": 10, "effects": ["The user of Bide stores energy for 2 turns. At the end of the second turn the Pokémon unleashes energy, dealing twice the HP damage it received.", "Bide deals fixed, typeless damage, so will hit Ghost-type Pokémon. It also ignores changes to the Accuracy and Evasion stats and can hit Pokémon in the invulnerable stage of Bounce, Dig, Dive, Fly, Shadow Force or Sky Drop."], "changes": ["In Generations 1-3, Bide is not an increased priority move. It also stores energy for 2-3 turns."]}
{"name": "bind", "type": "normal", "category": "physical", "power": 15, "accuracy": 0.85, "pp": 20, "effects": ["Bind inflicts damage on the first turn then traps the opponent, causing them to lose 1⁄16 of their maximum HP after each turn, for 4-5 turns."], "changes": ["In Generations 1-4, Bind has 75% accuracy. Its after-effects last for 2-5 turns instead of 4-5.", "In Generation 1, Bind simply inflicts its base power damage for 2-5 turns. While in effect, the target is unable to attack."]}
{"name": "bite", "type": "normal", "category": "physical", "power": 60, "accuracy": 1.0, "pp": 25, "effect": {"chance": 0.3, "statusCondition": "flinch"}}
{"name": "blizzard", "type": "ice", "category": "special", "power": 120, "accuracy": 0.9, "pp": 5, "effect": {"chance": 0.1, "statusCondition": "freeze"}}
{"name": "body slam", "type": "normal", "category": "physical", "power": 85, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.3, "statusCondition": "paralysis"}}
{"name": "bone club", "type": "ground", "category": "physical", "power": 65, "accuracy": 0.85, "pp": 20, "effect": {"chance": 0.1, "statusCondition": "flinch"}}
{"name": "bonemerang", "type": "ground", "category": "physical", "power": 50, "accuracy": 0.9, "pp": 10, "effects": ["Bonemerang deals damage and will strike twice (with 50 base power each time).\nEach strike of Bonemerang is treated like a separate attack:"], "changes": ["In Generations 1-3, Bonemerang ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "bubble", "type": "water", "category": "special", "power": 20, "accuracy": 1.0, "pp": 30, "effect": {"chance": 0.1, "stat": "speed", "stages": -1}}
{"name": "bubble beam", "type": "water", "category": "special", "power": 65, "accuracy": 1.0, "pp": 20, "effect": {"chance": 0.1, "stat": "speed", "stages": -1}}
{"name": "clamp", "type": "water", "category": "physical", "power": 35, "accuracy": 0.85, "pp": 10, "effects": ["Clamp inflicts damage on the first turn then traps the opponent, causing them to lose 1⁄16 of their maximum HP after each turn, for 4-5 turns. If the user holds a Grip Claw then it is always 5 turns."], "changes": ["In Generations 1-4, Clamp has 75% accuracy. Its after-effects last for 2-5 turns instead of 4-5.", "In Generation 1, Clamp simply inflicts its base power damage for 2-5 turns. While in effect, the target is unable to attack."]}
{"name": "comet punch", "type": "normal", "category": "physical", "power": 18, "accuracy": 0.85, "pp": 15, "changes": ["In Generations 1-3, Comet Punch ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "confuse ray", "type": "ghost", "category": "status", "power": null, "accuracy": 1.0, "pp": 10, "effect": {"statusCondition": "confused"}}
{"name": "confusion", "type": "psychic", "category": "special", "power": 50, "accuracy": 1.0, "pp": 25, "effect": {"chance": 0.1, "statusCondition": "confused"}}
{"name": "constrict", "type": "normal", "category": "physical", "power": 10, "accuracy": 1.0, "pp": 35, "effect": {"chance": 0.1, "stat": "speed", "stages": -1}}
{"name": "conversion", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 30, "changes": ["In Generation 1, Conversion changes the user's type to the target Pokémon's type."]}
{"name": "counter", "type": "fighting", "category": "physical", "power": null, "accuracy": 1.0, "pp": 20, "priority": -1, "effects": ["When hit by a Physical Attack, user strikes back with 2x power."]}
{"name": "crabhammer", "type": "water", "category": "physical", "power": 90, "accuracy": 0.85, "pp": 10, "highCriticalHitRatio": true}
{"name": "cut", "type": "normal", "category": "physical", "power": 50, "accuracy": 0.95, "pp": 30}
{"name": "defense curl", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 40, "effect": {"stat": "defense", "stages": 1}}
{"name": "dig", "type": "ground", "category": "physical", "power": 60, "accuracy": 1.0, "pp": 10, "effects": ["The user of Dig will burrow its way underground on the first turn, disappearing from view and becoming invulnerable to most attacks. On the second turn, Dig deals damage."]}
{"name": "disable", "type": "normal", "category": "status", "power": null, "accuracy": 0.55, "pp": 20, "effects": ["Disable causes the previous move the target used to be disabled for 1-8 turns, which prevents the move's use."]}
{"name": "dizzy punch", "type": "normal", "category": "physical", "power": 70, "accuracy": 1.0, "pp": 10}
{"name": "double kick", "type": "fighting", "category": "physical", "power": 30, "accuracy": 1.0, "pp": 30, "effects": ["Double Kick deals damage and will strike twice (with 30 base power each time).\nEach strike of Double Kick is treated like a separate attack:"], "changes": ["In Generations 1-3, Double Kick ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "double slap", "type": "normal", "category": "physical", "power": 15, "accuracy": 0.85, "pp": 10, "effects": [], "changes": ["In Generations 1-3, Double Slap ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest.", "In Generations 1-5, this move's name was formatted as DoubleSlap."]}
{"name": "double team", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 15, "effect": {"stat": "evasiveness", "stages": 1}}
{"name": "double-edge", "type": "normal", "category": "physical", "power": 100, "accuracy": 1.0, "pp": 15, "effects": ["Double-Edge deals damage, but the user receives 1⁄3 of the damage it inflicted in recoil. In other words, if the attack does 90 HP damage to the opponent, the user will lose 30 HP."], "changes": ["In Generations 1-2, the recoil is 1⁄4 of the damage inflicted."]}
{"name": "dragon rage", "type": "dragon", "category": "special", "power": null, "accuracy": 1.0, "pp": 10, "effects": ["Dragon Rage always deals 40 HP damage to the target, regardless of typing. It has no additional effect."]}
{"name": "dream eater", "type": "psychic", "category": "special", "power": 100, "accuracy": 1.0, "pp": 15, "effects": ["Dream Eater deals damage only on sleeping foes and the user will recover 50% of the HP drained."]}
{"name": "drill peck", "type": "flying", "category": "physical", "power": 80, "accuracy": 1.0, "pp": 20}
{"name": "earthquake", "type": "ground", "category": "physical", "power": 100, "accuracy": 1.0, "pp": 10}
{"name": "egg bomb", "type": "normal", "category": "physical", "power": 100, "accuracy": 0.75, "pp": 10}
{"name": "ember", "type": "fire", "category": "special", "power": 40, "accuracy": 1.0, "pp": 25, "effect": {"chance": 0.1, "statusCondition": "burn"}}
{"name": "explosion", "type": "normal", "category": "physical", "power": 170, "accuracy": 1.0, "pp": 5, "effects": ["Explosion deals high damage, but causes the user to faint."], "changes": ["In Generations 1-4, the opponent's defense stat is temporarily halved when calculating the damage. This gives Explosion an effective power of 340."]}
{"name": "fire blast", "type": "fire", "category": "special", "power": 120, "accuracy": 0.85, "pp": 5, "effect": {"chance": 0.1, "statusCondition": "burn"}}
{"name": "fire punch", "type": "fire", "category": "physical", "power": 75, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.1, "statusCondition": "burn"}}
{"name": "fire spin", "type": "fire", "category": "special", "power": 35, "accuracy": 0.85, "pp": 15, "effects": ["Fire Spin inflicts damage on the first turn then traps the opponent, causing them to lose 1⁄16 of their maximum HP after each turn, for 4-5 turns. If the user holds a Grip Claw then it is always 5 turns."], "changes": ["In Generations 1-4, Fire Spin has a base power of 15 and 70% accuracy. Its after-effects last for 2-5 turns instead of 4-5.", "In Generation 1, Fire Spin simply inflicts its base power damage for 2-5 turns. While in effect, the target is unable to attack."]}
{"name": "fissure", "type": "ground", "category": "physical", "power": null, "accuracy": null, "pp": 5, "effects": ["If it hits, Fissure is guaranteed to make the opponent faint. It is more likely to hit Pokémon that are of a lower level than the user.", "Its accuracy (as a percentage) is calculated as below, ignoring all other accuracy and evasion modifiers:"], "changes": ["In Generation 1, Fissure has 30% accuracy and can hit Pokémon of any level, but does not affect Pokémon faster than the user."]}
{"name": "flamethrower", "type": "fire", "category": "special", "power": 95, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.1, "statusCondition": "burn"}}
{"name": "flash", "type": "normal", "category": "status", "power": null, "accuracy": 0.7, "pp": 20, "effect": {"stat": "accuracy", "stages": -1}}
{"name": "fly", "type": "flying", "category": "physical", "power": 70, "accuracy": 0.95, "pp": 15, "effects": ["The user of Fly will fly up high on the first turn, disappearing from view and becoming invulnerable to most attacks. On the second turn, Fly deals damage.", "While in the air, the Pokémon can only be hit by the moves Gust, Twister, Thunder, Sky Uppercut and Smack Down, with Gust and Twister dealing twice normal damage. Moves from No Guard Pokémon, or any move following an identify move can also hit for regular power."]}
{"name": "focus energy", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 30, "highCriticalHitRatio": true}
{"name": "fury attack", "type": "normal", "category": "physical", "power": 15, "accuracy": 0.85, "pp": 20, "effects": [], "changes": ["In Generations 1-3, Fury Attack ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "fury swipes", "type": "normal", "category": "physical", "power": 18, "accuracy": 0.8, "pp": 15, "effects": [], "changes": ["In Generations 1-3, Fury Swipes ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "glare", "type": "normal", "category": "status", "power": null, "accuracy": 0.75, "pp": 30, "effect": {"statusCondition": "paralysis"}}
{"name": "growl", "type": "normal", "category": "status", "power": null, "accuracy": 1.0, "pp": 40, "effect": {"stat": "attack", "stages": -1}}
{"name": "growth", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 40, "effect": {"stat": "special", "stages": 1}}
{"name": "guillotine", "type": "normal", "category": "physical", "power": null, "accuracy": null, "pp": 5, "effects": ["If it hits, Guillotine is guaranteed to make the opponent faint. It is more likely to hit Pokémon that are of a lower level than the user.", "Its accuracy (as a percentage) is calculated as below, ignoring all other accuracy and evasion modifiers:"], "changes": ["In Generation 1, Guillotine has 30% accuracy, but does not affect opponents faster than the user."]}
{"name": "gust", "type": "normal", "category": "special", "power": 40, "accuracy": 1.0, "pp": 35}
{"name": "harden", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 30, "effect": {"stat": "defense", "stages": 1}}
{"name": "haze", "type": "ice", "category": "status", "power": null, "accuracy": null, "pp": 30, "effects": ["Resets all stat changes."]}
{"name": "headbutt", "type": "normal", "category": "physical", "power": 70, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.3, "statusCondition": "flinch"}}
{"name": "high jump kick", "type": "fighting", "category": "physical", "power": 85, "accuracy": 0.9, "pp": 20, "effects": ["High Jump Kick deals damage, however, if it misses the user keeps going and crashes, losing 1⁄2 of its maximum HP. High Jump Kick cannot be used if Gravity is in effect."], "changes": ["In Generation 1, the crash damage is always 1 HP."]}
{"name": "horn attack", "type": "normal", "category": "physical", "power": 65, "accuracy": 1.0, "pp": 25}
{"name": "horn drill", "type": "normal", "category": "physical", "power": null, "accuracy": null, "pp": 5, "effects": ["If it hits, Horn Drill is guaranteed to make the opponent faint. It is more likely to hit Pokémon that are of a lower level than the user.", "Its accuracy (as a percentage) is calculated as below, ignoring all other accuracy and evasion modifiers:"], "changes": ["In Generation 1, Horn Drill has 30% accuracy, but does not affect opponents faster than the user."]}
{"name": "hydro pump", "type": "water", "category": "special", "power": 120, "accuracy": 0.8, "pp": 5}
{"name": "hyper beam", "type": "normal", "category": "special", "power": 150, "accuracy": 0.9, "pp": 5, "effects": ["Hyper Beam deals damage, but the user must recharge on the next turn (bringing its effective power down to 75 per turn)."], "changes": ["In Generation 1, if Hyper Beam KOs a Pokemon, it does not need to recharge."]}
{"name": "hyper fang", "type": "normal", "category": "physical", "power": 80, "accuracy": 0.9, "pp": 15, "effect": {"chance": 0.1, "statusCondition": "flinch"}}
{"name": "hypnosis", "type": "psychic", "category": "status", "power": null, "accuracy": 0.6, "pp": 20, "effect": {"statusCondition": "sleep"}}
{"name": "ice beam", "type": "ice", "category": "special", "power": 95, "accuracy": 1.0, "pp": 10, "effect": {"chance": 0.1, "statusCondition": "freeze"}}
{"name": "ice punch", "type": "ice", "category": "physical", "power": 75, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.1, "statusCondition": "freeze"}}
{"name": "jump kick", "type": "fighting", "category": "physical", "power": 70, "accuracy": 0.95, "pp": 25, "effects": ["Jump Kick deals damage, however, if it misses the user keeps going and crashes, losing 1⁄2 of its maximum HP. Jump Kick cannot be used if Gravity is in effect."], "changes": ["In Generation 1, the crash damage is always 1 HP. From Generation 2 to Generation 4, the crash damage is 1⁄8 of the damage the attack would have inflicted (which could be all of the user's own HP)."]}
{"name": "karate chop", "type": "normal", "category": "physical", "power": 50, "accuracy": 1.0, "pp": 25, "highCriticalHitRatio": true}
{"name": "kinesis", "type": "psychic", "category": "status", "power": null, "accuracy": 0.8, "pp": 15, "effect": {"stat": "accuracy", "stages": -1}}
{"name": "leech life", "type": "bug", "category": "physical", "power": 20, "accuracy": 1.0, "pp": 15, "effects": ["Leech Life deals damage and the user will recover 50% of the HP drained."]}
{"name": "leech seed", "type": "grass", "category": "status", "power": null, "accuracy": 0.9, "pp": 10, "effects": ["Leech Seed plants a seed on the target that drains 1⁄8 of its maximum HP at the end of each turn and restores it to the user, or any Pokemon that takes its place. It does not work on Grass-type Pokemon; it does technically work against Pokemon with the Magic Guard ability, but no HP will be sapped."], "changes": ["In Generation 1, Leech Seed saps 1⁄16 of the target's HP. If the target is also badly poisoned, the damage increases by 1⁄16 each turn, in the same way as bad poison (and in addition to poison damage).", "In Generation 1 and Generation 2 only, Haze will also clear the effects of Leech Seed."]}
{"name": "leer", "type": "normal", "category": "status", "power": null, "accuracy": 1.0, "pp": 30, "effect": {"stat": "defense", "stages": -1}}
{"name": "lick", "type": "ghost", "category": "physical", "power": 20, "accuracy": 1.0, "pp": 30, "effect": {"chance": 0.3, "statusCondition": "paralysis"}}
{"name": "light screen", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 30, "effects": ["Light Screen reduces damage from Special attacks by 50%, for 5 turns. Its effects apply to all Pokémon on the user's side of the field."]}
{"name": "lovely kiss", "type": "normal", "category": "status", "power": null, "accuracy": 0.75, "pp": 10, "effect": {"statusCondition": "sleep"}}
{"name": "low kick", "type": "fighting", "category": "physical", "power": 50, "accuracy": 0.9, "pp": 20, "effect": {"chance": 0.3, "statusCondition": "flinch"}}
{"name": "meditate", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 40, "effect": {"stat": "attack", "stages": 1}}
{"name": "mega drain", "type": "grass", "category": "special", "power": 40, "accuracy": 1.0, "pp": 10, "effects": ["Mega Drain deals damage and the user will recover 50% of the HP drained.", "If the user is holding a Big Root, the move instead recovers 65% of the damage dealt (30% more than normal). If used on a Pokemon with the ability Liquid Ooze, the user instead loses the HP it would have otherwise gained."]}
{"name": "mega kick", "type": "normal", "category": "physical", "power": 120, "accuracy": 0.75, "pp": 5}
{"name": "mega punch", "type": "normal", "category": "physical", "power": 80, "accuracy": 0.85, "pp": 20}
{"name": "metronome", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 10, "effects": ["User performs any move in the game at random."]}
{"name": "mimic", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 10, "effects": ["Mimic copies the last move used by the target (replacing Mimic). The copied move always has 5 PP. The effect only lasts while the user is in battle: if the user switches out or when the battle ends, the move becomes Mimic again.", "Mimic cannot copy Chatter, Metronome, Sketch or Struggle."], "changes": ["In Generation 1, Mimic allows the user to choose any of the opponent's moves to copy."]}
{"name": "minimize", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 20, "effect": {"stat": "evasiveness", "stages": 1}}
{"name": "mirror move", "type": "flying", "category": "status", "power": null, "accuracy": null, "pp": 20, "effects": ["User performs the opponent's last move."]}
{"name": "mist", "type": "ice", "category": "status", "power": null, "accuracy": null, "pp": 30, "effects": ["User's stats cannot be changed for a period of time."]}
{"name": "night shade", "type": "ghost", "category": "special", "power": null, "accuracy": 1.0, "pp": 15, "effects": ["The damage of Night Shade is equal to the user's level. So at level 100 the Pokémon will inflict 100 HP damage."], "changes": ["In Generation 1, Night Shade also hits Normal- and Psychic-type Pokémon despite their immunity to Ghost-type attacks."]}
{"name": "pay day", "type": "normal", "category": "physical", "power": 40, "accuracy": 1.0, "pp": 20}
{"name": "peck", "type": "flying", "category": "physical", "power": 35, "accuracy": 1.0, "pp": 35}
{"name": "petal dance", "type": "grass", "category": "special", "power": 120, "accuracy": 1.0, "pp": 10, "effects": ["The user of Petal Dance attacks for 2-3 turns, during which it cannot switch out, and then becomes confused. Confused Pokémon have a 50% chance of hurting themselves each turn, for 1-4 turns. The damage received is as if the Pokémon attacks itself with a typeless 40 base power Physical attack.", "If Petal Dance is disrupted (e.g. if the move misses or the user cannot attack due to paralysis) then it will stop and not cause confusion.", "Pokémon with the ability Own Tempo or those behind a Substitute cannot be confused."], "changes": ["In Generations 1-3 Petal Dance has a base power of 70. In Generation 4 its base power is 90.", "In Generations 1-4, Petal Dance has 20 PP. Furthermore, sleep, freezing and flinching will pause but not disrupt Petal Dance.", "In Generation 1, Petal Dance lasts for 3-4 turns."]}
{"name": "pin missile", "type": "bug", "category": "physical", "power": 14, "accuracy": 0.85, "pp": 20, "changes": ["In Generations 1-3, Pin Missile ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "poison gas", "type": "poison", "category": "status", "power": null, "accuracy": 0.55, "pp": 40, "effect": {"statusCondition": "poison"}}
{"name": "poison powder", "type": "poison", "category": "status", "power": null, "accuracy": 0.75, "pp": 35, "effect": {"statusCondition": "poison"}}
{"name": "poison sting", "type": "poison", "category": "physical", "power": 15, "accuracy": 1.0, "pp": 35, "effect": {"chance": 0.3, "statusCondition": "poison"}}
{"name": "pound", "type": "normal", "category": "physical", "power": 40, "accuracy": 1.0, "pp": 35}
{"name": "psybeam", "type": "psychic", "category": "special", "power": 65, "accuracy": 1.0, "pp": 20, "effect": {"chance": 0.1, "statusCondition": "confused"}}
{"name": "psychic", "type": "psychic", "category": "special", "power": 90, "accuracy": 1.0, "pp": 10, "effect": {"chance": 0.3, "stat": "special", "stages": -1}}
{"name": "psywave", "type": "psychic", "category": "special", "power": null, "accuracy": 0.8, "pp": 15, "effects": ["Psywave inflicts a random amount of HP damage, varying between 50% and 150% of the user's level. In other words, at level 100 the damage will be 50-150 HP.", "The damage is typeless (not affected by type advantages/disadvantages) but it still does not affect Dark type Pokemon."]}
{"name": "quick attack", "type": "normal", "category": "physical", "power": 40, "accuracy": 1.0, "pp": 30, "priority": 1}
{"name": "rage", "type": "normal", "category": "physical", "power": 20, "accuracy": 1.0, "pp": 20, "effects": ["Rage deals damage, and if the user is hit by a direct attack - any time after Rage is first used but before a different move is used - the user's Attack is raised by one stage. The game will state the Pokemon's rage is building rather than explicitly assert the stat increase. Stats can be raised to a maximum of +6 stages each.", "The Attack increases will continue as long as Rage is the last move used, even if it misses, the user is incapacitated (paralyzed, sleeping, etc) or the player uses an item. The Attack increase activates for every blow of multi-hit moves such as DoubleSlap or Fury Swipes.", "As an example, if a Pokemon uses Rage then the opponent hits the user in the same turn, the user's Attack increases. If the user moves last it will not increase that turn, but will in the next turn if the opponent hits the user again."], "changes": ["In Generation 1, after Rage is selected it will continue to be used until the end of the battle or the user faints.", "In Generations 2-3, if the user is slower than the opponent, the Attack rise only occurs if Rage is selected in that turn - if a different move is selected (or an item used) and the Pokemon is hit before it uses the new move, its Attack does not increase."]}
{"name": "razor leaf", "type": "grass", "category": "physical", "power": 55, "accuracy": 0.95, "pp": 25, "highCriticalHitRatio": true}
{"name": "razor wind", "type": "normal", "category": "special", "power": 80, "accuracy": 0.75, "pp": 10, "effects": ["The user of Razor Wind will whip up a whirlwind on the first turn. On the second turn, Razor Wind deals damage."]}
{"name": "recover", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 20, "effects": ["Recover restores up to 50% of the user's maximum HP."]}
{"name": "reflect", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 20, "effects": ["Reflect reduces damage from Physical attacks by 50%, for 5 turns. Its effects apply to all Pokémon on the user's side of the field."]}
{"name": "rest", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 10, "effects": ["User sleeps for 2 turns, but user is fully healed."]}
{"name": "roar", "type": "normal", "category": "status", "power": null, "accuracy": 1.0, "pp": 20}
{"name": "rock slide", "type": "rock", "category": "physical", "power": 75, "accuracy": 0.9, "pp": 10, "effect": {"chance": 0.3, "statusCondition": "flinch"}}
{"name": "rock throw", "type": "rock", "category": "physical", "power": 50, "accuracy": 0.65, "pp": 15}
{"name": "rolling kick", "type": "fighting", "category": "physical", "power": 60, "accuracy": 0.85, "pp": 15, "effect": {"chance": 0.3, "statusCondition": "flinch"}}
{"name": "sand attack", "type": "normal", "category": "status", "power": null, "accuracy": 1.0, "pp": 15, "effect": {"stat": "accuracy", "stages": -1}}
{"name": "scratch", "type": "normal", "category": "physical", "power": 40, "accuracy": 1.0, "pp": 35}
{"name": "screech", "type": "normal", "category": "status", "power": null, "accuracy": 0.85, "pp": 40, "effect": {"stat": "defense", "stages": -2}}
{"name": "seismic toss", "type": "fighting", "category": "physical", "power": null, "accuracy": 1.0, "pp": 20, "effects": ["The damage of Seismic Toss is equal to the user's level. So at level 100 the Pokémon will inflict 100 HP damage."], "changes": ["In Generation 1 Seismic Toss can hit Ghost-type Pokémon despite their immunity to Fighting-type attacks."]}
{"name": "self-destruct", "type": "normal", "category": "physical", "power": 200, "accuracy": 1.0, "pp": 5, "effects": ["Self-Destruct deals high damage, but causes the user to faint."]}
{"name": "sharpen", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 30, "effect": {"stat": "attack", "stages": 1}}
{"name": "sing", "type": "normal", "category": "status", "power": null, "accuracy": 0.55, "pp": 15, "effect": {"statusCondition": "sleep"}}
{"name": "skull bash", "type": "normal", "category": "physical", "power": 100, "accuracy": 1.0, "pp": 15, "effects": ["The user of Skull Bash will tuck in its head on the first turn and raise its Defense by one stage. On the second turn, Skull Bash deals damage."], "changes": ["In Generation 1, Skull Bash does not raise the user's Defense."]}
{"name": "sky attack", "type": "flying", "category": "physical", "power": 140, "accuracy": 0.9, "pp": 5, "effects": ["The user of Sky Attack will become cloaked in a harsh light on the first turn. On the second turn, Sky Attack deals damage."]}
{"name": "slam", "type": "normal", "category": "physical", "power": 80, "accuracy": 0.75, "pp": 20}
{"name": "slash", "type": "normal", "category": "physical", "power": 70, "accuracy": 1.0, "pp": 20, "highCriticalHitRatio": true}
{"name": "sleep powder", "type": "grass", "category": "status", "power": null, "accuracy": 0.75, "pp": 15, "effect": {"statusCondition": "sleep"}}
{"name": "sludge", "type": "poison", "category": "special", "power": 65, "accuracy": 1.0, "pp": 20, "effect": {"chance": 0.3, "statusCondition": "poison"}}
{"name": "smog", "type": "poison", "category": "special", "power": 20, "accuracy": 0.7, "pp": 20, "effect": {"chance": 0.4, "statusCondition": "poison"}}
{"name": "smokescreen", "type": "normal", "category": "status", "power": null, "accuracy": 1.0, "pp": 20, "effect": {"stat": "accuracy", "stages": -1}}
{"name": "soft-boiled", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 10, "effects": ["Soft-Boiled recovers up to 50% of the user's maximum HP."]}
{"name": "solar beam", "type": "grass", "category": "special", "power": 120, "accuracy": 1.0, "pp": 10, "effects": ["The user of Solar Beam will absorb light on the first turn. On the second turn, Solar Beam deals damage."]}
{"name": "sonic boom", "type": "normal", "category": "special", "power": null, "accuracy": 0.9, "pp": 20, "effects": ["Sonic Boom always deals 20 HP damage to the target, regardless of typing (although Ghost type Pokémon are still immune). It has no additional effect."], "changes": ["In Generation 1, Sonic Boom hits Ghost types regardless of their immunity to Normal type moves."]}
{"name": "spike cannon", "type": "normal", "category": "physical", "power": 20, "accuracy": 1.0, "pp": 15, "effects": [], "changes": ["In Generations 1-3, Spike Cannon ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "splash", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 40}
{"name": "spore", "type": "grass", "category": "status", "power": null, "accuracy": 1.0, "pp": 15, "effect": {"statusCondition": "sleep"}}
{"name": "stomp", "type": "normal", "category": "physical", "power": 65, "accuracy": 1.0, "pp": 20, "effect": {"chance": 0.3, "statusCondition": "flinch"}}
{"name": "strength", "type": "normal", "category": "physical", "power": 80, "accuracy": 1.0, "pp": 15}
{"name": "string shot", "type": "bug", "category": "status", "power": null, "accuracy": 0.95, "pp": 40, "effect": {"stat": "speed", "stages": -1}}
{"name": "struggle", "type": "normal", "category": "physical", "power": 50, "accuracy": 1.0, "pp": null, "effects": ["Only usable when all PP are gone. Hurts the user."]}
{"name": "stun spore", "type": "grass", "category": "status", "power": null, "accuracy": 0.75, "pp": 30, "effect": {"statusCondition": "paralysis"}}
{"name": "submission", "type": "fighting", "category": "physical", "power": 80, "accuracy": 0.8, "pp": 25, "effects": ["Submission deals damage, but the user receives 1⁄4 of the damage it inflicts in recoil. In other words, if the attack does 100 HP damage to the opponent, the user will lose 25 HP."]}
{"name": "substitute", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 10, "effects": ["Uses HP to creates a decoy that takes hits."]}
{"name": "super fang", "type": "normal", "category": "physical", "power": null, "accuracy": 0.9, "pp": 10, "effects": ["Always takes off half of the opponent's HP."]}
{"name": "supersonic", "type": "normal", "category": "status", "power": null, "accuracy": 0.55, "pp": 20, "effect": {"statusCondition": "confused"}}
{"name": "surf", "type": "water", "category": "special", "power": 95, "accuracy": 1.0, "pp": 15}
{"name": "swift", "type": "normal", "category": "special", "power": 60, "accuracy": null, "pp": 20, "changes": ["In Generation 1, Swift can hit Pokémon during the invulnerable stage of Dig and Fly."]}
{"name": "swords dance", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 30, "effect": {"stat": "attack", "stages": 2}}
{"name": "tackle", "type": "normal", "category": "physical", "power": 35, "accuracy": 0.95, "pp": 35}
{"name": "tail whip", "type": "normal", "category": "status", "power": null, "accuracy": 1.0, "pp": 30, "effect": {"stat": "defense", "stages": -1}}
{"name": "take down", "type": "normal", "category": "physical", "power": 90, "accuracy": 0.85, "pp": 20, "effects": ["Take Down deals damage, but the user receives 1⁄4 of the damage it inflicted in recoil. In other words, if the attack does 100 HP damage to the opponent, the user will lose 25 HP."]}
{"name": "teleport", "type": "psychic", "category": "status", "power": null, "accuracy": null, "pp": 20}
{"name": "thrash", "type": "normal", "category": "physical", "power": 120, "accuracy": 1.0, "pp": 10, "effects": ["The user of Thrash attacks for 2-3 turns, during which it cannot switch out, and then becomes confused. Confused Pokémon have a 50% chance of hurting themselves each turn, for 1-4 turns. The damage received is as if the Pokémon attacks itself with a typeless 40 base power Physical attack.", "If Thrash is disrupted (e.g. if the move misses or the user cannot attack due to paralysis) then it will stop and not cause confusion.", "Pokémon with the ability Own Tempo or those behind a Substitute cannot be confused."], "changes": ["In Generations 1-4, Thrash has 20 PP and a base power of 90. Furthermore, sleep, freezing and flinching will pause but not disrupt Thrash.", "In Generation 1, Thrash lasts for 3-4 turns."]}
{"name": "thunder", "type": "electric", "category": "special", "power": 120, "accuracy": 0.7, "pp": 10, "effect": {"chance": 0.1, "statusCondition": "paralysis"}}
{"name": "thunder punch", "type": "electric", "category": "physical", "power": 75, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.1, "statusCondition": "paralysis"}}
{"name": "thunder shock", "type": "electric", "category": "special", "power": 40, "accuracy": 1.0, "pp": 30, "effect": {"chance": 0.1, "statusCondition": "paralysis"}}
{"name": "thunder wave", "type": "electric", "category": "status", "power": null, "accuracy": 1.0, "pp": 20, "effect": {"statusCondition": "paralysis"}}
{"name": "thunderbolt", "type": "electric", "category": "special", "power": 95, "accuracy": 1.0, "pp": 15, "effect": {"chance": 0.1, "statusCondition": "paralysis"}}
{"name": "toxic", "type": "poison", "category": "status", "power": null, "accuracy": 0.85, "pp": 10, "changes": ["In Generation 1, Toxic also increases the damage taken by Leech Seed."], "effect": {"statusCondition": "badly poison"}}
{"name": "transform", "type": "normal", "category": "status", "power": null, "accuracy": null, "pp": 10, "effects": ["User takes on the form and attacks of the opponent."]}
{"name": "tri attack", "type": "normal", "category": "special", "power": 80, "accuracy": 1.0, "pp": 10}
{"name": "twineedle", "type": "bug", "category": "physical", "power": 25, "accuracy": 1.0, "pp": 20, "effects": ["Twineedle deals damage and will strike twice (with 25 base power each time). It has a 20% chance of poisoning the target. Poison or Steel type Pokémon, those with the ability Immunity or those behind a Substitute cannot be poisoned.\nEach strike of Twineedle is treated like a separate attack:"], "changes": ["In Generations 1-2, Twineedle can poison Poison and Steel types.\nIn Generations 2-4, if a Focus Sash or Focus Band activates before the final hit, subsequent hits do not cause the holder to faint.", "In Generations 1-3, Twineedle ends immediately if any hit breaks a Substitute.", "In Generation 1, each hit will always deal the same damage - if the first critical hits, so will the rest."]}
{"name": "vice grip", "type": "normal", "category": "physical", "power": 55, "accuracy": 1.0, "pp": 30}
{"name": "vine whip", "type": "grass", "category": "physical", "power": 35, "accuracy": 1.0, "pp": 10}
{"name": "water gun", "type": "water", "category": "special", "power": 40, "accuracy": 1.0, "pp": 25}
{"name": "waterfall", "type": "water", "category": "physical", "power": 80, "accuracy": 1.0, "pp": 15}
{"name": "whirlwind", "type": "normal", "category": "status", "power": null, "accuracy": 0.85, "pp": 20}
{"name": "wing attack", "type": "flying", "category": "physical", "power": 35, "accuracy": 1.0, "pp": 35}
{"name": "withdraw", "type": "water", "category": "status", "power": null, "accuracy": null, "pp": 40, "effect": {"stat": "defense", "stages": 1}}
{"name": "wrap", "type": "normal", "category": "physical", "power": 15, "accuracy": 0.9, "pp": 20, "effects": ["Wrap inflicts damage on the first turn then traps the opponent, causing them to lose 1⁄16 of their maximum HP after each turn, for 4-5 turns. If the user holds a Grip Claw then it is always 5 turns."], "changes": ["In Generations 1-4, Wrap has 85% accuracy. Its after-effects last for 2-5 turns instead of 4-5.", "In Generation 1, Wrap simply inflicts its base power damage for 2-5 turns. While in effect, the target is unable to attack."]}
Binary file not shown.
Binary file not shown.
Binary file not shown.
+151
View File
@@ -0,0 +1,151 @@
{"national_pokedex_number": 63, "name": "abra", "types": ["psychic"], "baseStats": {"hp": 25, "attack": 20, "defense": 15, "speed": 90, "special": 105}}
{"national_pokedex_number": 142, "name": "aerodactyl", "types": ["rock", "flying"], "baseStats": {"hp": 80, "attack": 105, "defense": 65, "speed": 130, "special": 60}}
{"national_pokedex_number": 65, "name": "alakazam", "types": ["psychic"], "baseStats": {"hp": 55, "attack": 50, "defense": 45, "speed": 120, "special": 135}}
{"national_pokedex_number": 24, "name": "arbok", "types": ["poison"], "baseStats": {"hp": 60, "attack": 85, "defense": 69, "speed": 80, "special": 65}}
{"national_pokedex_number": 59, "name": "arcanine", "types": ["fire"], "baseStats": {"hp": 90, "attack": 110, "defense": 80, "speed": 95, "special": 80}}
{"national_pokedex_number": 144, "name": "articuno", "types": ["ice", "flying"], "baseStats": {"hp": 90, "attack": 85, "defense": 100, "speed": 85, "special": 125}}
{"national_pokedex_number": 15, "name": "beedrill", "types": ["bug", "poison"], "baseStats": {"hp": 65, "attack": 80, "defense": 40, "speed": 75, "special": 45}}
{"national_pokedex_number": 69, "name": "bellsprout", "types": ["grass", "poison"], "baseStats": {"hp": 50, "attack": 75, "defense": 35, "speed": 40, "special": 70}}
{"national_pokedex_number": 9, "name": "blastoise", "types": ["water"], "baseStats": {"hp": 79, "attack": 83, "defense": 100, "speed": 78, "special": 85}}
{"national_pokedex_number": 1, "name": "bulbasaur", "types": ["grass", "poison"], "baseStats": {"hp": 45, "attack": 49, "defense": 49, "speed": 45, "special": 65}}
{"national_pokedex_number": 12, "name": "butterfree", "types": ["bug", "flying"], "baseStats": {"hp": 60, "attack": 45, "defense": 50, "speed": 70, "special": 80}}
{"national_pokedex_number": 10, "name": "caterpie", "types": ["bug"], "baseStats": {"hp": 45, "attack": 30, "defense": 35, "speed": 45, "special": 20}}
{"national_pokedex_number": 113, "name": "chansey", "types": ["normal"], "baseStats": {"hp": 250, "attack": 5, "defense": 5, "speed": 50, "special": 105}}
{"national_pokedex_number": 6, "name": "charizard", "types": ["fire", "flying"], "baseStats": {"hp": 78, "attack": 84, "defense": 78, "speed": 100, "special": 85}}
{"national_pokedex_number": 4, "name": "charmander", "types": ["fire"], "baseStats": {"hp": 39, "attack": 52, "defense": 43, "speed": 65, "special": 50}}
{"national_pokedex_number": 5, "name": "charmeleon", "types": ["fire"], "baseStats": {"hp": 58, "attack": 64, "defense": 58, "speed": 80, "special": 65}}
{"national_pokedex_number": 36, "name": "clefable", "types": ["fairy"], "baseStats": {"hp": 95, "attack": 70, "defense": 73, "speed": 60, "special": 85}}
{"national_pokedex_number": 35, "name": "clefairy", "types": ["fairy"], "baseStats": {"hp": 70, "attack": 45, "defense": 48, "speed": 35, "special": 60}}
{"national_pokedex_number": 91, "name": "cloyster", "types": ["water", "ice"], "baseStats": {"hp": 50, "attack": 95, "defense": 180, "speed": 70, "special": 85}}
{"national_pokedex_number": 104, "name": "cubone", "types": ["ground"], "baseStats": {"hp": 50, "attack": 50, "defense": 95, "speed": 35, "special": 40}}
{"national_pokedex_number": 87, "name": "dewgong", "types": ["water", "ice"], "baseStats": {"hp": 90, "attack": 70, "defense": 80, "speed": 70, "special": 95}}
{"national_pokedex_number": 50, "name": "diglett", "types": ["ground"], "baseStats": {"hp": 10, "attack": 55, "defense": 25, "speed": 95, "special": 45}}
{"national_pokedex_number": 132, "name": "ditto", "types": ["normal"], "baseStats": {"hp": 48, "attack": 48, "defense": 48, "speed": 48, "special": 48}}
{"national_pokedex_number": 85, "name": "dodrio", "types": ["normal", "flying"], "baseStats": {"hp": 60, "attack": 110, "defense": 70, "speed": 100, "special": 60}}
{"national_pokedex_number": 84, "name": "doduo", "types": ["normal", "flying"], "baseStats": {"hp": 35, "attack": 85, "defense": 45, "speed": 75, "special": 35}}
{"national_pokedex_number": 148, "name": "dragonair", "types": ["dragon"], "baseStats": {"hp": 61, "attack": 84, "defense": 65, "speed": 70, "special": 70}}
{"national_pokedex_number": 149, "name": "dragonite", "types": ["dragon", "flying"], "baseStats": {"hp": 91, "attack": 134, "defense": 95, "speed": 80, "special": 100}}
{"national_pokedex_number": 147, "name": "dratini", "types": ["dragon"], "baseStats": {"hp": 41, "attack": 64, "defense": 45, "speed": 50, "special": 50}}
{"national_pokedex_number": 96, "name": "drowzee", "types": ["psychic"], "baseStats": {"hp": 60, "attack": 48, "defense": 45, "speed": 42, "special": 90}}
{"national_pokedex_number": 51, "name": "dugtrio", "types": ["ground"], "baseStats": {"hp": 35, "attack": 80, "defense": 50, "speed": 120, "special": 70}}
{"national_pokedex_number": 133, "name": "eevee", "types": ["normal"], "baseStats": {"hp": 55, "attack": 55, "defense": 50, "speed": 55, "special": 65}}
{"national_pokedex_number": 23, "name": "ekans", "types": ["poison"], "baseStats": {"hp": 35, "attack": 60, "defense": 44, "speed": 55, "special": 40}}
{"national_pokedex_number": 125, "name": "electabuzz", "types": ["electric"], "baseStats": {"hp": 65, "attack": 83, "defense": 57, "speed": 105, "special": 85}}
{"national_pokedex_number": 101, "name": "electrode", "types": ["electric"], "baseStats": {"hp": 60, "attack": 50, "defense": 70, "speed": 140, "special": 80}}
{"national_pokedex_number": 102, "name": "exeggcute", "types": ["grass", "psychic"], "baseStats": {"hp": 60, "attack": 40, "defense": 80, "speed": 40, "special": 60}}
{"national_pokedex_number": 103, "name": "exeggutor", "types": ["grass", "psychic"], "baseStats": {"hp": 95, "attack": 95, "defense": 85, "speed": 55, "special": 125}}
{"national_pokedex_number": 83, "name": "farfetch'd", "types": ["normal", "flying"], "baseStats": {"hp": 52, "attack": 65, "defense": 55, "speed": 60, "special": 58}}
{"national_pokedex_number": 22, "name": "fearow", "types": ["normal", "flying"], "baseStats": {"hp": 65, "attack": 90, "defense": 65, "speed": 100, "special": 61}}
{"national_pokedex_number": 136, "name": "flareon", "types": ["fire"], "baseStats": {"hp": 65, "attack": 130, "defense": 60, "speed": 65, "special": 110}}
{"national_pokedex_number": 92, "name": "gastly", "types": ["ghost", "poison"], "baseStats": {"hp": 30, "attack": 35, "defense": 30, "speed": 80, "special": 100}}
{"national_pokedex_number": 94, "name": "gengar", "types": ["ghost", "poison"], "baseStats": {"hp": 60, "attack": 65, "defense": 60, "speed": 110, "special": 130}}
{"national_pokedex_number": 74, "name": "geodude", "types": ["rock", "ground"], "baseStats": {"hp": 40, "attack": 80, "defense": 100, "speed": 20, "special": 30}}
{"national_pokedex_number": 44, "name": "gloom", "types": ["grass", "poison"], "baseStats": {"hp": 60, "attack": 65, "defense": 70, "speed": 40, "special": 85}}
{"national_pokedex_number": 42, "name": "golbat", "types": ["poison", "flying"], "baseStats": {"hp": 75, "attack": 80, "defense": 70, "speed": 90, "special": 75}}
{"national_pokedex_number": 118, "name": "goldeen", "types": ["water"], "baseStats": {"hp": 45, "attack": 67, "defense": 60, "speed": 63, "special": 50}}
{"national_pokedex_number": 55, "name": "golduck", "types": ["water"], "baseStats": {"hp": 80, "attack": 82, "defense": 78, "speed": 85, "special": 80}}
{"national_pokedex_number": 76, "name": "golem", "types": ["rock", "ground"], "baseStats": {"hp": 80, "attack": 110, "defense": 130, "speed": 45, "special": 55}}
{"national_pokedex_number": 75, "name": "graveler", "types": ["rock", "ground"], "baseStats": {"hp": 55, "attack": 95, "defense": 115, "speed": 35, "special": 45}}
{"national_pokedex_number": 88, "name": "grimer", "types": ["poison"], "baseStats": {"hp": 80, "attack": 80, "defense": 50, "speed": 25, "special": 40}}
{"national_pokedex_number": 58, "name": "growlithe", "types": ["fire"], "baseStats": {"hp": 55, "attack": 70, "defense": 45, "speed": 60, "special": 50}}
{"national_pokedex_number": 130, "name": "gyarados", "types": ["water", "flying"], "baseStats": {"hp": 95, "attack": 125, "defense": 79, "speed": 81, "special": 100}}
{"national_pokedex_number": 93, "name": "haunter", "types": ["ghost", "poison"], "baseStats": {"hp": 45, "attack": 50, "defense": 45, "speed": 95, "special": 115}}
{"national_pokedex_number": 107, "name": "hitmonchan", "types": ["fighting"], "baseStats": {"hp": 50, "attack": 105, "defense": 79, "speed": 76, "special": 35}}
{"national_pokedex_number": 106, "name": "hitmonlee", "types": ["fighting"], "baseStats": {"hp": 50, "attack": 120, "defense": 53, "speed": 87, "special": 35}}
{"national_pokedex_number": 116, "name": "horsea", "types": ["water"], "baseStats": {"hp": 30, "attack": 40, "defense": 70, "speed": 60, "special": 70}}
{"national_pokedex_number": 97, "name": "hypno", "types": ["psychic"], "baseStats": {"hp": 85, "attack": 73, "defense": 70, "speed": 67, "special": 115}}
{"national_pokedex_number": 2, "name": "ivysaur", "types": ["grass", "poison"], "baseStats": {"hp": 60, "attack": 62, "defense": 63, "speed": 60, "special": 80}}
{"national_pokedex_number": 39, "name": "jigglypuff", "types": ["normal", "fairy"], "baseStats": {"hp": 115, "attack": 45, "defense": 20, "speed": 20, "special": 25}}
{"national_pokedex_number": 135, "name": "jolteon", "types": ["electric"], "baseStats": {"hp": 65, "attack": 65, "defense": 60, "speed": 130, "special": 110}}
{"national_pokedex_number": 124, "name": "jynx", "types": ["ice", "psychic"], "baseStats": {"hp": 65, "attack": 50, "defense": 35, "speed": 95, "special": 95}}
{"national_pokedex_number": 140, "name": "kabuto", "types": ["rock", "water"], "baseStats": {"hp": 30, "attack": 80, "defense": 90, "speed": 55, "special": 45}}
{"national_pokedex_number": 141, "name": "kabutops", "types": ["rock", "water"], "baseStats": {"hp": 60, "attack": 115, "defense": 105, "speed": 80, "special": 70}}
{"national_pokedex_number": 64, "name": "kadabra", "types": ["psychic"], "baseStats": {"hp": 40, "attack": 35, "defense": 30, "speed": 105, "special": 120}}
{"national_pokedex_number": 14, "name": "kakuna", "types": ["bug", "poison"], "baseStats": {"hp": 45, "attack": 25, "defense": 50, "speed": 35, "special": 25}}
{"national_pokedex_number": 115, "name": "kangaskhan", "types": ["normal"], "baseStats": {"hp": 105, "attack": 95, "defense": 80, "speed": 90, "special": 40}}
{"national_pokedex_number": 99, "name": "kingler", "types": ["water"], "baseStats": {"hp": 55, "attack": 130, "defense": 115, "speed": 75, "special": 50}}
{"national_pokedex_number": 109, "name": "koffing", "types": ["poison"], "baseStats": {"hp": 40, "attack": 65, "defense": 95, "speed": 35, "special": 60}}
{"national_pokedex_number": 98, "name": "krabby", "types": ["water"], "baseStats": {"hp": 30, "attack": 105, "defense": 90, "speed": 50, "special": 25}}
{"national_pokedex_number": 131, "name": "lapras", "types": ["water", "ice"], "baseStats": {"hp": 130, "attack": 85, "defense": 80, "speed": 60, "special": 95}}
{"national_pokedex_number": 108, "name": "lickitung", "types": ["normal"], "baseStats": {"hp": 90, "attack": 55, "defense": 75, "speed": 30, "special": 60}}
{"national_pokedex_number": 68, "name": "machamp", "types": ["fighting"], "baseStats": {"hp": 90, "attack": 130, "defense": 80, "speed": 55, "special": 65}}
{"national_pokedex_number": 67, "name": "machoke", "types": ["fighting"], "baseStats": {"hp": 80, "attack": 100, "defense": 70, "speed": 45, "special": 50}}
{"national_pokedex_number": 66, "name": "machop", "types": ["fighting"], "baseStats": {"hp": 70, "attack": 80, "defense": 50, "speed": 35, "special": 35}}
{"national_pokedex_number": 129, "name": "magikarp", "types": ["water"], "baseStats": {"hp": 20, "attack": 10, "defense": 55, "speed": 80, "special": 20}}
{"national_pokedex_number": 126, "name": "magmar", "types": ["fire"], "baseStats": {"hp": 65, "attack": 95, "defense": 57, "speed": 93, "special": 85}}
{"national_pokedex_number": 81, "name": "magnemite", "types": ["electric", "steel"], "baseStats": {"hp": 25, "attack": 35, "defense": 70, "speed": 45, "special": 95}}
{"national_pokedex_number": 82, "name": "magneton", "types": ["electric", "steel"], "baseStats": {"hp": 50, "attack": 60, "defense": 95, "speed": 70, "special": 120}}
{"national_pokedex_number": 56, "name": "mankey", "types": ["fighting"], "baseStats": {"hp": 40, "attack": 80, "defense": 35, "speed": 70, "special": 35}}
{"national_pokedex_number": 105, "name": "marowak", "types": ["ground"], "baseStats": {"hp": 60, "attack": 80, "defense": 110, "speed": 45, "special": 50}}
{"national_pokedex_number": 52, "name": "meowth", "types": ["normal"], "baseStats": {"hp": 40, "attack": 45, "defense": 35, "speed": 90, "special": 40}}
{"national_pokedex_number": 11, "name": "metapod", "types": ["bug"], "baseStats": {"hp": 50, "attack": 20, "defense": 55, "speed": 30, "special": 25}}
{"national_pokedex_number": 151, "name": "mew", "types": ["psychic"], "baseStats": {"hp": 100, "attack": 100, "defense": 100, "speed": 100, "special": 100}}
{"national_pokedex_number": 150, "name": "mewtwo", "types": ["psychic"], "baseStats": {"hp": 106, "attack": 110, "defense": 90, "speed": 130, "special": 154}}
{"national_pokedex_number": 146, "name": "moltres", "types": ["fire", "flying"], "baseStats": {"hp": 90, "attack": 100, "defense": 90, "speed": 90, "special": 125}}
{"national_pokedex_number": 122, "name": "mr. mime", "types": ["psychic", "fairy"], "baseStats": {"hp": 40, "attack": 45, "defense": 65, "speed": 90, "special": 100}}
{"national_pokedex_number": 89, "name": "muk", "types": ["poison"], "baseStats": {"hp": 105, "attack": 105, "defense": 75, "speed": 50, "special": 65}}
{"national_pokedex_number": 34, "name": "nidoking", "types": ["poison", "ground"], "baseStats": {"hp": 81, "attack": 92, "defense": 77, "speed": 85, "special": 75}}
{"national_pokedex_number": 31, "name": "nidoqueen", "types": ["poison", "ground"], "baseStats": {"hp": 90, "attack": 82, "defense": 87, "speed": 76, "special": 75}}
{"national_pokedex_number": 29, "name": "nidoran♀", "types": ["poison"], "baseStats": {"hp": 55, "attack": 47, "defense": 52, "speed": 41, "special": 40}}
{"national_pokedex_number": 32, "name": "nidoran♂", "types": ["poison"], "baseStats": {"hp": 46, "attack": 57, "defense": 40, "speed": 50, "special": 40}}
{"national_pokedex_number": 30, "name": "nidorina", "types": ["poison"], "baseStats": {"hp": 70, "attack": 62, "defense": 67, "speed": 56, "special": 55}}
{"national_pokedex_number": 33, "name": "nidorino", "types": ["poison"], "baseStats": {"hp": 61, "attack": 72, "defense": 57, "speed": 65, "special": 55}}
{"national_pokedex_number": 38, "name": "ninetales", "types": ["fire"], "baseStats": {"hp": 73, "attack": 76, "defense": 75, "speed": 100, "special": 100}}
{"national_pokedex_number": 43, "name": "oddish", "types": ["grass", "poison"], "baseStats": {"hp": 45, "attack": 50, "defense": 55, "speed": 30, "special": 75}}
{"national_pokedex_number": 138, "name": "omanyte", "types": ["rock", "water"], "baseStats": {"hp": 35, "attack": 40, "defense": 100, "speed": 35, "special": 90}}
{"national_pokedex_number": 139, "name": "omastar", "types": ["rock", "water"], "baseStats": {"hp": 70, "attack": 60, "defense": 125, "speed": 55, "special": 115}}
{"national_pokedex_number": 95, "name": "onix", "types": ["rock", "ground"], "baseStats": {"hp": 35, "attack": 45, "defense": 160, "speed": 70, "special": 30}}
{"national_pokedex_number": 46, "name": "paras", "types": ["bug", "grass"], "baseStats": {"hp": 35, "attack": 70, "defense": 55, "speed": 25, "special": 55}}
{"national_pokedex_number": 47, "name": "parasect", "types": ["bug", "grass"], "baseStats": {"hp": 60, "attack": 95, "defense": 80, "speed": 30, "special": 80}}
{"national_pokedex_number": 53, "name": "persian", "types": ["normal"], "baseStats": {"hp": 65, "attack": 70, "defense": 60, "speed": 115, "special": 65}}
{"national_pokedex_number": 18, "name": "pidgeot", "types": ["normal", "flying"], "baseStats": {"hp": 83, "attack": 80, "defense": 75, "speed": 91, "special": 70}}
{"national_pokedex_number": 17, "name": "pidgeotto", "types": ["normal", "flying"], "baseStats": {"hp": 63, "attack": 60, "defense": 55, "speed": 71, "special": 50}}
{"national_pokedex_number": 16, "name": "pidgey", "types": ["normal", "flying"], "baseStats": {"hp": 40, "attack": 45, "defense": 40, "speed": 56, "special": 35}}
{"national_pokedex_number": 25, "name": "pikachu", "types": ["electric"], "baseStats": {"hp": 35, "attack": 55, "defense": 30, "speed": 90, "special": 50}}
{"national_pokedex_number": 127, "name": "pinsir", "types": ["bug"], "baseStats": {"hp": 65, "attack": 125, "defense": 100, "speed": 85, "special": 55}}
{"national_pokedex_number": 60, "name": "poliwag", "types": ["water"], "baseStats": {"hp": 40, "attack": 50, "defense": 40, "speed": 90, "special": 40}}
{"national_pokedex_number": 61, "name": "poliwhirl", "types": ["water"], "baseStats": {"hp": 65, "attack": 65, "defense": 65, "speed": 90, "special": 50}}
{"national_pokedex_number": 62, "name": "poliwrath", "types": ["water", "fighting"], "baseStats": {"hp": 90, "attack": 85, "defense": 95, "speed": 70, "special": 70}}
{"national_pokedex_number": 77, "name": "ponyta", "types": ["fire"], "baseStats": {"hp": 50, "attack": 85, "defense": 55, "speed": 90, "special": 65}}
{"national_pokedex_number": 137, "name": "porygon", "types": ["normal"], "baseStats": {"hp": 65, "attack": 60, "defense": 70, "speed": 40, "special": 75}}
{"national_pokedex_number": 57, "name": "primeape", "types": ["fighting"], "baseStats": {"hp": 65, "attack": 105, "defense": 60, "speed": 95, "special": 60}}
{"national_pokedex_number": 54, "name": "psyduck", "types": ["water"], "baseStats": {"hp": 50, "attack": 52, "defense": 48, "speed": 55, "special": 50}}
{"national_pokedex_number": 26, "name": "raichu", "types": ["electric"], "baseStats": {"hp": 60, "attack": 90, "defense": 55, "speed": 100, "special": 90}}
{"national_pokedex_number": 78, "name": "rapidash", "types": ["fire"], "baseStats": {"hp": 65, "attack": 100, "defense": 70, "speed": 105, "special": 80}}
{"national_pokedex_number": 20, "name": "raticate", "types": ["normal"], "baseStats": {"hp": 55, "attack": 81, "defense": 60, "speed": 97, "special": 50}}
{"national_pokedex_number": 19, "name": "rattata", "types": ["normal"], "baseStats": {"hp": 30, "attack": 56, "defense": 35, "speed": 72, "special": 25}}
{"national_pokedex_number": 112, "name": "rhydon", "types": ["ground", "rock"], "baseStats": {"hp": 105, "attack": 130, "defense": 120, "speed": 40, "special": 45}}
{"national_pokedex_number": 111, "name": "rhyhorn", "types": ["ground", "rock"], "baseStats": {"hp": 80, "attack": 85, "defense": 95, "speed": 25, "special": 30}}
{"national_pokedex_number": 27, "name": "sandshrew", "types": ["ground"], "baseStats": {"hp": 50, "attack": 75, "defense": 85, "speed": 40, "special": 30}}
{"national_pokedex_number": 28, "name": "sandslash", "types": ["ground"], "baseStats": {"hp": 75, "attack": 100, "defense": 110, "speed": 65, "special": 55}}
{"national_pokedex_number": 123, "name": "scyther", "types": ["bug", "flying"], "baseStats": {"hp": 70, "attack": 110, "defense": 80, "speed": 105, "special": 55}}
{"national_pokedex_number": 117, "name": "seadra", "types": ["water"], "baseStats": {"hp": 55, "attack": 65, "defense": 95, "speed": 85, "special": 95}}
{"national_pokedex_number": 119, "name": "seaking", "types": ["water"], "baseStats": {"hp": 80, "attack": 92, "defense": 65, "speed": 68, "special": 80}}
{"national_pokedex_number": 86, "name": "seel", "types": ["water"], "baseStats": {"hp": 65, "attack": 45, "defense": 55, "speed": 45, "special": 70}}
{"national_pokedex_number": 90, "name": "shellder", "types": ["water"], "baseStats": {"hp": 30, "attack": 65, "defense": 100, "speed": 40, "special": 45}}
{"national_pokedex_number": 80, "name": "slowbro", "types": ["water", "psychic"], "baseStats": {"hp": 95, "attack": 75, "defense": 110, "speed": 30, "special": 80}}
{"national_pokedex_number": 79, "name": "slowpoke", "types": ["water", "psychic"], "baseStats": {"hp": 90, "attack": 65, "defense": 65, "speed": 15, "special": 40}}
{"national_pokedex_number": 143, "name": "snorlax", "types": ["normal"], "baseStats": {"hp": 160, "attack": 110, "defense": 65, "speed": 30, "special": 65}}
{"national_pokedex_number": 21, "name": "spearow", "types": ["normal", "flying"], "baseStats": {"hp": 40, "attack": 60, "defense": 30, "speed": 70, "special": 31}}
{"national_pokedex_number": 7, "name": "squirtle", "types": ["water"], "baseStats": {"hp": 44, "attack": 48, "defense": 65, "speed": 43, "special": 50}}
{"national_pokedex_number": 121, "name": "starmie", "types": ["water", "psychic"], "baseStats": {"hp": 60, "attack": 75, "defense": 85, "speed": 115, "special": 100}}
{"national_pokedex_number": 120, "name": "staryu", "types": ["water"], "baseStats": {"hp": 30, "attack": 45, "defense": 55, "speed": 85, "special": 70}}
{"national_pokedex_number": 114, "name": "tangela", "types": ["grass"], "baseStats": {"hp": 65, "attack": 55, "defense": 115, "speed": 60, "special": 100}}
{"national_pokedex_number": 128, "name": "tauros", "types": ["normal"], "baseStats": {"hp": 75, "attack": 100, "defense": 95, "speed": 110, "special": 70}}
{"national_pokedex_number": 72, "name": "tentacool", "types": ["water", "poison"], "baseStats": {"hp": 40, "attack": 40, "defense": 35, "speed": 70, "special": 100}}
{"national_pokedex_number": 73, "name": "tentacruel", "types": ["water", "poison"], "baseStats": {"hp": 80, "attack": 70, "defense": 65, "speed": 100, "special": 120}}
{"national_pokedex_number": 134, "name": "vaporeon", "types": ["water"], "baseStats": {"hp": 130, "attack": 65, "defense": 60, "speed": 65, "special": 110}}
{"national_pokedex_number": 49, "name": "venomoth", "types": ["bug", "poison"], "baseStats": {"hp": 70, "attack": 65, "defense": 60, "speed": 90, "special": 90}}
{"national_pokedex_number": 48, "name": "venonat", "types": ["bug", "poison"], "baseStats": {"hp": 60, "attack": 55, "defense": 50, "speed": 45, "special": 40}}
{"national_pokedex_number": 3, "name": "venusaur", "types": ["grass", "poison"], "baseStats": {"hp": 80, "attack": 82, "defense": 83, "speed": 80, "special": 100}}
{"national_pokedex_number": 71, "name": "victreebel", "types": ["grass", "poison"], "baseStats": {"hp": 80, "attack": 105, "defense": 65, "speed": 70, "special": 100}}
{"national_pokedex_number": 45, "name": "vileplume", "types": ["grass", "poison"], "baseStats": {"hp": 75, "attack": 80, "defense": 85, "speed": 50, "special": 100}}
{"national_pokedex_number": 100, "name": "voltorb", "types": ["electric"], "baseStats": {"hp": 40, "attack": 30, "defense": 50, "speed": 100, "special": 55}}
{"national_pokedex_number": 37, "name": "vulpix", "types": ["fire"], "baseStats": {"hp": 38, "attack": 41, "defense": 40, "speed": 65, "special": 65}}
{"national_pokedex_number": 8, "name": "wartortle", "types": ["water"], "baseStats": {"hp": 59, "attack": 63, "defense": 80, "speed": 58, "special": 65}}
{"national_pokedex_number": 13, "name": "weedle", "types": ["bug", "poison"], "baseStats": {"hp": 40, "attack": 35, "defense": 30, "speed": 50, "special": 20}}
{"national_pokedex_number": 70, "name": "weepinbell", "types": ["grass", "poison"], "baseStats": {"hp": 65, "attack": 90, "defense": 50, "speed": 55, "special": 85}}
{"national_pokedex_number": 110, "name": "weezing", "types": ["poison"], "baseStats": {"hp": 65, "attack": 90, "defense": 120, "speed": 60, "special": 85}}
{"national_pokedex_number": 40, "name": "wigglytuff", "types": ["normal", "fairy"], "baseStats": {"hp": 140, "attack": 70, "defense": 45, "speed": 45, "special": 50}}
{"national_pokedex_number": 145, "name": "zapdos", "types": ["electric", "flying"], "baseStats": {"hp": 90, "attack": 90, "defense": 85, "speed": 100, "special": 125}}
{"national_pokedex_number": 41, "name": "zubat", "types": ["poison", "flying"], "baseStats": {"hp": 40, "attack": 45, "defense": 35, "speed": 55, "special": 40}}
+2
View File
@@ -0,0 +1,2 @@
numpy>=1.24.0
matplotlib>=3.5.0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More