2010-08-23 55 views
3

我只是在玩一個基於文本的RPG遊戲,我想知道,命令解釋器到底是如何實現的,是否有更好的方式來實現類似的東西?製作大量if語句會很容易,但看起來很麻煩,尤其是考慮到大部分pick up the goldpick up gold相同,其效果與take gold相同。我相信這是一個非常深入的問題,我只想知道這樣的解釋器是如何實現的總體思路。或者如果有一個開放源代碼的遊戲與一個體面的和具有代表性的翻譯,那將是完美的。基於文本的RPG命令解釋器

答案可以獨立於語言,但要儘量保持它的合理性,而不是序言或golfscript或其他東西。我不確定這是什麼標籤。

回答

6

對這種遊戲的名稱通常是文字冒險或互動小說,如果是單人遊戲,或者MUD,如果是多人遊戲。

有寫小說的互動幾個特殊用途的編程語言,如Inform 6Inform 7(即會編譯一個全新的語言,告知6),TADSHugo,等等。

下面是一個遊戲的例子在通知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. 

> 

對於多人遊戲,這往往比互動小說引擎簡單的解析器,你可以檢查出的MUD servers名單。

如果您想編寫自己的解析器,可以從簡單地根據正則表達式檢查輸入開始。例如,在紅寶石(因爲你沒有指定語言):

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" 
+0

感謝樹頂的例子,這幾乎是我感興趣的。 – Falmarri 2010-08-23 21:26:21