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

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

  var p = AdventureJS.Parser.prototype;

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

    // look for:
    // - ", then "
    // - " then "
    // - ", and then "
    // - " and then "

    input = input.replace(
      /(?:,\s*and\s*|,\s*|\s+and\s+|\s+)then\s+/i,
      (match, offset, string, groups) => {
        return " | ";
      }
    );

    const sentences = input
      .split("|")
      .map((sentence) => sentence.trim())
      .filter((sentence) => sentence.length);

    for (let i = 0; i < sentences.length; i++) {
      const sentence = sentences[i];
      const last_sentence = sentences[i - 1];
      const next_sentence = sentences[i + 1];
      if (last_sentence && last_sentence.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(last_sentence);
        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 sentence
            const next_potential_verb = this.parseVerb(sentence.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" ]
              sentences[i - 1] = sentences[i].replace(
                next_potential_verb,
                potential_verb
              );
            }
          }
        }
      }
    }

    // @TODO east then look - intransitive verb handling

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

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

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

    // reduce array back to string
    input = sentences.map((item) => item.trim()).join(" ");

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