1

I have starting working on this Text-Based Pokemon game and I am stuck on trying to figure an evolution system that can change one class object into another class object, if that makes sense.

I've attempted to do this just by simply making the class object equal to the one I want to change:

# Trainer
new_trainer = Trainer('Trainer', 'Male')

# Test pokemon (the parameter is just a level value)
bulbasaur = Bulbasaur(10)
ivysaur = Ivysaur(20)

# Adding pokemon to party
new_trainer.add_pokemon(bulbasaur)
new_trainer.add_pokemon(ivysaur)

# Display pokemon lists
print(new_trainer.pokemon_list)
new_trainer.display_party()

# Attempting to 'evolve' bulbasuar
bulbasaur = Ivysaur(bulbasaur.lvl)

# Displaying results again to see if it worked
print(new_trainer.pokemon_list)
new_trainer.display_party()

But by looking at the output, it shows that nothing has happened:

Bulbasaur was added to your party!
Ivysaur was added to your party!

[<__main__.Bulbasaur object at 0x0000023587EDA080>, <__main__.Ivysaur object at 0x0000023587EDA0F0>]

1. Bulbasaur
2. Ivysaur

[<__main__.Bulbasaur object at 0x0000023587EDA080>, <__main__.Ivysaur object at 0x0000023587EDA0F0>]

1. Bulbasaur
2. Ivysaur

EDIT: It turns that that the variable value DOES indeed change, but I simply need to update the Trainer's pokemon list. However, I am still unsure on how to do this.

The display_party function in the Trainer class looks like this:

def display_party(self):  # Displays pokemon party list
        if not self.pokemon_list:
            return print("There are no pokemon in your party.")
        else:
            for pokemon in range(len(self.pokemon_list)):
                print("{0}. {1}".format(pokemon + 1, self.pokemon_list[pokemon].name))

I was just thinking of adding an update_party function, which goes into the list, deletes the old value and inserts the new value, but how will it know what value to delete?

Perhaps there is a better way to do this? And sorry if my question doesn't include that much information, I will add more of my code if it doesn't make much sense already. This is my first time asking a question here :D

EDIT 2: For those who don't understand how the code works, this is basically how it works so far:

# Formula used to calculate pokemon health
def health_stat_calculation(base_stat, lvl):
    return int(((base_stat * 3 * lvl) / 100) + lvl + 10)

# Formula used to calculate pokemon stats
def stat_calculation(base_stat, lvl):
    return int(((base_stat * 3 * lvl) / 100) + 5)


# Trainer class
class Trainer:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        self.pokemon_list = []
        self.item_list = []


    def add_badge(self, badge):  # Gives player a badge
        self.player_badges.append(badge)


    def add_pokemon(self, pokemon):  # Adds a pokemon to party

        for poke in self.pokemon_list:
            if pokemon is poke:
                return print("You already have this pokemon in your party!")

        if len(self.pokemon_list) > 5:
            return print("You have too much pokemon in your party!")
        else:
            self.pokemon_list.append(pokemon)
            return print("{} was added to your party!".format(pokemon.name))


    def display_party(self):  # Displays pokemon party list
            if not self.pokemon_list:
                return print("There are no pokemon in your party.")
            else:
                for pokemon in range(len(self.pokemon_list)):
                    print("{0}. {1}".format(pokemon + 1, self.pokemon_list[pokemon].name))


    def add_item(self, item):  # Adds an item to player's inventory
        if len(self.item_list) > 50:
            print("You have too much items in your inventory!")
        else:
            self.item_list.append(item)
            print("{} was added to your inventory!")


# Generic pokemon class
class Pokemon:
    def __init__(self, name, lvl, exp, id_number, health, attack, defence, sp_attack, sp_defense, speed):
        self.name = name
        self.lvl = lvl
        self.exp = exp
        self.id_number = id_number
        self.health = health
        self.attack = attack
        self.defence = defence
        self.sp_attack = sp_attack
        self.sp_defense = sp_defense
        self.speed = speed


    def get_pokemon_name(self):
            return self.name


    # User friendly stat display
    def display_stats(self):
        print("\nStats for {}\n---------------".format(self.name))
        print("Level: {}".format(self.lvl))
        print("Index No.{}".format(self.id_number))
        print("Health: {}".format(self.health))
        print("Attack: {}".format(self.attack))
        print("Defense: {}".format(self.defense))
        print("Sp. Attack: {}".format(self.sp_attack))
        print("Sp. Defense: {}".format(self.sp_defense))
        print("Speed: {}\n".format(self.speed))


    # Level up pokemon and show change in stats
    def level_up(self):
        self.display_stats()
        self.lvl += 1
        print("\n{} has leveled up!\n".format(self.name))
        self.calculate_stats()
        self.display_stats()


    # Calculate generic pokemon stats
    def calculate_stats(self):
        self.health = health_stat_calculation(self.base_health, self.lvl)
        self.attack = stat_calculation(self.base_attack, self.lvl)
        self.defense = stat_calculation(self.base_defense, self.lvl)
        self.sp_attack = stat_calculation(self.base_sp_attack, self.lvl)
        self.sp_defense = stat_calculation(self.base_sp_defense, self.lvl)
        self.speed = stat_calculation(self.base_speed, self.lvl)


# Bulbasaur class
class Bulbasaur(Pokemon):
    def __init__(self, lvl, name="Bulbasaur"):
        self.name = name
        self.lvl = 16
        self.exp = 0
        self.id_number = 1

        # Bulbasaur Base stats
        self.base_health = 45 
        self.base_attack = 49
        self.base_defense = 49
        self.base_sp_attack = 65
        self.base_sp_defense = 65
        self.base_speed = 45

        self.calculate_stats()


# Ivysaur class
class Ivysaur(Pokemon):
    def __init__(self, lvl, name="Ivysaur"):
        self.name = name
        self.lvl = 16
        self.exp = 0
        self.id_number = 2

        # Bulbasaur Base stats
        self.base_health = 60
        self.base_attack = 62
        self.base_defense = 63
        self.base_sp_attack = 80
        self.base_sp_defense = 80
        self.base_speed = 60

        self.calculate_stats()
  • Possible duplicate of [Python list doesn't reflect variable change](https://stackoverflow.com/questions/12080552/python-list-doesnt-reflect-variable-change) – MB-F Nov 28 '17 at 12:56

3 Answers3

0

Casting from one class to another makes no sense in your case.

Just go with

class Pokemon():
    def __init__(self, name, level=0):
        self.level = level
        self.name = name

    def evolve(self):
        self.level += 1

    def __str__(self):
        return 'Pokemon: {}, Level: {}'.format(self.name, self.level)


p1 = Pokemon('Bulbasaur')
p2 = Pokemon('Ivysaur')

print(p1)
print(p2)

p1.evolve()
p2.evolve()

print(p1)
print(p2)
Prime Reaper
  • 176
  • 2
  • Thanks for the suggestion! However, the problem isn't to level up the pokemon, the problem is that both the Bulbasaur and Ivysaur classes are subclasses of a Pokemon class, but I want to be able to one to the other so things like stat calculation can be handled in those subclasses. – Nathan Baylon Nov 28 '17 at 13:34
  • @NathanBaylon you can override calculate_stats in your subclasses. – Prime Reaper Nov 28 '17 at 14:04
0

You could turn the kind, Bulbasaur, Ivysaur, etc., into a component of the Pokemon class. The Bulbasaur has its next evolution stage as an attribute and in the evolve method of the Pokemon you can just set the kind to the next evolution stage.

class Pokemon:

    def __init__(self, kind, level):
        self.level = level
        self.kind = kind  # The kind is just a component now.

    def evolve(self):
        # Create a new instance of the next evolution stage 
        # and use it to replace the previous kind.
        self.kind = self.kind.evolution_stage()


class Bulbasaur:

    def __init__(self):
        self.base_health = 45
        # A reference to the next evolution stage class.
        self.evolution_stage = Ivysaur


class Ivysaur:

    def __init__(self):
        self.base_health = 60
        # self.evolution_stage = Venusaur


# Pass a Bulbasaur instance as the `kind` argument.
pokemons = [Pokemon(Bulbasaur(), 3)]
print(pokemons[0].kind, pokemons[0].kind.base_health)
pokemons[0].evolve()  # Changes the .kind attribute.
print(pokemons[0].kind, pokemons[0].kind.base_health)
skrx
  • 19,980
  • 5
  • 34
  • 48
0

I don't know if this is the cleanest way, but somehow it worked when I added this function into the Pokemon class and used the dict dunder to update the contents of the old object to the new one. The temp_pos was used as a temporary placeholder for the current object's name so it didn't get changed when updating it to the new_pokemon object.

# Evolve function
def evolve(self, evln, trainer):
    temp_name = self.name
    new_pokemon = evln(self.lvl)
    self.__dict__.update(new_pokemon.__dict__)
    self.name = temp_name