-
Notifications
You must be signed in to change notification settings - Fork 14
Custom parser types
The parser is built around matching commands, and then matching items within the commands. What if you want your command to match something other than items? For example, FILL GOBLET WITH WINE. FILL and WITH are fine, they are part of the command matching. The GOBLET is an item. But what about WINE? You want the command to match other liquids too, but wine is not an item.
Every command has an "objects" attribute; an array or dictionary of dictionaries. Usually this tells Quest about what sort of objects to expect - hence the name. However, you can also use it to tell Quest to expect something else altogether, using the "special" attribute.
This example is taken from the SAY command. It says the first bit will be text (the verb; SAY, SHOUT, etc.), and the second bit is also text, what is being said.
objects:[
{special:'text'},
{special:'text'},
]
This example is for pushing an object in a direction, and shows how we can mix it up.
objects:[
{special:'text'},
{scope:parser.isHere, attName:"shiftable"},
{special:'direction'},
]
})
A number of options are built-in. In the table below, the name is what you need to use in the "objects" array, as seen in the examples above. The "Returns" indicates what value will be added to the array passed to the command's "script" function (on a successful match).
Name | Matches | Returns |
---|---|---|
ignore | Anything | Nothing |
text | Anything | The full text |
direction | Any direction, as set up in lang.exit_list | The full name of the direction (eg "northwest") |
number | Any number in digits or any number as a word from zero to twenty | The number (as a number, not a string) |
fluid | Any fluid listed in settings.fluids | The fluid |
tone | Any fluid listed in settings.tones | The tone |
You can add your own types. Let us say you want to add adverbs. It is debatable if it is a good idea at all, but it does illustrate the technique.
We set up the adverbs in the "setup" function in settings.js. If you already have a set up function, you just want to insert this - without the first and last line - into that.
settings.setup = function() {
parser.generateSpecialText(
'adverb',
['carefully', 'quickly', 'elegantly'],
'Not recognising the adverb there.'
)
}
The parser.generateSpecialText
function takes three parameters; a name, an array of allowed values and a message to use when there is no match.
Then (in code.js, perhaps), add your command, setting the "objects" array to use a special with the name you used before.
new Cmd('TalkToAdverb', {
regex:/^(?:talk to|speak to|talk|speak) (.+) (.+)$/,
objects:[
{scope:parser.isNpcAndHere},
{special:'adverb'},
],
script:function(objects) {
msg('You talk to {nm:npc:the} {show:text}', {npc:objects[0][0], text:objects[1]})
return world.SUCCESS
},
})
Note that in the script, the item is an element in an array, which is itself in an array (objects[0][0]
). This is because the player can use commands with several items at once in some cases, such as GET ALL. However, the special text is just an element in an array, so is objects[1]
, not objects[1][0]
.
We can make it better! The parser.generateSpecialText
can handle arrays in the array, allowing for synonyms. The value passed to the command's "script" function will always be the first element of the array. We can also use the text processor in the error message.
settings.setup = function() {
parser.generateSpecialText(
'adverb',
[['carefully', 'cautiously', 'c'], ['quickly', 'fast', 'q'], 'elegantly'],
'Not recognising the adverb "{show:text}".'
)
}
We can also modify the command to allow the adverb at the start. This is best done using named capture groups, so the "objects" attribute is now a dictionary.
new Cmd('TalkToAdverb', {
regexes:[
/^(?:talk to|speak to|talk|speak) (?<npc>.+) (?<adverb>.+)$/,
/^(?<adverb>.+) (?:talk to|speak to|talk|speak) (?<npc>.+)$/,
],
objects:{
npc:{scope:parser.isNpcAndHere},
adverb:{special:'adverb'},
},
script:function(objects) {
msg('You talk to {nm:npc:the} {show:text}', {npc:objects[0][0], text:objects[1]})
return world.SUCCESS
},
})
What if you want something more complicated? We can add a new attribute to parser.specialText
. This has to have two function attributes, "error" and "exec", both of which will be sent the text. The "error" function should either return false
if it is not an error - the text is acceptable - or a message otherwise (it should not print anything itself).
The "exec" function should return whatever is to be added to the list of matched items. In this example (which is doing adverbs the long way), it is the text, but you could look up a value in a dictionary and return that. If this returns false
, nothing gets added to the list of items.
parser.specialText.adverb = {
error:function(text) {
if (settings.adverbs.includes(text)) return false
return processText("Hmm, I was expecting an adverb, and I got {show:text}. Not one I know.", {text:text})
},
exec:function(text) {
return text
},
}
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
respond
function - 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
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
- 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
- Following an agenda
- Reactions
- Giving
- Followers
- 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!)
- Attributes for characters
- Attacking and guarding
- Skills and Spells
- Limiting Magic
- Effects
- The Attack Object
- 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)
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
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