0

所以,这可能会,也可能不会变得复杂。希望不会。无论如何,我在业余时间一直在写一个相当雄心勃勃的 Python 文本游戏,只是想看看我能不能完成它。我意识到那里有大量的交互式小说引擎、解析器等,但我是从头开始做的。这是我学习的方式——我猜是艰难的方式。

所以它是如何分解的:

  • 您在 engine.py 模块中有 main() 函数,它几乎可以抓取房间对象并显示房间描述。然后它等待用户输入并将其发送到解析器。
  • parser.py 模块中的解析器通过用户输入运行并构造一个 Sentence 对象(由动词和对象组成 - 可以是名词或方向)。Sentence 对象还有一个输出函数,它从 command.py 模块内部调用 xxxCommand 类。
  • 示例:您输入“向北”,解析器将其作为合适的句子接受。因此解析器输出函数将搜索 GoCommand 类。

现在这就是我遇到麻烦的地方。在我继续之前,为了清楚起见,我将粘贴我的 Engine & Sentence 类:

class Engine(object):
    def __init__(self, start_room):
        self.L = lexi.Lexicon() #Imported earlier
        self.P = parser.Parser() #Imported earlier
        self.room = start_room

    def main(self):
        while True:
            self.room.describe() #Describes the current room.

            # Ask for user prompt
            input = raw_input(self.room.prompt)
            cmd = input.lower()

            # Scans user input & creates tokens from Lexicon table
            # For example: [('verb', 'go'), ('direction', 'north')]
            tokenizer = self.L.scan(cmd)

            # Runs through tokens and creates a sentence object
            # With noun & object attributes
            parsed_sentence = self.P.parse_sentence(tokenizer)

            # See below
            parsed_sentence.output(self.room)


class Sentence(object):

    def __init__(self, verb, noun):
        self.verb = verb[1]
        self.obj = noun[1]

    # There's a command module with different xxxCommand classes with an execute method
    # as seen on last line. So pretend the command module has already been imported.
    def output(self, current_room):
        verb = self.verb.capitalize()
        obj = self.obj
        command = getattr(commands, '%sCommand' % verb)(obj)
        command.execute(current_room)   

好的,经过漫长的设置,我的 GoCommand 类如下所示:

# Subclassed from Command parent class. Has one method called execute. Does nothing else.
class GoCommand(Command):
    def __init__(self, direction):
        self.direction = direction

    def execute(self, current_room):
        # 'E' is the instantiation of the Engine class, declared within engine.py
        from engine import E

        # self.direction is 'north' in our example
        # current_room.map is a dict within any Room class named 'map'.
        # For example: Intro.map = {'north': char_intro }
        if self.direction in current_room.map:
            print "You head %s\n" % self.direction # Pretty explanatory

            # HERE'S WHERE I HAVE TROUBLE
            E.room = current_room.map[self.direction]
        else:
            print "You can't go that way."

所以我希望实现的是,当循环结束时,E.room 将等于一个名为 char_intro 的房间类,并且当循环再次运行时,它会显示 char_intro 的描述,基本上是重新开始。

这不是正在发生的事情。它只停留在第一个房间。虽然 GoCommand.execute() 正在运行,但 E.room 没有改变。有谁知道为什么?

哦,天哪,我意识到这很长,但我希望有人知道我在说什么并且可以帮助我。我应该如何解决这个问题,以便当用户说向北并且为 North 设置了路径时,它会改变房间等级?

4

2 回答 2

0

So it looks like the game state (current room, inventory) is being kept on the Engine. Just for comparison's sake, look over the text adventure game I wrote as a command-parsing exercise at http://www.ptmcg.com/geo/python/confs/adventureEngine.py.txt. In that code, I kept the current room and inventory on a Player instance. The main game loop then looks like:

parser = Parser()
p = Player("Joe")
p.moveTo( startRoom )
while not p.gameOver:
    cmdstr = raw_input(">> ")
    cmd = parser.parseCmd(cmdstr)
    if cmd is not None:
        cmd.command( p )

parseCmd parses the input string, and if valid, returns a Command object that implements command(p) where p is the Player. Through the player, the command has access to the current room, current inventory, and any special player state or skills (for instance, a player with heightened vision might have better odds at detecting a trap when entering a particular room). This also makes it easier to test your commands with a mock Player, instead of having to mock any globals or attributes in the Engine itself.

于 2012-12-16T09:13:24.710 回答
0

为了回答我自己的问题,Engine.main() 中的循环按预期工作,但我将 self.room.describe() 从 while 语句中取出:

def main(self):
    self.room.describe() #Describes the current room.
    while True:
        # Ask for user prompt
        input = raw_input(self.room.prompt)
        cmd = input.lower()
        ...etc, etc, etc...

然后我将 GoCommand 更改为:

class GoCommand(Command):
def __init__(self, direction):
    self.direction = direction

def execute(self):
    # 'E' is the instantiation of the Engine class, declared within engine.py
    from engine import E

    # self.direction is 'north' in our example
    if self.direction in E.room.map.keys():
        print "You head %s\n" % self.direction # Pretty explanatory

        E.room = E.room.map[self.direction]
        print E.room.describe()
    else:
        print "You can't go that way."

一切都按预期进行。

于 2012-12-16T05:44:30.573 回答