Doerclass | doer.t[194] |
Superclass Tree | Subclass Tree | Global Objects | Property Summary | Method Summary | Property Details | Method Details |
Doer objects are inherently static. All Doer objects should be defined at compile time; they're not designed to be created dynamically during execution. Rather than creating and removing Doer objects as conditions in the game change, use the Doer conditions to define when a given Doer is active and when it's dormant.
class
Doer : Redirector
Doer
Redirector
object
default1Doer
default2Doer
default3Doer
default4Doer
getOnGroundDoer
putOnGroundDoer
removeDoer
reverseAttachableDoer
takePathDoer
cmd
handleAction
ignoreError
priority
strict
checkDirection
exec
execAction
redirect
Inherited from Redirector
:
askMissingLiteral
doInstead
doNested
doOtherAction
cmd | doer.t[244] |
The command string specifies a verb and its objects, generally using the same verb phrase syntax that a player would use to enter a command to the game. The exact verb syntax is up to the language library to define; for English, we replicate the same verb phrases used to parse command input.
The verb phrase syntax is generally the same as for regular player commands, but the noun syntax is different. Each noun is written as the SOURCE CODE name of a game object or class. That is, not a noun-and-adjective phrase as the player would type it, but the program symbol name as it appears in the source code. If you use a class name, the command matches any object of the class. For example, to handle putting any treasure in any container:
cmd = 'put Treasure in Container'
You can match multiple objects or classes in a single noun slot (and you can freely mix objects and classes). For example, to handle putting any treasure or magic item in a container:
cmd = 'put Treasure|Magical in Container'
You can't use the '|' syntax with verbs, because the verb syntax covers the entire phrase. You can match multiple verbs by writing out the entire phrasing for each verb, separating each phrase with a semicolon:
cmd = 'take skull; put skull in Thing'
You can also write a command that matches ANY verb, by using "*" as the verb. You can follow the "*" with any number of objects; the first is the direct object, the second is the indirect, and the third is the accessory. This phrasing will match any verb that matches the given objects AND the given number of objects. For example, '* Thing' will match any verb with a direct object that's of class Thing, but it won't match verbs without any objects or verbs with an indirect object. Using "*" as a noun will match any object as well as no object at all. So to write a handler for every possible command, you'd write:
cmd = '* * * *'
That is, match any verb, with or without any direct object, indirect object, and accessory object.
handleAction | doer.t[399] |
ignoreError | doer.t[501] |
priority | doer.t[311] |
Most of the time, you shouldn't need to set a priority manually. If you don't, the library determines the precedence automatically according to the degree of specialization. However, the way the library figures specialization is a heuristic, so it's not always right. In cases where the heuristic produces the wrong results, you can bypass the rules by setting a priority manually. A manual priority takes precedence over all of the standard rules.
Our basic approach is to process Doers in order from most specific to most general. This creates a natural hierarchy of handlers where more specific rules override the generic, default handlers. Here are the degrees of specialization, in order of importance:
1. A Doer with a higher 'priority' value takes precedence over one with a lower value.
2. A Doer with a 'when' condition is more specific than a Doer without one. A 'when' condition means that the Doer is designed to operate only at specific times, so it's inherently more specialized than one that always operates.
3. A Doer with a 'where' condition is more specific than a Doer without one. A 'where' condition means that the Doer only applies to a limited geographical area.
4. A Doer that matches a particular Action is more specific than one that matches any Action.
5. If two Doer commands are for the same Action, the Doer that matches a more specialized subclass (or just a single object instance) for a noun phrase is more specific than one that matches a base class for the same noun phrase. For example, 'take Container' is more specific than 'take Thing', because Container is a subclass of Thing, and 'take backpack' (where the 'backpack' is a Container) is more specific than either. This type of specialization applies in the canonical object role order: direct object, indirect object, accessory. For example, we consider 'put Container in Thing' to be more specific than 'put Thing in Container', because we look at the direct object by itself before we even consider the indirect object. This rule only applies when the Action is the same: 'put Thing in Container' and 'open Door' are equal for the purposes of this rule.
It's important to understand that each degree of specialization is considered independently of the others, in the order above. For example, if you have a Doer with just a 'when' condition, and another with only a 'where' condition, the one with the 'when' condition has higher priority. This is because we look at the presence of a 'when' condition first, before even considering whether there's a 'where' condition.
The library has no way to gauge the specificity of a 'when' or 'where' condition, so there's no finer-grained priority to the conditions than simply their presence or absence.
If two Doers have the same priority based on the rules above, the one that's defined LATER in the source code has priority. This means that Doers defined in the game take priority over library definitions.
strict | doer.t[494] |
checkDirection (curCmd) | doer.t[420] |
exec (curCmd) | doer.t[322] |
execAction (curCmd) | doer.t[407] |
redirect (curCmd, altAction, dobj, :, =, 0, iobj, :, =, 0, aobj, :, =, 0, isReplacement, :, =, true) | doer.t[464] |