首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类似Zork的文本冒险w/ Python

类似Zork的文本冒险w/ Python
EN

Code Review用户
提问于 2020-04-09 23:51:05
回答 1查看 6.3K关注 0票数 24

我已经使用Python大约3个月了,并且决定制作一个简单的文本冒险游戏来取乐,并练习我一直在学习的许多想法。我最近才学到了类和OOP,以及模块,所以这是我最不确定的两个特性。它主要是一个基地,有两个房间,但我很自豪,因为我觉得它的可读性和良好的风格(虽然我承认没有什么可比较的)。到目前为止,我有四个模块,它们相互区别开来,主要是为了提高可读性。我对课程的使用很肤浅,让我知道如何改进它!到目前为止,我有两个房间。

主要模块:

代码语言:javascript
复制
 """ 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()

行动单元:

代码语言:javascript
复制
  """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")

字符和项目模块:

代码语言:javascript
复制
"""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.")

房间信息模块:

代码语言:javascript
复制
"""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
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-04-10 05:49:36

你游戏的一个有趣的开始。我很想看看结果如何。

文字冒险游戏通常是由数据驱动的。这意味着您将有一个游戏引擎(程序),它将读取游戏描述文件(数据),并对游戏中每个位置的每个动作执行相同的指令,根据游戏数据产生不同的结果。

您所写的不是数据驱动的。您有一个函数用于处理burrow()中的操作,另一个用于burrow_basement(),另一个用于front_of_house()。代码是这些函数看起来非常相似,而且非常重复,这就是为什么我们可以编写它一次,并根据数据更改结果。

你写游戏的方式的一个问题是递归。如果你从地洞开始,你可以下到地下室,或者往北到房子的前部。这些操作中的每一个都调用永远不返回的load_room(location),并调用自己的函数来处理这个新的房间位置。例如,如果您下到地下室,则调用load_room("burrow_basement"),它调用burrow_basement(),后者响应"up“操作将调用load_room("burrow"),后者将调用burrow()。我们不断地深入到调用堆栈中。如果玩家继续探索,最终他们会遇到Python的堆栈限制。您可以通过增加堆栈大小来解决这个问题,但这只是一个模棱两可的问题;正确的解决方案是消除递归。

对象模型

Place

你应该从定义一些东西开始。就像房间。一个房间是玩家可以进入的位置。它应该有一个短的名字(“厨房”,“布罗的地下室”),和一个更长的描述。玩家以前可能在房间里也可能不在房间里。它将有连接(出口)到其他地点。房间里可能有东西。

代码语言:javascript
复制
class Room:
    def __init__(self, name, description):
        self.name = name
        self.description = description
        self.visited = False
        self.exits = { }
        self.contents = []

Things

除了房间,世界上到处都是物体或东西。事情将有一个名字,也许是一个描述。有些东西可以随身携带(照片,小册子,罐子,.)其他东西必须留在的地方(炉子、水槽)。有些东西可以穿,比如外套或帽子。它可能是隐藏的:

代码语言:javascript
复制
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

容器

有些东西可以放在另一些东西里面。鱼条可以在冰柜里找到。冰盒通常是封闭的,但偶尔会打开。有些容器可能会被锁上,就像一个柜子。一些集装箱可能会被看穿,比如中国内阁。你可以爬进一些容器,如衣柜或汽车,但大多数你不能。

代码语言:javascript
复制
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

房间是集装箱吗?房间里有名字,描述和内容。而且他们很有娱乐性。

支持者

有些东西可以放在另一些东西上。你可以把一个罐子放在桌子上。你可以把钥匙放在钩子上。因此,也许某些容器应该被视为支持者,而不是。你甚至可以进入一些支持者,如爬到床上。

动画

有些东西可以移动,并有行为。你可以和他们中的一些人交谈,比如店主,他们会回话的。其他演员,可能不会顶嘴,比如猫。

店主(一个有生命的东西)可能穿着裤子,口袋(容器),其中可能包含怀表(可操作)。

玩家是一个有生命的容器吗?他们可以持有物品(库存),移动(有生命的),拿东西(容器),持有东西,穿东西。

Doors

两间房之间有一扇门。门可以是开的,也可以是关的。如果它关闭了,它可能被锁定,也可能不会被锁定。

代码语言:javascript
复制
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_doortrap_door是隐藏的,所以如果玩家在客厅,并试图“向下”,最初他们应该得到一个“你不能走那条路”。移动地毯应该揭示陷阱门(标记它没有隐藏),允许通过门到它连接的另一个位置。也许:

代码语言:javascript
复制
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

现在,如果您的游戏逻辑允许您键入“抬起地毯”或“移动地毯”,您可以解析“地毯”一词,在location.contents中找到具有该名称的对象,并调用该对象的.on_move()函数,该函数告诉您发生了什么,更改了地毯的描述,并从陷阱门中删除了隐藏的属性。

示例

让你开始吧。灯笼只是一个Thingrug实际上是一个Rug (一个特殊的Thing),它在frog.py游戏文件中定义了一个动作。

请注意,冒险游戏框架可以用于许多不同的游戏。

这是一个“更好”的方式,你是以前的方法,但我不会说这是一个好办法,目前。该框架有很多细节需要清理,并重新工作以包括更好的可见性和可触摸性。项应该有一个.has_light属性。房间.has_light --如果它本身将该属性设置为True,或者其中的项具有该属性,除非该项位于封闭容器中(除非该容器是透明的)。

如果你继续沿着这条路走下去,最终你将重新发明通知7互动小说框架。祝好运。

adventure.py

代码语言:javascript
复制
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

代码语言:javascript
复制
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()
票数 21
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/240237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档