patternpythonMinor
Text-based adventure game with combat and game-reset functionality
Viewed 0 times
combatwithtextadventuregamebasedandfunctionalityreset
Problem
Please suggest improvements/refactoring to this game to make it more idiomatic Python.
```
import random
import time
class Hero:
def __init__(self):
self.level = 1
self.max_hp = 3
self.hp = self.max_hp
self.attack = 5 + self.level
self.defense = 5 + self.level
self.name = ''
self.xp = 0
def name_self(self):
self.name = raw_input("What do you call yourself, anyway? ")
if self.name == "":
self.name_self()
def heal_self(self):
amount = self.xp * .2
self.hp += amount
print "You attempt to heal yourself..."
time.sleep(1)
print "You healed yourself for %d HP, but used half your XP. Feels good, man." % amount
self.xp *= .5
self.hp_limit()
def hp_limit(self):
if self.hp > self.max_hp:
self.hp = self.max_hp
def death(self):
print "Sorry, %s, you is dead now." % (self.name)
time.sleep(1)
print "Well, aren't you lucky, there is an afterlife after all."
def xp_up(self, xp):
self.xp += xp
print "You gain: %s XP" % xp
def look_self(self):
print ("You are %s, not from around here.") % self.name
print ("You are level %s with %s attack and %s defense.") % (self.level, self.attack, self.defense)
print ("You need %s XP to level up.") % (self.level**2 * 10)
class Monster:
def __init__(self, name):
self.name = name
self.hp = random.randint(2,10)
self.attack = random.randint(2,5)
self.defense = random.randint(2,5)
self.xp = random.randint(2,8)
class Room:
def __init__(self, key):
self.room_data = {
"home":{"description":"You're at home. This is where you live, unfortunately.",
"exits":["forest"]},
"forest":{"description":"You're in a dark forest. It's fairly gloomy.",
"exits":["home", "lake"]},
"lake"
```
import random
import time
class Hero:
def __init__(self):
self.level = 1
self.max_hp = 3
self.hp = self.max_hp
self.attack = 5 + self.level
self.defense = 5 + self.level
self.name = ''
self.xp = 0
def name_self(self):
self.name = raw_input("What do you call yourself, anyway? ")
if self.name == "":
self.name_self()
def heal_self(self):
amount = self.xp * .2
self.hp += amount
print "You attempt to heal yourself..."
time.sleep(1)
print "You healed yourself for %d HP, but used half your XP. Feels good, man." % amount
self.xp *= .5
self.hp_limit()
def hp_limit(self):
if self.hp > self.max_hp:
self.hp = self.max_hp
def death(self):
print "Sorry, %s, you is dead now." % (self.name)
time.sleep(1)
print "Well, aren't you lucky, there is an afterlife after all."
def xp_up(self, xp):
self.xp += xp
print "You gain: %s XP" % xp
def look_self(self):
print ("You are %s, not from around here.") % self.name
print ("You are level %s with %s attack and %s defense.") % (self.level, self.attack, self.defense)
print ("You need %s XP to level up.") % (self.level**2 * 10)
class Monster:
def __init__(self, name):
self.name = name
self.hp = random.randint(2,10)
self.attack = random.randint(2,5)
self.defense = random.randint(2,5)
self.xp = random.randint(2,8)
class Room:
def __init__(self, key):
self.room_data = {
"home":{"description":"You're at home. This is where you live, unfortunately.",
"exits":["forest"]},
"forest":{"description":"You're in a dark forest. It's fairly gloomy.",
"exits":["home", "lake"]},
"lake"
Solution
A few suggestions:
Simplify and reduce duplication using inheritance, for example:
Move general class data out of the instance:
Similarly e.g.
Simplify the display using "magic methods" and
Use looping rather than recursion for input validation (see e.g. this SO community wiki):
Consider structuring your functions differently, such that they call each other, to cut down multiple lines of calls at the top level. For example:
Put the top-level code in an
Simplify and reduce duplication using inheritance, for example:
class Character(object): # note new-style classes
def __init__(self, name, hp, attack, defence, xp):
self.name = name
self.hp = hp
self.attack = attack
self.defence = defence
self.xp = xp
class Monster(Character):
def __init__(self, name):
super(Monster, self).__init__(name, random.randint(2,10),
random.randint(2,5),
random.randint(2,5),
random.randint(2,8))
class Hero(Character):
MAX_HP = 3
def __init__(self, level=1):
super(Hero, self).__init__('', self.MAX_HP, level+5,
level+5, 0)
self.level = levelMove general class data out of the instance:
class Room(object):
ROOM_DATA = {"home": {"description": "You're at home. This is where you live, unfortunately.",
"exits": ["forest"]},
"forest": {"description": "You're in a dark forest. It's fairly gloomy.",
"exits": ["home", "lake"]},
"lake": {"description": "You see a lake circled by rocks. It's too cold to swim.",
"exits": ["forest", "mountain"]},
"mountain": {"description":"You can see for miles around. Don't fall off.",
"exits": ["lake"]}}
def __init__(self, key):
self.description = self.ROOM_DATA[key]["description"]
self.exits = self.ROOM_DATA[key]["exits"]
self.name = str(key)
self.monster_list = {}Similarly e.g.
Game.COMMAND_LIST isn't instance-specific.Simplify the display using "magic methods" and
str.format:class Monster(Character):
...
def __str__(self):
template = "The {0} has {1.hp} HP, {1.attack} attack, ..." # etc.
return template.format(self.name.capitalize(), self)
class Game(object):
...
def look_monster(self, monster):
print str(monster)Use looping rather than recursion for input validation (see e.g. this SO community wiki):
def name_self(self):
while True:
self.name = raw_input("What do you call yourself, anyway? ")
if self.name != "":
breakConsider structuring your functions differently, such that they call each other, to cut down multiple lines of calls at the top level. For example:
Game.__init__ could call populate and look; Hero.__init__ could call name_self and look_self(); and you could add Game.play_round to call handle_input(), game.update() and game.output().Put the top-level code in an
if __name__ == '__main__': block (see e.g. this SO question).Code Snippets
class Character(object): # note new-style classes
def __init__(self, name, hp, attack, defence, xp):
self.name = name
self.hp = hp
self.attack = attack
self.defence = defence
self.xp = xp
class Monster(Character):
def __init__(self, name):
super(Monster, self).__init__(name, random.randint(2,10),
random.randint(2,5),
random.randint(2,5),
random.randint(2,8))
class Hero(Character):
MAX_HP = 3
def __init__(self, level=1):
super(Hero, self).__init__('', self.MAX_HP, level+5,
level+5, 0)
self.level = levelclass Room(object):
ROOM_DATA = {"home": {"description": "You're at home. This is where you live, unfortunately.",
"exits": ["forest"]},
"forest": {"description": "You're in a dark forest. It's fairly gloomy.",
"exits": ["home", "lake"]},
"lake": {"description": "You see a lake circled by rocks. It's too cold to swim.",
"exits": ["forest", "mountain"]},
"mountain": {"description":"You can see for miles around. Don't fall off.",
"exits": ["lake"]}}
def __init__(self, key):
self.description = self.ROOM_DATA[key]["description"]
self.exits = self.ROOM_DATA[key]["exits"]
self.name = str(key)
self.monster_list = {}class Monster(Character):
...
def __str__(self):
template = "The {0} has {1.hp} HP, {1.attack} attack, ..." # etc.
return template.format(self.name.capitalize(), self)
class Game(object):
...
def look_monster(self, monster):
print str(monster)def name_self(self):
while True:
self.name = raw_input("What do you call yourself, anyway? ")
if self.name != "":
breakContext
StackExchange Code Review Q#56873, answer score: 6
Revisions (0)
No revisions yet.