3

I'm having a little bit of trouble with my text adventure game. The idea is to start in the living room, make your way to the basement to grab the key, and when you enter the living room again you should win. When I execute my code though, it just has me enter the room, the boolean should tell the if statement that has_key = true but it always doesn't work. Any thoughts?

def welcomeMessage():
    print "Welcome to my game!!"

def winnerMessage():
    print "You're a winner!! Congratulations!!"
    userQuit()

def userQuit(): 
    print "Thanks for playing!"

def living_room():
    # This part isn't executing (Boolean doesn't work here)
    # I want the if statement to execute, not the else statement
    if has_key == True:
        winnerMessage()
        userQuit()
    else: 
        print ("\nYou are in the living room. The paint from the walls is tearing off."
        +" There is a door near you, but it seems to be locked. To your west is the"
        +" kitchen, where you can eat some tasty snacks and to your south is a bedroom. ")
        direction = raw_input("Which direction would you like to go? (W)est or (S)outh? You also have the option to (Q)uit. ")
        if direction == "W":
            kitchen()
        elif direction == "S":
            bed_room()
        elif direction == "N":
            print "Sorry, you can't go north here."
            living_room()
        elif direction == "E":
            print "Sorry, you can't go east here."
            living_room()
        elif direction == "Q":
            userQuit()
        else:
            print "Sorry, that's not a valid direction."
            living_room()


def kitchen():
    print ("\nYou are in the kitchen. The water from the sink is slightly running. All of the"
    +" cupboards in the kitchen have been left open, like someone has searched through them."
    +" To your south is the dining room, and to your east is the living room. ")
    direction = raw_input("Which direction would you like to go? (S)outh or (E)ast? You also have the option to (Q)uit. ")
    if direction == "S":
        dining_room()
    elif direction == "E":
        living_room()
    elif direction == "N":
        print "Sorry, you can't go north here."
        kitchen()
    elif direction == "W":
        print "Sorry, you can't go west here."
        kitchen()
    elif direction == "Q":
        userQuit()  
    else:
        print "Sorry, that's not a valid direction."
        kitchen()


def bed_room():
    print ("\nYou are in the bedroom. One of the windows in the room is slightly ajar. The other window"
    +" is shattered with a brick laying on the floor next to it. To your west is the dining room and"
    +" to your north is the living room.")
    direction = raw_input("Which direction would you like to go? (W)est or (N)orth? You also have the option to (Q)uit. ")  
    if direction == "W":
        dining_room()
    elif direction == "N":
        living_room()
    elif direction == "E":
        print "Sorry, you can't go east here."
        bed_room()
    elif direction == "S":
        print "Sorry, you can't go south here."
        bed_room()
    elif direction == "Q":
        userQuit()
    else:
        print "Sorry, that's not a valid direction."
        bed_room()

def dining_room():
    print ("\nYou are in the dining room. It is very hard to see in here due to the dim lighting. You notice a staircase is the"
    +" in the center of the room. To your north is the kitchen, and to your east is the bedroom.")
    direction = raw_input("Which direction would you like to go? (N)orth or (E)ast or go (D)own the staircase? You also have the option to (Q)uit. ")
    if direction == "N":
        kitchen()
    elif direction == "E":
        bed_room()
    elif direction == "D":
        basement()
    elif direction == "S":
        print "Sorry, you can't go south here."
        dining_room()
    elif direction == "W":
        print "Sorry, you can't go west here."
        dining_room()
    elif direction == "Q":
        userQuit()
    else:
        print "Sorry, that's not a valid direction."
        dining_room()

def basement():
    print ("\nYou are now in the basement. A cloud of dust passes by you and makes it hard to breath. You move away from the area"
    +" and you notice a key on the floor. You pick up the key and hold onto it. You may use it for later. ")
    direction = raw_input("Press U to go upstairs. You also have the option to (Q)uit. ")
    if direction == "U":
        has_key = True
        dining_room()
    elif direction == "Q":
        userQuit()
    else:
        print "Sorry, the only place you can go is back upstairs."
        basement()

welcomeMessage()
has_key = False
living_room()
Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
  • Reminder: if you are satisfied with an answer, click on the checkmark next to the voting controls to accept it. Welcome to StackOverflow! – sleblanc Oct 11 '15 at 16:35

4 Answers4

2

Although has_key is defined before the call to living_room() its scope does not penetrate to any variable of the same name defined in a routine called from living_room(). That's because in Python a function body is a local scope block. Any variable declared or assigned in a function body is local to that function, unless explicitly declared global.

In particular, the has_key defined in basement() is of local scope to basement(). It's a different, new local variable.

State changes made to has_key in basement() are not reflected in the has_key originally defined before calling living_room(). They are at different scope.

Although one option is to declare the has_key variable global in routines where its state will be changed (like basement()), global variables often are not considered best practice. Changing state of globals in functions can lead to difficult to find bugs. Probably a better practice is to have basement return its state and check that state in its caller.

I notice several of your functions are recursive, not sure that's the best choice in this context, but that's another question.

Look at http://spartanideas.msu.edu/2014/05/12/a-beginners-guide-to-pythons-namespaces-scope-resolution-and-the-legb-rule/ as one tutorial on Python variable scoping.

paisanco
  • 4,098
  • 6
  • 27
  • 33
2

Python has to be told that your has_key variable is of type global:

def basement():
    global has_key
    ...
    if direction == "U":
        has_key = True

With minor rewriting, you could use message passing to control where the player is currently located.

So instead of calling the living_room() function and letting it control where the player goes by calling the function from inside, the living_room function can return the function that your "game loop" should call next:

def game_loop():
    first_room = living_room

    next_room = first_room()
    while callable(next_room):
        next_room = next_room()

Typical game code will look more like this than yours does. It has a few advantages, the first is that there will be less recursion involved, so that the "stack" does not go as deep. Second is that it lets you apply some common logic between rooms, e.g. to track where the player has been.

sleblanc
  • 3,821
  • 1
  • 34
  • 42
1

Insert this line before you change the value of has_key in your basement() function:

global has_key

It will tell Python to assign the value to the globally scoped has_key instead of creating a new, locally scoped has_key inside the function.

Jason
  • 2,725
  • 2
  • 14
  • 22
0

You could also make the whole program a little bit more object orientated and set has_key as attribute of the object. Just need to add a class, a init method to initialize self.has_key = False and spend all functions a bunch of self's. In order to prevent you from a lot copying and pasting i already did that for you.

 class TextAdventure(object):
    def __init__(self):
        self.has_key = False

    def welcomeMessage(self):
        print "Welcome to my game!!"

    def winnerMessage(self):
        print "You're a winner!! Congratulations!!"
        self.userQuit()

    def userQuit(self): 
        print "Thanks for playing!"

    def living_room(self):
        # This part isn't executing (Boolean doesn't work here)
        # I want the if statement to execute, not the else statement
        if self.has_key == True:
            self.winnerMessage()
            self.userQuit()
        else: 
            print ("\nYou are in the living room. The paint from the walls is tearing off."
            +" There is a door near you, but it seems to be locked. To your west is the"
            +" kitchen, where you can eat some tasty snacks and to your south is a bedroom. ")
            direction = raw_input("Which direction would you like to go? (W)est or (S)outh? You also have the option to (Q)uit. ")
            if direction == "W":
                self.kitchen()
            elif direction == "S":
                self.bed_room()
            elif direction == "N":
                print "Sorry, you can't go north here."
                self.living_room()
            elif direction == "E":
                print "Sorry, you can't go east here."
                self.living_room()
            elif direction == "Q":
                self.userQuit()
            else:
                print "Sorry, that's not a valid direction."
                self.living_room()


    def kitchen(self):
        print ("\nYou are in the kitchen. The water from the sink is slightly running. All of the"
        +" cupboards in the kitchen have been left open, like someone has searched through them."
        +" To your south is the dining room, and to your east is the living room. ")
        direction = raw_input("Which direction would you like to go? (S)outh or (E)ast? You also have the option to (Q)uit. ")
        if direction == "S":
            self.dining_room()
        elif direction == "E":
            self.living_room()
        elif direction == "N":
            print "Sorry, you can't go north here."
            self.kitchen()
        elif direction == "W":
            print "Sorry, you can't go west here."
            self.kitchen()
        elif direction == "Q":
            self.userQuit()  
        else:
            print "Sorry, that's not a valid direction."
            self.kitchen()


    def bed_room(self):
        print ("\nYou are in the bedroom. One of the windows in the room is slightly ajar. The other window"
        +" is shattered with a brick laying on the floor next to it. To your west is the dining room and"
        +" to your north is the living room.")
        direction = raw_input("Which direction would you like to go? (W)est or (N)orth? You also have the option to (Q)uit. ")  
        if direction == "W":
            self.dining_room()
        elif direction == "N":
            self.living_room()
        elif direction == "E":
            print "Sorry, you can't go east here."
            self.bed_room()
        elif direction == "S":
            print "Sorry, you can't go south here."
            self.bed_room()
        elif direction == "Q":
            self.userQuit()
        else:
            print "Sorry, that's not a valid direction."
            self.bed_room()

    def dining_room(self):
        print ("\nYou are in the dining room. It is very hard to see in here due to the dim lighting. You notice a staircase is the"
        +" in the center of the room. To your north is the kitchen, and to your east is the bedroom.")
        direction = raw_input("Which direction would you like to go? (N)orth or (E)ast or go (D)own the staircase? You also have the option to (Q)uit. ")
        if direction == "N":
            self.kitchen()
        elif direction == "E":
            self.bed_room()
        elif direction == "D":
            self.basement()
        elif direction == "S":
            print "Sorry, you can't go south here."
            self.dining_room()
        elif direction == "W":
            print "Sorry, you can't go west here."
            self.dining_room()
        elif direction == "Q":
            self.userQuit()
        else:
            print "Sorry, that's not a valid direction."
            self.dining_room()

    def basement(self):
        print ("\nYou are now in the basement. A cloud of dust passes by you and makes it hard to breath. You move away from the area"
        +" and you notice a key on the floor. You pick up the key and hold onto it. You may use it for later. ")
        direction = raw_input("Press U to go upstairs. You also have the option to (Q)uit. ")
        if direction == "U":
            self.has_key = True
            self.dining_room()
        elif direction == "Q":
            self.userQuit()
        else:
            print "Sorry, the only place you can go is back upstairs."
            self.basement()

def main():
    t = TextAdventure()
    t.welcomeMessage()
    t.living_room()

if __name__ == "__main__":
    main()

Great game. Had a lot of fun playing it. Although it was a little bit short, but thanks for sharing and keep up the good work! You could also provide some user actions if you make it a little more OOP. :)

class TextAdventure(object):

    def __init__(self):
        self.has_key = False

    def use(self):
        print 'You used something'

    def eat(self):
        print 'You ate something'

    def drink(self):
        print 'You drank something'


def main():
    t = TextAdventure()
    actions = { 'use' : t.use, 'eat' : t.eat, 'drink' : t.drink }
    a, b, c = actions.keys()
    action = raw_input('Choose what to do [{0}, {1}, {2}]'.format(a,b,c))
    if action in actions:
        actions[action]()
BigZ
  • 836
  • 8
  • 19
  • Thank you very much guys. I'm still a beginner at Python and making games overall so I'll be sure to work on further improving the structure of the code and the game itself! Ciao! :D – Justin K. Maddox Oct 11 '15 at 03:28
  • The code doesn't work, as the `TextAdventure.has_key` method is undefined. – pppery Oct 11 '15 at 13:31
  • Woops, you're right. I edited it. has_key should be a boolean not a method. – BigZ Oct 12 '15 at 18:09