Verbs, commands and templates
From QuestWiki
Overview
Quest 5.0 currently follows relatively similar principles to previous versions when it comes to processing player input. I say "currently" as this may change over the course of the technical previews and beta versions, and I say "relatively" as although based on the "old" system, there is a lot more flexibility and power in the new way of doing things. In a nutshell, we retain the concepts of verbs and commands.
Here is a simple command:
<command>
<pattern>test</pattern>
<script>
msg ("Hello")
</script>
</command>
This allows the user to type "test", and in response prints "Hello". So far, very similar to Quest 4.
Verbs let you add "doing" words, to let players interact with objects. For example:
<verb>
<pattern>eat</pattern>
<defaulttext>You cannot eat that.</defaulttext>
</verb>
<object name="crisps">
<eat type="script">
msg ("Yum yum yum")
crisps.parent = stomach
player.health = player.health + 5
</eat>
</object>
This would let the player type "eat crisps", and provide a sensible response for when the player tries to eat other objects in the game.
Templates
Core.aslx defines the behaviour for standard verbs such as "look at", "speak to" and so on, but the actual text for the verbs themselves comes from the language library (English.aslx). To have the behaviour in one place but the verb itself in another, we have templates, which look like this in English.aslx:
<template name="eat">eat</template> <template name="cannot_eat">You cannot eat that.</template>
A French version might look like:
<template name="eat">mangez</template> <template name="cannot_eat">Vous ne pouvez pas manger ça.</template>
We use square brackets in Core.aslx to dynamically replace text with the template. So Core.aslx might have a line like this to define the verb, which will behave in exactly the same way as the verb in the above example:
<verb>
<pattern>[eat]</pattern>
<defaulttext>[cannot_eat]</defaulttext>
</verb>
Matching objects in commands
For more complicated commands, such as "put apple on table", you can match objects within a command. Quest 5 lets you use a similar syntax to Quest 4 with a "pattern" element, for example:
<command name="put"> <pattern>put #object1# on #object2#</pattern> <script> ... </script> </command>
The words within the #hashes# are called "named groups" - the pattern is translated into a regular expression. For any named group with a name starting with "object", Quest tries to match it to an object in the current visible scope (e.g. the objects in the current room, plus the objects in the inventory – I’ll be discussing scopes in more detail in a future post). You can also have named groups starting with "exit" to match available exits.
When the script for the command runs, local variables "object1" and "object2" are set to the objects specified in the command, so you can access their properties directly using "object1.parent" etc.
You can also specify a regex directly by specifying type="string" for the pattern tag (without a type specified, Core.aslx defines an implied type of "simplepattern", which creates a regex for you from the simpler command syntax).
For example:
<command name="put">
<pattern type="string"><![CDATA[
^put (?<object1>.*) (on|in) (?<object2>.*)$
]]></pattern>
<script> ... </script>
</command>
Note that when specifying regular expressions:
- A <![CDATA[ ... ]]> section must be used, otherwise the named group syntax will cause XML parsing to fail
- You should use ^ and $ to ensure the regular expression matches the entire player input
