954,525 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Dictionary help

Hi I am new to the forums, and somewhat new to python. I'm trying to make a Text Based Adventure game. I don't have an error, but a bug.

This is the code:

import descriptions

inventory = []
gold = 0
acts = {"north":"hi"}

def start(acts):
    print(descriptions.start)
    rm_a(acts)

def rm_a(acts):
    print("FOYER")
    print(descriptions.foyer)
    acts={"north":print("You can't go that way."),
       "east":rm_b(acts),
       "south":print("You can't go that way."),
       "west":print("You can't go that way."),
       "take book":inventory.append(descriptions.book[0])}
    prompt(acts)

def rm_b(acts):
    print("DINING ROOM")
    print(descriptions.dining)
    acts={"north":print("You can't go that way."),
       "east":rm_c(acts),
       "south":rm_e(acts),
       "west":rm_a(acts),
       "take sandwich":inventory.append(descriptions.sandwich[0])}
    prompt(acts)

def rm_c(acts):
    print("KITCHEN")
    print(descriptions.kitchen)
    acts={"north":print("You can't go that way."),
       "east":print("You can't go that way."),
       "south":print("You can't go that way."),
       "west":rm_b(acts),
       "take sandwich":inventory.append(descriptions.sandwich[0])}
    prompt(acts)

def rm_d(acts):
    print("YOUR ROOM")
    print(descriptions.yourRoom)
    acts={"north":print("You can't go that way."),
       "east":rm_e(acts),
       "south":print("You can't go that way."),
       "west":print("You can't go that way."),
       "take sandwich":inventory.append(descriptions.sandwich[0])}
    prompt(acts)

def rm_e(acts):
    print("NORTH HALL")
    print(descriptions.northHall)
    acts={"north":rm_b(acts),
       "east":rm_f(acts),
       "south":rm_h(acts),
       "west":rm_d(acts),
       "take sandwich":inventory.append(descriptions.sandwich[0])}
    prompt(acts)

def rm_f(acts):
    pass

def rm_g(acts):
    pass

def rm_h(acts):
    print("SOUTH HALL")
    print(descriptions.northHall)
    acts={"north":rm_e(acts),
       "east":rm_i(acts),
       "south":print("You can't go that way."),
       "west":rm_g(acts),
       "take sandwich":inventory.append(descriptions.sandwich[0])}
    prompt(acts)

def rm_i(acts):
    pass

def prompt(acts):
    message = input(':').lower
    if message == "north":
        acts['north']

    if message == "east":
        acts['east']

    if message == "south":
        acts['south']

    if message == "west":
        acts['west']

start(acts)


This produces a bug where the program goes back and forth between rm_b() and rm_c(). I have identified where the bug is, right here:

acts={"north":print("You can't go that way."),
       "east":print("You can't go that way."),
       "south":print("You can't go that way."),
       "west":rm_b(acts),
       "take sandwich":inventory.append(descriptions.sandwich[0])}


I have that part so that I don't have to make a prompt for each one, I can just define actions in acts and pass it to the prompt. The problem is, the function aren't being assigned to a word, they're executing right then.

I don't know what to do to fix this. Can someone please help?

Geemon
Newbie Poster
4 posts since Feb 2011
Reputation Points: 10
Solved Threads: 0
 

Save it as a string and then eval it. It may impose security problems though, so don't quote me if this is the bad way to do it.

acts={"north":'print("You can\'t go that way.")',
       "east":'print("You can\'t go that way.")',
       "south":'print("You can\'t go that way.")',
       "west":'rm_b(acts)',
       "take sandwich":inventory.append(descriptions.sandwich[0])}


Then just use eval to get the function or print the stuff, etc etc. You will have to change it for all of your assigning of acts though.

Then to execute:

def prompt(acts):
    message = input(':').lower
    if message == "north":
        eval(acts['north'])

    if message == "east":
        eval(acts['east'])

    if message == "south":
        eval(acts['south'])

    if message == "west":
        eval(acts['west'])
zizuno
Junior Poster in Training
62 posts since Jan 2011
Reputation Points: 10
Solved Threads: 8
 

There's a problem at line 81: message = input(':').lower returns "". You need message = input(':').lower() (note the empty parens)

I would have written:

def prompt(acts):
    while True:
        m = input(':')
        message = m.lower()[0]
        if message == "n":
            acts['north']
            break

        elif message == "e":
            acts['east']
            break

        elif message == "s":
            acts['south']
            break
        
        elif message == "w":
            acts['west']
            break
        else:
            print('Illegal option "%s"'%m)
griswolf
Veteran Poster
1,165 posts since Apr 2010
Reputation Points: 344
Solved Threads: 256
 
Save it as a string and then eval it. It may impose security problems though, so don't quote me if this is the bad way to do it.


Better: acts should have the actual function, not call it (same applies to the printed messages. Here:

def no_exit(a):
    print("You can't go that way.")

def rm_a(acts):
    print("FOYER")
    print(descriptions.foyer)
    acts={"north":no_exit,
       "east":rm_b,
       "south":no_exit,
       "west":no_exit,
       "take book":inventory.append(descriptions.book[0])}
    prompt(acts)
# ...
def prompt(acts):
    while True:
        try:
            m = input(':')
            message = m.lower()[0]
            if message == "n":
                acts['north'](acts)
                break

            elif message == "e":
                acts['east'](acts)
                break

            elif message == "s":
                acts['south'](acts)
                break

            elif message == "w":
                acts['west'](acts)
                break
            else:
                print('Illegal option: "%s"'%m)
        except:
            no_exit(None)


I did a very quick edit on function prompt() leaving it more useful, but still probably not quite right.

griswolf
Veteran Poster
1,165 posts since Apr 2010
Reputation Points: 344
Solved Threads: 256
 

More user friendly :)

def prompt(acts):
    while True:
        print """
              Please select one of the choices\n
              ==================================\n\n
              north\t south\n
              east\t west\n"""
            
        m = input("choice please: ")
        message = m.lower()[0]
        if message == "n":
            acts['north']
            break

        elif message == "e":
            acts['east']
            break

        elif message == "s":
            acts['south']
            break
        
        elif message == "w":
            acts['west']
            break
        else:
            print('Illegal option "%s"'%m)
richieking
Master Poster
764 posts since Jun 2009
Reputation Points: 61
Solved Threads: 152
 


how about doubling key 'north' as 'n' etc and get rid of the if. Would only use try except to catch incorrect input.

pyTony
pyMod
Moderator
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
 

Thank you. I will try that.

Geemon
Newbie Poster
4 posts since Feb 2011
Reputation Points: 10
Solved Threads: 0
 

And, I now realize, any other key in acts needs the function itself, not to do the work. Such as 'take sandwich' etc.

griswolf
Veteran Poster
1,165 posts since Apr 2010
Reputation Points: 344
Solved Threads: 256
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: