Snapple55
Snapple55

Reputation: 11

Is the loop body changing my call method? (NEWB)

So I am completely new to programming of any sort. I am taking an introductory python class which requires the students to provide code for walking around a set of rooms. I figured it would be a good idea to assign some dictionaries from the layouts and go from there. When I try to call the value for the key on the first assignment of command it works as expected. But when I do the same exact operations two lines later I get a type error. I am stumped.

rooms = {
    'r1': {'name': 'Room1', 'north': 'room7', 'east': 'room2', 'item': 'ob1'},
    'r2': {'name': 'Room2', 'west': 'room1', 'item': 'ob2'},
    'r3': {'name': 'Room3', 'north': 'room4', 'west': 'room7', 'item': 'ob3'},
    'r4': {'name': 'Room4', 'south': 'room3', 'item': 'ob4'},
    'r5': {'name': 'Room5', 'east': 'room6', 'south': 'room7', 'item': 'ob5'},
    'r6': {'name': 'Room6', 'west': 'room5', 'item': 'ob6'},
    'r7': {'name': 'Room7', 'north': 'room5', 'east': 'room3', 'south': 'room1', 'west': 'room8', 'item': 'nothing'},
    'r8': {'name': 'Room8', 'east': 'room7', 'item': 'monster'}
}

location = rooms['r7']

command = input('You are in {}.  What would you like to do?: '.format(location['name']))#WORKS 
    #HERE
while True:
    command = input('You are in {}.  What would you like to do?: '.format(location['name']))#ERROR
    if command in location:
        location = command
        continue
    else:
        print('Invalid Input.  Please type a direction.')

Upvotes: 0

Views: 36

Answers (2)

Samwise
Samwise

Reputation: 71562

Here's a fixed version of the code you have so far.

rooms = {
    'room1': {'name': 'Room1', 'north': 'room7', 'east': 'room2', 'item': 'ob1'},
    'room2': {'name': 'Room2', 'west': 'room1', 'item': 'ob2'},
    'room3': {'name': 'Room3', 'north': 'room4', 'west': 'room7', 'item': 'ob3'},
    'room4': {'name': 'Room4', 'south': 'room3', 'item': 'ob4'},
    'room5': {'name': 'Room5', 'east': 'room6', 'south': 'room7', 'item': 'ob5'},
    'room6': {'name': 'Room6', 'west': 'room5', 'item': 'ob6'},
    'room7': {'name': 'Room7', 'north': 'room5', 'east': 'room3', 'south': 'room1', 'west': 'room8', 'item': 'nothing'},
    'room8': {'name': 'Room8', 'east': 'room7', 'item': 'monster'}
}

location = rooms['room7']

while True:
    command = input(
        f"You are in {location['name']}.  What would you like to do?: "
    )
    if command in location:
        location = rooms[location[command]]
    else:
        print('Invalid Input.  Please type a direction.')

The while loop didn't really have anything to do with the problem. The two major bugs were:

  1. Your rooms dict doesn't use the room IDs consistently. In order to be able to use a direction to look up the corresponding room, they need to refer to the rooms the same way. I've normalized the rooms keys to use the roomN format that the rooms themselves use.

  2. You need to correctly translate the direction into the next room. This requires that you first get the room ID based on the combination of the current location and the command, and second that you get the next room from the rooms dict -- all together this is simply rooms[location[command]].

Note that if the user types in "name" or "item" as the direction, your program will still crash! I'd probably fix this by separating the directions from the others pieces of room data, so that it's not possible for your program to confuse the directions with the other information about the room. For example:

from typing import Dict, List, NamedTuple


class Room(NamedTuple):
    name: str
    exits: Dict[str, str]  # map of direction to room ID
    items: List[str]


rooms = {
    'room1': Room('Room1', {'north': 'room7', 'east': 'room2'}, ['ob1']),
    'room2': Room('Room2', {'west': 'room1'}, ['ob2']),
    # etc
    'room7': Room('Room7', {'north': 'room5', 'east': 'room3', 'south': 'room1', 'west': 'room8'}, []),
    'room8': Room('Room8', {'east': 'room7'}, ['monster'])
}

location = rooms['room7']

while True:
    command = input(
        f"You are in {location.name}.  What would you like to do?: "
    )
    if command in location.exits:
        location = rooms[location.exits[command]]
    elif command == "look":
        print(f"Exits are {', '.join(location.exits.keys())}.")
        if location.items:
            print(f"There is {', '.join(location.items)} here.")
    elif command == "quit"
        print("Bye!")
        break
    else:
        print("Invalid Input.  Please type a direction.")
        print(f"Exits from this room: {', '.join(location.exits.keys())}")
You are in Room7.  What would you like to do?: south
You are in Room1.  What would you like to do?: look
Exits are north, east.
There is ob1 here.
You are in Room1.  What would you like to do?: east
You are in Room2.  What would you like to do?: look
Exits are west.
There is ob2 here.
You are in Room2.  What would you like to do?: get ob2
Invalid Input.  Please type a direction.
Exits from this room: west
You are in Room2.  What would you like to do?:

Upvotes: 4

Alejandro A
Alejandro A

Reputation: 1190

The problem is in this line

location = command

You replace the location (a dictionary room['r7']) with the variable command, which is a string like "north".

Then you go again in the while loop (while True) and you do:

format(location['name']))

At this point, location is a string and in Python you cannot slice a string like that.

I still not have clear what you want to achieve when doing

location = command

Upvotes: 0

Related Questions