我刚刚玩了一个基于文本的RPG,我想知道,命令解释器究竟是如何实现的,现在有更好的方法来实现类似的东西吗?制作大量的if语句很容易,但这看起来很麻烦,特别是考虑到大部分pick up the gold
与pick up gold
相同,其效果与take gold
相同。我确信这是一个非常深入的问题,我只想知道如何实现这样的解释器的一般概念。或者,如果有一个开源游戏,有一个体面和有代表性的翻译,那将是完美的。
答案可以与语言无关,但要尽量保持合理,而不是prolog或golfscript等。我不确定该标记到底是什么。
答案 0 :(得分:6)
这种游戏的通常名称是文本冒险或互动小说(如果是单人游戏),或MUD(如果是多人游戏)。
有几种用于编写交互式小说的特殊用途编程语言,例如Inform 6,Inform 7(一种编译为Inform 6的全新语言),TADS,{{3等等。
以下是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. >
对于通常比交互式小说引擎更简单的解析器的多人游戏,您可以查看Hugo列表。
如果您想编写自己的解析器,可以先从正则表达式中检查输入。例如,在Ruby中(因为您没有指定语言):
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
如果您有很多命令,这可能会开始变慢,并且它会依次检查每个命令的输入。您也可能会发现它仍然难以阅读,并且涉及一些难以简单地提取为短序的重复。
此时,您可能希望查看MUD servers和lexers,这个话题对我来说太大了,无法在此回复。有许多词法分析器和解析器生成器,给出一个语言的描述,将产生一个能够解析该语言的词法分析器或解析器;查看链接文章的一些起点。
作为解析器生成器如何工作的示例,我将在基于Ruby的解析器生成器parsers中给出一个示例:
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"
答案 1 :(得分:1)
如果通过“基于文本的RPG”指的是交互式小说,则有针对此的特定编程语言。我最喜欢的(我认识的唯一一个; P)是Inform:http://en.wikipedia.org/wiki/Inform
rec.arts.int-fiction常见问题解答提供了更多信息:http://www.plover.net/~textfire/raiffaq/FAQ.htm