-1

Hey stackoverflow users,

I am trying to write a Python class for a pokemon battle. I followed the posts here, but I am trying to integrate the different pokemon typing. For instance, fire, grass, and water and allow them to function as they do in the game. For example, fire is super effective against grass. I am not sure if I should add in another function for type or define the typing within the constructor and write a series of nesting statements that determine effectiveness or ineffectiveness.

class Pokemon(object):
        def __init__(self, name, HP, Damage, type):
        self.name = name     #Sets the name of the Pokemon
        self.HP = HP         #The Hit Points or health of this pokemon
        self.Damage = Damage #The amount of Damage this pokemon does every     attack
        self.type = type #Determines the type of the pokmeon to factor in effectiveness

    def Battle(self, Opponent):
        if self.type == 'grass':
            self.Damage = self.Damage * 1.35

        if(self.HP > 0): #While your pokemon is alive it will coninute the Battle
            print("%s did %d Damage to %s"%(self.name, self.Damage, Opponent.name)) #Text-based combat descriptors
            print("%s has %d HP left"%(Opponent.name,Opponent.HP)) #Text-based descriptor for the opponent's health

        Opponent.HP -= self.Damage #The damage you inflict upon the opponent is subtracted here
        return Opponent.Battle(self)  #Now the Opponent pokemon attacks
    else:
        print("%s wins! (%d HP left)" %(Opponent.name, Opponent.HP)) #declares the winner of the Battle
        return Opponent, self  #return a tuple (Winner, Loser)

Squirtle = Pokemon('Squirtle', 100, 5, 'water')
Bulbasaur = Pokemon('Bulbasaur', 100, 10, 'grass')
Winner, Loser = Bulbasaur.Battle(Squirtle)
Community
  • 1
  • 1
Babeeshka
  • 105
  • 1
  • 4
  • 21
  • What exactly is your question? – jwodder Nov 29 '16 at 19:25
  • I want to add in the option to select a 'type' and have that affect the damage in the battle function based on the type. For example, if fire type is selected and the opponent is grass, then the damage will be x2. – Babeeshka Nov 29 '16 at 19:30

3 Answers3

2

your problem seems like it could be elegantly solved by Python's dict data type [1] in a nested manner [2]:

attacking = {'fire': {'fire': 0.5, 'grass': 2.0, 'water': 0.5}, 'grass': {'fire': 0.5, 'grass': 0.5, 'water': 2.0}, 'water': {'fire': 2.0, 'grass': 0.5, 'water': 0.5}}

creates a nested dictionary for the weaknesses when the first type attacks. You can then access the multiplier for a fire type attacking a grass type like this:

attacking['fire']['grass'] # yields 2.0

As a side note: you are overwriting the damage of the Pokemon with this instruction: self.Damage = self.Damage * 1.35. This works as long as you don't have e.g. Squirtle battle first a Bulbasaur, then a ground-type Pokemon, against which Squirtle has the effectiveness 1. As soon as you'd start the battle against the Charmander, the damage of the Squirtle will be 5*2.0*1.0 = 10.0, which is not equal to the damage it should deal (5.0). If you created a new variable (turnDamage = self.Damage * attack[self.type][Opponent.type], this would not be a problem.

Yet another edit: this actually works for me:

class Pokemon(object):
    attackingDict = {'fire': {'fire': 0.5, 'grass': 2.0, 'water': 0.5}, 'grass': {'fire': 0.5, 'grass': 0.5, 'water': 2.0}, 'water': {'fire': 2.0, 'grass': 0.5, 'water': 0.5}}
    def __init__(self, name, HP, Damage, type):
        self.name = name     #Sets the name of the Pokemon
        self.HP = HP         #The Hit Points or health of this pokemon
        self.Damage = Damage #The amount of Damage this pokemon does every     attack
        self.type = type #Determines the type of the pokmeon to factor in effectiveness

    def Battle(self, Opponent):
        attackDamage = self.Damage * self.attackingDict[self.type][Opponent.type]

        if(self.HP > 0): #While your pokemon is alive it will coninute the Battle
            print("%s did %d Damage to %s"%(self.name, attackDamage, Opponent.name)) #Text-based combat descriptors
            print("%s has %d HP left"%(Opponent.name,Opponent.HP)) #Text-based descriptor for the opponent's health

            Opponent.HP -= attackDamage #The damage you inflict upon the opponent is subtracted here
            return Opponent.Battle(self)  #Now the Opponent pokemon attacks
        else:
            print("%s wins! (%d HP left)" %(Opponent.name, Opponent.HP)) #declares the winner of the Battle
            return Opponent, self  #return a tuple (Winner, Loser)


Squirtle = Pokemon('Squirtle', 100, 5, 'water')
Bulbasaur = Pokemon('Bulbasaur', 100, 10, 'grass')
Winner, Loser = Bulbasaur.Battle(Squirtle)

The multipliers are intrinsic to the class (i.e. every pokemon obeys the same rules), so the field attackingDict belongs in the class.

Community
  • 1
  • 1
  • This is the easiest solution. Since Pokemon might have multiple types, you might have to multiply all the multipliers together before applying the multiplier to your damage. – Jon Winsley Nov 29 '16 at 19:42
  • Thanks for your help LtSurgekopf. I can now see that the damage would be overwritten with how I initially wrote it, which will cause problems with initializing other battles. I have a question regarding the attacking dictionary. Would I access the types within the dictionary within the class or the function for battle or would that be declared when the pokemon are defined after the class? – Babeeshka Nov 29 '16 at 20:24
  • Gotcha, thank you for clearing that up. I misunderstood that there needed to be another value to call the different types and apply the damage. I was assuming that it would have to be applied to self.Damage instead. – Babeeshka Nov 29 '16 at 20:49
  • I messed up using attackDamage in my previous example. I edited my post to actually factor in the multipliers now ;) – LtSurgekopf Nov 29 '16 at 20:53
0

It sounds like your looking to compare the type of each Pokemon in the Battle function. You will need to write your own function that compares types. The naive way would be using if and elif

def typecomp(type1, type2):
    if type1 == 'fire':
        if type2 == 'grass'
            return 2.0
        elif ...
    elif type1 == ...

this function will return the damage multiplier and you can use it like self.Damage = self.Damage * typecomp(self.type, Opponent.type)

Peter Krasinski
  • 182
  • 1
  • 10
0

I would just like to mention that your pokemon definition system is not very optimal:

Squirtle = Pokemon('Squirtle', 100, 5, 'water')
Bulbasaur = Pokemon('Bulbasaur', 100, 10, 'grass')

- The way I did it was make a .txt file called pokemon.txt and that has all the data, I did it in Ruby but you could make it work in Python

Pol
  • 39
  • 9