-
Notifications
You must be signed in to change notification settings - Fork 18
Command Matching
This page discusses how the parser matches a command to what the user typed. Each command has a "matchItems" function that scores the command against the input.
In a sense this function is the heart of the parser - when the player enters a command, the parser goes through every command and runs this function, allowing the command itself to decide how good a match it is to the text. The command that gives the highest score is selected. As part of the process, it will also attempt to match objects to the command (if there is a decent match; otherwise it will not bother).
This function is automatically added to all your commands, but it is just possible you will want to write your own. As an example, the GIVE command uses this to allow GIVE MAN BOOTS.
The function is passed the normalised string as a parameter, but is also passed the text the user types as a second parameter in case you ever want to use that.
Note that rather than returning a value, it sets an attribute on the command itself. This allows the command's script to access the values later.
More specifically, it creates a dictionary attribute for the command called "tmp" that will exist only for the this turn. This will hold the results of the matching process.
- objectTexts - the matched object names from the player input
- objects - the matched objects (lists of lists ready to be disambiguated)
- score - a rating of how good the match is
- error - a string to report why it failed, if it did!
The objects will be an array for each object role (so PUT HAT IN BOX is two), of arrays for each object listed (so GET HAT, TEAPOT AND GUN is three), of possible object matches (so GET HAT is four if there are four hats in the room). After disambiguation, the lowest level will be resolved into a single object, but the "matchItems" function can rely on that happening elsewhere.
The score is a rating for how well this command matches, based on the score attribute of the command itself (defaults to 10); if zero or less, this is an error.
If this does give an error, it is only reported if no command is a success, and then only if this command scored highest.
In the first place, this uses the "_test" function to decide if the regular expressions match. If not, it sets the score to parser.NO_MATCH (i.e., -100) and gives up.
The standard "matchItems" function in each command uses regular expressions to match input to commands, and then fragments of the text to match items. It is a big subject, discussed here.
You can give a command multiple regular expressions, using "regexes" rather than "regex". You can put some of your alternatives in dictionaries and tell Quest to rearrange the ordering. Here is a command that will let the player do USE x TO SLICE y or USE y to SLICE x. in the latter case, the regex is flagged so the objects will be reversed. You can also flag it with "reverseNotFirst", which you would have to use if you were telling an NPC to do it. You can also use a custom function, "func", which will be passed the object list, and you can manipulate it as you see fit.
new Cmd('SliceCarrot', {
regexes:[
/^use (.+) to slice (.+)$/,
/^use (.+) slice (.+)$/,
{ regex:/slice (.+) with (.+)/, mod:{reverse:true}},
],
objects:[
{scope:parser.isPresent},
{scope:parser.isPresent},
],
script:function(objects) {
msg("You slice {nm:ob1:the} with {nm:ob2:the}.", {ob1:objects[1][0], ob2:objects[0][0]})
// ...
},
})
There is a concrete example of this here.
You can give a command an array of regular expressions that it must not match.
This can be helpful if you have two similar commands. One example is with GIVE where we want to match GIVE MAN BOOTS, but not GIVE BOOTS TO MAN (which is handled by the GIVE TO command).
Another is for casting spells, where you want CAST STONESKIN and CAST STONESKIN ON ME to be handled by one command, but CAST ICE SHARD AT ORC to be handled with another. The issue is that CAST STONESKIN ON ME is going to be matched by both, and the latter will win as it matches an item. The solution is to give an antiRegex.
new Cmd('CastSpell', {
regexes:[
/^(?:cast|invoke) (.+)$/,
/^(?:cast|invoke) (.+) on (?:me|myself|self)$/,
],
...
new Cmd('CastSpellAt', {
antiRegexes:[
/^(?:cast|invoke) (.+) on (?:me|myself|self)$/,
],
regex:/^(?:cast|invoke) (.+) (?:at|on) (.+)$/,
...The language file, lang-en.js, contains a dictionary, lang.regex, where the regular expressions for all the built-in commands are stored. This allows other language files to use the same commands.
You can add your own entries:
lang.regex.Attack = /^(?:attack|att) (.+)$/
lang.regex.Search = /^(?:search) (.+)$/This is probably only useful for libraries that might one day get translated, but is worth mentioning in case anyone is wondering why the built-in commands have no regex entries.
You might want to do this to implement your own command. The RPG library does it to disable the generic HIT command, so it will not interfere with the various attack commands it has.
Just set the "matchItems" to always fail.
findCmd("Attack").matchItems = function() { this.tmp = {score:parser.NO_MATCH} }There are various ways to point the parser to a command or item, but an easy one is to give the command a "score" attribute, or the item a "parserPriority" attribute, both of which should be a number. The higher the number, the more the parser will tend to pick that one. Or set it to a negative number to discourage the parser from picking it.
Tutorial
- First steps
- Rooms and Exits
- Items
- Templates
- Items and rooms again
- More items
- Locks
- Commands
- Complex mechanisms
- Uploading
QuestJS Basics
- General
- Settings
- Attributes for items
- Attributes for rooms
- Attributes for exits
- Naming Items and Rooms
- Restrictions, Messages and Reactions
- Creating objects on the fly
- String Functions
- Random Functions
- Array/List Functions
- The
respondfunction - Other Functions
The Text Processor
Commands
- Introduction
- Basic commands (from the tutorial)
- Complex commands
- Example of creating a command (implementing SHOOT GUN AT HENRY)
- More on commands
- Shortcut for commands
- Modifying existing commands
- Custom parser types
- Note on command results
- Meta-Commands
- Neutral language (including alternatives to "you")
- The parser
- Command matching
- Vari-verbs (for verbs that are almost synonyms)
Templates for Items
- Introduction
- Takeable
- Openable
- Container and surface
- Locks and keys
- Wearable
- Furniture
- Button and Switch
- Readable
- Edible
- Vessel (handling liquids)
- Components
- Countable
- Consultable
- Rope
- Construction
- Backscene (walls, etc.)
- Merchandise (including how to create a shop)
- Shiftable (can be pushed from one room to another)
See also:
- Custom templates (and alternatives)
Handing NPCs
- Introduction
- Attributes
- Allowing the player to give commands
- Conversations
- Simple TALK TO
- SAY
- ASK and TELL
- Dynamic conversations with TALK TO
- TALK and DISCUSS
- Following an agenda
- Reactions
- Giving
- Followers
- Visibility
- Changing the player point-of-view
The User Experience (UI)
The main screen
- Basics
- Printing Text Functions
- Special Text Effects
- Output effects (including pausing)
- Hyperlinks
- User Input
The Side Panes
Multi-media (sounds, images, maps, etc.)
- Images
- Sounds
- Youtube Video (Contribution by KV)
- Adding a map
- Node-based maps
- Image-based maps
- Hex maps
- Adding a playing board
- Roulette!... in a grid
Dialogue boxes
- Character Creation
- Other example dialogs [See also "User Input"]
Other Elements
- Toolbar (status bar across the top)
- Custom UI Elements
Role-playing Games
- Introduction
- Getting started
- Items
- Characters (and Monsters!)
- Spawning Monsters and Items)
- Systema Naturae
- Who, When and How NPCs Attack
- Attributes for characters
- Attacking and guarding
- Communicating monsters
- Skills and Spells
- Limiting Magic
- Effects
- The Attack Object
- [Extra utility functions](https://github.com/ThePix/QuestJS/wiki/RPG-Library-%E2%80%90-Extra Functions)
- Randomly Generated Dungeon
- Quests for Quest
- User Interface
Web Basics
- HTML (the basic elements of a web page)
- CSS (how to style web pages)
- SVG (scalable vector graphics)
- Colours
- JavaScript
- Regular Expressions
How-to
Time
- Events (and Turnscripts)
- Date and Time (including custom calendars)
- Timed Events (i.e., real time, not game time)
Items
- Phone a Friend
- Using the USE verb
- Display Verbs
- Change Listeners
- Ensembles (grouping items)
- How to spit
Locations
- Large, open areas
- Region,s with sky, walls, etc.
- Dynamic Room Descriptions
- Transit system (lifts/elevators, buses, trains, simple vehicles)
- Rooms split into multiple locations
- Create rooms on the fly
- Handling weather
Exits
- Alternative Directions (eg, port and starboard)
- Destinations, Not Directions
Meta
- Customise Help
- Provide hints
- Include Achievements
- Add comments to your code
-
End The Game (
io.finish)
Meta: About The Whole Game
- Translate from Quest 5
- Authoring Several Games at Once
- Chaining Several Games Together
- Competition Entry
- Walk-throughs
- Unit testing
- Debugging (trouble-shooting)
Releasing Your Game
Reference
- The Language File
- List of settings
- Scope
- The Output Queue
- Security
- Implementation notes (initialisation order, data structures)
- Files
- Code guidelines
- Save/load
- UNDO
- The editor
- The Cloak of Darkness
- Versions
- Quest 6 or QuestJS
- The other Folders
- Choose your own adventure