I've been using Python for around 3 months and decided to make a simple text adventure game for fun and to exercise a lot of ideas I've been learning about. I've just recently learned about classes and OOP, as well as modules so those are the two features I'm the least sure of. It's mostly a base and has two rooms set up, but I'm pretty proud of it so far as I feel like its fairly readable and has good style (though I admittedly have nothing to compare it with.) So far I have four modules that I've distinguished from each other, mostly for readability. My use of classes is shallow, let me know how I could improve on it! I have two rooms set up so far.
Main module:
""" This is the main file, it contains the functions for the rooms as well as the startup sequences."""
import actions
import room_info as rooms
import character_and_items as char
"""TODO LIST:
-Implement save features(Save module?)
-Add some spunk into the descriptions, make it fun yet concise!!
"""
# output
def print_frog_title():
print(" ____ ___ __ __ ")
print(" / __/______ ___ _ / _ |___/ / _____ ___ / /___ _________ ")
print(" / _// __/ _ \/ _ `/ / __ / _ / |/ / -_) _ \/ __/ // / __/ -_)")
print("/_/ /_/ \___/\_, / /_/ |_\_,_/|___/\__/_//_/\__/\_,_/_/ \__/ ")
print(" /___/ ")
# input
def check_start():
print_frog_title()
print(" A game by Mopi Productions ")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("For a list of commands type 'h', 'help', or '?'")
def load_room(room):
char.current_room = room
room_dict = {
"burrow": burrow,
"burrow_basement": burrow_basement,
"front_of_house": front_of_house
}
func = room_dict.get(room, lambda: "ERROR") # To be quite frank I don't really understand lambda: ERROR yet
func()
def burrow():
print("You are in your burrow. The front door is to the north.")
while True:
action = actions.get_action(rooms.burrow)
if action[0] == "mopi":
load_room(action[1])
if action == "down":
if rooms.burrow.variables["trapdoor_opened"] and "lantern" in char.character_inventory:
load_room("burrow_basement")
break
elif not rooms.burrow.variables["rug_moved"]:
print("You cant go that way!")
elif rooms.burrow.variables["rug_moved"] and not rooms.burrow.variables["trapdoor_opened"]:
print("The trapdoor is shut.")
elif "lantern" not in char.character_inventory:
print("It's far too dark down there, you should stay up here until you find a light source.")
elif action == "north":
if rooms.burrow.variables["door_unlocked"]:
load_room("front_of_house")
else:
print("The front door is locked!")
elif action in rooms.directions:
print("You cant go that way!")
elif action[0] == "examine":
if action[1] in ("rug", "carpet", "lump"):
if not rooms.burrow.variables["rug_moved"]:
print("Upon further examination, the 'lump' appears to be handle shaped. You should try moving "
"the rug.")
else:
print("Your beloved family heirloom has been rudely shoved against a wall. What would Aunt Frogatha think?")
elif action[1] == "door":
print("Your door is locked. You'd unlock it, but you've lost the key.")
elif action[1] == "cabinet":
if rooms.burrow.variables["cabinet_opened"]:
if rooms.burrow.variables["jar_taken"]:
print("It's an open cabinet with barren shelves.")
else:
print("It's an open cabinet with barren shelves excepting a single empty jar.")
else:
print("It's a closed cabinet where you keep your dishware.")
elif action[0] == "move":
if action[1] in ("rug", "carpet"):
if not rooms.burrow.variables["rug_moved"]:
print("You moved the rug, and underneath you found a trapdoor! This isn't a new discovery.")
rooms.burrow.variables["rug_moved"] = True
else:
print("You've already kicked the rug into the corner! Better to not do any more damage.")
elif action[0] == "use":
if action[1] == "trapdoor" and rooms.burrow.variables["rug_moved"]:
print("You opened the trapdoor.")
rooms.burrow.variables["trapdoor_opened"] = True
elif action[1] == "door":
if not rooms.burrow.variables["door_unlocked"] and "key" not in char.character_inventory:
print("The door is locked, and you seem to have misplaced your key.")
elif not rooms.burrow.variables["door_unlocked"] and "key" in char.character_inventory:
print("The door is locked, you should using your key.")
else:
load_room("burrow_basement")
break
elif action[0] == "open":
if action[1] == "trapdoor" and rooms.burrow.variables["rug_moved"]:
print("You opened the trapdoor.")
rooms.burrow.variables["trapdoor_opened"] = True
elif action[1] == "door":
if not rooms.burrow.variables["door_unlocked"] and "key" in char.character_inventory:
print("You unlocked the front door! Welcome to the outside ")
elif "key" not in char.character_inventory:
print("The door is locked, and you seem to have misplaced your key.")
else:
print("The door is already open!")
elif action[1] == "cabinet":
if not rooms.burrow.variables["jar_taken"]:
print("You opened the cabinet, there is an empty jar inside.")
rooms.burrow.room_contents.append("jar")
else:
print("You opened the cabinet, it is empty")
elif action[0] == "close":
if action[1] == "trapdoor" and rooms.burrow.variables["rug_moved"]:
print("You closed the trapdoor.")
rooms.burrow.variables["trapdoor_opened"] = False
elif action[1] == "door":
print("The door is already closed, you like it that way.")
else:
continue
def burrow_basement():
print("You are in your basement. There is a trapdoor above you.")
while True:
action = actions.get_action(rooms.burrow_basement)
if action == "up":
if rooms.burrow.variables["trapdoor_opened"]:
load_room("burrow")
break
else:
print("The trapdoor is shut.")
elif action in rooms.directions:
print("You can't go that way!")
elif action[0] == "examine":
if action[1] == "key_hook":
if "key" in rooms.burrow_basement.room_contents:
print("It is a handmade key hook your Uncle Frogert made. Its single hook remains unoccupied.")
else:
print("It is handmade key hook your Uncle Frogert made. It holds an old key.")
elif action[1] == "icebox":
print("It is an icebox where you store your cold foods, but it hasn't been filled in months.")
elif action[0] == "move":
if action[1] == "icebox" and not rooms.burrow_basement.variables["icebox_moved"]:
pass
elif action[1] == "icebox":
pass
elif action[0] == "use":
if action[1] == "icebox" and not rooms.burrow_basement.variables["icebox_opened"]:
rooms.burrow_basement.variables["icebox_opened"] = True
if not rooms.burrow_basement.variables["fish_sticks_taken"]:
print("You opened the icebox, there's a lonely box of fish sticks inside with colorful writing on it.")
rooms.burrow_basement.room_contents.append("fish_sticks")
else:
print("You opened the icebox, it's empty devoid of a few lonely ice cubes. ")
elif action[1] == "icebox":
print("You closed the icebox like a good roommate.")
rooms.burrow_basement.variables["icebox_opened"] = False
if "fish_sticks" in rooms.burrow_basement.room_contents and not rooms.burrow.variables["fish_sticks_taken"]:
rooms.burrow_basement.room_contents.remove("fish_sticks")
elif action[0] == "open":
if action[1] == "trapdoor" and not rooms.burrow.variables["trapdoor_opened"]:
print("You opened the trapdoor.")
rooms.burrow.variables["trapdoor_opened"] = True
elif action[1] == "trapdoor":
print("The trapdoor is already opened.")
elif action[1] == "icebox" and not rooms.burrow_basement.variables["icebox_opened"]:
rooms.burrow_basement.variables["icebox_opened"] = True
if not rooms.burrow_basement.variables["fish_sticks_taken"]:
print("You opened the icebox, there's a lonely box of fish sticks inside with colorful writing on it.")
rooms.burrow_basement.room_contents.append("fish_sticks")
else:
print("You opened the icebox, it's empty devoid of a few lonely ice cubes. ")
elif action[0] == "close":
if action[1] == "trapdoor" and rooms.burrow.variables["rug_moved"]:
print("You closed the trapdoor.")
rooms.burrow.variables["trapdoor_opened"] = False
elif action[1] == "icebox" and rooms.burrow_basement.variables["icebox_opened"]:
print("You closed the icebox like a good roommate.")
rooms.burrow_basement.variables["icebox_opened"] = False
if "fish_sticks" in rooms.burrow_basement.room_contents and not rooms.burrow.variables["fish_sticks_taken"]:
rooms.burrow_basement.room_contents.remove("fish_sticks")
else:
continue
def front_of_house():
print("You are in front of your burrow")
while True:
break
"""
def room_template():
print("ROOM. EXITS")
while True:
action = actions.get_action(rooms.ROOM)
if action[0] == "mopi":
load_room(action[1])
if action == DIRECTION:
elif action in rooms.directions:
print("You cant go that way!")
elif action[0] == "examine":
elif action[0] == "move":
elif action[0] == "use":
elif action[0] == "open":
elif action[0] == "close":
else:
continue
"""
def main():
check_start()
print(
"You are in a burrow, but not just any burrow. The burrow you reside in is in fact"
"\nthe estate of Von Frogerick III, who just so happens to be your great great grandfather."
"\nThe immense and fascinating history of your lineage matters not though, for you are hungry."
"\nYou should find a fly to eat.")
load_room("burrow")
main()
Actions module:
"""This is the actions module, it contains functions required to process user input and
processes minor actions itself"""
import random
import room_info as rooms
import character_and_items as char
snarky_remark_list = ["And how exactly are you going to do that?", "Fat chance", "In your dreams", "Inconceivable!",
"Aunt Frogatha would be ashamed.."]
# Commands to add, - eat - anything else?
# output
def print_help():
print("--HELP--\n-'l' or 'look' - Provides description of room\n-'north' or 'n' - goes in specified direction"
"\n-'examine' + object to examine it more closely\n-'move' + object to move an object"
"\n-'use' + object to use an object\n-'down' or 'd' - move up or down"
"\n-'inventory' or 'i' - displays inventory\n-'open' or 'close' - opens or closes an object"
"\n-'read' - reads an object\n-'use __ on __' - uses one object on another")
# this checks if the complex action is able to be performed on the object given
def actions_match(complex_u_in, room):
if (complex_u_in[0] == "take" and complex_u_in[1] in rooms.take_ob(room)) \
or (complex_u_in[0] == "use" and complex_u_in[1] in rooms.use_ob(room)) \
or (complex_u_in[0] == "examine" and complex_u_in[1] in rooms.exam_ob(room)) \
or (complex_u_in[0] == "move" and complex_u_in[1] in rooms.mov_ob(room)) \
or (complex_u_in[0] in ("open", "close") and complex_u_in[1] in rooms.open_ob(room)):
return True
else:
return False
# Consider moving this into the items module?
def use_on(obj1, obj2):
if obj1 == "key" and char.current_room == "burrow" and "key" in char.character_inventory and obj2 == "door":
rooms.burrow.variables["door_unlocked"] = True
print("You unlocked the door!")
# Sort objects under the world class into an array.
def get_room_contents(room):
return rooms.exam_ob(room) + rooms.use_ob(room) + rooms.mov_ob(room) + rooms.take_ob(room) + rooms.open_ob(room)
# Every action that doesn't return an input should be ended with return False
# a complex action is an action containing more than one word.
def check_complex_actions(room, complex_u_in):
room_contents_list = get_room_contents(room)
# relabeled for readability
action = complex_u_in[0]
item = complex_u_in[1]
try:
# Dev command to load rooms for testing
if action == "mopi" and item in rooms.all:
return ["mopi", item]
# Dropping items is a character based action, and not a room based. Therefore it is separated.
if len(complex_u_in) == 4 and (action == "use" and complex_u_in[2] == "on") \
and (char.use_on_items[item] == complex_u_in[3]):
use_on(item, complex_u_in[3])
return False
elif len(complex_u_in) == 3 and (item + "_" + complex_u_in[2]) in char.double_word_list:
item = item + "_" + complex_u_in[2]
complex_u_in.pop()
if action == "drop" and item in char.character_inventory:
rooms.append_to_room(room, item)
char.character_inventory.remove(item)
print("You dropped the " + item)
return False
elif action == "take" and item in rooms.take_ob(room):
if item in rooms.contents(room):
char.character_inventory.append(item)
rooms.remove_from_room(room, item)
# This removes the underscore in two-word objects
if "_" in item:
item = item.replace("_", " ")
print("You took the " + item)
return False
else:
print("You see no such thing!")
return False
elif action == "read" and (item in room_contents_list or item in char.character_inventory):
item_description = char.get_description(item, "read")
if item_description != "":
if "_" in item:
item = item.replace("_", " ")
print("The " + item + " reads: " + item_description)
else:
print("You can't read that!")
return False
elif action == "examine" and (item in char.character_inventory or
(item in rooms.contents(room) and item not in rooms.exam_ob(room))):
item_description = char.get_description(item, "examine")
if "_" in item:
item = item.replace("_", " ")
print(item_description)
return False
elif item in room_contents_list:
if actions_match(complex_u_in, room):
return complex_u_in
elif action[0] == "examine":
print("There's nothing to see of importance.")
else:
print(random.choice(snarky_remark_list))
return False
else:
print("You see no such thing!")
return False
except IndexError:
# In case user inputs half of a command
print(action + " what?")
return False
def get_action(room):
complex_actions = ["move", "use", "examine", "take", "drop", "open", "close", "read", "mopi"]
while True:
# u_in stands for user input
u_in = input("-> ").lower().strip()
print()
complex_u_in = u_in.split(" ")
if complex_u_in[0] in complex_actions:
u_in = check_complex_actions(room, complex_u_in)
if u_in != False: # Consider editing this bit? little sloppy
return u_in
else:
# This loops if an action is not returned.
continue
if u_in in ("h", "?", "help"):
print_help()
elif u_in in ("look", "l"):
rooms.get_description(room)
elif u_in in ("inventory", "i"):
char.print_inventory()
elif u_in in ("north", "n"):
return "north"
elif u_in in ("south", "s"):
return "south"
elif u_in in ("west", "w"):
return "west"
elif u_in in ("east", "e"):
return "east"
elif u_in in ("northwest", "nw"):
return "northwest"
elif u_in in ("northeast", "ne"):
return "northeast"
elif u_in in ("southwest", "sw"):
return "southwest"
elif u_in in ("southeast", "se"):
return "southeast"
elif u_in in ("down", "d"):
return "down"
elif u_in in ("up", "u"):
return "up"
elif u_in in ("ribbit", "r"):
print("you let out a cute ribbit")
elif u_in in ("fuck", "shit", "damn"):
print("That was awfully rude of you :(")
elif u_in == "heck":
print("No swearing!!!! >:(")
elif u_in in ("mopi", "mopi productions"):
print("Mopi says: 'eat hot pant,, lie.'")
else:
print("That command was not recognized")
Character and items module:
"""This is the character module, it stores information on the character and items."""
double_word_list = ["fish_sticks", "key_hook", "front_door", "bedroom_door"]
character_inventory = []
current_room = None
def print_inventory():
if len(character_inventory) < 1:
print("Your pockets are empty! Wait, how do frogs have pockets?")
else:
print("--INVENTORY--")
for item in character_inventory:
print("-" + item)
# This could get tedious for every item in the game, look for an alternative solution?
def get_description(item, form):
item_dict = {
"pamphlet": pamphlet,
"fish_sticks": fish_sticks,
"key": key,
"lantern": lantern,
"photo": photo,
"jar": jar
}
ob = item_dict.get(item, lambda: "ERROR")
try:
if form == "read":
return ob.read_description
elif form == "examine":
return ob.exam_description
except AttributeError:
return "There's nothing to see of importance."
use_on_items ={
"key": "door"
}
class Items:
def __init__(self, read_desc, exam_desc):
self.read_description = read_desc
self.exam_description = exam_desc
pamphlet = Items("The flies future is YOUR Future. Donate today!",
"This is an annoying pamphlet, it came in the mail")
fish_sticks = Items("MOPI Brand Fish Sticks! Unethically sourced, deep fried fun!",
"These fish sticks are LONG expired, and unethically sourced at that. Better leave them be.")
key = Items("34TH BURROW STREET",
"It's an old cast iron key, it's been in your family for generations.")
lantern = Items("",
"It's a trusty oil lamp. It provides plenty of light, and was just recently topped off.")
photo = Items("Forever yours and always :) Jan. 10, 1993",
"It's a wedding photo of your Aunt Frogatha and Uncle Frogert. They're posing in front of the pond, "
"many flies can be seen buzzing in the background. There's something written on the back.")
jar = Items("",
"It is an empty glass jar.")
Room info module:
"""This module contains information on every room as well as the room class"""
directions = ["north", "n", "south", "s", "east", "e", "west", "w", "up", "u", "down", "d"]
all = ["burrow", "burrow_basement"]
# This is a workaround for the from room_info import * method.
# Ideally this would all be one function, with a room parameter and an info parameter
def exam_ob(room):
return room.examinable_objects
def use_ob(room):
return room.usable_objects
def mov_ob(room):
return room.movable_objects
def take_ob(room):
return room.takeable_objects
def open_ob(room):
return room.open_ob
def contents(room):
return room.room_contents
def append_to_room(room, item):
room.room_contents.append(item)
def remove_from_room(room, item):
try:
room.room_contents.remove(item)
except ValueError:
print("You see no such thing!")
def get_description(room):
print(room.description)
if room == burrow:
if not burrow.variables["rug_moved"]:
print("There is a handwoven rug lying in the center of your room, with a bothersome lump in the middle.")
elif burrow.variables["rug_moved"] and not burrow.variables["trapdoor_opened"]:
print("There is a handwoven rug rudely shoved in to the corner. In the center of your room, there is a "
"shut trapdoor.")
else:
print("There is a handwoven rug rudely shoved in to the corner. In the center of your room is an open "
"trapdoor. Talk about a safety hazard!")
if "lantern" in burrow.room_contents:
print("A lit lantern hangs loosely on the wall.")
if "pamphlet" in burrow.room_contents:
print("An annoying informational pamphlet lies on the floor.")
if "photo" in burrow.room_contents:
print("A framed photo rests cheerily on the mantle.")
if burrow.variables["cabinet_opened"]:
print("There is an open cabinet on the far wall where you store dishware.")
else:
print("There is a shut cabinet on the far wall.")
for item in burrow.room_contents:
if item not in ("lantern", "pamphlet", "cabinet", "photo", "jar"):
print("You've left a " + item + " here.")
if room == burrow_basement:
if not burrow_basement.variables["icebox_moved"]:
if not burrow_basement.variables["icebox_opened"]:
print("A securely shut ice box sits near the ladder.")
else:
print("An open ice box sits near the ladder")
elif burrow_basement.variables["icebox_moved"]:
if not burrow_basement.variables["icebox_opened"]:
print("A knocked over ice box lies miserably near the ladder, luckily its still latched shut.")
else:
print("A knocked over ice box lies miserably near the ladder, spilling its contents everywhere."
"\nIf only someone hadn't knocked it over...")
if "fish sticks" in burrow_basement.room_contents:
if burrow_basement.variables["icebox_moved"] and burrow_basement.variables["icebox_opened"]:
print("A box of fish sticks is rapidly defrosting on the floor.")
class World:
def __init__(self, exam_ob, mov_ob, use_ob, take_ob, open_ob):
self.examinable_objects = exam_ob
self.movable_objects = mov_ob
self.usable_objects = use_ob
self.takeable_objects = take_ob
self.open_ob = open_ob
burrow = World(["rug", "door", "lump"], ["rug"], ["door", "trapdoor", "cabinet"], ["lantern", "pamphlet", "photo", "jar"],
["front_door", "trapdoor", "bedroom_door", "cabinet"])
burrow.room_contents = ["lantern", "pamphlet", "photo", "cabinet"]
burrow.description = "You're in a cozy burrow, and a well furnished one at that. The room is lit by an assortment of " \
"\nwarm candles and lanterns. Your front door is to the north, and the door to your Aunt and " \
"Uncle's bedroom lies to the South West"
burrow.variables = {
"rug_moved": False,
"trapdoor_opened": False,
"door_unlocked": False,
"cabinet_opened": False,
"jar_taken": False
}
burrow_basement = World(["key_hook", "key", "icebox", "fish_sticks"], ["icebox"], ["icebox"], ["fish_sticks", "key"], ["trapdoor", "icebox"])
burrow_basement.room_contents = ["key", "icebox"]
burrow_basement.description = "You're in a muddy basement that serves as more of a storage room than any sort of " \
"living quarters.\nThere is a key hook on the far wall." \
" A ladder leads out of the basement."
burrow_basement.variables = {
"icebox_moved": False,
"icebox_opened": False,
"fish_sticks_taken": False
}
owner
andlocation
, but almost everything, including people, rooms, containers, doors, even a text editor, are implemented with end-user-written methods and properties added to those minimal objects. \$\endgroup\$