I've been hacking away on a little game, just for fun, and I've run into a problem. I'll post the code and try my best to explain:
def parseCmd(string):
cmd = string.split(' ')
if cmd[0] == 'help':
showHelp()
elif cmd[0] == 'add':
addServer()
elif cmd[0] == 'bag':
viewInventory(inventory)
elif len(cmd) == 1 and cmd[0] == 'look':
describeRoom()
elif len(cmd) == 1 and cmd[0] == 'take':
print 'What do you want me to take?'
elif cmd[0] == 'take':
pickUp(cmd[1], items)
elif cmd[0] == 'exit':
sys.exit(0)
else:
print 'I don\'t know how to ' + cmd[0]
def describeRoom():
print locations[player_location]
def pickUp(item, item_list):
if item in item_list[player_location]:
item_list[player_location].remove(item)
inventory.append(item)
print 'You took the ' + item
else:
print 'I can\'t find any ' + item
inventory = ['id card', 'money', 'keys']
player_location = 'cookieroom'
items = {'cookieroom': ['crowbar', 'hammer']}
locations = {'cookieroom': 'The cookieroom, where all the hard work gets done. \n\nNORTH: LFA - ITEMS: %s' % items[player_location],
'LFA': 'The infamous LFA, where dreams of office supplies become reality. there is a big guy sleeping in his chair next to a fire extinguisher.\n\nSOUTH: Cookieroom, WEST: WC'}
if __name__ == "__main__":
while 1:
t = raw_input('-> ')
parseCmd(t)
So, as you can see I want the list of items in the items dictionary to change when you pick up an item available in that specific room. I can pick up the item and it gets added to my inventory but if I issue the command 'look' it shows the list of items in it's original state.
I've been googling and stackoverflowing for 1½ day now and I can't find anything that seems to solve this problem.
If something is unclear, just ask me and I'll try to answer.
The locations dictionary, which is from where the describeRoom function picks up its room description, is initialised once when the program starts. At that time, the location of the player is the cookieroom and the objects there are the crowbar and the hammer. So, a string is created like so
'The cookieroom, where all the hard work gets done. \n\nNORTH: LFA - ITEMS: ["crowbar", "hammer"]'
This string never changes even if you later alter the contents of the items dictionary.
Your locations dictionary should only contain the non changing part of the room description. The changing part (e.g. the list of items in the room etc.) should be recomputed everytime the users requests the description of the room.
Related
So far I have been able to add either one-word values or 2-word values but not both. For example, I want to go to one location and add a skull to my inventory, then move to another location and add an energy potion to my inventory. With my current code, I can add the energy potion by using .split(maxsplit=1) or .split(' ', 1). That was to solve the issue of not being able to add a value with 2 words. But this seems to prevent adding values with one word to the inventory.
while True:
instructions()
player_status(rooms, current_room, inventory)
time.sleep(0.5)
# sets up user command to move player between rooms.
command = input('\nWhat do you want to do?\n>').title().strip()
if command in rooms[current_room]:
current_room = rooms[current_room][command]
time.sleep(0.5)
# command to add item to inventory and remove it from dict.
elif command.lower().split()[0] == 'get':
obj = command.lower().split(maxsplit=1)[1]
if obj in rooms[current_room]['item']:
del rooms[current_room]['item']
inventory.append(obj)
else:
print("I don't see that here.")
# a command to quit the game.
elif command.lower() in ('q', 'quit'):
time.sleep(0.5)
print('\nThanks for playing.')
break
# if player inputs an invalid command.
else:
time.sleep(0.5)
print('\nYou can\'t go that way!')
Here is an example of the output:
You are at occult bookstore.
There is a Skull
You have: ['energy potion']
What do you want to do?
>get skull
I don't see that here.
if obj in rooms[current_room]['item']:
That's searching for skull but Skull doesn't match. You could use [for a case-insensitive search]
if obj.lower() in [i.lower() for i in rooms[current_room]['item']]:
but that doesn't feel very efficient. It might be better to just apply .title() or .capitalize() to obj and make sure that all items in rooms[current_room]['item'] are in consistent format.
I'm mostly new to this so apologies in advance if the answer is blindingly obvious to this. For a school assignment (and out of interest also) I'm building a sort of basic car app that uses lists to store cars (objects) as they are made then a separate list to record cars that are rented.
The rent process works perfectly fine and when I tested it it was appending a car to my rentedcars list, however when I call it (rentedcars) later in a separate function its saying that it cannot pop an empty list.
I assumed this was because the list was being modified inside a function, however when I returned the outputed modified list and assigned a variable to the function for later use it gave me the error that I was calling a variable before assigning it and giving the variable a global definition didn't resolve it.
The segment of code is below, anyone have any thoughts? It would be much appreciated. I've looked this sort of problem a couple of times on the forums here but the solutions (at least as I tried to implement them) didn't seem to fix it.
The function rental_system is called later, I've just shown the section I'm having problems with due to size, all lists for the 4 types of car are made under init self. etc and work.
def rent(self, car_list, rented_cars, amount): # Process to rent a car function
if len(car_list) < amount:
print 'Not enough cars in stock' # Make sure enough cars in stock
return
total = 0
while total < amount:
carout = car_list.pop() # Pop last item from given car list and return it
rented_cars.append(carout) # Then append to a new list of rented cars that are now unavailable
total = total + 1
print 'Make: ' + carout.getMake()
print 'Colour: ' + carout.getColour()
print 'Engine Size(Cylinders): ' + carout.getEngineSize()
print 'You have rented ' + str(amount) + ' car(s)'
return rented_cars
def rented(self, car_list, rented_cars, amount): # Process for returning cars
total = 0
while total < amount:
carin = rented_cars.pop()
car_list.append(carin)
total = total + 1
print 'You have returned' +str(amount) + 'car(s)'
return rented_cars, car_list
def rental_system(self):
rentedcars = []
rented = raw_input('Are you returning or renting a car? Type either return/rent ')
if rented.lower() == 'return': # Return system
type = raw_input('Are you returning a petrol, electric, diesel or hybrid car? ')
amount = raw_input('How many would you like to return? ')
if type == 'petrol':
self.rented(self.petrolcars, rentedcars, amount)
elif type.lower() == 'diesel':
self.rented(self.dieselcars, rentedcars, amount)
elif type.lower() == 'hybrid':
self.rented(self.hybridcars, rentedcars, amount)
elif type.lower() == 'electric':
self.rented(self.electriccars, rentedcars, amount)
else:
print 'Error, please check your spelling'
return
if rented.lower() == 'rent':
Rental process
answer = raw_input('What type of car would you like? Type: petrol/diesel/hybrid/electric ')
amount = int(raw_input('How many of that type of car?'))
if answer.lower() == 'petrol':
self.rent(self.petrolcars, rentedcars, amount)
elif answer.lower() == 'diesel':
self.rent(self.dieselcars, rentedcars, amount)
elif answer.lower() == 'hybrid':
self.rent(self.hybridcars, rentedcars, amount)
elif answer.lower() == 'electric':
self.rent(self.electriccars, rentedcars, amount)
else:
print 'Error, please check your spelling'
return
The problem is that you are passing an empty list through the rental_system method to the rented method.
You have defined rentedcars = [] in rental_system method and without modifying it you are trying to pop from it in the rented method.
Why don't you add the rented_cars as an attribute in your class design?
here is a piece of the code I am working with:
if second_do.lower() == "market":
print "You are now inside of the market place. It appears to be abandoned. The shelves are almost empty, however, you to manage find some salvagable goods, including peanut butter, beans, and crackers."
goods = raw_input(">>> ")
if goods.lower() == "collect":
print "You have collected the food items. These will help you later on."
if goods.lower() == "get":
print "You have collected the food items. These will help you later on."
if goods.lower() == "collect food":
print "You have collected the food items. These will help you later on."
if goods.lower() == "collect goods":
print "You have collected the food items. These will help you later on."
if goods.lower() == "get food":
print "You have collected the food items. These will help you later on."
if goods.lower() == "get goods":
print "You have collected the food items. These will help you later on."
after_market = raw_input("What's next?")
if "mansion" in after_market:
elif second_do.lower() == "mansion":
print "You are now inside of the mansion."
I was wondering how I make it so one part of the script (in this case,if mansion in after_market:) can take me to another part. (elif second_do.lower() == "mansion":)
You probably want to restructure you code a bit and use variables to keep track of where your user "is" while looping. Something like...
location = "start"
while location != "exit":
if location == "market":
# do market related stuff
elif location == "mansion":
# do mansion related stuff
location = raw_input("Where to next?")
You can then go one step further and use functions for each location, e.g.
def doMarket():
# do market related stuff
def doMansion():
# do mansion related stuff
location = "start"
while location != "exit":
if location == "market":
doMarket()
elif location == "mansion":
doMansion()
location = raw_input("Where to next?")
You could also have it be more controlled where someone in one place can go next, by having the functions return the new location:
def doMarket():
# do market related stuff
# User can go anywhere from the market
return raw_input("Where to next?")
def doMansion():
# do mansion related stuff
# User must always go to the market after the mansion
return "market"
location = "start"
while location != "exit":
if location == "market":
location = doMarket()
elif location == "mansion":
location = doMansion()
The minimal change you need to make is this:
if second_do.lower() == "market":
print "You are now inside of the market place. It appears to be abandoned. The shelves are almost empty, however, you to manage find some salvagable goods, including peanut butter, beans, and crackers."
goods = raw_input(">>> ")
if goods.lower() == "collect":
print "You have collected the food items. These will help you later on."
if goods.lower() == "get":
print "You have collected the food items. These will help you later on."
if goods.lower() == "collect food":
print "You have collected the food items. These will help you later on."
if goods.lower() == "collect goods":
print "You have collected the food items. These will help you later on."
if goods.lower() == "get food":
print "You have collected the food items. These will help you later on."
if goods.lower() == "get goods":
print "You have collected the food items. These will help you later on."
after_market = raw_input("What's next?")
if "mansion" in after_market:
second_do = "mansion"
# After this, the control drops to the next if-statement
if second_do.lower() == "mansion":
print "You are now inside of the mansion."
To make this code DRY, you have to place these options in a loop which asks the user for what to do next and the actions are functions which are executed for the option the user chose
I don't really know how to explain this exactly.. But I'm making a text adventure for learning the basics. Now I want to make a gold and money system, I am using def... things for different levels and such. but in every prompt I have to put in if the user types gold, or inv it shows the inventory and then go back to the def where it was.. which I find irritating to do every time. And I forget it too at some periods. I want to do it as default in the prompt.
I have a def prompt(): that is this easy code:
def prompt():
x = input('Type a command: ')
return x
and if I put it there it just ends the code. I have to do this in every prompt:
def AlleenThuis():
command = prompt()
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
elif command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
return AlleenThuis()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
return AlleenThuis()
else: #The else has to stay in this place because it's part of the 'if not inv:' guys.
print('\n\t' + str(inv) + '\n')
return AlleenThuis()
#Actions end here
So if there's any way to just implement it so that I don't have to put it in again every time that would be awesome!
Thanks.
EDIT: It looks like you guys aren't understanding what I'm saying, so I have 2 images.
So..
http://i.imgur.com/GLArsyu.png (I can't post pictures yet =[ )
As you can see in this picture, I have included gold and inv.
But in http://i.imgur.com/V3ZhJ36.png I have also done that, so I have coded that in the code again, that is what I Don't want!
I just want to have that in the code 1 time, and let the gold and inventory show all the time when the player enters the commands for them!
On a more fundamental level, the object-oriented paradigm elegantly solves the problem of repetitive code like this:
global gold = 0
def cave():
print "You are in a cave."
print "You have %i gold." % gold
direction = input()
if direction = 'N':
stream()
elif direction == 'S':
house()
elif direction == 'W':
mountain()
elif direction == 'directions':
print "You can go North, West, or South."
else:
print "You cannot go there."
def stream():
print "A small stream flows out of the building and down a gully."
print "You have %i gold." % gold
direction = input()
if direction == 'N':
tree()
elif direction == 'S':
cave()
elif direction == 'directions':
print "You can go North or South."
else:
print "You cannot go there."
def main():
cave()
by turning it into something like this:
class Location:
map = { 'cave': {
'description': 'You are in a cave.',
'directions': { 'N': 'stream', 'S': 'house', 'W': 'mountain' } },
'stream': {
'description':
'A small stream flows out the building and down a gully.',
'directions': { 'N': 'tree', 'S': 'cave' } } #...
}
def __init__ (self):
self.location = 'cave'
def enter (self, direction):
self.location = self.map[self.location]["directions"][direction]
print self.map[self.location]["description"]
def directions(self):
return self.map[self.location]["directions"].keys()
def readable(self, dirs):
readable = { 'S': 'South', 'N': 'North', 'W': 'West', 'E': 'East' }
return [readable[d] for d in dirs]
class Inventory:
def __init__ (self):
self.inventory = { 'gold': 0 }
def query (self):
print "You have %i gold." % self.inventory['gold']
def main:
loc = Location()
inv = Inventory()
while True:
directions = loc.directions()
action = raw_input()
if action in directions:
loc.enter(action)
inv.query()
elif action == 'directions':
where = loc.readable(directions)
print "You can go " + ", ".join(where[:-1])\
+ ", or " + where[-1]
else:
print "You cannot go there."
You will notice that the more modular code is also easier to extend. For example, the inventory can now hold more things than gold, and it's easy to add new commands to query for weapons, potions, etc. Furthermore, it somewhat separates the code from the data, making it less cumbersome and error-prone to add new locations and actions.
Next up, define class Object with subclasses for animate objects, objects you can pick up, immobile objects, etc; and populate the locations with instances of these. Different subclasses can have different interactions defined, and inherit from more basic superclasses which implement fundamentals like take, drop, kill, etc.
What to map into objects is a broad topic, but a few simple guidelines would be to isolate and encapsulate unrelated code into their own classes, and make them as decoupled as possible (code implementing "location" should not need to know pretty much anything about code in "inventory", and vice versa).
Your code for this has some serious structural problems. If I understand correctly, you're trying to accept repeated commands and execute some code to make them function the way you intend.
The problem is that your function to run the game is recursive, so every time you execute a command other than 1, 2, 3, or 4, you're calling your function again without returning from the first one. Eventually, if you enter enough commands, you'll get an error saying that you're recursing too deeply and the game will error out.
What you want is something more like this:
def prompt():
x = input('Type a command: ')
return x
def ProcessAction(command):
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
elif command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
#Actions end here
curr_command = None
while curr_command not in ("1", "2", "3", "4"):
curr_command = prompt()
ProcessAction(curr_command)
What this will do is keep asking for new commands and processing them until one of the commands that exits the game is entered.
Edit: From your comment below, it sounds like you're trying to figure out how to display gold and inventory every time a command is entered without requiring a special command to do it. If this is what you're after, you can add print statements to the while loop above to ensure that it's printed before every prompt. In that case, the while loop might look like:
while curr_command not in ("1", "2", "3", "4"):
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
curr_command = prompt()
ProcessAction(curr_command)
Hope that gets closer to what you're after.
Edit 2: Ok, after reading the full code for your game, I think you might want to consider reorganizing the entire thing. Think about what you want the game to be: the player enters a series of commands and each command does two things, it changes the game's state and it prints out a response based on both the current state and the new state.
So, you should think about processing your commands with a loop like I described. Then, fold all those different functions into ONE ProcessAction(command) function that figures out from the game's state (which you store in variables) what to print out and how to change the state.
If it's a game where you're going room to room, for example, you might keep a global variable room that defines where you are. Your ProcessAction function then follows logic that says "If I'm in room A and the character types this thing then print out B and change room to C, and sets gold to 0."
To make this work well, you'll have to step back and think about the overall "story" of your game, how to store the state in various variables, and how to make your ONE ProcessAction function handle all the possible states and commands that can be issued.
Doing this puts you on the path of developing what's called a "state machine," where you have a simple, general function that looks at a data structure (probably some nested dicts) that you fill up with what each command does when your game is in each state and where to go next, as well as what to print out.
This Wikipedia article describes the concept of a state machine. How you implement it in Python is up to you. I can tell you that if you're careful you should be able to do this without repeating any code. http://en.wikipedia.org/wiki/State_machine
Another edit: Answering a question you placed in the comments below, if you think you have to print out, for example, the value of a player's gold in multiple places, you can do something like this:
def print_gold(gold_value):
print('\n\tYou have ' + str(gold_value) + ' euro. RICH BOY BRO!.\n')
print()
then use print_gold(gold) in place of those print statements whenever you need to do that. However, I think you may want to take a step back and think about rewriting the whole thing with some of the thoughts I've offered before you tackle that problem.
My earlier answer is long and addresses a number of problems in the OP's code, but he's asking about one specific thing, so I thought I'd separate out that answer here.
If you have some code you'd like to repeat multiple times, you might be tempted to copy and paste it around in your code In your case, that would be something like:
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
Wrapping that in a function will allow you to execute that same code anytime you need to do that thing, without copying and pasting. You're already defining functions, so you seem to have the concept down, but this wrapped in a function might look like:
def print_gold(gold_value):
print('\n\tYou have ' + str(gold_value) + ' euro. RICH BOY BRO!.\n')
print()
With this function defined, anytime you place print_gold(gold) in your code, it'll pass the value of gold into that function as the variable gold_value and print it out as you've specified.
So, if for some reason you had code that looked like this:
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
you could turn this into:
def print_gold(gold_value):
print('\n\tYou have ' + str(gold_value) + ' euro. RICH BOY BRO!.\n')
print()
... somewhere else in your code ...
print_gold(gold)
print_gold(gold)
print_gold(gold)
Those three lines are function calls, which tell Python to execute the function you've defined with def.
I am assuming you are currently pasting something into this prompt everytime you want to run your Python program, and your question is about how to avoid that:
The answer to this problem is generally to save your program's code in a whatever.py file and run that file... either by doubleclick or through the terminal. The exact instructions depend on your operating system etc.
If I understood correctly the latest edit to your question, then you might want something like:
def get_gold_or_inv(command):
if command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
while True:
command = prompt()
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
get_gold_or_inv(command)
Are you trying to say that you want this to run in an infinite loop until quit?
You can do that either by encapsulating the entire function block with a while True: or just by calling AlleenThuis() after the ifs and elifs. I took the liberty to rewrite your implementation using the first option below.
def AlleenThuis():
while True:
command = prompt()
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
elif command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
else:
print("Invalid command")
Hope I didn't misunderstand you.
EDIT:
def action(cmd):
if cmd == 'geld':
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif cmd == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
else:
# If the command was not found
return False
# If the command was found and the else statement was not run.
return True
Then just run this at the start of every scenario if action(command): return ScenarioName().
Hope that helps!
I am attempting to create a text-based adventure game for class, but I have been experiencing problems in getting the 'use' function to work when using an item in inventory.
The game has 2 interactive menus, the main menu (where you can travel, search, display and use inventory, display an ASCII map, or quit) and the travel menu (a while loop that moves you between locations). I wanted to lock one of the doors to a location, requiring the user to find a key in a different location (thereby adding it to inventory) and then choose that item from inventory when prompted to gain access to the location.
I created a dictionary to be referenced by the use function to verify if the item can be used in a specific location. I tested the logic within the function and it worked. However, it will accept any item to be used on the door for some reason and I think it has to do with the way the functions deal with each other seeing as the use function is called on by the show inventory function.
Any help would be appreciated here, whether to the specific question or anything that you might do differently.
These are the functions in question:
def eHouseAccess(action, location, oldLocation): # called by travel to validate if the location is accessable
global eHouse
if eHouse == 'locked' and inventory == []:
print "The door is locked! You need to find a key for this door."
travel(oldLocation)
elif eHouse == 'locked':
print "The door is locked! You need to find a key for this door."
print "Maybe you have it in your inventory?"
a = showInv(inventory, location, items)
if a == True:
eHouse = 'open'
travel(location)
else:
travel(oldLocation)
else:
location = travelOpt[location][action - 1]
travel(location)
def travel(location):
while True:
print "You are in the", location[0]+"."
print location[1]
print 'You can travel to:'
for (i, t) in enumerate(travelOpt[location]):
print i + 1, t[0]
action = raw_input("Pick a destination, or enter 'menu' for the main menu: ")
if action == 'menu':
main_menu(location, inventory, items)
else:
action = int(action)
if travelOpt[location][action - 1] == engineer_house:
oldLocation = location
location = engineer_house
eAccess = eHouseAccess(action, location, oldLocation)
elif travelOpt[location][action - 1] == castle_inside:
cInside = cInsideAccess(action, location, cInside)
else:
location = travelOpt[location][action - 1]
def main_menu(location, inventory, items):
print "You are in the", location[0] + "."
menu_list = ['Travel', 'Inventory', 'Search', 'Map', 'Quit']
print "Choose one:"
for (num, t) in enumerate(menu_list):
print num + 1, t
main_choice = int(raw_input("> "))
action = menu_list[main_choice - 1]
if action == 'Travel':
travel(location)
elif action == 'Inventory':
showInv(inventory, location, items)
elif action == 'Search':
search(location, inventory, items)
elif action == 'Map':
map(location)
elif action == 'Quit':
exit()
else:
print "That is not a valid option!"
main_menu(location, inventory, items)
def showInv(inventory, location, items):
if inventory == []:
print "Your inventory is EMPTY"
sInv = raw_input("Hit 'enter' to return to the 'main menu': ")
main_menu(location, inventory, items)
else:
print "These 'items' are in your 'inventory':"
for (num, i) in enumerate(inventory):
print num + 1, i
sInv = raw_input("Type 'menu' to return to the main menu or 'use' to use and item: ")
if sInv == 'menu':
main_menu(location, inventory, items)
if sInv == 'use':
a = use(items, inventory, location)
return a
else:
print "That is not a valid entry!"
showInv(inventory, location, items)
def use(items, inventory, location):
if inventory == []:
print "There is nothing to use."
invEmpty = raw_input("Hit 'enter' to return to the 'main menu': ")
main_menu(location, inventory, items)
else:
uItem = int(raw_input("Choose an item to use: "))
curItem = inventory[uItem - 1]
if location == items[curItem][0]:
print "You used", inventory[uItem - 1]+"."
inventory.pop(uItem -1)
main_menu(location, inventory, items)
return True
else:
print "You cannot use that here!"
main_menu(location, inventory, items)
return False
There are two issues that stand out to me. First, use(...) is returning a boolean value, not the item used. No matter what the item used is, use(...) will return True. Second, in the eHouseAction method, you are testing to see if the value returned from showInv(...) is equal to True.
Since use(...) returns True and showInv(...) returns use(...), then a = showInv(...) is being set to True. eHouseAction is checking against True to open the door. Since using ANY item in your inventory will result in showInv(...) returning True, using ANY item in your inventory will open the door.
The solution is to make two changes:
def eHouseAccess(action, location, oldLocation):
[snip]
a = showInv(inventory, location, items)
if a == house_key: # I'm not exactly sure what you called the key
eHouse = 'open'
travel(location)
def use(items, inventory, location):
[snip]
if location == items[curItem][0]:
print "You used", inventory[uItem - 1]+"."
return inventory.pop(uItem -1)
Now, it would probably be a good idea to place the used item back in the player's inventory if they do not try to use a house_key. Without that check, any item they use will disappear forever.
Well, I'm not sure how eHouseAccess could even work — you should be getting NameError: global name 'items' is not defined. You probably wanted, global eHouse, items. Your bug, my guess, has to do with engineer_house. You are trying to compare it to items[curItem][0]. Are you setting that correctly?
Other notes:
Inside of use (which is not the best name), you probably want a return statement before the first else clause.
I would also point this out as an issue in a code review:
if location == items[curItem][0]:
Why does that have a 0 index? It seems like putting some sort of data object there would make more sense. Then the code might look something like this:
if location == items[curItem].location:
Or better yet, make that location property a list of places where it can be used and the you can have:
if location in items[curItem].valid_locations:
Of course, I would still return the object selected and not whether or not it could be used. Otherwise, in a situation where you have two or more things you can do, then you could accidentally brush your teeth with hand soap.