This question already has an answer here:

Currently I have got a system set up where I split each sentence handed to me into it's baser parts and then compare each word against a list of known words. Once I have the verbs, adjectives and nouns contained in each sentence (ignoring all other words in the sentence) I go left to right in the list and try and create a recognisable command from it. However this doesn't allow for multiple commands in one line.

e.g. get the shiny sword and hit troll.

This would read get, shiny, sword, troll. It would ignore the hit part because currently I've only written the parser to handle one verb per line, but this would not be a recognisable command and would tell the player that it doesn't know what they're asking them.

I think my current system of tokenising the words and parsing them as arguments to an arbitrary action function is simple enough but not very elegant.

So I was just wondering what are some good ways to implement text adventure parsers? Are there any tried and true algorithms or ways to approach it?


marked as duplicate by Kromster says support Monica, bummzack, congusbongus, Josh Jan 21 '15 at 16:54

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • \$\begingroup\$ How complex are your commands? Do you ever need to parse "hit the troll in the back of the neck while doing a backflip over the fence"? \$\endgroup\$ – Anko Jan 18 '15 at 11:39
  • \$\begingroup\$ I'm hoping for comments and criticisms on my current way, how I could improve it and if there is a better way to do it. Also that question didn't really offer me a satisfactory answer. \$\endgroup\$ – J-' Jan 18 '15 at 11:40
  • \$\begingroup\$ @Anko no not that complex, think much more zork-like. e.g. Hit troll with elven sword \$\endgroup\$ – J-' Jan 18 '15 at 11:40

I think you are going at this the right way. Always keep in mind the English grammar (predicate, object) with adjective in between. If a second sentence is concatenated with "and" you have to re-run the parser again.

I would implement much more verbs, objects and adjectives than are used in the game. That way you can recognize the sentence structure even if less-common words are used.

Btw. you could implement some sort of "auto-correction", e.g. "I don't see 'sword', did you maybe mean 'swan'?" or "I can't 'kick troll', did you maybe mean 'kill troll'?" :D

  • 1
    \$\begingroup\$ Oh man that 'and' thing is so simple and brilliant. I can't believe I didn't even think of that. I will definitely add those other parts in, they could really make things a lot smoother. Thanks for this. \$\endgroup\$ – J-' Jan 18 '15 at 12:17

I have one primary answer to your question, but first a few thoughts:

  • There seem to be two forces you have to balance between with commands; helping a new user by supporting more natural and less idiomatic syntax, and helping minimize growing frustration with long/expressive syntax.
  • Prepositions can be really useful, because you can have a short list of prepositions that are relatively stable and useful when it comes to chunking actions into smaller parts that do something recognizable and then figuring out what nouns they're referring to. At, from, in, into, to, and with alone are a good start, while a number of the locational prepositions (above, below, between, besides, through etc.) may be worth looking for if you have any commands that need this sort of detail.
  • Be aware that letting the user execute multiple logical commands in a statement introduces a lot of ambiguity due to everything we infer from this proximity that your parser will have trouble resolving. Is get the shiny sword and hit troll to be expanded as pick up the shiny sword and put it in my inventory then hit the troll with whatever I am already wielding? or are the commands going to try to infer that the user wanted to hit the troll with the new weapon instead of the old, since they're on the same line?
  • Regarding the actual act of parsing, I guess the scale might run from:
    • a large centralized parser which attempts to understand each command without the command itself doing any syntax parsing. This will make it easier to have predictable, well-controlled syntax, avoid re-inventing wheels per command, and is more or less essential for something like sensibly inferring what one command should do based on what another in the same line is doing; it can also make edge-case syntax cumbersome for you, or awkward in the game.
    • a smaller centralized parser that is just trying to figure out where it can hand the command off to for further parsing. The light-weight central parser can give you tons of flexibility in individual commands, but may mean you're re-implementing similar features again and again. It may also mean you're implementing them slightly differently in a way that makes sense for the command but surprises a user.
  • Write down a long list of syntax examples you'd like to be able to support for a variety of commands. Try to pick a few commands that are similar but not quite logical copies, as well as many that differ much more. Start picking these apart for structural similarities. Try writing both the most expressive and terse versions you can imagine wanting to support. You'll probably notice some heuristics you can use (like where prepositions, verbs, and targets tend to fall) that can help.
  • Write a script that feeds this list of commands into your parser and meaningfully communicates the results back to you as a test-case.

Ok--to the point:

Depending on a lot of things like your skill/comfort, how many commands you think you'll have, and how long you plan to work on the game--I would consider writing a small command-syntax-specification format, and parsing this format into rules the command parser itself will use. This is more like an advanced version of the large centralized parser above (especially since you need two parsers--one for your specification format, and one that can apply the rules it generates). For a small number of commands this inevitably won't pay dividends. With something like this you could declare your kill syntax as: kill <targ:living>( with <weap:weapon>) and your get syntax as get <obj:object>( <prep:from|out of> <where:container|room>) and your parser can walk the statement and give each matcher a chance to ingest part of the command or object to the syntax with a message about what didn't work. If your game doesn't let the player attack peaceful npcs, you might have two commands like: kill <targ:aggressive>( with <weap:weapon>) and talk <prep:to|with> <targ:peaceful>( about <topic:word>).


Not the answer you're looking for? Browse other questions tagged or ask your own question.