#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    2
    Rep Power
    0

    Looping User Input for many different things?


    I'm writing a text based adventure game in python and I need to know how to bring a user back to a certain spot. For example, if they continuously enter nonsense, I want to infinitely prompt them with '>>>' until they have a valid response. Here is some of the code:

    Code:
    def dark_room(): 
         print "You can barely see save for the faint light that    streams from the boarded up windows. Perhaps you can OPEN them up." 
         prompt_dark_room=raw_input('>>> ')
         if prompt_dark_room=='open window': 
              print "Any statement" dark_room2() 
         elif prompt_dark_room=='open windows': 
              print "Barely lifting your feet from the ground, you make your way over to the source of light. you eventually make it to the window and tear the boards away from the window." 
              dark_room2() 
         elif prompt_dark_room=='prompt': 
              dark_room() 
         while prompt_dark_room=='stats': 
              stats.display_stats() 
              prompt_dark_room=raw_input('>>> ') 
         while prompt_dark_room=='inventory': 
              print inventory 
              prompt_dark_room=raw_input('>>> ') 
         else: dark_room()
    So if they put in stats i want it to display stats then prompt them again with >>>. With this i also want the >>> prompt to abide by the SAME code for the function dark_room(). If they say 'inventory' i want to bring up their inventory again and again infinitely until they say 'open windows' to go to the next function. Or if they put in nonsense I want them to be prompted with '>>>' over and over again. I've tried while loops such as while True, as well as try: and except: but it doesn't seem to work the way i do it. It either brings an error or gives me an unwanted/unexpected result like running through a loop once then terminating.

    Can you modify my example to show me how to do this/or at least be very specific as I am new to this.
    Thanks!
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,709
    Rep Power
    480
    The "while bad try again with different input" pattern is common. And recursively coding it looks smart but it's actually not smart because incorrect answers fill the stack. If you're on unix you'll see the stack dump if you command
    Code:
    $ yes nonsense| python text_adventure_game.py
    Code:
    def dark_room():
        if invalid:
            dark_room() # don't do this!
    Recursion is useful technique. You'll need to understand how the stack unwinds (termination---your recursion hasn't got termination). Here's a recursive version of towers of Hanoi. It displays the content of each tower after each transfer.
    Code:
    def transfer(source, sink):
        towers[sink].append(towers[source].pop())
        print(towers)
    
    def hanoi(n, source, sink, extra):
        if n == 1:
            transfer(source,sink)
        elif 1 < n:
            hanoi(n-1, source, extra, sink) # move n-1 blocks to the extra tower
            hanoi(  1, source, sink, extra) # move the big block to the destination
            hanoi(n-1, extra, sink, source) # move the n-1 blocks from the extra onto the destination.
    
    towers = (list(reversed(range(4))), [], [])
    print(towers)
    hanoi(4,0,1,2)
    The recursion stops because it calls itself for diminished action. For a transfer of 1 it does not recur.

    Hmm. Back to your question. How should it work? Hard to say. You should probably redesign your program. If "inventory" and "stats" should work the same in most rooms then it doesn't make sense to handle these requests in each room function. Here's my essentially useless and too difficult to understand answer:
    Code:
    import sys
    
    def yourprompt(question,verify,*args,**kwargs):
        while True:
            sys.stdout.write(message)
            sys.stdout.flush()
            answer = sys.stdin.readline()
            if verify(answer, *args, **kwargs):
                return answer
    
    def verify(answer, room, character):
        answer_lower_case = answer.lower()
        if room.verify(answer_lower_case):
            return True
        (verb, noun, *junk) = (answer_lower_case+' verb noun junk').split() # assume python 3
        if verb in ('inventory', 'i'):
            character.inventory()
        elif (verb in ('get', 'take')) and (noun in room):
            character.get(room.give(noun))
        return False
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    2
    Rep Power
    0
    When you're right you're right. Like I said, I'm a beginner so when you have stuff like kwargs,sys.stdout and all I don't understand it. Also I don't mind reiterating 'stats' and 'inventory' each time. This is the first game I am making so if there is an easy way, I usually take the easy way and don't mind the extra work. But if there is any simpler way (perhaps that I can understand) that would be nice. Basically I just want to be able to say "If you don't put in any of the options I have defined, you get the prompt again (aka prompt_dark_room=raw_input('>>> '). Also I may have forgotten to mention I am using Python 2.7.

IMN logo majestic logo threadwatch logo seochat tools logo