Become A Pokemon Master

HI, below I public my code for “Become A Pokemon Master” practice. I will be grateful if you can check it and give me a constructive feedback :slight_smile:
FYI: im totalny noob :stuck_out_tongue:

# dictionar with pokemon type advantages, first type in value is stronger than second in pair 
pokemon_advantages = { 'adv_1': ["Fire", "Grass"], 'adv_2':["Water", "Fire"], 'adv_3': ["Grass", "Water"]  }

class Pokemon():
  def __init__(self, name, level, p_type):
    self.name = name
    self.level = level
    self.p_type = p_type
    self.health = 100 * level
    self.max_health = 100 * level
    self.exp = 0
    self.max_exp = 5 * level
    self.knocked_down = False

  def __repr__(self):
    return self.name
    return self.level
    return self.health
    return self.p_type
    return self.exp
    return self.knocked_down

  def knocked_out(self):
    self.knocked_down = True
    self.health = 0
    print("{name} is knocked down.".format(name = self.name))

  def lose_health(self, lose_health):
    self.health -= lose_health
    if self.health > 0:
      print("{name} lose health! Curent health brings: {health} points".format(name=self.name, health=self.health))
    else:
      self.knocked_out()
    
  def gain_health (self, add_health):
    self.health += add_health
    if self.knocked_down == True:
      self.health = 0
      print("{name} is KO!!! You should first revive Pokemon".format(name=self.name))
    elif self.health < self.max_health:
      print("{name} recovered +{h} health points, current have {health} health points".format(h = add_health, name=self.name, health=self.health))
    else:
      self.health = self.max_health
      print("{name} recovered MAX health points, current have {health} health points".format(name=self.name, health=self.health))
  
  def revive(self):
    if self.knocked_down == True:
      self.knocked_down = False
      self.health = 100
      print ("{name} is revive!!!".format(name = self.name))
      print ("{name} current health points: {health}".format(name = self.name, health = self.health))
    else: 
      print("{p} is still alive.".format(p = self.name))
      
  def attack(self, other_p, ind = 20):
    if self.knocked_down == True or other_p.knocked_down == True:
      print("One of Pokemon's are KO, attack is not possible.")
    else:
      damage = (self.level*ind)/2
      for p1,p2 in pokemon_advantages.values():
        if self.p_type == p1 and other_p.p_type == p2:
          damage = 2 * self.level * ind
          break         
        else:
          continue
      print( self.name+" attack " + other_p.name +" for "+str(damage))
      other_p.lose_health(damage)
      self.exp_up()

  def exp_up(self):
    self.exp+=1
    if self.exp < self.max_exp:
      print("{name} receive new exp points. Total exp points is {exp}.".format(name=self.name, exp=self.exp))
    else:
      self.exp = 0
      self.level+= 1
      print("Congratulations {name} level up!!!. New level is {lvl}.".format(name=self.name, lvl=self.level))


class Trainer(): 
  def __init__(self, name, pokemons, current_pokemon = "N/A"):
    self.name = name
    self.pokemons = pokemons
    self.potions = int(len(pokemons))
    self.current_pokemon = current_pokemon

  def __repr__(self):
    self.name
    self.pokemons
    self.potions
    self.current_pokemon

  def potion(self):
    self.potions -=1
    if self.potions > 0:
      pokemon = self.current_pokemon
      pokemon.gain_health(50)
    else:
      print("No potions.")
    
  def pick_p(self, pokemon):# set a current pokemon,
    print ("Available pokemons: "+ str(self.pokemons)+"\n""Your choice is {p}".format(p = pokemon))
    if pokemon in self.pokemons:
      if pokemon.knocked_down == False:
        self.current_pokemon = pokemon
        print ("{pokemon} is active pokemon".format(pokemon = self.current_pokemon.name))
      else:
        print("You can't pick this pokemon, {p} is KO.".format(p = pokemon.name ))
    else:
      print("You can't pick this pokemon, {p} is not available for You.".format(p= pokemon.name))

  def attack_other_trainer(self, other_trainer): # attack between current pokemons, belonging to two different trainers  
    if self.current_pokemon != "N/A" and other_trainer.current_pokemon!= "N/A" :
      print("{t1} pick {p1} and attack {t2} who pick to defence a {p2}".format(t1 = self.name, p1 = self.current_pokemon.name, t2 = other_trainer.name, p2 = other_trainer.current_pokemon.name))
      self.current_pokemon.attack(other_trainer.current_pokemon)
    else:
      if self.current_pokemon == "N/A" and other_trainer.current_pokemon == "N/A":
        print ("{t1} and {t2} should pick pokemons to fight.".format(t1 = self.name, t2 = other_trainer.name))
      elif self.current_pokemon == "N/A":
        print ("{t1} should pick pokemon to fight.".format(t1 = self.name))
      else:
        print ("{t1} should pick pokemon to fight.".format(t1 = other_trainer.name))

  def add_p(self, new_p): # add new pokemon to trainer pocket with available pokemons
    if not new_p in  self.pokemons:
      self.pokemons.append(new_p)
      print("{np} is added to Your pocket.".format(np = new_p.name))
      print("Current pocket:")
      print(self.pokemons)
    else:
      print("You had {np} in pocket before.".format( np = new_p.name))   

# Test it :) 
a = Pokemon("Pokemon A", 1, "Fire")
b = Pokemon("Pokemon B", 1,"Grass")
c = Pokemon("Pokemon C", 1,"Water")
d = Pokemon("Pokemon D", 1,"Water")
t1 = Trainer("Trainer 1", [a,b,c,d])
t2 = Trainer("Trainer 2", [a,b,d])

1 Like

Nice!

Some ideas:

It’d be nice to have some input option to interact with it. (not too hard to add given what you’ve done here). Could walk you through the prompt of picking pokemon and trainers to attack.

Some functions to list available pokemons, available trainers to attack, show current pokemons in pocket, display pokemon stats, would also be cool.

Hi @micro0381828704.

Have a close look at both __repr__ defintiions and perhaps try printing them, they may not work as you expect. I guess it’s because it’s a practice but be aware that you’ve used the same Pokemon instance objects for two different Trainer instances; attributes like health would effectively be shared. Worth having a once over of the potion method too, the order there seems a little off. Keep up the good work though.

Hi,
Thanks for the feedback, I will be work on your tips :slight_smile:

@toastedpitabread
I had a issue with input, but i resolve it and i will add this functionality and other new functions.

@tgrtim
Can you expand what did you mean about repr. How it should look?
Mentioned to potion method, you have right I will change it.

I will be back with upgrade code. Give me a time :slight_smile:
Thanks A lot.

1 Like

Your __repr__ attribute should always return a string. If it doesn’t it will throw an error. Also be careful about how the return statement executes in a function. Statements following it won’t be of much use.

Hi,

Im back with up to data code :slight_smile: Please look on and give me feedback. :slight_smile:
Im not sure this “input” solution.
I added some new function:

Below new cods:

# dictionar with pokemon type advantages, first type in value is stronger than second in pair 
pokemon_advantages = { 'adv_1': ["Fire", "Grass"], 'adv_2':["Water", "Fire"], 'adv_3': ["Grass", "Water"]  }

class Pokemon():
  def __init__(self, name, level, p_type):
    self.name = name
    self.level = level
    self.p_type = p_type
    self.health = 100 * level
    self.max_health = 100 * level
    self.exp = 0
    self.max_exp = 5 * level
    self.knocked_down = False
    self.atk = 20
    self.deff = 10

  def __repr__(self):
    return self.name
    return self.p_type

  def knocked_out(self):
    self.knocked_down = True
    self.health = 0
    print("{name} is knocked down.".format(name = self.name))

  def lose_health(self, lose_health):
    self.health -= lose_health
    if self.health > 0:
      print("{name} lose health! Curent health brings: {health} points".format(name=self.name, health=self.health))
    else:
      self.knocked_out()
    
  def gain_health (self, add_health):
    self.health += add_health
    if self.knocked_down == True:
      self.health = 0
      print("{name} is KO!!! You should first revive Pokemon".format(name=self.name))
    elif self.health < self.max_health:
      print("{name} recovered +{h} health points, current have {health} health points".format(h = add_health, name=self.name, health=self.health))
    else:
      self.health = self.max_health
      print("{name} recovered MAX health points, current have {health} health points".format(name=self.name, health=self.health))
  
  def revive(self):
    if self.knocked_down == True:
      self.knocked_down = False
      self.health = 100
      print ("{name} is revive!!!".format(name = self.name))
      print ("{name} current health points: {health}".format(name = self.name, health = self.health))
    else: 
      print("{p} is still alive.".format(p = self.name))
      
  def attack(self, other_p):
    ind = self.atk - other_p.deff
    if self.knocked_down == True or other_p.knocked_down == True:
      print("One of Pokemon's are KO, attack is not possible.")
    else:
      damage = (self.level*ind)
      for p1,p2 in pokemon_advantages.values():
        if self.p_type == p1 and other_p.p_type == p2:
          damage = 2 * self.level * ind
          self.atk+=1
          other_p.deff+=2
          break         
        else:
          continue
      print( self.name+" attack " + other_p.name +" for "+str(damage))
      other_p.lose_health(damage)
      if damage == self.level*ind:
        self.atk+=2
        other_p.deff+=1
      else:
        pass
      self.exp_up()
    
  def exp_up(self):
    self.exp+=1
    if self.exp < self.max_exp:
      print("{name} receive new exp points. Total exp points is {exp}.".format(name=self.name, exp=self.exp))
    else:
      self.exp = 0
      self.level+= 1
      self.max_exp = self.level*5
      self.health = self.level*100
      self.max_health = self.level*100
      print("Congratulations {name} level up!!!. New level is {lvl}.".format(name=self.name, lvl=self.level))

  def stats(self):# display actual stats pokemons 
    print("Name: {n}\n Type: {t}\n Level: {l}\n Health|max: {h}|{hm}\n Exp|max: {e}|{em}\n Attack: {a}\n Defence: {d}\n".format(n=self.name,t=self.p_type,l=self.level, h=self.health, hm=self.max_health, e=str(self.exp), em=str(self.max_exp), a=self.atk, d=self.deff))
    

class Trainer(): 
  def __init__(self, name, pokemons, current_pokemon = "N/A"):
    self.name = name
    self.pokemons = pokemons
    self.potions = int(len(pokemons))
    self.current_pokemon = current_pokemon
    
  def __repr__(self):
    return self.name

  def potion(self):
    try:
      pots = int(input("How many potions do you want use?:"))
      pot = int(pots)
      if pot <=0:
        print("You don't have any potion.")
      elif self.potions >= pot:
        pokemon = self.current_pokemon
        if pokemon != "N/A":
          if pokemon.health == pokemon.max_health:
            pokemon.gain_health(50)
          else:
            self.potions -= pot
            pokemon.gain_health(50*pot)
        else:
          print("Pick pokemon!")
      else:
        print("You don't have enough potions.")
    except ValueError:
        print("Put in only value.")
 
  def pick_p(self):# set a current pokemon,
    print ("Available pokemons to set a active pokemon: "+ str(self.pokemons))
    pokemon_in = input("Your choice?:")
    pokemon = pokemon_in.title()
    for i in range(0, len(self.pokemons)):
      if pokemon == self.pokemons[i].name:
        if self.pokemons[i].knocked_down == False:
          self.current_pokemon = self.pokemons[i]
          print ("{p} is active pokemon".format(p = pokemon))
          break
        else:
          print("You can't pick this pokemon, {p} is KO.".format(p = pokemon ))
          break
      else:
        if i < len(self.pokemons)-1:
          continue
        else:
          print("You can't pick this pokemon, {p} is not available for You.".format(p= pokemon))

  def attack_other_trainer(self): # attack between current pokemons, belonging to two different trainers
    print("Available trainers to attack:")
    print(trainers_to_attack)
    other = input("Pick trainer to attack: ")
    other_trainer = other.title()
    for i in range(0, len(trainers_to_attack)):
      if self.name == other_trainer:
        print("You can't attack self!")
        break
      elif other_trainer == trainers_to_attack[i].name:
        if self.current_pokemon != "N/A" and trainers_to_attack[i].current_pokemon!= "N/A" :
          print("{t1} pick {p1} and attack {t2} who pick to defence a {p2}".format(t1 = self.name, p1 = self.current_pokemon.name, t2 = trainers_to_attack[i].name, p2 = trainers_to_attack[i].current_pokemon.name))
          self.current_pokemon.attack(trainers_to_attack[i].current_pokemon)
          break
        else:
          if self.current_pokemon == "N/A" and trainers_to_attack[i].current_pokemon == "N/A":
            print ("{t1} and {t2} should pick pokemons to fight.".format(t1 = self.name, t2 = trainers_to_attack[i].name))
            break
          elif self.current_pokemon == "N/A":
            print ("{t1} should pick pokemon to fight.".format(t1 = self.name))
            break
          else:
            print ("{t1} should pick pokemon to fight.".format(t1 = trainers_to_attack[i].name))
            break
      else:
        if i < len(trainers_to_attack)-1:
          continue
        else:
          print(other_trainer + " didn't exist. Pick trainer from above list.")

  def add_p(self): # add new pokemon to trainer pocket with available pokemons
    print ("Available pokemons to add your pocket, "+ self.name+":")
    print(available_pokemons)
    pokemon_in = input("Which pokemon you want to add to your pocket?:")
    new_p = pokemon_in.title()
    for i in range(0, len(available_pokemons)):
      if new_p == available_pokemons[i].name:
        if not available_pokemons[i] in self.pokemons:
          self.pokemons.append(available_pokemons[i])
          print("{np} is added to Your pocket.".format(np = new_p))
          print("Current pocket:")
          print(self.pokemons)
          break
        else:
          print("You had {np} in pocket before.".format( np = new_p))
          break
      else:
        if i < len(available_pokemons)-1:
          continue
        else:
          print("Pokemon didn't exist.")

  

# Test it :) 
a = Pokemon("Pokemon 1", 1, "Fire")
b = Pokemon("Pokemon 2", 1,"Grass")
c = Pokemon("Pokemon 3", 1,"Water")
d = Pokemon("Pokemon 4", 1,"Water")
t1 = Trainer("Trainer 1", [a,b,c,d],a)
t2 = Trainer("Trainer 2", [a,b,d],b)
t3 = Trainer("Trainer 3",[a,d])
t4 = Trainer("Trainer 4",[a])
trainers_to_attack = [t1,t2,t3,t4]
available_pokemons = [a,b,c,d]



Kudos on trying to improve your code.Apologies if this seems a bit lengthy but I tried running the code and there were a number of issues, just try and tick them off one by one.

Have you tried using any of the methods? I tried running the code and I’m getting errors with undefined names in most of them. Is this an error with self.name vs. name?

Unfortunately you still have a function with more than one return, this will not do what you want. A return statemet exits that code block immediately. Nothing after it will be used.

I can see a few redundant else: statements. It’s perfectly acceptable to have an if statement without a following else statement. In some cases it might be more readable to include an else that doesn’t do anything but think very carefully if they actually help anyone to understand your code.

Be careful about reusing instances. You have four trainers with exactly the same Pokemon- a. Damage to one is shared betweem all of them. It’s the same object.

Hi,
Thanks for reply.

Reference to your coments.
Paragraph 2: Yes, i tried and my methods looked fine. Can you give me some example where you found a errors. Also, what do you mean error self.name vs. name?

Rest is for me clear, i will try fix it.

I had a problem with syntax/code. I’m not sure this solution. Can yo help me resolve it.
My question reference to my cod:

  1. I have few instances Pokemon, variable: a, b, c, d. Is any possibility to collect all instances variable in for example list? I did it manualy.
  2. When i have self.name (some instance ), can i call other atributs this instance, using name this instance?
    In my code i made list with all instances variable. Mayby i can do this better?

Thanks :slight_smile:

I meant that certain names bound to the object need to be prefaced by self. Without this they only exist in the scope of each individual method and so on. Since I got name errors from the following methods I was wondering if that was the cause (I did not actually check).

t1.add_p() # throws a name error
t1.attack_other_trainer() # another name error

It’s perfectly reasonable to gather up references to your instances. A list would work, perhaps a dictionary would be even nicer if they have unique names?
Yes you can call methods and attributes from the same instance-

class ATest:
    def method1(self, a_value):
        print(f"This is a value printed from method1: {a_value}")

    def method2(self, another_value):
            return self.method1(another_value)  # calls method1 attribute


test_instance = ATest()
test_instance.method2(3)
Out: This is a value printed from method1: 3

Hi,

Below my new cod. I tried resolve an issue.
PLease look on corrected cod and give me a feedback :slight_smile: :

# dictionar with pokemon type advantages, first type in value is stronger than second in pair 
pokemon_advantages = { 'adv_1': ["Fire", "Grass"], 'adv_2':["Water", "Fire"], 'adv_3': ["Grass", "Water"]  }
import math

class Pokemon():

    def __init__(self, name, level, p_type):
        self.name = name
        self.level = level
        self.p_type = p_type
        self.health = 100 * level
        self.max_health = 100 * level
        self.exp = 0
        self.max_exp = 5 * level
        self.knocked_down = False
        self.atk = 20
        self.deff = 10

    def __repr__(self):
        return self.name

    def knocked_out(self):
        self.knocked_down = True
        self.health = 0
        print("{name} is knocked down.".format(name = self.name))

    def lose_health(self, lose_health):
        self.health -= math.fabs(lose_health)
        if self.health > 0:
            print("{name} lose health! Curent health brings: {health} points".format(name=self.name, health=self.health))
        else:
            self.knocked_out()
    
    def gain_health (self, add_health):
        self.health += math.fabs(add_health)
        if self.knocked_down == True:
            self.health = 0
            print("{name} is KO!!! You should first revive Pokemon".format(name=self.name))
        elif self.health < self.max_health:
            print("{name} recovered +{h} health points, current have {health} health points".format(h = add_health, name=self.name, health=self.health))
        else:
            self.health = self.max_health
            print("{name} recovered MAX health points, current have {health} health points".format(name=self.name, health=self.health))
  
    def revive(self):
        if self.knocked_down == True:   
            self.knocked_down = False
            self.health = 100
            self.level = 1
            self.max_health = 100 * self.level
            self.max_exp = 5 * self.level
            print ("{name} is revive!!!".format(name = self.name))
            print ("{name} current health points: {health} and level: {lvl}".format(lvl = self.level, name = self.name, health = self.health))
        else: 
            print("{p} is still alive.".format(p = self.name))
      
    def attack(self, other_p):
        ind = math.fabs(self.atk - other_p.deff) # coefficient attack, define power attack given pokemon experience atk and deff.
        damage = self.level*ind # attack power 
        for p1,p2 in pokemon_advantages.values():#loop change damage value if pokemon have advantage
            if self.p_type == p1 and other_p.p_type == p2:
                damage = 2 * self.level * ind
                break         
            else:
                continue

        if self.knocked_down == True or other_p.knocked_down == True: # check KO
            print("One of Pokemon's are KO, attack is not possible.")
        elif damage == self.level*ind: # attack without advantage
            self.atk+=2
            other_p.deff+=1
            print( self.name+" attack " + other_p.name +" for "+str(damage))
            other_p.lose_health(damage)
            self.exp_up()
        else: # attack with advanage
            self.atk+=1
            other_p.deff+=2
            print( self.name+" attack " + other_p.name +" for "+str(damage))
            other_p.lose_health(damage)
            self.exp_up()
    
    def exp_up(self):
        self.exp+=1
        if self.exp < self.max_exp:
            print("{name} receive new exp points. Total exp points is {exp}.".format(name=self.name, exp=self.exp))
        else:
            self.exp = 0
            self.level+= 1
            self.max_exp = self.level*5
            self.health = self.level*100
            self.max_health = self.level*100
            print("Congratulations {name} level up!!!. New level is {lvl}.".format(name=self.name, lvl=self.level))

    def stats(self):# display actual stats pokemons 
        print("Name: {n}\n Type: {t}\n Level: {l}\n Health|max: {h}|{hm}\n Exp|max: {e}|{em}\n Attack: {a}\n Defence: {d}\n".format(n=self.name,t=self.p_type,l=self.level, h=self.health, hm=self.max_health, e=str(self.exp), em=str(self.max_exp), a=self.atk, d=self.deff))
    

class Trainer(): 

    def __init__(self, name, current_pokemon = "N/A"):
        self.name = name
        self.pokemons = []
        self.potions = 4
        self.current_pokemon = current_pokemon
    
    def __repr__(self):
        return self.name

    def potion(self):
        if self.potions == 0:
            print("You don't have any potion.")
        elif self.current_pokemon != "N/A":
            self.potions -= 1
            self.current_pokemon.gain_health(50)
        else:
            print("Pick pokemon!")      
 
    def pick_p(self):# set a current pokemon
        print ("Available pokemons to set a active pokemon: "+ str(self.pokemons))
        pokemon_in = input("Your choice?:")
        pokemon = pokemon_in.title()
        if len(self.pokemons)>0:
            for i in range(0, len(self.pokemons)): #set pokemon
                if pokemon == self.pokemons[i].name and self.pokemons[i].knocked_down == False:
                    self.current_pokemon = self.pokemons[i]
                    print ("{p} is active pokemon".format(p = pokemon))
                    break
                else:
                    if i < len(self.pokemons)-1: # loop looking for a input pokemon 
                        continue
                    else:
                        print("You can't pick this pokemon, {p} is not available for You or is KO".format(p= pokemon))
        else:
            print ("You don't have any pokemon in pocket")

    def attack_other_trainer(self): # attack between current pokemons, belonging to two different trainers
        print("Available trainers to attack:")
        print(trainers_to_attack)
        other = input("Pick trainer to attack: ")
        other_trainer = other.title()
        if self.name == other_trainer: # 1 step
            print("You can't attack self!")
        else:
            for i in range(0, len(trainers_to_attack)): 
                if other_trainer == trainers_to_attack[i].name: # attack if treiners have current pokemons
                    if self.current_pokemon != "N/A" and trainers_to_attack[i].current_pokemon!= "N/A" :
                        print("{t1} pick {p1} and attack {t2} who pick to defence a {p2}".format(t1 = self.name, p1 = self.current_pokemon.name, t2 = trainers_to_attack[i].name, p2 = trainers_to_attack[i].current_pokemon.name))
                        self.current_pokemon.attack(trainers_to_attack[i].current_pokemon)
                        break
                    else: # other possibility 
                        if self.current_pokemon == "N/A" and trainers_to_attack[i].current_pokemon == "N/A":
                            print ("{t1} and {t2} should pick pokemons to fight.".format(t1 = self.name, t2 = trainers_to_attack[i].name))
                            break
                        elif self.current_pokemon == "N/A":
                            print ("{t1} should pick pokemon to fight.".format(t1 = self.name))
                            break
                        else:
                            print ("{t1} should pick pokemon to fight.".format(t1 = trainers_to_attack[i].name))
                            break
                else:
                    if i < len(trainers_to_attack)-1:
                        continue
                    else:
                        print(other_trainer + " didn't exist. Pick trainer from above list.")

    def add_p(self): # add new pokemon to trainer pocket from available pokemons
        print ("Available pokemons to add your pocket "+ self.name+":")
        print(available_pokemons)
        pokemon_in = input("Which pokemon do you want to add to your pocket?:")
        new_p = pokemon_in.title()
        if len(available_pokemons)>0:
            for i in range(0, len(available_pokemons)):
                if new_p == available_pokemons[i].name:
                    if not available_pokemons[i] in self.pokemons:
                        self.pokemons.append(available_pokemons.pop(i))
                        print("{np} is added to Your pocket.".format(np = new_p))
                        print("Current pocket:")
                        print(self.pokemons)
                        break
                    else:
                        print("You had {np} in pocket before.".format( np = new_p))
                        break
                else:
                    if i < len(available_pokemons)-1:
                        continue
                    else:
                        print("You had pokemon in pocket before or pokemon didn't exist.")
        else:
            print("No available pokemons.")

    def current_p_revive(self):# back trainer pokemon to life
        self.current_pokemon.revive()

    def current_p_stats(self): # current pokemon stats
        self.current_pokemon.stats()
        
  

# Class objects********************
a = Pokemon("Charmander", 1, "Fire")
b = Pokemon("Bulbasaur", 1,"Grass")
c = Pokemon("Squirtle", 1,"Water")
d = Pokemon("Blastoise", 1,"Water")
e = Pokemon("Vulpix", 1,"Fire")
f = Pokemon("Oddish", 1,"Grass")
g = Pokemon("Psydck", 1,"Water")
h = Pokemon("Ponyta", 1,"Fire")
t1 = Trainer("Ash")
t2 = Trainer("Brock")
t3 = Trainer("Jessie")
t4 = Trainer("James")
trainers_to_attack = [t1,t2,t3,t4]
available_pokemons = [a,b,c,d,e,f,g,h]
# Test it ************************
# Use my objects
# 1. add pokemon to trainer pocket
# 2. pick pokemon to current pokemon 
# 3. now you can attack