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?

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'])

There's a problem at line 81: message = input(':').lower returns "<built-in method lower of str object at 0x2ca360>". 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)

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.

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)

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

Thank you. I will try that.

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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.