7
\$\begingroup\$

As some of you may know, part of creating, or leveling up a character in almost any game is ability score increases. In this example, the character has six abilities with preassigned scores: strength, dexterity, intelligence, wisdom, charisma, and constitution. Users of the code have the option of choosing to level up one score by 2 points, or two different scores by one each.

The code I have works, and it works well, however, I realize that it's bulky, ugly, and probably a sin for python to be running it. Can you help me simplify/streamline it? Thank you

def ability(self):
    choice = raw_input("leveling up: do you want to increase 'one' score by two, or 'two' scores by one each?")
    if choice == "one":
        score = raw_input("which ability do you want to increase by two?")
        if score == "strength":
            self.strength = self.strength + 2
        elif score == "dexterity":
            self.dexterity = self.dexterity + 2
        elif score == "intelligence":
            self.intelligence = self.intelligence + 2
        elif score == "wisdom":
            self.wisdom = self.wisdom + 2
        elif score == "charisma":
            self.charisma = self.charisma + 2
        else:
            self.constitution = self.constitution + 2
    else:
        score = raw_input("which ability do you want to increase by one?")
        if score == "strength":
            self.strength = self.strength + 1
        elif score == "dexterity":
            self.dexterity = self.dexterity + 1
        elif score == "intelligence":
            self.intelligence = self.intelligence + 1
        elif score == "wisdom":
            self.wisdom = self.wisdom + 1
        elif score == "charisma":
            self.charisma = self.charisma + 1
        else:
            self.constitution = self.constitution + 1
        score_two = raw_input("which second ability do you want to increase?")
        if score_two == "strength":
            self.strength = self.strength + 1
        elif score_two == "dexterity":
            self.dexterity = self.dexterity + 1
        elif score_two == "intelligence":
            self.intelligence = self.intelligence + 1
        elif score_two == "wisdom":
            self.wisdom = self.wisdom + 1
        elif score_two == "charisma":
            self.charisma = self.charisma + 1
        else:
            self.constitution = self.constitution + 1
\$\endgroup\$
3
  • \$\begingroup\$ if choice == "one": score = raw_input("which ability do you want to increase by two?") \$\endgroup\$
    – Mast
    Jun 19 '18 at 19:32
  • 1
    \$\begingroup\$ Take a good look at that. It's quite confusing phrased like that, even with the line above it. \$\endgroup\$
    – Mast
    Jun 19 '18 at 19:32
  • \$\begingroup\$ that's understandable. I think I can easily rename the variables to make it more readable on the back-end. Thank you \$\endgroup\$
    – cricketts
    Jun 19 '18 at 19:48
5
\$\begingroup\$

Duplicate code is almost always better replaced with a function. Consider a class method which alters an ability by a given value. This can be achieved (most cleanly, I believe) with getattr and setattr. Calling getattr(x,'spam') will return the value x.spam, and similarly setattr(x,'spam',n) will set the value of x.spam to n.

This, combined with a helpful message when the user enters something unexpected, would yield code like that below:

def ability(self):
    choice = raw_input("Leveling up: do you want to increase 'one' score by two, or 'two' scores by one each?")
    while True:
        if choice == "one":
            stat = raw_input("Which ability do you want to increase by two?")
            self.alter_stat(self, stat, 2)

            break
        elif choice == "two":
            first_stat = raw_input("Which first ability do you want to increase by one?")
            self.alter_stat(self, first_stat, 1)
            second_stat = raw_input("Which second ability do you want to increase?")
            self.alter_stat(self, second_stat, 1)

            break
        else:
            print("Hmm, I don't understand. Enter 'one' or 'two' next time!")

def alter_stat(self, stat, alteration):
    assert stat in ['charisma', 'constitution', 'dexterity', 'intelligence', 'strength', 'wisdom'], "That's not a valid ability!"
    old_value = getattr(self, stat)
    setattr(self, stat, old_value + alteration)
\$\endgroup\$
2
  • \$\begingroup\$ Thank you so much! This is exactly what I was looking for. I greatly appreciate it. I hadn't thought of using 'assert' in a non-testing functionality as well. \$\endgroup\$
    – cricketts
    Jun 20 '18 at 13:25
  • \$\begingroup\$ My one comment is that this might be a place to use an enum or similar. \$\endgroup\$ Jun 20 '18 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.