Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// convertThenToPeriod.js

(function () {
  /* global adventurejs A */

  var p = adventurejs.Parser.prototype;

  /**
   * Convert any of these FROM
   *   "verb1 noun1, then verb2 noun2"
   *   "verb1 noun1 then verb2 noun2"
   *   "verb1 noun1 and then verb2 noun2"
   * TO
   *   "verb1 noun1. verb2 noun2."
   * Try to convert FROM
   *   "verb1 then verb2 noun1"
   * TO
   *   "verb1 noun1. verb2 noun2."
   *
   * Each clause separated by 'then' is a distinct input.
   * We treat clauses as unrelated without depencencies
   * and stack each into a queue.
   * <br><br>
   * Example: "take sword then go north"
   * @memberOf adventurejs.Parser
   * @method adventurejs.Parser#convertThenToPeriod
   * @param {String} input
   * @returns {String}
   */
  p.convertThenToPeriod = function Parser_convertThenToPeriod(input) {
    this.game.log(
      "L1597",
      "log",
      "high",
      `[convertThenToPeriod.js] convertThenToPeriod() receive: ${input}`,
      "Parser"
    );

    // const pattern = /\sthen\s+/gi;
    const pattern = /(?:, and |, | and | )then\s+/gi;

    let match;
    let result = input;
    let offset = 0;

    let split_input = [];
    let lastIndex = 0;

    while ((match = pattern.exec(input)) !== null) {
      const originalIndex = match.index; // index in the ORIGINAL input
      const currentIndex = originalIndex + offset; // adjust for edits

      // split by ' then '
      split_input.push(input.slice(lastIndex, originalIndex));
      lastIndex = originalIndex + match[0].length;

      // Perform replacement on the live string
      result =
        result.slice(0, currentIndex) +
        ". " +
        result.slice(currentIndex + match[0].length);

      // Update offset: replacement is shorter than matched input
      offset += 1 - match[0].length;
    }
    split_input.push(input.slice(lastIndex));

    // console.warn(`split_input`, split_input);

    // try to catch the form of "take then wear eyeglasses"
    if (split_input.length > 1 && split_input[0].split(" ").length === 1) {
      // we got a split where the language preceding the then
      // is only one word. Is that word a verb?
      const potential_verb = this.parseVerb(split_input[0]);
      if (potential_verb) {
        // we found a verb - can that verb be intransitive?
        // this isn't conclusive but it's the best we got
        const dictionary_verb = this.game.getVerb(potential_verb);
        if (dictionary_verb && !dictionary_verb.accepts_structures.verb) {
          // get first word from split_input[1]
          const next_potential_verb = this.parseVerb(
            split_input[1].split(" ")[0]
          );
          const next_dictionary_verb = this.game.getVerb(next_potential_verb);
          if (next_dictionary_verb) {
            // yes, it appears that player input
            // "verb1 then verb2 something"
            // we can't make anything of verb1 alone
            // so copy second clause to first clause
            // then restore verb1 to first clause
            // we should wind up with
            // [ "verb1 something", "verb2 something" ]
            split_input[0] = split_input[1].replace(
              next_potential_verb,
              potential_verb
            );
          }
        }
      }
    }

    // @TODO east then look - intransitive verb handling

    // ensure every phrase but the last ends with a period
    if (split_input.length > 1) {
      for (let i = 0; i < split_input.length - 1; i++) {
        split_input[i] = split_input[i].trim();

        // does it end with a period because it ends with an abbreviation?
        // ie: give glass key to mrs. go east
        if (split_input[i].endsWith(".")) {
          let words = split_input[i].split(" ");
          let lastword = words[words.length - 1].toLowerCase();
          if (
            "undefined" !== typeof this.game.world_lookup[lastword] ||
            this.game.dictionary.getAbbreviation(lastword)
          ) {
            // add a second period which will be trimmed later
            split_input[i] += ".";
          }
        }

        if (!split_input[i].endsWith(".")) split_input[i] += ".";
      }
    }

    // reduce array back to string
    input = split_input.join(" ");

    this.game.log(
      "L1598",
      "log",
      "high",
      `[convertThenToPeriod.js] convertThenToPeriod() return: ${input}`,
      "Parser"
    );
    return input;
  };
})();