tags:

views:

62

answers:

2

I was just playing a text based RPG and I got to wondering, how exactly were the command interpreters implemented and is there a better way to implement something similar now? It would be easy enough to make a ton of if statements, but that seems cumbersome especially considering for the most part pick up the gold is the same as pick up gold which has the same effect as take gold. I'm sure this is a really in depth question, I'd just like to know the general idea of how interpreters like that were implemented. Or if there's an open source game with a decent and representative interpreter, that would be perfect.

Answers can be language independent, but try to keep it in something reasonable, not prolog or golfscript or something. I'm not sure exactly what to tag this as.

A: 

If by 'text based RPG' you are referring to Interactive Fiction, there are specific programming languages for this. My favorite (the only one I know ;P) is Inform: http://en.wikipedia.org/wiki/Inform

The rec.arts.int-fiction FAQ has further information: http://www.plover.net/~textfire/raiffaq/FAQ.htm

rak5hasa
+3  A: 

The usual name for this sort of game is text adventure or interactive fiction, if it is single player, or MUD if it is multiplayer.

There are several special purpose programming languages for writing interactive fiction, such as Inform 6, Inform 7 (an entirely new language that compiles down to Inform 6), TADS, Hugo, and more.

Here's an example of a game in Inform 7, that has a room, an object in the room, and you can pick up, drop, and otherwise manipulate the object:

"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."

Produces when played:

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

You may discover that this becomes cumbersome after a while. You could simplify it somewhat using some shorthands to avoid repetition:

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

This may start to get slow if you have a lot of commands, and it checks the input against each command in sequence. You also may find that it still becomes hard to read, and involves some repetition that is difficult to simply extract into shorthands.

At that point, you might want to look into lexers and parsers, a topic much too big for me to do justice to in a reply here. There are many lexer and parser generators, that given a description of a language, will produce a lexer or parser that is capable of parsing that language; check out the linked articles for some starting points.

As an example of how a parser generator would work, I'll give an example in Treetop, a Ruby based parser generator:

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

Which can be used as follows:

require 'treetop'
Treetop.load 'adventure.tt'

parser = AdventureParser.new
tree = parser.parse('take the key')
tree.command            # => :take
tree.object.text_value  # => "key"
Brian Campbell
Thanks for the treetop example, that's pretty much what I was interested in.
Falmarri