aaa
aaa

Reputation: 101

Take advantage of the same attributes in a class

In this class here:

class Hero():
    def __init__(self, Type, name):
        self.Type = Type
        self.name = name
        self.atk = 'Undefined'

        if Type == 'Paladin':
            self.hp = 150
            self.dmg = [10, 20]
            self.atk = random.randint(self.dmg[0], self.dmg[1])
            self.defence = 25
            self.dodge = 5

        elif Type == 'Mage':
            self.hp = 70
            self.dmg = [60, 70]
            self.atk = random.randint(self.dmg[0], self.dmg[1])
            self.defence = 15
            self.dodge = 8

        elif Type == 'Archer':
            self.hp = 100
            self.dmg = [40, 50]
            self.atk = random.randint(self.dmg[0], self.dmg[1])
            self.defence = 10
            self.dodge = 13

I'm noticing that I always have hp, dmg, atk, defence, dodge for each if statement. Since python is OOP, is there a way to take advantage if that and not need to write all of these things manually?

Upvotes: 1

Views: 51

Answers (2)

Reblochon Masque
Reblochon Masque

Reputation: 36742

You can use inheritance to derive various Hero Characters from a superclass and give each new type a specific set of values; you can also give them specific attributes, and behaviors:

Using class variables to store the values simplifies the code:

from abc import ABC
import random


class Hero(ABC):   # this cannot be instantiated 
    def __init__(self, name):
        self.name = name
        self.atk = random.randint(self.dmg[0], self.dmg[1])
        self.hp = self.__class__.hp
        self.dmg = list(self.__class__.dmg)
        self.defence = self.__class__.defence
        self.dodge = self.__class__.dodge
    def __str__(self):
        return f'{self.__class__.__qualname__}: {self.name}, atk: {self.atk}, hp: {self.hp}, dmg: {self.dmg}, defense: {self.defence}, dodge: {self.dodge}'


class Paladin(Hero):
    hp = 150
    dmg = (10, 20)
    defence = 25
    dodge = 5
    def __init__(self, name):
        super().__init__(name)


class Mage(Hero):
    hp = 70
    dmg = (60, 70)
    defence = 15
    dodge = 8
    def __init__(self, name, spells):
        super().__init__(name)
        self.spells = spells[:]
    def __str__(self):
        return f'{super().__str__()}\n\tspells: {self.spells}'


class Archer(Hero):
    hp = 100
    dmg = (40, 50)
    defence = 10
    dodge = 13
    def __init__(self, name):
        super().__init__(name)


A = Archer('Guillaume Tell')
B = Mage('Gandalf', ['quadratus lumborum', 'rectus femoris'])
C = Paladin('Ali Baba')

print(A)
print(B)
print(C)

Output:

Archer: Guillaume Tell, atk: 49, hp: 100, dmg: [40, 50], defense: 10, dodge: 13
Mage: Gandalf, atk: 62, hp: 70, dmg: [60, 70], defense: 15, dodge: 8
    spells: ['quadratus lumborum', 'rectus femoris']
Paladin: Ali Baba, atk: 13, hp: 150, dmg: [10, 20], defense: 25, dodge: 5

Upvotes: 0

azro
azro

Reputation: 54168

You may use inheritance and create 3 subclasses of your Hero class to move the code.

The Hero class where you can write an util method to create different types of Hero

class Hero():
    def __init__(self, Type, name):
        self.name = name
        self.atk = 'Undefined'

    def _init_atk(self):
        self.atk = random.randint(self.dmg[0], self.dmg[1])

    @staticmethod
    def get_hero(hero_type, name):
        if hero_type == 'Paladin':
          return Paladin(name)
        elif hero_type == 'Mage':
          return Mage(name)
        elif hero_type == 'Archer':
          return Archer(name)
        return None

The heroes classes, that defined their own value of the attributs

class Paladin(Hero):
    def __init__(self,name):
        super(Paladin, self).__init(name)
        self.hp = 150
        self.dmg = [10, 20]
        self.defence = 25
        self.dodge = 5
        self._init_atk()

class Mage(Hero):
    def __init__(self,name):
        super(Mage, self).__init(name)
        self.hp = 70
        self.dmg = [60, 70]
        self.defence = 15
        self.dodge = 8
        self._init_atk()

class Archer(Hero):
    def __init__(self,name):
        super(Archer, self).__init(name)
        self.hp = 100
        self.dmg = [40, 50]
        self.defence = 10
        self.dodge = 13
        self._init_atk()

Then you can create object like

a = Archer("RobinHood")
b = Hero.get_hero("Mage", "HarryPotter")

Upvotes: 3

Related Questions