// verifySentence.js
(function () {
/*global adventurejs A*/
"use strict";
var p = adventurejs.Parser.prototype;
/**
* After parse, verify each word in sentence.
* @memberOf adventurejs.Parser
* @method adventurejs.Parser#verifySentence
*/
p.verifySentence = function Parser_parseSentence() {
let this_turn = this.input_history[0];
this.game.log(
"log",
"high",
"verifySentence.js > " + this_turn.input,
"Parser"
);
let count = {
noun: 0,
prep: 0,
verb: 0,
adverb: 0,
adjective: 0,
direction: 0,
exclusion: 0,
unknown: 0,
string: 0,
phrase: 0,
};
let firstverb;
for (
let position = 0;
position < this_turn.parsed_sentence.length;
position++
) {
let this_word = this_turn.parsed_sentence[position];
let last_word = this_turn.parsed_sentence[position - 1];
let next_word = this_turn.parsed_sentence[position + 1];
let msg = "";
this.game.debug(
`F1203 | verifySentence.js | ${this_word.type}/${this_word.word} `
);
// ----------------------------------------
// verb
// ----------------------------------------
if (this_word.type === "verb") {
// we don't accept double verbs except for "oops verb"
if (
last_word &&
last_word.type === "verb" &&
last_word.word !== "oops"
) {
// too many verbs
this.game.debug(
`F1198 | verifySentence.js | input found two verbs in a row`
);
msg += this.getUnparsedMessage(this_turn.input);
this.game.print(msg);
return false;
}
count.verb++;
this_turn.verified_sentence_structure += "verb ";
this_turn.verified_sentence["verb" + count.verb] = {
verb: this_word.word,
verb_properties: this_word.properties,
};
continue;
} // verb
// ----------------------------------------
// adverb
// ----------------------------------------
// if (this_word.type === "adverb") {
// adverbcount++;
// this_turn.verified_sentence_structure += "adverb ";
// this_turn.verified_sentence['phrase'+count.phrase] = {
// adverb: adverb
// }
// continue;
// } // adverb
// ----------------------------------------
// direction
// ----------------------------------------
// if (this_word.type === "direction") {
// continue;
// } // direction
// ----------------------------------------
// preposition
// ----------------------------------------
// @TODO any special handling for preposition is direction?
if (this_word.type === "preposition") {
if (last_word && last_word.type === "preposition") {
// too many prepositions
this.game.debug(
`F1030 | verifySentence.js | parser found two or more prepositions`
);
msg += this.getUnparsedMessage(this_turn.input);
this.game.print(msg);
return false;
}
count.prep++;
count.phrase++; // a preposition starts a new phrase
this_turn.verified_sentence_structure += "preposition ";
this_turn.verified_sentence["phrase" + count.phrase] = {
preposition: this_word.word,
preposition_properties: this_word.properties,
};
continue;
} // preposition
// ----------------------------------------
// string
// ----------------------------------------
// if(this_word.type==="string") {
// continue;
// } // string
// ----------------------------------------
// noun
// ----------------------------------------
// noun and itself ----------------------------------------
// @TODO we have no other handling for itself yet
if (this_word.type === "noun" && this_word.word === "itself") {
if (!this_turn.verified_sentence["phrase" + count.phrase]?.noun) {
this.game.debug(`F1862 | verifySentence.js | itself has no referent`);
msg += this.getUnparsedMessage(this_turn.input);
this.game.print(msg);
return false;
}
if (last_word && last_word.type !== "preposition") {
count.phrase++; // a new noun starts a new phrase
}
this_turn.verified_sentence_structure += "noun ";
this_turn.verified_sentence["phrase" + count.phrase].noun = {
noun: this_turn.verified_sentence["phrase" + (count.phrase - 1)].noun,
noun_properties: this_word.properties,
};
// if there is a prior phrase...
if (
this_turn.verified_sentence["phrase" + (count.phrase - 1)].parsedNoun
) {
// copy that phrase's noun to this phrase
this_turn.verified_sentence["phrase" + count.phrase].parsedNoun =
new adventurejs.ParsedNoun().set(
this_turn.verified_sentence["phrase" + (count.phrase - 1)]
.parsedNoun
);
}
continue;
} // itself
// spatial_direction aka up/down/in/out ----------------------------------------
if (
this_word.type === "noun" &&
this_word.properties.spatial_direction &&
last_word &&
last_word.type === "verb" &&
next_word &&
next_word.type === "noun"
) {
// player has likely said something like "climb up tree"
// we typically parse directions as nouns but in cases like this
// we want to treat the direction as a preposition
this.game.debug(
` | verifySentence.js | ${this_word.word} appears to be a spatial direction / preposition for ${next_word.word}`
);
count.phrase++;
this_turn.verified_sentence["phrase" + count.phrase] = {}; // add new phrase
this_turn.verified_sentence["phrase" + count.phrase].preposition =
this_word.word;
continue;
} // this_word.properties.spatial_direction
// noun and this_word.adjective ----------------------------------------
if (
this_word.type === "noun" &&
this_word.adjective &&
next_word &&
next_word.type === "noun"
) {
// word is both noun and adjective
// if next word is noun then it's likely that
// this is an adjective for the next word
// if we treat the two nouns as one phrase,
// do they have an unambiguous match?
// first try getting an asset
let found_asset_id;
let found_asset = this.game.getAsset(
this_word.word + " " + next_word.word
);
if (found_asset) found_asset_id = found_asset.id;
// otherwise parseNoun which does a wider search
if (!found_asset) {
let parse_both = this.parseNoun(
this_word.word + " " + next_word.word
);
found_asset_id = parse_both.matches.unambiguous;
found_asset = this.game.getAsset(found_asset_id);
}
if (!found_asset_id) {
this.game.debug(
`F1219 | verifySentence.js | ${this_word.word} appears to be an adjective for ${next_word.word} and no ${this_word.word} ${next_word.word} was found`
);
msg += `$(We) don't know of any ${this_word.word} ${next_word.word}. `;
this.game.print(msg, this_turn.output_class);
return false;
}
// we found a noun that matches both words
this.game.debug(
`F1863 | verifySentence.js | ${found_asset_id} was found to match ${this_word.word} + ${next_word.word} `
);
this_word.asset = found_asset;
this_word.word = found_asset_id;
position++; // advance past next word
// allow to go on to default noun handling
} // noun and adjective
// noun default ----------------------------------------
if (this_word.type === "noun") {
if (last_word && last_word.type !== "preposition") {
count.phrase++;
this_turn.verified_sentence["phrase" + count.phrase] = {}; // add new phrase
}
// save the noun
this_turn.verified_sentence["phrase" + count.phrase].noun =
this_word.word;
// carry forward properties from parseSentence
this_turn.verified_sentence["phrase" + count.phrase].noun_properties =
this_word.properties;
// save any exclusions
if (this_word.exclusion) {
this_turn.verified_sentence["phrase" + count.phrase].exclusion =
this_word.exclusion;
}
this_turn.verified_sentence_structure += "noun ";
count.noun++;
continue;
} // noun
// ----------------------------------------
// adjective
// ----------------------------------------
if (this_word.type === "adjective") {
// Adjectives are tricky because nouns can have them defined in
// their names, like "red door", and nouns can also have specific
// adjectives assigned to them, so that "red" and "door" will find
// the "door" asset with adjective "red". If player entered an
// adjective that resolved to a noun, that noun will have been recorded
// and probably our sentence structure will have two nouns in it,
// something that we won't catch here, so we'll have to check again
// in handleSentence.js.
// We only end up here if an
// adjective has been typed that is not attached to a noun. For
// instance, no noun in the game uses "violet" but we understand that
// "violet" is an adjective and if a user inputs "x violet door"
// we can say "you don't see any violet door".
if (next_word && next_word.type === "noun") {
this.game.debug(
`F1218 | verifySentence.js | ${this_word.word} appears to be an adjective for ${next_word.word} and no ${this_word.word} ${next_word.word} was found`
);
msg += `$(We) don't know of any ${this_word.word} ${next_word.word}. `;
this.game.print(msg, this_turn.output_class);
return false;
} // adjective + noun
continue;
} // adjective
// ----------------------------------------
// unknown
// ----------------------------------------
if (this_word.type === "unknown") {
// @TODO: soft prompt for "oops"
this_turn.unknown_word = this_word.word;
this.game.debug(
`F1200 | verifySentence.js | ${this_word.word} is unknown`
);
msg += `The word <em class='unparsed'>${this_word.word}</em> wasn't recognized. `;
this.game.print(msg, this_turn.output_class);
return false;
} // unknown
}
// trim the sentence structure
this_turn.verified_sentence_structure =
this_turn.verified_sentence_structure.trim();
return true;
}; // verifySentence
})();