// findDirective.js
(function () {
/* global adventurejs A */
var p = adventurejs.Parser.prototype;
/**
* Look for an NPC directive in the form of
* input that begins with a character name followed by
* a comma, as in "Conan, give me the ax"
*
* If the input starts with one word followed by a comma, we
* always take it to mean that a character has been addressed
* and issue a success or failure depending on circumstances.
* ie: "roger, make shrubbery"
*
* If the input starts with multiple words followed by a comma,
* we'll check to see if a character was addressed
* ie: "roger the shrubber, make shrubbery"
* but our search pattern also matches something like
* "look at roger, look at shrub"
* so if we don't find a character we won't issue a failure.
*
* If we find a character directive, we save
* a record of the target character back to the input.
* @memberOf adventurejs.Parser
* @method adventurejs.Parser#findDirective
* @param {String} input Player input.
* @returns {String|Boolean}
*/
p.findDirective = function Parser_findDirective(input) {
this.game.log(
"L1610",
"log",
"high",
`[findDirective.js] findDirective() receive: ${input}`,
"Parser"
);
let this_turn = this.input_history[0];
let player = this.game.getPlayer();
const pattern = /^([A-Za-z.'. ]+?),\s/;
const match = input.match(pattern);
if (!match) {
return input;
}
const name = match[1]; // Captures the name before the comma
const remaining = input.slice(match[1].length + 2, input.length);
const parsed_noun = this.parseNoun(name);
// if the input had spaces and we didn't find a noun,
// it's safe to assume it was not addressed to a character
if (
parsed_noun.matches.qualified.length === 0 &&
name.split(" ").length > 1
) {
return input;
}
let char;
let chars = [];
let msg = "";
let debug = "";
// if only one word preceded the comma, we treat that as
// a character directive even if we don't find a character
switch (parsed_noun.matches.qualified.length) {
case 0:
// no asset found
msg = `{We} {don't} know of anyone named ${name}. `;
debug = "not found";
break;
case 1:
// found an asset
char = this.game.getAsset(parsed_noun.matches.qualified[0]);
if (!char) {
msg = `{We} {don't} know of anyone named ${name}. `;
debug = "not found";
break;
} else if (!player.knowsAbout(char)) {
msg = `{We} {don't} know of anyone named ${name}. `;
debug = "not known";
break;
} else if (!char.hasClass("Character")) {
msg = char.is.present
? `${char.Article_name} ignores {us}. `
: `{We} {don't} see any ${name} here. `;
debug = "not a character";
break;
} else {
if (!char.is.present) {
msg = `{We} {don't} see ${char.article_name} here. `;
debug = "not present";
break;
}
}
break;
default:
// found multiple assets
// can we find a singular character?
for (let i = 0; i < parsed_noun.matches.qualified.length; i++) {
let asset = this.game.getAsset(parsed_noun.matches.qualified[i]);
if (asset.hasClass("Character") && asset.is.present) {
chars.push(asset);
}
}
switch (chars.length) {
case 0:
msg = `No one named ${name} is present. `;
debug = `not found`;
break;
case 1:
char = chars[0];
break;
default:
msg = `{We'll} have to be more specific. `;
debug = `not unique`;
break;
}
break;
}
if (msg) {
// any msg means we failed to identify a target character
this.game.log(
"L1596",
"warn",
"high",
`[findDirective.js] ${name} is ${debug}`,
"Parser"
);
this.game.debug(`D1178`, `findDirective.js `, ` ${name} is ${debug}`);
this.game.print(msg);
return false;
}
if (char) {
this_turn.setSubject(char);
return remaining;
}
return input;
};
})();