Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// 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;
  };
})();