Hero vs Monster input problem

Started by
3 comments, last by Zahlman 15 years, 4 months ago
I have for the last few days been making a classical DOS RPG fight in Python. I have completed it for the most part and I am happy with it except for one problem while playing. Whenever you don't input a # when picking the Hero's attack\defend\ whatever the game gets an error and shuts down. I need help with making it so that whenever someone doesn't put in an # the option menu resets itself and tells the user of their mistake. I don't have much of an Idea on how to do this so any help is appreciated. Who knows I might learn something from this.:) heres the code for where I believe the problem lays. if anyone wants me to post the entire games code please ask.
 
def Pturn(self):
        choice = int(raw_input('Option,   MP\n1.Attack   0 \n2.Defend   0\n3.Heal     5\n4.Drain    10\n5.Fireball 4\nPlease enter your choice: '))
        
        if choice == 1:
            Hero.Attack()
        elif choice == 2:
            Hero.defend()
        elif choice == 3:
            Hero.heal()
        elif choice == 4:
            Hero.drainattack()
        else:
            Hero.fireball()
        winlose()
        

---------------------------------------------------------------------------------------Exercise, eat right and be the best you can be!Translation: Play video games for finger streangth and eat lots of hot pockets to be at top programming efficiency.
Advertisement
I am not sure about python, but you may want to look into storing the input as a string, not as an integer, and then checking to see if the string contains a #, if not, add one. Frankly I am not sure why you need the # anyway, is it to represent a number?

Either way, you can just change your whole menu to check to see if the input was the character '1' or the character '2', etc. There's no need to make it a number.

Also, you should add an 'elif' for fireball, and make 'else' display the error message and restart the menu.
Thanks I'll try that.
---------------------------------------------------------------------------------------Exercise, eat right and be the best you can be!Translation: Play video games for finger streangth and eat lots of hot pockets to be at top programming efficiency.
Thx for the help it is officially fixed. :). and here is the complete (till I fell like tinkering around more) game for anyone who is bored enough to try it. It is in python 2.6 so you need python installed to use it.

import osimport randomDone = 1class Monster():    def __init__(self, name,hp,mp,strength,defence):        self.name = name        self.hp = hp        self.mp = mp        self.strength = strength        self.defence = defence        def Attack(self):        print 'The %s attacks\n' % self.name        Damage = (Monster1.strength - (Hero.defence/random.randint(2,4)))        if Damage <= 0:            Hero.hp -= 1        else:            Hero.hp -= Damage        Printdata()            def defend(self):        print 'The %s defends itself\n' % self.name        self.defence += self.defence/10        Printdata()            def Mturn(self):        choice = random.randint(1,2)        if choice == 1:            Monster1.Attack()        if choice == 2:            Monster1.defend()        winlose()    class Hero:    def __init__(self,name,hp,mp,strength,defence):        self.name = name        self.hp = hp        self.mp = mp        self.strength = strength        self.defence = defence        def Attack(self):        print '\n%s attacks\n' % self.name        Damage = (Hero.strength - (Monster1.defence/random.randint(2,4)))        if Damage <= 0:            Monster1.hp -= 1        else:            Monster1.hp -= Damage                                    def heal(self):        if Hero.mp >= 5:            self.mp -= 5            self.hp += 25            print '\n%s healed 25 hp. Hp is now %s\n' % (self.name,self.hp)        else:            print '\nToo little Mp left your turn was wasted.'                    def defend(self):        print '\n%s defends himself. Defence is now %s\n' % (self.name, self.defence)         self.defence += self.defence/10    def fireball(self):        if Hero.mp >= 3:            self.mp -= 7            Monster1.hp -= 14            print '\n%s burns the %s with a fireball\n' % (Hero.name, Monster1.name)        else:            print '\nToo little MP left your turn was wasted.'    def drainattack(self):        if Hero.mp >= 10:            self.mp -= 10            self.hp += 8            Monster1.hp -= 8            print '\n%s drains 8 life from %s\n.' % (Hero.name, Monster1.name)        else:            print '\nToo little MP left your turn was wasted.'                def Pturn(self):        choice = raw_input('Option,   MP\n1.Attack   0 \n2.Defend   0\n3.Heal     5\n4.Drain    10\n5.Fireball 4\nPlease enter your choice: ')                if choice == '1':            Hero.Attack()        elif choice == '2':            Hero.defend()        elif choice == '3':            Hero.heal()        elif choice == '4':            Hero.drainattack()        elif choice == '5':            Hero.fireball()        else:            print ' \n\n\n\n selection not entered correctly please try again'            Printdata()            Hero.Pturn()        winlose()        def Printdata():    print '------------------------------------------------------------'    print '[%s]' % Hero.name    print 'HP[%s]' % Hero.hp    print 'MP[%s]' % Hero.mp    print '\n\n\n'    print '[%s]' % Monster1.name    print 'HP[%s]\n\n\n' % Monster1.hpdef winlose():    global Done    if Monster1.hp <= 0:        print 'you win! good job'        Done = 2            if Hero.hp <=0:        print '%s has died' %Hero.name        print 'game over'        Done = 2def gameloop():    while Done == 1:        Hero.Pturn()        Monster1.Mturn()        Hero = Hero('Roy', 50,50,15,15)Monster1 = Monster('Goblin',20,10,10,10)print '\n\n\n'Printdata()gameloop()del Monster1Done = 1print '\n\n\n'Monster1 = Monster('Basilisk',60,10,10,10)Printdata()gameloop()del Monster1Done = 1print'\n\n\n'Monster1 = Monster('Wyvern',120,20,20,15)Printdata()gameloop()del Monster1Done = 1print '\n\n\n'Monster1 = Monster('Satin',200,100,30,10)Printdata()gameloop()del Monster1print 'You really won you cheeting bastard if you didnt cheat then oh well.!!!!!'print ' God comes shakes your hand then he smites you'print 'OUCH! burned you stipid little kid.... or adult.'print 'Press enter to end the game'print '\n\n\n\n'os.system("pause")
---------------------------------------------------------------------------------------Exercise, eat right and be the best you can be!Translation: Play video games for finger streangth and eat lots of hot pockets to be at top programming efficiency.
Quote:Original post by steveworks
Whenever you don't input a # when picking the Hero's attack\defend\ whatever the game gets an error


The ValueError is Python's way of telling your program that the input wasn't a number. (This causes int() to fail, because it doesn't have any rules for turning text representing a non-number into a number.)

Quote:and shuts down.


Because your program doesn't have any rules for this case either. You must provide some. You should also handle the case where the input is some number not in the list; currently if I ask for option 1,023,387, I will still get a fireball.

Take a deep breath, because I'm about to offer you a firehose to drink from. :)

There is a neat way to do this: looking something up in a dictionary will also fail with an exception if it isn't there (with a KeyError), so we can put all the "normal" actions into a dictionary, and use one set of try/except logic to guard the whole process.

def Pturn(self):  actions = {1: Hero.Attack, 2: Hero.defend, 3: Hero.heal, 4: Hero.drainattack, 5: Hero.fireball}  try:    choice = int(raw_input('Option,   MP\n1.Attack   0 \n2.Defend   0\n3.Heal     5\n4.Drain    10\n5.Fireball 4\nPlease enter your choice: '))    action = actions[choice]  except:    # The user's input was invalid; put some logic to handle it here!    # What should happen?  # Now that we have the action, we can invoke it:  action()  winlose()


Notice how I've separated out the calling of the action code from the exception handling block. This way, you can design the Hero methods to allow them to throw exceptions too, and catch those separately.

A more sophisticated way is to make some basic structure to represent the player options, and keep them in a tuple; then you can use some logic to label the options and assign numbers to them automatically. You can also design a loop that keeps asking until a valid option is requested.

Probably a lot of this will be beyond what you've seen in Python to date, but it's very useful stuff. After I have everything set up below, I only have to add a player action to the 'actions' list and everything else will work automatically. (I could even change Pturn to accept a list of actions as a parameter. Maybe we could ask the Hero what actions are currently possible? :) )

def Pturn(self):  # For each action, we'll use a tuple of the name, the Hero method and the MP cost.  actions = (    ('Attack', Hero.Attack, 0),    ('Defend', Hero.defend, 0),    ('Heal', Hero.heal, 5),    ('Drain', Hero.drainattack, 10),    ('Fireball', Hero.fireball, 4)  )  # The code to create the menu is a little complicated, so let's do it ahead of time  menu = '  Option  MP\n' + '\n'.join('%d.%-8s%2d' % ((i + 1), action[0], action[2]) for i, action in enumerate(actions))  # We'll loop presenting the menu until we get a choice we like.  action = None  while action == None:    try:      # We subtract 1 from the user's input to turn the label value (numbers      # starting from 1) into an index into the tuple (numbers starting from 0).      # If the input is invalid, we get an IndexError, which is caught by the      # try/except logic.      action = actions[int(raw_input(menu)) - 1]    except:      print "That is an invalid menu option. Please try again."      # 'action' is still None, so the loop will continue automatically.  # You could also move the logic for handling MP costs here, instead of  # having to repeat it in every Hero function that costs MP. This way, all the  # MP cost information is in one place, too, so you don't have to worry about  # lying to the player about the cost.  # Hero.pay_MP(action[2])  # Think about how to set this up so that the action is only performed if the  # player has enough MP. Better yet, maybe you can think of a way to restrict  # the menu ahead of time to only options the player can afford at the moment.  action[1]()  winlose()


(EDIT: I suppose the code is long enough for source blocks...)

This topic is closed to new replies.

Advertisement