Commandclass | command.t[15], english.t[2109]

A Command describes the results of parsing one player predicate - that is, a single verb phrase, with all its parts. This includes the action to be performed and the objects to perform it on. It also includes information on the text of the player's input, and how it maps onto the grammar structures defined by the language module.

The Command object is built in several steps, so its contents aren't complete until all of the steps are completed.

Modified in english.t[2109]:
Modification to the Command class so that when reconstructing a command string from its tokens a separate apostrophe-S token is concatenated with the previous word when storing the name (which undoes the effect on building the name of what the English-language tokenizer does with apostrophe-S).

`class Command : object`

Superclass Tree (in declaration order)

`Command`
`object`

Subclass Tree

`Command`
`FuncCommand`

Global Objects

(none)

Summary of Properties

`acc accInfo accNPs accs action actions actor actorNPs actorPerson actors afterReports aobj badMulti cmdErr disambig disambigIdx dobj dobjInfo dobjNPs dobjs endOfSentence implicitActionReports iobj iobjInfo iobjNPs iobjs lastAction madeTopic matchedAll matchedMulti miscWordLists missingNouns nextTokens npList npListSorted npToResolve originalAction parseTree predActive predPriority priority reflexiveAnte tokenLen verbProd`

Summary of Methods

`addDisambigNP addNounListItem addNounProd afterReport buildCommandString buildObjLists calcPriority changeAction clone cloneNP construct emptyNounRole exec execCombos execDoer execIter fetchDisambigReply fixPriority forEachNP forEachObj getCommandPhrase noteMiscWords npTokenLen numNounSlots resolveNouns resolveReflexive saveReflexiveAnte sortList startDisambigReply terseOK`

Properties

`acc` | `command.t[1244]`

the accessory object for the current iteration

`accInfo` | `command.t[1250]`

the NPMatch object for the current accessory

`accNPs` | `command.t[1238]`

the accessory phrases, as a list of NounPhrase objects

`accs` | `command.t[1241]`

the list of resolved accessory objects, as NPMatch objects

`action` | `command.t[1185]`

the Action object giving the action to be performed

`actions` | `command.t[341]`

A list of actions executed directly by this command or via a Doer

`actor` | `command.t[1194]`

the resolved actor; we determine this before disambiguation

`actorNPs` | `command.t[1197]`

the actor(s) to whom the command is addressed, as a NounPhrase list

`actorPerson` | `command.t[1211]`

The grammatical person in which we're addressing the actor. This is 2 for a second-person address, 3 for third-person orders. (It's hard to think of a case for first-person orders, but

The conventional IF syntax for giving orders is ACTOR, DO SOMETHING, which addresses ACTOR in the second person (as YOU). This means that second-person pronouns

`actors` | `command.t[1200]`

the actor(s), as NPMatch objects

`afterReports` | `command.t[354]`

A list of strings containing reports to be displayed at the end of the command execution cycle for this command.

`aobj` | `command.t[1247]`

synonym for the accessory object

`badMulti` | `command.t[1300]`

Error flag: we have a noun list (grammatically) where a single noun is required. When this occurs, this will be set to the role where the error was noted.

`cmdErr` | `command.t[1317]`

The error we encountered building the command, if any. This is usually a noun resolution error.

`disambig` | `command.t[1262]`

Disambiguation replies. Each time the player answers a disambiguation question, we add the reply to this list. We then go back and re-resolve the noun phrases, fetching replies from the list as we encounter the ambiguous objects again.

Note that this is a list of list. Each reply is a list of NounPhrase objects, and we might have a series of replies, so one list represents one reply.

`disambigIdx` | `command.t[1265]`

the next available disambiguation reply

`dobj` | `command.t[1220]`

the current direct object for the current action iteration

`dobjInfo` | `command.t[1223]`

the NPMatch object for the current iteration's direct object

`dobjNPs` | `command.t[1214]`

the direct object phrases, as a list of NounPhrase objects

`dobjs` | `command.t[1217]`

the list of resolved direct objects, as NPMatch objects

`endOfSentence` | `command.t[1275]`

Is this command at the end of a sentence? The grammar match sets this to true if the input syntax puts this predicate at the end of a sentence. For example, in the English grammar, this is set if there's a period after this predicate. This tells the parser that the next predicate in the same line is the start of a new sentence, so sentence-opening syntax is allowed.

`implicitActionReports` | `command.t[383]`

A list of reports of previous implicit actions performed in the course of executing this command which can be used if we need to collate a report of a stack of implicit actions.

`iobj` | `command.t[1232]`

the indirect object for the current iteration

`iobjInfo` | `command.t[1235]`

the NPMatch object for the current indirect object

`iobjNPs` | `command.t[1226]`

the indirect object phrases, as a list of NounPhrase objects

`iobjs` | `command.t[1229]`

the list of resolved indirect objects, as NPMatch objects

`lastAction` | `command.t[1188]`

the Previous action performed by this command

`madeTopic` | `command.t[1327]`

no description available

`matchedAll` | `command.t[1322]`

Does this command apply to objects matched to ALL?

`matchedMulti` | `command.t[1325]`

Does this command apply to objects matched to multiple objects?

`miscWordLists` | `command.t[1126]`

List of noun phrases containing misc word phrases. The misc word phrase grammar rules will notify us when they're visited in the build process, and we'll note them here.

`missingNouns` | `command.t[1132]`

Do we have any missing or empty noun phrases in the match? The verb and noun phrases will fill this in.

`nextTokens` | `command.t[1311]`

The token list for the next predicate. The first predicate production fills this in during the build process with the token list for the next predicate on the same command line, based on the location of the conjunction or punctuation that ends the first predicate. This is just what's left of the token list after the tokens used for our own predicate and after any conjunctions or punctuation marks that separate our predicate from the next one.

`npList` | `command.t[1285]`

The noun phrase roles (as NounRole objects), in the order they actually appear in the user input. We build this list as the VerbProduction adds our noun phrases. The phrase order is important when there are reflexive pronouns, because a reflexive pronoun generally refers back to the nearest preceding phrase of the same number and gender.

`npListSorted` | `command.t[1293]`

A copy of the npList sorted to ensure that the direct and indirect objects of a TIAction are verified in the order specified on that action.

`npToResolve` | `command.t[895]`

If the parser has just asked the player to supply a missing object via the askMissingObject() function, we don't want to resolve the nouns for every object role, but only for the role with which askMissingObject() is currently concerned; askMissingObject() stores that role here so that our resolvedNouns() method knows to resolve only the noun for this role rather than for all the roles in the command. If npToResolve is nil (as it normally will be) then it will be ignored, and all noun roles will be resolved.

`originalAction` | `command.t[347]`

The originalAction this Command started out with, which may be changed by a Doer (or some other mechanism)

`parseTree` | `command.t[1182]`

The parse tree (the root of the grammar match), if applicable. Commands built from user input have a parse tree; those built internally don't. Note that the parse tree doesn't necessarily include *all* of the user input, since we could have asked questions (disambiguation, missing noun phrases) before the command was completed. The question replies will be represented in noun phrases or other data added to the command after the initial parse.

`predActive` | `command.t[1170]`

is our predicate currently active (see VerbProduction.isActive)

`predPriority` | `command.t[1167]`

the predicate priority (see VerbProduction.priority)

`priority` | `command.t[1119]`

the calculated priority

`reflexiveAnte` | `command.t[986]`

table of reflexive pronoun antecedents

`tokenLen` | `command.t[1150]`

The number of tokens from the command line that we matched for the command. The CommandProduction object sets this for us as it builds the command from the parse tree. We use this to determine the priority order of the syntax matches, when there are multiple matches: other things being equal, we'll take the longest match. Longer matches are better because they come closer to using everything the user typed, which is our eventual goal.

This reflects the number of tokens used in the first predicate phrase; it omits any additional predicates or conjunctions. We only count the first predicate because we always go back and re-parse any additional text on the line from scratch after executing the first predicate, in case the execution changes the game state in such a way that the parsing changes.

`verbProd` | `command.t[1191]`

the VerbProduction object for the command

Methods

`addDisambigNP (prod)` | `command.t[705]`

Add a disambiguation list item. This adds a NounPhrase item to the current reply list.

`addNounListItem (role, prod)` | `command.t[633]`

add a noun phrase to the given role (a NounRole)

`addNounProd (role, prod)` | `command.t[615]`

Add a noun production, building it out as though it had been part of the original parse tree. This can be used to add a noun phrase after the initial parsing, such as when the player supplies a missing object.

`afterReport ( )` | `command.t[365]`

Run through our list of afterReports displaying each in turn. We do this on the Command rather than on any of the Actions since actions may invoke other actions (implicit, remapped, nested or replaced), while the afterReports pertain to the command as a whole.

`buildCommandString ( )` | `command.t[334], english.t[2110]`

Rebuild the original command string from the tokens. We call this out as a separate method so language-specific code can override it.

`buildObjLists ( )` | `command.t[902]`

Build the object lists. This runs through each NounPhrase in the command to build its 'objs' list, then builds the corresponding master list in the Command object.

`calcPriority ( )` | `command.t[1091]`

Calculate the parsing priority.

When the parser looks for grammar rule matches to the input, it considers *all* of the possible matches. Natural language is full of syntactic ambiguity, so a given input string can often be parsed into several different, but equally valid, syntax trees. It's often impossible to tell which parsing is correct based on syntax alone - you often have to look at the overall meaning of the sentence. For example, GIVE BOOK TO BOB could be interpreted as having a direct object (BOOK) and an indirect object (BOB), or it could be seen as having only a direct object (BOOK TO BOB, treating the TO as a prepositional phrase modifying BOOK rather than as a part of the verb phrase structure). The initial parsing phase only looks at the syntax, so it has to consider all of the valid phrase structures, even though a human speaker would immediately dismiss many of them as nonsensical. Once we find all of the syntax matches, the parser puts them into priority order, and then goes down the list looking for the first one that makes sense semantically (which is defined roughly as having noun phrases that refer to actual objects).

The priority, then, represents our guess at the likelihood that the grammar structure matches the user's intentions, based on the syntax. Our fundamental assumption is that the command is valid: that is, it's well-formed grammatically, AND it expresses something that's possible, or at least logical to try, within the game-world context. Given this, our strategy is to find a grammar structure that gives us a command that we can actually carry out.

The priority is a composite value, made up of weighted component values. We combine the components into a single scalar value simply by adding up the parts multiplied by their weights. (Or, looked at another way, we combine the values using a high-radix numbering system.) The components are, from most significant to least significant:

- Grammatically correct commands sort ahead of commands with structural errors.

- The predicate priority, from the VerbProduction. (This tells us how "complete" the predicate structure is: a predicate with missing information has a lower priority. This is in keeping with our assumption that the user's input is well-formed - we'll try the most complete structures first before falling back on the possibility that the user left out some information.)

- Filled noun slots ahead of missing noun slots. A missing noun slot occurs when the player leaves one of the noun roles empty (PUT BOX, TAKE). We can fill in this information with automatic defaults, so it's not necessarily a reason to reject the parsing, but if there's another interpretation that has fully occupied noun slots, try the occupied one first.

- More noun phrase slots first. For example, sort a command with a direct and indirect object (two slots) ahead of one with only a direct object. More slots means that we found more "structure" in the command; we can sometimes interpret the same command with less structure by subsuming more words into a long noun phrase.

- Longest noun phrases, in aggregate, first. This is in terms of tokens matched from the user input. (We want to consider longer noun phrases first because it's more likely that they'll match exact objects, so there's less chance of ambiguity, *and* it's more likely that if we're wrong about the structure, we'll simply fail to find a matching object and move on to other parse trees. Longer noun phrases are less likely to yield spurious matches simply because they have more words that have to match.)

- Grammatical noun phrases take priority over misc word phrases (a misc word phrase is text in a noun phrase slot that doesn't match any of the defined patterns in the grammar rules).

- Longest command first, in terms of tokens matched from the user input. (The more user input we use the better, since that gives us more confidence that we're correctly interpreting what the user said. When we leave extra tokens for later, we can't be sure that we'll be able to make any sense of what's left over, whereas tokens in the current match are known to fit a grammar rule.)

`changeAction (newAct, newDo, newIo, newAo)` | `command.t[497]`

Change the action to a new action with a new set of objects

`clone ( )` | `command.t[129]`

clone - create a new Command based on this Command

`cloneNP (np)` | `command.t[154]`

clone a noun phrase that's part of this command

`construct ([args])` | `command.t[41]`

Create the command object. There are several ways to create a command:

new Command(parseTree) - create from a parsed command syntax tree.

new Command(action, dobjProd...) - create from a given Action and a set of parsed syntax trees for the noun phrases. The first noun phrase is the direct object, the second is the indirect object, and the third is the accessory.

new Command(action, dobjs...) - create from a given Action and a set of objects or object lists for the noun slots. The first argument after the Action, dobjs, can be a single Mentionable object to use as the resolved direct object, or a list or vector of Mentionables to use as the multiple direct objects. The next argument is in the same format and is used for the indirect object. The third is the accessory.

new Command(actor, action, dobjs...) - create from a given actor (as a Mentionable object), an Action object, and the object list.

new Command() - create a blank Command, for setting up externally or in a subclass.

`emptyNounRole (role)` | `command.t[732]`

mark a noun phrase role as empty

`exec ( )` | `command.t[183]`

Execute the action. This carries out the entire command processing sequence for the action. If the action involves a list of objects (as in TAKE ALL or DROP BOOK AND CANDLE), we iterate over the listed objects, executing the action on each object in turn.

`execCombos (predRoles, n, lst)` | `command.t[394]`

Execute the command for each combination of objects for noun role index 'n' and above. 'lst' is a list containing a partial object combination for roles at lower indices. We iterate over each combination of the remaining objects. predRoles is a list containing predicate roles (such DirectObject, IndirectObject, AccessoryObject) relating to this action. Callers are responsible for sorting predRoles into the correct order before calling this method.

`execDoer (lst)` | `command.t[474]`

Execute the command via the Doers that match the command's action and objects. 'lst' is the object combination to execute: [action, dobj, iobj, ...].

`execIter (lst)` | `command.t[441]`

Execute one iteration of the command for a particular combination of objects. 'lst' is the object combination to execute: this is an [action, dobj, iobj, ...] list.

`fetchDisambigReply ( )` | `command.t[724]`

Fetch a disambiguation reply. If we have more replies available, this returns the next reply's noun phrase list, otherwise nil.

`fixPriority ( )` | `command.t[1108]`

Set a fixed priority. This makes the priority a fixed value rather than a calculated value. We call this before sorting a list of commands, so that we don't have to recalculate the priority value repeatedly during the sort.

`forEachNP (func)` | `command.t[870]`

carry out a callback for each noun phrase in each list

`forEachObj (func)` | `command.t[524]`

Invoke a callback for each object in the current command iteration. This invokes the callback on the direct object, indirect object, accessory, and any other custom roles added by the game.

`getCommandPhrase ( )` | `command.t[1335]`

Get the command phrase entered by the player, with the words used to match the direct, indirect and accessory objects replaced by (dobj), (iobj) and (acc) respectively; e.g. PUT RED BALL ON TABLE becomes 'put (dobj) on (iobj)'

`noteMiscWords (np)` | `command.t[1111]`

note a noun phrase with a miscellaneous word list

`npTokenLen ( )` | `command.t[1153]`

Calculate the sum of the token lengths of our noun phrases

`numNounSlots ( )` | `command.t[1164]`

Calculate the number of noun slots we have filled in

`resolveNouns ( )` | `command.t[746]`

resolve the noun phrases

`resolveReflexive (pronoun)` | `command.t[968]`

Resolve a reflexive pronoun on behalf of one of the NounPhrases within this command.

`saveReflexiveAnte (obj)` | `command.t[940]`

Save a potential antecedent for a reflexive pronoun coming up later in the command. Each time we visit a noun phrase during the reflexive pronoun phase, we'll note its resolved objects here. Since we visit the noun phrases in their order of appearance in the command, we'll naturally always have the latest one mentioned when we come to a reflexive pronoun. This gives us the correct resolution, which is the nearest preceding noun. Note that the noun phrase shouldn't call this routine to note reflexive pronouns, since they don't bind to earlier reflexive pronouns - they only bind to regular noun phrases.

`sortList (cmdLst)` | `command.t[995]`

Class method: Sort a list of Command matches, in priority order. The priority order is the order for processing predicate grammar matches: start at the highest priority, and work through the list until you find one where the noun phrases resolve to valid game-world objects; that's the one to execute.

`startDisambigReply (parent, prod)` | `command.t[689]`

Start processing a new disambiguation reply. This adds a reply to a disambiguation question.

`terseOK ( )` | `command.t[569]`

Are terse messages OK for this command? A terse message is a simple acknowledgment of a standard command, such as "Taken", "Dropped", "Done", etc. The action is so ordinary that the result of a successful attempt should be obvious to the player; so the only reply needed is an acknowledgment, not an explanation.

Terse replies only apply to simple actions, and only when the actor is the player character, AND there's no disambiguation involved. If the actor isn't the PC, an acknowledgment isn't sufficient; we should instead describe the NPC carrying out the action, since it's something we observe, not something we do. If any objects were disambiguated, we also want to describe the action fully, because the ambiguity calls for a description of precisely which objects were chosen. Disambiguation guesses are sometimes wrong, so when they're involved, it's not safe to assume that the player and parser must both be thinking the same thing. Showing a full description of the action will make it obvious to the player when we guessed wrong, because the description won't accord with what they had in mind. A terse acknowledgment would hide this difference, allowing the player to wrongly assume that the parser did what they thought it was going to do and potentially leading to confusion down the road.

Adv3Lite Library Reference Manual
Generated on 15/03/2023 from adv3Lite version 1.6.1