我只是在玩基于文本的RPG,我想知道命令解释器是如何实现的,现在有没有更好的方法来实现类似的功能?制作大量的if语句很容易,但是这似乎很麻烦,尤其是考虑到pick up the goldpick up gold相同,而take gold与ojit_code具有相同的效果。我确信这是一个非常深入的问题,我只想了解实现此类解释器的总体思路。或者,如果有一款具有体面且具有代表性的口译员的开源游戏,那将是完美的。

答案可以是独立于语言的,但请尝试将答案保持在合理的范围内,而不是序言,golfscript之类的内容。我不确定究竟该将其标记为什么。

最佳答案

这种游戏的通常名称是文本冒险或互动小说(如果是单人游戏),或者是MUD(如果是多人游戏)。

有几种用于编写交互式小说的专用编程语言,例如Inform 6Inform 7(一种编译为Inform 6的全新语言),TADSHugo等。

这是Inform 7中的一个游戏示例,其中包含一个房间,一个房间中的对象,您可以拾取,放下或以其他方式操纵该对象:

"Example Game" by Brian Campbell

The Alley is a room. "You are in a small, dark alley." A bronze key is in the
Alley. "A bronze key lies on the ground."

播放时产生:
Example Game
An Interactive Fiction by Brian Campbell
Release 1 / Serial number 100823 / Inform 7 build 6E59 (I6/v6.31 lib 6/12N) SD

Alley
You are in a small, dark alley.

A bronze key lies on the ground.

>take key
Taken.

>drop key
Dropped.

>take the key
Taken.

>drop key
Dropped.

>pick up the bronze key
Taken.

>put down the bronze key
Dropped.

>

For the multiplayer games, which tend to have simpler parsers than interactive fiction engines, you can check out a list of MUD servers.

If you would like to write your own parser, you can start by simply checking your input against regular expressions. For instance, in Ruby (as you didn't specify a language):

case input
  when /(?:take|pick +up)(?: +(?:the|a))? +(.*)/
    take_command(lookup_name($3))
  when /(?:drop|put +down)(?: +(?:the|a))? +(.*)/
    drop_command(lookup_name($3))
end

一段时间后,您可能会发现这变得很麻烦。您可以使用一些速记来简化它,以避免重复:
OPT_ART = "(?: +(?:the|a))?"  # shorthand for an optional article
case input
  when /(?:take|pick +up)#{OPT_ART} +(.*)/
    take_command(lookup_name($3))
  when /(?:drop|put +down)#{OPT_ART} +(.*)/
    drop_command(lookup_name($3))
end

如果您有很多命令,这可能会开始变慢,并且会依次检查每个命令的输入。您还可能会发现它仍然很难阅读,并且涉及一些重复,很难简单地提取为简写。

在这一点上,您可能想要研究lexersparsers,这是一个太大的主题,我在这里的答复中不适合对此进行公道。有许多词法分析器和解析器生成器,只要给出了一种语言的描述,它们就会生成能够解析该语言的词法分析器或解析器。查看链接文章以了解一些起点。

作为解析器生成器如何工作的示例,我将在Treetop(基于Ruby的解析器生成器)中给出一个示例:
grammar Adventure
  rule command
    take / drop
  end

  rule take
    ('take' / 'pick' space 'up') article? space object {
      def command
        :take
      end
    }
  end

  rule drop
    ('drop' / 'put' space 'down') article? space object {
      def command
        :drop
      end
    }
  end

  rule space
    ' '+
  end

  rule article
    space ('a' / 'the')
  end

  rule object
    [a-zA-Z0-9 ]+
  end
end

可以如下使用:
require 'treetop'
Treetop.load 'adventure.tt'

parser = AdventureParser.new
tree = parser.parse('take the key')
tree.command            # => :take
tree.object.text_value  # => "key"

关于interpreter - 基于文本的RPG命令解释器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3546044/

10-13 06:01