Jump to content
  • Advertisement
Sign in to follow this  
steveworks

Hero vs Monster input problem

This topic is 3670 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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()
        

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 os
import random
Done = 1
class 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.hp

def 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 = 2
def 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 Monster1
Done = 1
print '\n\n\n'
Monster1 = Monster('Basilisk',60,10,10,10)
Printdata()
gameloop()
del Monster1
Done = 1
print'\n\n\n'
Monster1 = Monster('Wyvern',120,20,20,15)
Printdata()
gameloop()
del Monster1
Done = 1
print '\n\n\n'
Monster1 = Monster('Satin',200,100,30,10)
Printdata()
gameloop()
del Monster1
print '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")


Share this post


Link to post
Share on other sites
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...)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!