Commandclass | command.t[15], english.t[2150] |
Superclass Tree | Subclass Tree | Global Objects | Property Summary | Method Summary | Property Details | Method Details |
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[2150]:
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
Command
FuncCommand
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
postImplicitReports
predActive
predPriority
priority
reflexiveAnte
tokenLen
verbProd
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
acc | command.t[1259] |
accInfo | command.t[1265] |
accNPs | command.t[1253] |
accs | command.t[1256] |
action | command.t[1200] |
actions | command.t[341] |
actor | command.t[1209] |
actorNPs | command.t[1212] |
actorPerson | command.t[1226] |
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[1215] |
afterReports | command.t[354] |
aobj | command.t[1262] |
badMulti | command.t[1315] |
cmdErr | command.t[1332] |
disambig | command.t[1277] |
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[1280] |
dobj | command.t[1235] |
dobjInfo | command.t[1238] |
dobjNPs | command.t[1229] |
dobjs | command.t[1232] |
endOfSentence | command.t[1290] |
implicitActionReports | command.t[387] |
iobj | command.t[1247] |
iobjInfo | command.t[1250] |
iobjNPs | command.t[1241] |
iobjs | command.t[1244] |
lastAction | command.t[1203] |
madeTopic | command.t[1342] |
matchedAll | command.t[1337] |
matchedMulti | command.t[1340] |
miscWordLists | command.t[1141] |
missingNouns | command.t[1147] |
nextTokens | command.t[1326] |
npList | command.t[1300] |
npListSorted | command.t[1308] |
npToResolve | command.t[910] |
originalAction | command.t[347] |
parseTree | command.t[1197] |
postImplicitReports | command.t[360] |
predActive | command.t[1185] |
predPriority | command.t[1182] |
priority | command.t[1134] |
reflexiveAnte | command.t[1001] |
tokenLen | command.t[1165] |
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[1206] |
addDisambigNP (prod) | command.t[720] |
addNounListItem (role, prod) | command.t[648] |
addNounProd (role, prod) | command.t[630] |
afterReport ( ) | command.t[369] |
buildCommandString ( ) | command.t[334], english.t[2151] |
buildObjLists ( ) | command.t[917] |
calcPriority ( ) | command.t[1106] |
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[512] |
clone ( ) | command.t[129] |
cloneNP (np) | command.t[154] |
construct ([args]) | command.t[41] |
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[747] |
exec ( ) | command.t[183] |
execCombos (predRoles, n, lst) | command.t[398] |
execDoer (lst) | command.t[489] |
execIter (lst) | command.t[445] |
fetchDisambigReply ( ) | command.t[739] |
fixPriority ( ) | command.t[1123] |
forEachNP (func) | command.t[885] |
forEachObj (func) | command.t[539] |
getCommandPhrase ( ) | command.t[1350] |
noteMiscWords (np) | command.t[1126] |
npTokenLen ( ) | command.t[1168] |
numNounSlots ( ) | command.t[1179] |
resolveNouns ( ) | command.t[761] |
resolveReflexive (pronoun) | command.t[983] |
saveReflexiveAnte (obj) | command.t[955] |
sortList (cmdLst) | command.t[1010] |
startDisambigReply (parent, prod) | command.t[704] |
terseOK ( ) | command.t[584] |
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.