Updating properties of an object in Python OOP
<p>I am trying to create a simple game in Python using the OOP style.
The parent class is set up and there are two sub-classes, one for the hero and one for the ork.</p>

<p>Basically, when the hero attacks the ork (or vice versa) I want the health to be updated based on the damage done (damage is the amount of power the attacking character has). Currently, every time it loops it resets the health values back to the original of 100.</p>

<p>What is the best way of doing this using OOP? I can figure out how to do it in my own procedural and messy way, but I would like to see how it should be done.</p>

<pre><code>class Character:
    '''Blueprint for game characters'''
    def __init__(self):
        #default values
        self.character = ""
        self.speed = 0
        self.power = 0
        self.health = 100

    def attack(self, attackObj):
        self.attacker = self.character
        self.attackerPower = self.power
        self.victim = attackObj.character
        self.victimHealth = attackObj.health
        self.newHealth = self.victimHealth - self.attackerPower
        print(self.character, "you have chosen to attack", self.victim)
        print(self.victim, "you have suffered", self.attackerPower, "damage and     your health is now", self.newHealth)


class Hero(Character):
    '''Inherits from character to create hero'''
    def __init__(self):
        Character.__init__(self)
        self.character = "Hero"
        self.speed = 8
        self.power = 9
        print(self.character, "you have",self.speed, "speed,", self.power, "power and", self.health, "health.")


class Ork(Character):
    '''Inherits from character to create ork'''
    def __init__(self):
        Character.__init__(self)
        self.character = "Ork"
        self.speed = 2
        self.power = 8
        print(self.character, "you have",self.speed, "speed,", self.power,     "power and", self.health, "health.")

def main():
    charclass = Character()
    hero = Hero()
    ork = Ork()

    endLoop = False
    while endLoop == False:
        print("Please choose your character by typing the corresponding key: ")
        print("H for hero")
        print("O for ork")
        charChoice = input()
        if charChoice in ("H", "h", "hero", "Hero"):
            charChoice = hero
            enemy = ork
            hero = Hero()

        elif charChoice in ("O", "o", "ork", "Ork"):
            charChoice = ork
            enemy = hero

        print("Please choose an action by typing the corresponding key: ")
        print("A to attack")
        actionChoice = input()
        if actionChoice in ("A", "a"):
            charChoice.attack(enemy)  
        else:
            print("Nothing chosen!")

        finishedYN = input("Have you finished? Y/N ")
        if finishedYN in ("Y", "y", "Yes", "yes", "YES"):
            print("You have chosen to end the game...")
            endloop = True
            break
        else:
            pass

if __name__ == "__main__":
    main()
</code></pre>

<p>A quick fix to your code. Remove all these unecessary attributes, e.g. <code>self.attacker</code> (that's just <code>self</code>), <code>self.attackPower</code> (that's just <code>self.power</code>). <code>self.victim = attackObj.character</code> just gives your object a new attribute that is the same string as whatever <code>attackObj.character</code> is. Similarly, this:<code>self.newHealth = self.victimHealth - self.attackerPower</code> just creates a new attribute each time the method is called that will <em>always</em> be 100 - <code>self.attack</code></p>

<pre><code>def attack(self, attackObj):
    attackObj.health -= self.power
    print(self.character, "you have chosen to attack", attackObj.character)
    print(attackObj.character, "you have suffered", self.power, "damage and     your health is now", attackObj.health)
</code></pre>

<p>Really, an even better way is to add methods that mutate your object, that will be used as an interface with how your object interacts with other objects. So, for example:</p>

<pre><code>class Character:
    '''Blueprint for game characters'''
    def __init__(self):
        #default values
        self.character = ""
        self.speed = 0
        self.power = 0
        self.health = 100

    def attack(self, victim):
        victim.receive_damage(self.power)

    def receive_damage(raw_damage):
        self.health -= raw_damage
</code></pre>

<p>This improves the extensibility of your code. You could more easily implement a "buffs" system, or add an "armor" element, that affects how you recieve damage, without ever having to change the code in <code>attack</code>. You can override these methods in subclasses. So, perhaps you want all orks to have "thickskin", and in <code>Ork</code>:</p>

<pre><code>    def receive_damage(raw_damage):
        self.health -= raw_damage*self.thickskin_modifier
</code></pre>

<p>Where <code>self.thickskin_modifier</code> was set in the <code>Ork</code> class <code>__init__</code>. It could be something like 0.9.</p>

python oop