I've recently been learning on how to write Python. I'm still a beginner. I've read multiple times that creating a text based adventure game in Python is a good exercise to learn the in's and out's.
I've finished the basic structure of the script. I've already run the script and so far everything is working great. I haven't implemented thought out descriptions and rooms, but I've got this down first to get the structure ready for detail.
The shop in the game works fine and I can buy/sell items. Right now all of the items are free and you don't receive anything for selling. I'm having trouble on implementing a money system.
My code is here:
North = 'north'
South = 'south'
East = 'east'
West = 'west'
DESC = 'desc'
Ground = 'ground'
GroundDesc = 'grounddesc'
ShortDesc = 'shortdesc'
LongDesc = 'longdesc'
DESCWORDS = 'descwords'
Takeable = 'takeable'
SHOP = 'shop'
SCREEN_WIDTH = 80
room_list = {
'Prison Cell' : {
DESC: 'You are in a prison cell. The cell door is unlocked and there is a hallway to the North.',
North: 'Prison Hallway',
Ground: ['Prison Sentence']},
'Prison Hallway' : {
DESC: 'You step out to the Prison Hallway. There is an unlocked cell to the East. A locked cell is close by to the West. Travelling North will take you to the Center of the Dungeon.',
North: 'Dungeon Center',
East: 'Unlocked Cell',
West: 'Locked Cell',
South: 'Prison Cell',
Ground: []},
'Unlocked Cell' : {
DESC: 'You open the door to the unlocked cell. You do not see anyone here. The floor is littered with hay.',
South: 'Prison Hallway',
Ground: ['Bedroll']},
'Locked Cell' : {
DESC: 'The cell is locked. There is a prisoner in the cell, but you cannt tell if he is alive. Its best not to bother him.',
South: 'Prison Hallway',
Ground: []},
'Dungeon Center' : {
DESC: 'You have entered the heart of the dungeon. From this point on, there is no going back.',
North: 'North Wing',
East: 'East Wing',
South: 'South Wing',
West: 'West Wing',
Ground: []},
'North Wing' : {
DESC: 'You are now in the North Wing.',
North : '$hop',
South: 'Dungeon Center',
Ground: []},
'$hop' : {
DESC: 'The shop owner gives you a friendly wave as you enter.',
South: 'North Wing',
SHOP: ['LongBow', 'Iron Arrow', 'Fidget Spinner'],
Ground: []},
'East Wing' : {
DESC: 'You are now in the East Wing.',
North: 'Treasure Room',
West: 'Dungeon Center',
South: 'South Wing',
Ground: []},
'West Wing' : {
DESC: 'You are now in the West Wing.',
East: 'Dungeon Center',
Ground: []},
'South Wing' : {
DESC: 'You are now in the South Wing.',
North: 'Dungeon Center',
Ground: []},
}
Dungeon_Items = {
'Prison Sentence' : {
GroundDesc: 'Your Prison Sentence is in your inventory.',
ShortDesc: 'your Prison Sentence',
LongDesc: 'You pull your Prison Sentence out of your inventory and unfold the first page. It reads: PRISONER 69, You have been locked away in this dreadful dungeon despite being innocent of any crimes. The only method of escape is death. Enjoy rotting away for no reason. --- Warden.''The first page angers you and instead of reading on, you fold the document and stow it away into back into your pocket.',
DESCWORDS: ['Prison Sentence', 'document', 'prison sentence', 'unfold']},
'Bedroll' : {
GroundDesc: 'You see a bedroll in the corner of the cell. You will need to enter the cell in order to examine the bedroll further.',
ShortDesc: 'the bedroll',
LongDesc: 'Looks comfy.',
Takeable: True,
DESCWORDS: ['bedroll', 'bed']},
'LongBow' : {
GroundDesc: 'A LongBow lies on the ground.',
ShortDesc: 'a LongBow',
LongDesc: 'The LongBow is made with oak wood. Your hands run smoothly over the wood as you draw it back. Worth 25 gold.',
DESCWORDS: ['bow', 'longbow']},
'Iron Arrow' : {
GroundDesc: 'An iron arrow lies on the ground.',
ShortDesc: 'an iron arrow.',
LongDesc: 'This iron arrow looks brand new. Nothing special, but gets the job done. Worth 1 gold.',
DESCWORDS: ['arrow', 'iron arrow', 'iron']},
'Fidget Spinner' : {
GroundDesc: 'On the back of the fidget spinner, you see some strange writing. As you look closer it reads: "Cant believe you bought this PoS... -- Pete".',
ShortDesc: 'a fidget spinner',
LongDesc: 'Gay',
DESCWORDS: ['fidget spinner', 'spinner']},
'Gold' : {
GroundDesc: 'Hey look, free money!',
ShortDesc: 'Gold.',
LongDesc: 'Not a fake.',
DESC: ['gold', 'money', 'gold pieces']},
}
location = 'Prison Cell'
inventory = ['Prison Sentence']
showFullExits = True
import cmd, textwrap
def displayLocation(loc):
print(loc)
print('=' * len(loc))
print('\n'.join(textwrap.wrap(room_list[loc][DESC], SCREEN_WIDTH)))
if len(room_list[loc][Ground]) > 0:
print()
for item in room_list[loc][Ground]:
print(Dungeon_Items[item][GroundDesc])
exits = []
for direction in (North, South, East, West):
if direction in room_list[loc].keys():
exits.append(direction.title())
print()
if showFullExits:
for direction in (North, South, East, West):
if direction in room_list[location]:
print('%s: %s' % (direction.title(), room_list [location][direction]))
else:
print('Exits: %s' % ' '.join(exits))
def moveDirection(direction):
global location
if direction in room_list[location]:
print('You move to the %s.' % direction)
location = room_list[location][direction]
displayLocation(location)
else:
print('You cannot move in that direction')
def getAllDescWords(itemList):
itemList = list(set(itemList))
descWords = []
for item in itemList:
descWords.extend(Dungeon_Items[item][DESCWORDS])
return list(set(descWords))
def getAllFirstDescWords(itemList):
itemList = list(set(itemList))
descWords = []
for item in itemList:
descWords.append(Dungeon_Items[item][DESCWORDS][0])
return list(set(DescWords))
def getFirstItemMatchingDesc(desc, itemList):
itemList = list(set(itemList))
DescWords = []
for item in itemList:
if desc in Dungeon_Items[item][DESCWORDS]:
return item
return None
def getAllItemsMatchingDesc(desc, itemList):
itemList = list(set(itemList))
matchingItems = []
for item in itemList:
if desc in Dungeon_Items[item][DESCWORDS]:
matchingItems.append(item)
return matchingItems
class TextAdventureCmd(cmd.Cmd):
prompt = '\n> '
def default(self, arg):
print('Invalid command. Type "help" for a list of commands.')
def do_quit(self,arg):
return True
def help_combat(self):
print('Combat is not implemented in this program.')
def do_north(self, arg):
moveDirection('north')
def do_south(self, arg):
moveDirection('south')
def do_west(self, arg):
moveDirection('west')
def do_east(self, arg):
moveDirection('east')
def do_exits(self,arg):
global showFullExits
showFullExits = not showFullExits
if showFullExits:
print('Showing full exit descriptions.')
else:
print('Showing brief exit descriptions.')
def do_inventory(self, arg):
if len(inventory) == 0:
print('Inventory:\n (nothing)')
return
itemCount = {}
for item in inventory:
if item in itemCount.keys():
itemCount[item] += 1
else:
itemCount[item] = 1
print('Inventory:')
for item in set(inventory):
if itemCount[item] > 1:
print(' %s (%s)' % (item, itemCount[item]))
else:
print(' ' + item)
do_inv = do_inventory
def do_take(self, arg):
itemToTake = arg.lower()
if itemToTake == '':
print('Take what? type "look" the items on the ground here.')
return
cantTake = False
for item in getAllItemsMatchingDesc(itemToTake, room_list[location][Ground]):
if Dungeon_Items[item].get(Takeable, True) == False:
cantTake= True
continue
print('You take %s.' % (Dungeon_Items[item][ShortDesc]))
room_list[location][Ground].remove(item)
inventory.append(item)
return
if cantTake:
print('You cannot take "%s".' % (itemToTake))
else:
print('That is not on the ground.')
def do_drop(self,arg):
itemToDrop = arg.lower()
invDescWords = getAllDescWords(inventory)
if itemToDrop not in invDescWords:
print('You do not have "%s" in your intentory' % (itemToDrop))
return
item = getFirstItemMatchingDesc(itemToDrop, inventory)
if item != None:
print('You drop %s.' % (Dungeon_Items[item][ShortDesc]))
inventory.remove(item)
room_list[location][Ground].append(item)
def complete_take(self, text, line, begidx, endidx):
possibleItems = []
text = text.lower()
if not text:
return getAllFirstDescWords(room_list[location][Ground])
for item in list(set(room_list[location][Ground])):
for descWord in Dungeon_items[item][DESCWORDS]:
if descWord.startswith(text) and Dungeon_Items[item].get(Takeable, True):
possibleItems.append(descWord)
return list(set(possibleItems))
def do_look(self,arg):
lookingAt = arg.lower()
if lookingAt == '':
displayLocation(location)
return
if lookingAt == 'exits':
for direction in (North, South, East, West):
if direction in room_list[location]:
print('%s: %s' % (direction.title(), room_list[location][direction]))
return
if lookingAt in ('north', 'west', 'east', 'south', 'n', 'w', 'e', 's'):
if lookingAt.startswith('n') and North in room_list[location]:
print(room_list[location][North])
elif lookingAt.startswith('w') and West in room_list[location]:
print(room_list[location][West])
elif lookingAt.startswith('e') and East in room_list[location]:
print(room_list[location][East])
elif lookingAt.startswith('s') and South in room_list[location]:
print(room_list[location][South])
else:
print('There is nothing in that direction.')
return
item = getFirstItemMatchingDesc(lookingAt, room_list[location][Ground])
if item != None:
print('\n'.join(textwrap.wrap(Dungeon_Items[item][LongDesc], SCREEN_WIDTH)))
return
item = getFirstItemMatchingDesc(lookingAt, inventory)
if item != None:
print('\n'.join(textwrap.wrap(Dungeon_Items[item][LongDesc], SCREEN_WIDTH)))
return
print('You do not see that nearby.')
def complete_look(self, text, line, begidx, endidx):
possibleItems = []
lookingAt = text.lower()
invDescWords = getAllDescWords(inventory)
groundDescWords = getAllDescWords(room_list[location][Ground])
shopDescWords = getAllDescWords(room_list[location].get(SHOP, []))
for descWord in invDescWords + groundDescWords + shopDescWords + [North, South, East, West]:
if line.startswith('look %s' % (descWord)):
return []
if lookingAt == '':
possibleItems.extend(getAllFirstDescWords(room_list[location][Ground]))
possibleItems.extend(getAllFirstDescWords(room_list[location].get(SHOP, [])))
for direction in (North, South, East, West):
if direction in room_list[location]:
possibleItems.append(direction)
return list(set(possibleItems))
for descWord in groundDescWords:
if descWord.startswith(lookingAt):
possibleItems.append(descWord)
for direction in (North, South, East, West):
if direction.startswith(lookingAt):
possibleItems.append(direction)
for descWord in invDescWords:
if descWord.startswith(lookingAt):
possibleItems.append(descWord)
return list(set(possibleItems))
def do_list(self,arg):
if SHOP not in room_list[location]:
print('This is not a shop.')
return
arg = arg.lower()
print('For sale:')
for item in room_list[location][SHOP]:
print(' - %s' % (item))
if arg == 'full':
print('\n'.join(textwrap.wrap(Dungeon_Items[item][LongDesc], SCREEN_WIDTH)))
def do_buy(self, arg):
"""buy <item>" - buy an item at the current location's shop."""
if SHOP not in room_list[location]:
print('This is not a shop.')
return
itemToBuy = arg.lower()
if itemToBuy == '':
print('Buy what? Type "list" or "list full" to see a list of items for sale.')
item = getFirstItemMatchingDesc(itemToBuy, room_list[location][SHOP])
if item != None:
print('You have purchased %s' % (Dungeon_Items[item][ShortDesc]))
inventory.append(item)
return
print('"%s" is not sold here. Type "list or "list full" to see a list of items for sale.' % (itemToBuy))
def complete_buy(self, text, line, begidx, endidx):
if SHOP not in room_list[location]:
return []
itemToBuy = text.lower()
possibleItems = []
if not itemToBuy:
return getAllFirstDescWords(room_list[location][SHOP])
for item in list(set(room_list[location][SHOP])):
for DescWord in room_list[item][DESCWORDS]:
if descWord.startswith(text):
possibleItems.append(descWord)
return list(set(possibleItems))
def do_sell(self, arg):
if SHOP not in room_list[location]:
print('This is not a shop.')
return
itemToSell = arg.lower()
if itemToSell == '':
print('Sell what? Type "inventory" or "inv" to see your inventory.')
return
for item in inventory:
if itemToSell in Dungeon_Items[item][DESCWORDS]:
print('You have sold %s' % (Dungeon_Items[item][ShortDesc]))
inventory.remove(item)
return
print('You do not ave "%s". Type "inventory" or "inv" to see your inventory.' % (itemToSell))
def complete_sell(self, text, line, begidx, endidx):
if SHOP not in room_list[location]:
return []
itemToSell = text.lower()
possibleItems = []
if not itemToSell:
return getAllFirstDescWords(inventory)
for item in list(set(inventory)):
for descWords in Dungeon_Items[item][DESCWORDS]:
if descWord.startswith(text):
possibleItems.append(descWord)
return list(set(possibleItems))
if __name__ == '__main__':
print('Text Adventure Demo!')
print('====================')
print
print('(Type "help" for commands.)')
print
displayLocation(location)
TextAdventureCmd().cmdloop()
print('Thanks for playing!')
I know so far that I need to insert a money function under the "def do_buy" loop. (Lines 350-365). But I just can't understand how.
Do I need to create the money variable under my Dungeon_Items dictionary? Or does this variable need to be specfic to that loop? How would I go about coding in each item's set price that will only let you buy it if you have enough money in your inventory?
I'm also assuming this can be implemented in a similar way that these TextAdventureCmd Classes.
If hints can be provided so that I can figure it out on my own, that would be best. I want to make sure I'm learning and not just copying and pasting.