I have a Sugarcube-based parser that I have used in a few games. They are Spanish-only at the moment. However, I translated the prototype into English, and you can try it here.
How it’s done?
- There’s a Javascript object that parses the command matching the 1st token, and returns the passage name with the implementation of the verb (object matching would work likewise: parse 2nd token + find object).
Javascript helper
var parser = {
"actions": [
{"id": "ACT_COGER", "vbs": ["get","take"]},
{"id": "ACT_IR", "vbs": ["n","s","e","w",
"up","down","in", "out"]},
{"id": "ACT_MIRAR", "vbs": ["l","look","describe"]},
{"id": "ACT_EXAMINAR", "vbs": ["x","ex","examine"]},
{"id": "ACT_INVENTARIO", "vbs": ["i","inv","inventory"]},
{"id": "ACT_SALIR", "vbs": ["quit","exit","end"]},
],
"parse": function (cmd){
var tokens = cmd.toLowerCase().match(/\S+/gi);
if (tokens == null) {return;}
for (var i=0;i<this.actions.length;i++){
if (this.actions[i].vbs.indexOf(tokens[0])>=0){
var ret = {};
ret.action = this.actions[i];
ret.args = tokens.slice(1);
return ret;
}
}
}
};
- The main UI is a passage printing the game log and the prompt. Notice that entering a command takes the player to the
Parser
passage.
'Input' passage
$log > <<textbox "$player_input" "" "Parser" autofocus>>
- The
Parser
passage takes the input, passes it to the function and moves the player to the parsed action (or to the error message). Notice that the 1st line echoes the command to the log, so we get a nice transcript.
'Parser' passage
<<set $log = $log + "> " + $player_input + "\n" >>
<<set $command = parser.parse($player_input) >>
<<if $command>>
<<goto $command.action.id>>
<<else>>
<<goto ACT_ERROR>>
<</if>>
- Action passages work by adding text to the game log (large string stored in
$log
), and returning the player back to Input
.
ACT_COGER passage (take action)
<<set $log = $log + "Taken (not really).\n" >>
<<goto Input>>
And… this is it, really. Execution model is:
Input
→ Parser
→ ‘ACT_SOMETHING’ → Back to Input
with the ACT_SOMETHING
passages appending text to the game log, and changing the state of the game world as needed (moving objects from locations to inventory, changing the player location, etc).
Typically I keep track of the player location, inventory and so on into a object variable called $state
.
For different games I have implemented a map, directions, inventory, ‘soft’ save/restore, log pruning… Save for the small piece of JS, is all implemented with macros, so the actions have access to the story variables and the game state is properly serialized on save and restore.
If you can handle some Spanish text, my game whoami has a short parser subsection with proper inventory, map (with no directions, just a universal GO TO ) and interaction with an NPC.
Edit: A couple of pro-tips:
- disable navigation to prevent the text logs cluttering your memory (set maxStates to 1), and
- add a
parser
tag in all the parser nodes and use it a to customize the style, and disable the fade in-out effect for these nodes.