# Map generator for a text-based role-playing game

I am semi new to coding and have been following a tutorial on making a "text based RPG" on CodeClub.

Here is the full code:

#!/bin/python3

# Replace RPG starter project with this code when new instructions are live

def showInstructions():
#print a main menu and the commands
print('''
RPG Game
========

Get to the Garden with a key, a knife and a matchbox
But beware of the monsters!

Commands:
go [direction]
get [item]
''')

def showStatus():
#print the player's current status
print('---------------------------')
print('You are in the ' + currentRoom)
#print the current inventory
print('Inventory : ' + str(inventory))
#print an item if there is one
if "item" in rooms[currentRoom]:
print('You see a ' + rooms[currentRoom]['item'])
print("---------------------------")

#an inventory, which is initially empty
inventory = []

#a dictionary linking a room to other rooms
rooms = {

'Hall' : {
'south' : 'Kitchen',
'east'  : 'Dining Room',
'item'  : 'key'
},

'Kitchen' : {
'north' : 'Hall',
'east'  : 'Living Room',
'item'  : 'knife'
},
'Dining Room' : {
'west'  : 'Hall',
'south' : 'Living Room',
'east'  : 'Garden',
'item'  : 'matchbox'
},
'Living Room' : {
'north' : 'Dining Room',
'west'  : 'Kitchen',
'item'  : 'monster'
},
'Garden' : {
'west'  : 'Dining Room'
}

}

# Displays a map of all the accesable rooms from the current room.
def room_map():

# Makes sure that a variable defaults to an empty string...
# ...if the current room doesnt link to another room in that direction.
try:
north = rooms[currentRoom]['north']
except:
north = ""
try:
south = rooms[currentRoom]['south']
except:
south = ""
try:
east = rooms[currentRoom]['east']
except:
east = ""
try:
west = rooms[currentRoom]['west']
except:
west = ""

# Prints the map
n = "N"
s = "S"
vert_line = "|"
hzt_line = "-- W -- X -- E --"
print(north.center(30))
print("")
print(vert_line.center(30))
print(n.center(30))
print(vert_line.center(30))
print(west + hzt_line.center(30 - len(west) * 2) + east)
print(vert_line.center(30))
print(s.center(30))
print(vert_line.center(30))
print("")
print(south.center(30))
print("")

#start the player in the Hall
currentRoom = 'Hall'

showInstructions()

#loop forever
while True:
room_map()
showStatus()

#get the player's next 'move'
#.split() breaks it up into an list array
#eg typing 'go east' would give the list:
#['go','east']
move = ''
while move == '':
move = input('>')

move = move.lower().split()

#if they type 'go' first
if move[0] == 'go':
#check that they are allowed wherever they want to go
if move[1] in rooms[currentRoom]:
#set the current room to the new room
currentRoom = rooms[currentRoom][move[1]]
#there is no door (link) to the new room
else:
print('You can\'t go that way!')

#if they type 'get' first
if move[0] == 'get' :
#if the room contains an item, and the item is the one they want to get
if "item" in rooms[currentRoom] and move[1] in rooms[currentRoom]['item']:
#add the item to their inventory
inventory += [move[1]]
#display a helpful message
print(move[1] + ' got!')
#delete the item from the room
del rooms[currentRoom]['item']
#otherwise, if the item isn't there to get
else:
#tell them they can't get it
print('Can\'t get ' + move[1] + '!')
# player loses if they enter a room with a monster
if 'item' in rooms[currentRoom] and 'monster' in rooms[currentRoom]['item']:
print('A monster has got you....GAME OVER!')
break

# player wins if they get to the garden with a key, a matchbox and a knife
if currentRoom == 'Garden' and 'key' in inventory and 'matchbox' in inventory and 'knife' in inventory:
print('You escaped the house... YOU WIN!')
break


I have tried to implement my own map/compass to display the players current location in relationship to the accesable rooms. My code works but is very repetitive and not very efficient.

I am interested in simplifying the room_map() function.

I will eventually go about creating a real map with rooms and walls that can be updated in terms of player location, enemies etc.

The map looks like this and updates when I go to another room:

Since “Dining Room” (11 characters long) is west of the garden, you probably want

west.rjust(11) + hzt_line + east


for your room map. (You’ll have to increase your centering values to accommodate the additional characters.)

Since ['item'] is often in a room dictionary, the player can type “go item”, moving to the “item” room, crashing the game. You should validate the move directions. One way: instead of move directions stored as keys of the room, store them in a 'exits' dictionary in the room.

'Kitchen' : {
'exits' : { 'north': 'Hall', 'east': 'Living Room'},
...


You can test for many similar conditions using all(...) and list comprehension.

if currentRoom == 'Garden'  and  all(item in inventory for item in ('key', 'matchbox', 'knife')):
...


But really you want inventory to be a set. Then you can test:

if currentRoom == 'Garden'  and  inventory >= {'key', 'matchbox', 'knife'}:
...

• Thank you! The last line of code is much better than what I had Apr 8 '20 at 22:42
#!/bin/python3


This is rarely where Python lives. Typically you should instead write

#!/usr/bin/env python3


Your rooms dict shouldn't really be a dict. Dicts are good for serialization and web APIs, but in Python they're often abused. You should use a namedtuple, if not an actual class.

Here:

# Displays a map of all the accesable rooms from the current room.
def room_map():


The convention for function documentation is to use the following format:

def room_map():
"""
Displays a map of all the accessible rooms from the current room.
"""


When you do this:

try:
north = rooms[currentRoom]['north']
except:
north = ""


There are several problems. First, your except clause is way, way too broad. You probably want to catch KeyError. However, the saner thing to do is:

north = rooms.get(currentRoom, {}).get('north', '')


You also have a bunch of code in global scope. This should be reduced - you should move that code into one or more functions.

'You can\'t go that way!'


should simply be

"You can't go that way!"

• Thank you! I somehow missed these replies, but I am very thankful for the response! I might just dive into that project again with your insight :) Apr 8 '20 at 22:41

I'm going to assume that you borrowed code from this page on usingpython.com in order to make this because of the dictionary and the move = input("").lower().split(). No shame in that, it's a useful site. I use it too. Try instead of if item in room and if enemy in room, try if a enemy is in the room. So if a enemy is in the room, then it would display game over if a enemy is in the room, meaning you dont have to add extra items into a room

• Welcome to Code Review! This answer is a little in the brief side, which isn’t bad but could you expand it a little? Specifically you stated “Try instead of if item in room and if enemy in room, try if a enemy is in the room.” can you explain to the OP what advantages this would have? Apr 5 '19 at 23:39
• (The diction differs between Axel Sorensen's qustion and the site/code linked: pleas use the terms (monster) from the question.) Apr 6 '19 at 9:29