主模块:
""" 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()
动作模块:
"""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")
字符和项目模块:
"""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.")
房间信息模块:
"""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
}
#1 楼
游戏的有趣开始。我想看看结果如何。文本冒险游戏通常是数据驱动的。这意味着您将拥有一个游戏引擎(程序),该程序可以读取游戏描述文件(数据),并对游戏中每个位置的每个动作执行相同的指令,从而根据游戏数据产生不同的结果。
您写的不是数据驱动的。您在
burrow()
中具有处理操作的功能,对于burrow_basement()
具有另一个功能,对于front_of_house()
具有另一个功能。这些功能的代码看起来非常相似,而且非常重复,这就是为什么我们只编写一次并根据数据更改结果的原因。游戏编写方式存在问题是递归。如果您从洞穴开始,则可以下到地下室或北到房子的前面。这些操作中的每一个都调用永不返回的
load_room(location)
,并调用其自己的函数来处理该新房间位置。例如,如果您下到地下室,则会调用load_room("burrow_basement")
,并调用burrow_basement()
,作为对“ up”动作的响应,它将调用load_room("burrow")
,后者将调用burrow()
。我们越来越深入到调用堆栈中。如果玩家继续探索,最终他们将遇到Python的堆栈限制。您可以通过增加堆栈大小来解决此问题,但这只是一个麻烦。正确的解决方案是摆脱递归。对象模型
地点
您应该先定义一些东西。喜欢房间。房间是玩家可以进入的位置。房间名称应简短(“厨房”,“地下室”)和较长的描述。玩家之前可能没有来过房间。它将具有到其他位置的连接(出口)。房间里可能有物品。
class Room:
def __init__(self, name, description):
self.name = name
self.description = description
self.visited = False
self.exits = { }
self.contents = []
事物
除了房间,世界上到处都是物体。事物将具有名称,也许还有描述。可以携带某些东西(照片,小册子,罐子……),而其他东西必须保留在原处(炉子,水槽)。可以穿一些东西,例如大衣或帽子。它可能是隐藏的:
class Thing:
def __init__(self, name, description):
self.name = name
self.description = description
self.fixed = False
self.moved = False
self.wearable = False
self.concealed = False
容器
有些东西可以放在其他东西里面。在冰盒中可以找到鱼条。冰盒通常是关闭的,但偶尔会打开。某些容器可能被锁定,例如柜子。可能会看到一些容器,例如瓷器柜。您可以爬进一些容器,例如衣柜或汽车,但大多数都不能。
class Container(Thing):
def __init__(self, name, description):
super().__init__(name, description)
self.contents = []
self.open = False
self.locked = False
self.key = None
self.transparent = False
self.enterable = False
房间是容器吗?房间有名称,描述和内容。它们是可输入的。
支持者
有些东西可以放在其他东西上。您可以在桌子上放一个罐子。您可以将钥匙挂在钩子上。因此,也许应该将某些容器视为支持者。您甚至可以输入一些支持者,例如爬上床。
动画
有些东西可以四处走动,并且有行为。您可以与其中的一些人交谈,例如店主,他们会与您交谈。
其他店员可能不会说话,例如猫。
店主(有生命的东西)可能穿着带口袋的裤子(一个容器),里面可能装有怀表(可打开)。
玩家是动画容器吗???他们可以存放东西(清单),四处走动(动画),拿东西(容器),拿东西,穿东西。门可以打开或关闭。如果关闭,则它可能被锁定,也可能未被锁定。
class Door(Thing):
def __init__(self, name, description, key=None)
self.name = name
self.description = description
self.open = False
self.lockable = key is not None
self.locked = True if key else False
self.key = key
self.connects = []
living_room = Room("Living Room", "A place for the family to hang out")
dining_room = Room("Dining Room", "Many meals were had here")
basement = Room("Basement", "A dark and dingy hole in the ground")
trap_door = Door("Trap door", "A piece of wood, with a basic hinge and a ring handle")
trap_door.concealed = True
trap_door.connects = [living_room, basement]
dining_room.exits["south"] = living_room
living_room.exits["north"] = dining_room
living_room.exits["down"] = trap_door
basement.exits["up"] = trap_door
在这里,我们有两个从客厅出来的出口,直接向北到饭厅(无门),一直到
trap_door
。 trap_door
处于隐藏状态,因此,如果玩家在客厅里并且尝试“下沉”,则最初他们应该得到“您不能那样走”。移动地毯应露出活板门(标记为未隐藏),允许通过活板门到达其连接的其他位置。也许:rug = Thing("A rug", "A thick heavy rug, passed down through the ages")
rug.fixed = True
def rug_move():
print("You pull back the corner of the rug, revealing a trap door")
rug.description = "One corner of the rug has been lifted to reveal a trap door"
trap_door.concealed = False
rug.on_move = run_move
现在,如果您的游戏逻辑允许您键入“ lift rug”或“ move rug”,则可以解析单词“ rug”,找到对象在
location.contents
中使用该名称,并调用该对象的.on_move()
函数,该函数可以告诉您发生了什么,更改地毯的描述,并从活板门中删除隐蔽的属性。 /> 可以帮助您入门。灯笼只是一个
Thing
。 rug
实际上是Rug
(特殊的Thing
),具有在frog.py
游戏文件中定义的操作。请注意,冒险游戏框架可用于许多不同的游戏。 />这是您以前使用的一种“更好”的方法,但是我不会说这是一个好方法。该框架有很多细节需要刷新,并进行了重新设计以包括更好的可见性和可触摸性。项目应该有一个
.has_light
属性(可选)。如果房间.has_light
本身的属性设置为True,或者房间中的某个项目具有该属性,除非该项目位于封闭的容器中(除非该容器是透明的)。如果继续沿着这条路,最终您将重新发明Inform 7交互式小说框架。祝你好运。
冒险.py
COMMANDS = { 'go', 'move', 'use', 'examine', 'open', 'close', 'inventory' }
DIRECTIONS = set()
REVERSE_DIRECTION = {}
for fwd, rev in (('n', 's'), ('e', 'w'), ('u', 'd')):
DIRECTIONS.add(fwd)
DIRECTIONS.add(rev)
REVERSE_DIRECTION[fwd] = rev
REVERSE_DIRECTION[rev] = fwd
class CantSee(Exception):
pass
class Thing:
def __init__(self, short_description, **kwargs):
self.short_description = short_description
self.long_description = None
self.concealed = False
self.scenery = False
self.fixed = False
self.openable = False
for key, value in kwargs.items():
if not key in self.__dict__:
raise ValueError("Unrecognized argument: "+key)
self.__dict__[key] = value
def description(self):
return self.short_description
def examine(self):
if self.long_description:
print(self.long_description)
else:
print("There is nothing special about it")
def move(self):
if self.fixed:
print("You can't move it")
else:
print("You move it a bit.")
class Container(Thing):
def __init__(self, short_description, **kwargs):
self.contents = {}
self.openable = True
self.open = False
self.transparent = False
super().__init__(short_description, **kwargs)
def containing():
if self.contents:
return ", ".join(item.description() for item in self.contents())
return "nothing"
def description(self):
text = self.short_description
if self.openable:
if self.open:
text += " (which is closed)"
else:
text += " (which is open)"
if self.open or self.transparent:
if self.contents:
text += "(containing " + self.containing() + ")"
return description
class Door(Thing):
def __init__(self, short_description, **kwargs):
self.lockable = False
self.locked = False
self.key = None
self.connects = {}
super().__init__(short_description, **kwargs)
self.fixed = True
self.closed = True
class Room(Thing):
def __init__(self, name, **kwargs):
self.exits = {}
self.visited = False
self.contents = set()
super().__init__(name, **kwargs)
def exit_to(self, direction, destination, door=None):
reverse = REVERSE_DIRECTION[direction]
if door:
door.connects[direction] = destination
door.connects[reverse] = self
self.exits[direction] = door
destination.exits[reverse] = door
else:
self.exits[direction] = destination
destination.exits[reverse] = self
def enter(self):
print("Location:", self.short_description)
if not self.visited:
self.describe()
self.visited = True
def visible_things(self):
return [item for item in self.contents if not item.concealed]
def describe(self):
if self.long_description:
print(self.long_description)
print()
items = [item for item in self.visible_things() if not item.scenery]
for item in items:
if item.concealed or item.scenery:
continue
if items:
print("You see:")
for item in items:
print(" ", item.description())
class Player(Container):
def __init__(self):
super().__init__("yourself")
self.long_description = "As good looking as ever."
self.openable = False
self.location = None
self.alive = True
def inventory(self):
if self.contents:
print("You are carring:")
for item in self.contents:
print(" ", item.description)
else:
print("You have nothing.")
def go(self, direction):
destination = self.location.exits.get(direction, None)
if isinstance(destination, Door):
door = destination
destination = door.connects[direction]
if door.concealed:
destination = None
elif door.closed:
if door.locked:
print("You'd need to unlock the door first")
return
print("First opening the", door.short_description)
if destination:
self.location = destination
destination.enter()
else:
print("You can't go that way")
class Game:
def __init__(self, protagonist):
self.player = protagonist
self.game_over = False
self.turns = 0
def welcome(self):
print("A text adventure game.")
def help(self):
print("Examine everything.")
def get_action(self):
while True:
command = input("\n> ").lower().split()
if command:
if len(command) == 1:
if command[0] in DIRECTIONS:
command.insert(0, 'go')
if command[0] == 'i':
command[0] = 'inventory'
if command == ['inventory']:
self.player.inventory()
elif command == ['help']:
self.help()
elif command[0] == 'go':
if len(command) == 2 and command[1] in DIRECTIONS:
return command
else:
print("I'm sorry; go where?")
elif command[0] in COMMANDS:
return command
else:
print("I don't understand")
def go(self, direction):
self.player.go(direction)
def item(self, thing):
items = self.player.location.visible_things()
for item in items:
if thing in item.short_description:
return item
raise CantSee(thing)
def move(self, thing):
item = self.item(thing)
item.move()
def perform_action(self, command):
if command[0] == 'go' and len(command) == 2:
self.go(command[1])
elif command[0] == 'move' and len(command) == 2:
self.move(command[1])
else:
print("Command not implemented")
def play(self):
self.welcome()
self.player.location.enter()
while not self.game_over:
command = self.get_action()
try:
self.perform_action(command)
self.turns += 1
except CantSee as thing:
print("You don't see a", thing)
if not self.player.alive:
print("You have died.")
else:
print("Game over.")
frog.py
from adventure import Thing, Room, Door, Player, Game
burrow = Room("Your Burrow")
basement = Room("Your Basement")
front_yard = Room("Your Front Yard")
front_door = Door("Front Door")
trap_door = Door("Trap Door", concealed=True)
burrow.exit_to('n', front_yard, front_door)
burrow.exit_to('d', basement, trap_door)
class Rug(Thing):
def move(self):
if trap_door.concealed:
print("Moving the rug reveals a trap door to the basement.")
trap_door.concealed = False
else:
super().move()
rug = Rug("a rug", fixed=True)
burrow.contents.add(rug)
lantern = Thing("a lantern")
burrow.contents.add(lantern)
player = Player()
player.location = burrow
class FrogGame(Game):
def welcome(self):
print("""\
You are in a burrow, but not just any burrow. The burrow you reside in is in
fact the estate of Von Frogerick III, who just so happens to be your great
great grandfather. The immense and fascinating history of your lineage matters
not though, for you are hungry. You should find a fly to eat.
""")
game = FrogGame(player)
if __name__ == '__main__':
game.play()
评论
\ $ \ begingroup \ $
嘿!首先,感谢您的答复。它非常有见地,并且确实显示了python中类的有用性。这个概念对我来说还很陌生,所以希望我介意您不要介意。根据我目前的理解,切换到对象模型基本上可以消除对房间功能的需求,而拥有一个主要功能可以通过引用类和类方法来处理动作?还会细分为多个房间吗?还是我可以通过将“移动地毯”引用到已知位于洞穴中的地毯来处理动作?如果我有重复的物品怎么办?
\ $ \ endgroup \ $
–digital_drako
20-4-10下午6:51
\ $ \ begingroup \ $
我还要补充一点,每个对象(包括动作)都应该有一个可以使用的同义词列表,因此,如果玩家选择“举地毯”,它将理解这与“移动地毯”相同。
\ $ \ endgroup \ $
–达雷尔·霍夫曼(Darrel Hoffman)
20-4-10的15:23
#2 楼
import room_info as rooms
import character_and_items as char
如果要一直以这种方式导入它们,为什么不只是分别命名模块
rooms
和char
?所有额外的输入有什么意义?顺便说一句,在文本冒险中通常会引用player
;我会选择import player
而不是import char
,只是为了消除语法高亮显示。您的函数
print_frog_title
仅在一个地方使用。您应该在此处内联它。snarky_remark_list = ["And how exactly are you going to do that?", "Fat chance", "In your dreams", "Inconceivable!",
"Aunt Frogatha would be ashamed.."]
开始对源代码进行版本控制时,您会意识到缩进序列更好,这样每行只有一个元素。这使您可以添加和删除元素,而不会在历史记录中引入额外的差异。同时在每个元素上添加逗号。
snarky_remark_list = [
"And how exactly are you going to do that?",
"Fat chance",
"In your dreams",
"Inconceivable!",
"Aunt Frogatha would be ashamed..",
]
英语语法:我注意到其中有些评论以标点符号结尾,有些则没有。另一个:您写
mantle
的意思是mantel
。 > character_inventory = []
current_room = None
这两个变量感觉它们应该是
room_dict
的数据成员。但是此模块中还有其他与播放器显然无关的东西,例如# This could get tedious for every item in the game...
def get_description(item, form):
所以第一,我考虑将其拆分为
class Player
或items
模块第二,您已经知道了非繁琐的解决方案!试想一下,而不是写pamphlet = Items("The flies future is YOUR Future. Donate today!",
"This is an annoying pamphlet, it came in the mail")
您写了
pamphlet = Item(
name="pamphlet",
read="The flies future is YOUR Future. Donate today!",
examine="This is an annoying pamphlet, it came in the mail",
)
而不是
key = Items("34TH BURROW STREET",
"It's an old cast iron key, it's been in your family for generations.")
你写的想像
key = Item(
name="key",
read="34TH BURROW STREET",
examine="It's an old cast iron key, it's been in your family for generations.",
use_on=["door"],
)
你能看到现在如何实现
objects
的构造函数吗?编辑后:类似这样。
class Item:
def __init__(self, name, read, examine, use_on=None):
self.name = name
self.read = read
self.examine = examine
self.use_on = use_on or []
# self.location = burrow
# self.inroom_description = "There is a %s here." % name
还不需要成员函数。
以及如何实施
class Item
? ...好吧,差不多。假设我们这样写了“游戏中所有物品”的列表!all_items = [
Item(
name="pamphlet",
read="The flies future is YOUR Future. Donate today!",
examine="This is an annoying pamphlet, it came in the mail",
),
Item(
name="key",
read="34TH BURROW STREET",
examine="It's an old cast iron key, it's been in your family for generations.",
use_on=["door"],
),
]
现在
get_description
开始是类似def get_description(verb, noun):
for item in all_items:
if item.name == noun:
if verb == "examine":
return item.examine
elif verb == "read":
return item.read
return "I don't see what you're referring to."
您可以将
get_description
预处理为从名称到all_items
对象的字典映射,以节省该循环中的两个缩进级别。def get_description(verb, noun):
item = all_items_by_name.get(noun, None)
[...]
注意我悄悄地将
Item
的复数形式转换为Items
的单数形式,还将Item
转换为form
。# 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
好吧,这似乎很疯狂。为什么不只用一个叫
verb
的地方代替,而是写一个rooms.exam_ob(room)
?对消息的控制级别。 (照片在壁炉架上令人愉悦;鱼竿在地板上正在除霜;等等。)如果要增加在任意位置放置任意物体的能力,则必须找到一种处理这些消息的新方法。 您看过唐纳德·努斯的文学版冒险吗?尤其请参阅第43页的第63节。
评论
\ $ \ begingroup \ $
非常感谢您提供较小的样式指针,它确实有帮助。项目类的更好利用是超级聪明的,而且我不确定为什么我没有想到它!话虽这么说,您将如何定义类?它是一个简单的类Item:pass,还是仍然使用参数?上课肯定仍然让我感到困惑,但是我通过提问来学习得最好。谢谢你的帮助!
\ $ \ endgroup \ $
–digital_drako
20年4月10日在7:00
\ $ \ begingroup \ $
添加了对Item类的定义。
\ $ \ endgroup \ $
– Quuxplusone
20 Apr 10 '15:37
评论
如果您这样做是为了学习编程和Python,请继续进行游戏,这是一个很好的实验。如果您实际上是在尝试制作文字冒险游戏,我建议您考虑使用TADS 3,它是为此目的而精心设计的系统。正如@xxbbcc正确指出的那样,这是学习Python的好方法,但是如果您的目标是编写交互式小说,请查看Inform7。这是构建此类游戏的惊人复杂系统。
构造事物的另一种方法是LambdaMOO,其中所有事物都是一个对象,而播放器类型的命令则作为这些对象上的方法实现。对象具有继承性,并且具有一些内置属性,例如所有者和位置,但是几乎所有的东西,包括人,房间,容器,门,甚至是文本编辑器,都通过最终用户编写的方法来实现,并且将属性添加到最低限度中对象。