1

I'm having trouble trying to get a game creation exercise to stop printing the else statement (at the bottom of the code block). the idea is, you can navigate from room to room, but if you go in a direction you're not supposed it should tell you. However, it seems to be doing that even when you CAN go somewhere. I'd greatly appreciate any advice.

Code is below:

class Room:

    number_of_rooms = 0

    def __init__(self, room_name):
        self.name = room_name
        self.description = None
        self.linked_rooms = {}
        self.character = None
        Room.number_of_rooms = Room.number_of_rooms + 1
         
    def set_description(self, room_description):
        self.description = room_description

    def get_description(self):
        return self.description

    def set_name(self, room_name):
        self.name = room_name

    def get_name(self):
        return self.name

    def describe(self):
        print(self.description)

    def set_character(self, new_character):
        self.character = new_character
    
    def get_character(self):
        return self.character

    def describe(self): 
        print( self.description )
        
    def link_room(self, room_to_link, direction):
        self.linked_rooms[direction] = room_to_link

    def get_details(self):
        print(self.name)
        print("--------------------")
        print(self.description)
        for direction in self.linked_rooms:
            room = self.linked_rooms[direction]
            print( "The " + room.get_name() + " is " + direction)
        
    def move(self, direction):
        if direction in self.linked_rooms:
            return self.linked_rooms[direction]
        else:
            print("You can't go that way")
            return self

I would greatly appreciate any advice on this, it's maddening. I just need it to stop printing "You can't go that way" when you can. It actually does work, it just insist on printing it every time you go into a new room as well as when you can't.

This is the code it links to

    foyer = Room("foyer")
    ballroom = Room("ballroom")
    dining_hall = Room("dining hall")
    kitchen = Room("kitchen")

    foyer.link_room(ballroom, "south")
    ballroom.link_room(foyer, "north")
    ballroom.link_room(dining_hall, "east")
    dining_hall.link_room(ballroom, "west")
    dining_hall.link_room(kitchen, "north")
    kitchen.link_room(dining_hall, "south")
Matt
  • 25,467
  • 18
  • 120
  • 187
  • Just to be clear, you're saying the if statement evaluates to true and you are still seeing the message printed? – Portal Nov 08 '22 at 15:28
  • Yeah, that's exactly right – Battlebanana Nov 08 '22 at 15:29
  • What is the value of `direction` and `self.linked_rooms` when this happens? – wwii Nov 08 '22 at 15:29
  • 1
    [How to step through Python code to help debug issues?](https://stackoverflow.com/questions/4929251/how-to-step-through-python-code-to-help-debug-issues) If you are using an IDE **now** is a good time to learn its debugging features Or the built-in [Python debugger](https://docs.python.org/3/library/pdb.html). Printing *stuff* at strategic points in your program can help you trace what is or isn't happening. [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – wwii Nov 08 '22 at 15:29
  • There isn't enough information - please read [mre]. – wwii Nov 08 '22 at 15:30
  • I tried this out with your code. I was able to run the `move` command without problems. Did you link your rooms before running move? I did ```a = Room("a"); b = Room("b"); a.link_room(b, "left"); a.move("left")``` and the result was room b – PirateNinjas Nov 08 '22 at 15:32
  • `move` works for me for *valid* and *invalid* direction arguments. – wwii Nov 08 '22 at 15:39
  • @PirateNinjas This is the code it link to. As far as I can see, it's all linked up alright `foyer.link_room(ballroom, "south") ballroom.link_room(foyer, "north") ballroom.link_room(dining_hall, "east") dining_hall.link_room(ballroom, "west") dining_hall.link_room(kitchen, "north") kitchen.link_room(dining_hall, "south")` – Battlebanana Nov 08 '22 at 15:45
  • Could you look into the [answer](https://stackoverflow.com/a/74363440/1016343) I gave and tell me if it solves the issue? If not then maybe the sample code there helps you how to create a test case that resembles the issue you are facing. – Matt Nov 08 '22 at 15:58
  • In the `move` function, print the direction and the linked room dictionary keys. You'll learn something. – Peter Wood Nov 08 '22 at 16:10
  • @Matt Yup, it's all working now! Thanks you – Battlebanana Nov 08 '22 at 16:11
  • @Battlebanana - good to hear! :-) – Matt Nov 09 '22 at 09:10

1 Answers1

0

If you add the following test code to the end of your class (assuming that it is inside a module Room.py):

if __name__ == "__main__":
    print("Testing")

    # rooms
    room1 = Room("Floor")
    room2 = Room("Kitchen")
    room3 = Room("Living Room")

    # link the rooms
    room2.link_room(room1, "left")
    room3.link_room(room1, "right")

    # move
    room2.move("up") # not allowed
    room3.move("right")  # should be possible

Then you can run the test code directly if you execute the module.

Now if you are in room 3 (living room) it is possible to get out on the right. But if you are in room 2 (kitchen) you can only move to the left.

The test prints "You can't go that way" only if you do a move like room2.move("up") which is correct, because only "left" is allowed. Comment that line and you won't see that message any more.

According to this test, the class is behaving as it should. Note that you could (and should!) also write a unit test from the example I gave, asserting the expected output.


Update:

In your example, allowed moves are:

    # allowed
    kitchen.move("south")
    dining_hall.move("north")
    ballroom.move("east")
    foyer.move("south")

And examples for not allowed moves are:

    # not allowed
    kitchen.move("west")
    dining_hall.move("east")
    ballroom.move("south")
    foyer.move("north")

For these you will get "You can't go that way".

Maybe the issue you had was that you were using objects rather than strings as parameter to describe the direction.

For example, this will always fail (printing "You can't go that way"):

    foyer.move(ballroom)  # param should be a string, not an object

To prevent this kind of error, you could add a check to the move method:

    def move(self, direction):
        if not isinstance(direction, str):
                raise ValueError("Direction needs to be a string!")
        if direction in self.linked_rooms:
                return self.linked_rooms[direction]
        else:
                print("You can't go that way")
        return self

With that addition, the application will throw an exception, if you pass an object and not a string:

ValueError: Direction needs to be a string!

For interactive testing, you could use this code:

    new_dir = "nop"
    current_room = foyer
    while new_dir != "":
        print("current room: " + current_room.name)
        print("please enter direction:")
        new_dir = input()
        if new_dir == "":
             print("leaving")
             break
        new_room = current_room.move(str(new_dir))
        if new_room != current_room:
            print("moving to: " + new_room.name)
            current_room = new_room

For debugging, it might be also helpful if you add the following code to the top of the module:

def Log(func):
    def inner(*args, **kwargs):
        print(f"Logging {str(func)}: {args[1:]}")
        result = func(*args, **kwargs)
        print(f"Result: {str(result)}")
        return result
    return inner

Now you can decorate any of the functions with the @Log attribute like so:

@Log
def __init__(self, room_name):
...

@Log
def move(self, direction):
...

Whenever such a decorated function is called, it will print it to the console, e.g.:

please enter direction:
south
Logging <function Room.move at 0x000001994B97C720>: ('south',)
Result: <main.Room object at 0x000001994B97A150>
moving to: ballroom
current room: ballroom
please enter direction:

If you're done with debugging, you can comment out the attributes (# @Log) to remove the extra print outs.

Matt
  • 25,467
  • 18
  • 120
  • 187