I need more coffee. I forgot I refactored the constructor and forgot to update those objects down below. Thank you for spotting that!
Just playing around with this. I added the first 10 Pokemon from the Gen 6 deck and all the elements, then made a battle royale where round after round each pokemon attacks a random target in random order until there’s only one remaining.
Gonna start work on adding trainer class later. Fun times.
Still have a couple functions to add.
https://github.com/HTH24/Pokemon-Game/blob/master/Pokemon_Project.py
How can i set “is_knocked_out” =True, without calling any method on my instance, i think that my code should know automatically when the health of pokemon has become zero and automatically change its attribute is_knocked_out to True,
I searched online but didn’t find any definitive solution
Can someone please explain me how to do this, because i think i might have hit a wall here.
The easy answer should be
class Pokeman
def __init__(self, name, current_health = 50, is_knocked_out = False)
self.is_knocked_out = is_knocked_out
self.current_health = current_health
self.name = name
pikachu = Pokemon("Pikachu")
if pikachu.current_health <= 0:
pikachu.is_knocked_out = True
It’s hard to understand without seeing your code, however I suggest creating a knockout method in your class. Here is how I did it:
def knockout(self):
print("{} has been knocked out!".format(self.name))
self.is_knocked_out = True
Then
if pikachu.current_health <= 0:
pikachu.knockout()
Or create separate method for losing health which calls the knockout method when health fall below zero:
def lose_health(self, hit):
self.current_health -= hit
print("{} loses {} health".format(self.name, hit))
if self.current_health <= 0:
self.current_health = 0
self.knockout()
else:
print("{}'s current health is {}".format(self.name, self.current_health))
Hope this helps
Just a bit of fun halfway through this one
Perhaps a silly questions, but was the download for this supposed to be an empty file? The wording of the project seems to imply that items are already written.
This is exactly what I came to ask! The instructions for this whole project seem to be constantly referring to some previously-completed project that I’ve never seen.
Really enjoyed that challenge, and it’s given me a lot more confidence, particularly with classes.
Here’s my effort:
Haven’t put that much work into it but had some fun!
Hope anyone can get some inspo from what I’ve done
Hi everyone, this is my first project and I wanted to share it with you
class Pokemon:
def init (self, name, level, type, max_health, health, is_knocked_out):
self.name = name
self.level = level
self.type = type
self.max_health = max_health
self.health = health
self.is_knocked_out = is_knocked_out
def lose_health (self, health_change):
self.health = self.health - health_change
if self.health <= 0:
self.health = 0
print("{} is knocked out.".format(self.name))
self.is_knocked_out = True
def gain_health (self, health_change):
self.health = self.health + health_change
if self.health > self.max_health:
self.health = self.max_health
if self.health > 0:
self.is_knocked_out = False
print("{} now has {} health.".format(self.name,self.health))
def attack (self, other_pokemon):
damage = 0
if self.type == "Fire" and other_pokemon.type == "Fire":
damage = 0.5 * self.level
elif self.type == "Fire" and other_pokemon.type == "Water":
damage = 0.5 * self.level
elif self.type == "Fire" and other_pokemon.type == "Grass":
damage = 2 * self.level
elif self.type == "Water" and other_pokemon.type == "Fire":
damage = 2 * self.level
elif self.type == "Water" and other_pokemon.type == "Water":
damage = 0.5 * self.level
elif self.type == "Water" and other_pokemon.type == "Grass":
damage = 0.5 * self.level
elif self.type == "Grass" and other_pokemon.type == "Fire":
damage = 0.5 * self.level
elif self.type == "Grass" and other_pokemon.type == "Water":
damage = 2 * self.level
else:
damage = 0.5 * self.level
print("{} has attacked {} and caused {} points of damage.".format(self.name, other_pokemon.name,damage))
Pokemon.lose_health(other_pokemon,damage)
print("{}'s health is now {}.".format(other_pokemon.name, other_pokemon.health))
class Trainer (Pokemon):
def init (self, name, pokemons, current_pokemon, potions):
self.name = name
self.pokemons = pokemons
self.current_pokemon = current_pokemon
self.potions = potions
len(pokemons) <= 6
def use_potion (self, potion):
Pokemon.gain_health(self.current_pokemon,self.potions[potion])
def attack_other_trainer (self, other_trainer):
if self.current_pokemon.is_knocked_out == False:
Pokemon.attack(self.current_pokemon,other_trainer.current_pokemon)
else:
print("{} is knocked out and cannot attack.".format(self.current_pokemon.name))
def change_current_pokemon (self, new_pokemon):
if new_pokemon in self.pokemons and new_pokemon != self.current_pokemon:
self.current_pokemon = new_pokemon
print("Current pokemon is now {}.".format(self.current_pokemon.name))
elif self.current_pokemon.is_knocked_out:
print("You cannot change to a pokemon that is knocked out. Try again.")
else:
print("This change is not allowed. Try again.")
This isn’t the prettiest code, but it works! I think I’m finally starting to understand classes.
I wanted to prevent instances of the Trainer class from having duplicate names. So I created a global Trainers list which would be populated as new Trainer instances are created.
Then in the Trainer __init__
method, I tried to test the incoming name against all the instances in the Trainer list. If the name already exists in the list, I tried raising an error.
Unfortunately, that did not prevent a malformed Trainer from being created.
So if the name is used already, I create a trainer named ‘bad_trainer_prepare_to_destroy’. Next I implemented the __del__
dunder method.
I tried calling __del__
within the __init__
method for the case of bad input data. That didn’t work.
I tried calling it from within the __repr__
dunder method for the bad trainer: self.__del__()
Unfortunately it destroyed ALL of my Trainer class instances.
My guess is there is a more or less standard way to prevent instantiating a class with incorrect values such as a duplicate trainer name. But after quite a bit of googling, I haven’t found it yet. Any ideas for me for this type of coding problem?
Thanks in advance!
Here is the relevant code from my Trainer class:
class Trainer():
# pokemons is a list of Pokemon instances.
# potions is a list of keys to the potions dictionary.
# current pokemon is the index in list of pokemons
def __init__(self, name, pokemons, potions, current_pokemon):
try:
if name not in trainers:
self.name = name
self.pokemons = pokemons
self.potions = potions
self.current_pokemon = current_pokemon
trainers.append(self.name)
else:
self.name = 'bad_trainer_prep_for_destruction'
self.pokemons = []
self.potions = []
self.current_pokemon = -1
raise ValueError
except ValueError:
print("OOPS! Trainer name {name} already taken.".format(name = name))
# unfortunately, while this raises an error, a broken class is still instantiated. Can we manage it via __del__ ?
# at least in my tests, the __del__ dunder method destroys ALL instances of the class, even if i call it for the current instance (from inside then __repr__ when the class instance got set up incorrectly). How do i just destroy the current instance?
def __del__(self):
instance_name = self.name
print(instance_name, "destroyed")
def __repr__(self):
if self.name != 'bad_trainer_prep_for_destruction':
trainer = self.name
poke_names = self.pokemons[0].name if len(self.pokemons) > 0 else 'NONE!'
potion_names = ', '.join(self.potions)
active_poke = self.pokemons[self.current_pokemon].name if len(self.pokemons) > 0 else 'NONE!'
for poke in self.pokemons:
curr_name = poke.name
if poke_names.find(curr_name) == -1:
poke_names = poke_names + ', ' + curr_name
return "Trainer {name} is ready to go!\n{name}'s pokemons include: {pokemons}.\nAvailable healing potions are {potions}.\nActive pokemon is {active}.\n".format(name=Fore.BLUE + trainer + Style.RESET_ALL, pokemons=Fore.MAGENTA + poke_names + Style.RESET_ALL, potions=Fore.GREEN + potion_names + Style.RESET_ALL,active=Fore.RED + active_poke + Style.RESET_ALL)
else:
self.__del__()
return
And here we build some trainers, including one with a duplicate name:
# Build some trainers
ash = Trainer('Ash',[charmander, bulbasaur, charizard, wartortle], ['firewater', 'grasstea', 'nutstew', 'seaweed', 'chocolate'],0)
print(ash)
serena = Trainer('Serena',[squirtle, venusaur, charmeleon, blastoise], ['firewater', 'grasstea', 'nutstew', 'seaweed', 'chocolate'],0)
print(serena)
test that trainer names cannot be duplicated:
test = Trainer('Ash',[], ['firewater', 'grasstea', 'nutstew', 'seaweed', 'chocolate'],0)
print(test)
And here are results:
Trainer Ash is ready to go!
Ash's pokemons include: Charmander, Bulbasaur, Charizard, Wartortle.
Available healing potions are firewater, grasstea, nutstew, seaweed, chocolate.
Active pokemon is Charmander.
Trainer Serena is ready to go!
Serena's pokemons include: Squirtle, Venusaur, Charmeleon, Blastoise.
Available healing potions are firewater, grasstea, nutstew, seaweed, chocolate.
Active pokemon is Squirtle.
OOPS! Trainer name Ash already taken.
bad_trainer_prep_for_destruction destroyed
Traceback (most recent call last):
File "/Users/kevinoh/Workspace/scratchpad/pokemon_starting/pokemon.py", line 197, in <module>
print(test)
TypeError: __str__ returned non-string (type NoneType)
Ash destroyed
Serena destroyed
bad_trainer_prep_for_destruction destroyed