Pre-release
Adventure.js Docs Downloads
Score: 0 Moves: 0
// parseSentence.js

(function () {
  /*global adventurejs A*/
  "use strict";

  var p = adventurejs.Parser.prototype;

  /**
   * Parse each word in a sentence.
   * @memberOf adventurejs.Parser
   * @method adventurejs.Parser#parseSentence
   * @TODO Will eventually need to look for "person, do thing"
   * or "tell person to do thing"
   */
  p.parseSentence = function Parser_parseSentence() {
    var this_turn = this.input_history[0];
    this.game.log(
      "log",
      "high",
      "parseSentence.js > " + this_turn.input,
      "Parser"
    );

    let last_word_type;
    let last_word;
    let firstverb;
    let count = {
      noun: 0,
      prep: 0,
      verb: 0,
      adverb: 0,
      adjective: 0,
      direction: 0,
      exclusion: 0,
      unknown: 0,
      string: 0,
      phrase: 0,
    };

    for (
      let position_in_parsed_input = 0;
      position_in_parsed_input < this_turn.parsed_input_array.length;
      position_in_parsed_input++
    ) {
      let word = this_turn.parsed_input_array[position_in_parsed_input];

      let verb = this.parseVerb(word);

      let adverb = this.game.dictionary.getAdverb(word);

      let direction = this.game.dictionary.getDirection(word);
      let compass_direction =
        direction && this.game.dictionary.verbs[word].is_compass_direction;
      let spatial_direction =
        direction && this.game.dictionary.verbs[word].is_spatial_direction;
      let parsed_direction = direction && this.parseNoun(direction);

      let preposition = this.game.dictionary.getPreposition(word);

      let string = word === "global_string" ? word : false;

      let noun =
        this.parseNoun(word).matches.all.length > 0 ||
        word.indexOf("&") > -1 ||
        word.indexOf("=") > -1 ||
        "undefined" !== typeof adventurejs[A.propercase(word)];

      let exclusion = word.charAt(0) === "-";

      let number = !isNaN(Number(word)) ? word : false;

      let adjective = this.game.dictionary.getAdjective(word);

      let properties = {
        word: word,
        verb: verb,
        direction: direction,
        compass_direction: compass_direction,
        spatial_direction: spatial_direction,
        parsed_direction: parsed_direction,
        preposition: preposition,
        string: string,
        noun: noun,
        exclusion: exclusion,
        number: number,
        adjective: adjective,
      };

      //this.game.print(
      //  `F1191 | parseSentence.js | \n<br/> - word/ ${word}\n<br/> - verb/ ${verb}\n<br/> - direction/ ${direction}\n<br/> - preposition/ ${preposition}\n<br/> - adverb/ ${adverb}\n<br/> - number/ ${number}\n<br/> - string/ ${string}\n<br/> - noun/ ${noun}`
      //);

      if (noun && exclusion) {
        // both have & in them, get caught by noun check
        // but only exclusion has the leading -
        noun = false;
      }

      // Handle type-of-word ambiguities.
      // Any direction can be a verb.
      // Check position in sentence:
      // - if it's the first word, it's a verb
      // - if it's the second word, it's a direction
      // Directions that are not verbs can be treated like nouns.
      // Later during verification we'll check if direction is a preposition.

      if (verb && direction && preposition) {
        // this catches 'in' and 'out', which are defined as direction
        // verbs in addition to being prepositions
        // @TODO 2/4/24 it can be used to catch 'up' and 'down'
        // if 'up' and 'down' are added to dictionary.prepositions
        // currently evaluating that
        if (position_in_parsed_input === 0) {
          // almost certainly a verb
          direction = false;
          preposition = false;
        } else if (position_in_parsed_input === 1) {
          // could be "go in" - direction and preposition
          // could be "look in" or "put in" - prepositions
          // treat it like a preposition and let verbs handle it
          verb = false;
          direction = false;
        } else {
          // probably preposition
          verb = false;
          direction = false;
        }
      }

      // not parsing adverbs currently but keep this for future
      // if( verb && direction && adverb )
      // {
      //   // this catches 'up' and 'down', which are
      //   // defined as direction verbs and are also adverbs
      //   if( position_in_parsed_input === 0 )
      //   {
      //     // almost certainly a verb
      //     direction = false;
      //     adverb = false;
      //     noun = false;
      //   }
      //   else if ( position_in_parsed_input === 1 || last_word_type === 'verb' )
      //   {
      //     // could be "go up" - direction and adverb
      //     // could be "look up" or "put up" - adverbs
      //     // treat it like an adverb and let verbs handle it
      //     verb = false;
      //     direction = false;
      //     noun = false;
      //   }
      //   else
      //   {
      //     // in the case of a phrase like "throw ball up",
      //     // up would be an adverb
      //     // in the case of a phrase like "throw ball up the stairs",
      //     // up would be a preposition
      //     // at this moment we don't know which, so treat it like a direction
      //     // which is to say, a noun
      //     verb = false;
      //     adverb = false;
      //   }
      // }

      if (verb && noun && direction) {
        // this catches most directions
        if (position_in_parsed_input === 0) {
          // almost certainly a verb
          direction = false;
          noun = false;
        } else {
          // if it's a verb and a direction, but not an adverb
          // or a preposition, treat it as a noun
          // as in "go north" or "look north"
          direction = false;
          verb = false;
        }
      }

      if (verb && noun) {
        // consider the verb plug and the noun plug
        if (position_in_parsed_input === 0) {
          noun = false;
        } else {
          verb = false;
        }
      }

      if (verb && direction) {
        if (position_in_parsed_input === 0) {
          direction = false;
        } else {
          verb = false;
        }
      }

      if (verb && preposition) {
        if (position_in_parsed_input === 0) {
          preposition = false;
        } else {
          verb = false;
        }
      }

      /* verb ---------------------------------------- OK */

      if (verb) {
        this.game.log("log", "high", "parseInput > verb: " + verb, "Parser");
        if (count.verb === 0) firstverb = verb;
        count.verb++;
        this_turn.pushParsedWord({
          type: "verb",
          word: verb,
          properties: properties,
        });

        last_word_type = "verb";
        last_word = word;
        continue;
      }

      /* adverb ---------------------------------------- */

      // not parsing adverbs for now but keep this for later
      // this block was a git copilot auto-complete and needs to be checked before implementing
      // if( adverb )
      // {
      //   this.game.log( "log", "high", "parseInput > adverb: " + adverb, 'Parser' );
      //   count.adverb++;
      //   count.phrase++;
      //   this_turn.pushParsedWord({
      //     type:'adverb',
      //     word: adverb,
      //     properties: properties,
      //   });

      //  last_word_type = 'adverb';
      //  last_word = word;
      //  continue;
      // }

      // distinguish directions from nouns,
      // but also allow directions to be used as nouns

      /* direction ---------------------------------------- */

      if (direction) {
        this.game.log(
          "log",
          "high",
          "parseInput > direction: " + direction,
          "Parser"
        );
        count.direction++;
        count.phrase++;
        this_turn.pushParsedWord({
          type: "direction",
          word: direction,
          properties: properties,
        });

        last_word_type = "direction";
        last_word = word;
        continue;
      }

      /* preposition ---------------------------------------- OK */

      if (preposition) {
        // it's recognized as a preposition
        this.game.log(
          "log",
          "high",
          "parseInput > preposition: " + word,
          "Parser"
        );
        count.prep++;
        count.phrase++;

        // store the typed words in their original order
        this_turn.pushParsedWord({
          type: "preposition",
          word: word,
          phrase: count.phrase,
          properties: properties,
        });

        last_word_type = "preposition";
        last_word = word;
        continue;
      }

      /* string ---------------------------------------- */

      // if( string )
      // {
      //   // it's a string, but we're not handling them that way yet
      //   this_turn.pushParsedWord( { type:'string',this_turn.parsed_input_array[position_in_parsed_input] } );
      //   // save it as a string or continue to save it as a noun?
      // }

      /* noun ---------------------------------------- */

      if (noun) {
        // Treat it like a noun. We do more checks later to see
        // if it's unknown, and if it's not we want to soft prompt
        // for "oops"
        this.game.log("log", "high", "parseInput > noun: " + word, "Parser");

        count.noun++;

        this_turn.pushParsedWord({
          type: "noun",
          word: word,
          preposition: null,
          properties: properties,
          adjective: adjective,
        });

        last_word_type = "noun";
        last_word = word;
        continue;
      }

      /* exclusion ---------------------------------------- */

      if (exclusion) {
        // it's an exclusionary noun, like "take all but thing"
        // the last noun will be the one we want to exclude from

        this.game.log(
          "log",
          "high",
          "parseInput > exclude noun: " + word,
          "Parser"
        );

        // remove the leading '-' which has done its job
        word = word.slice(1);

        if (last_word_type === "noun") {
          let l = this_turn.parsed_sentence.length - 1;
          this_turn.parsed_sentence[l].exclusion = word;
        } else {
          // this should not happen
          this_turn.pushParsedWord({
            type: "exclusion",
            word: word,
            properties: properties,
          });
        }
        // END BLOCK

        last_word_type = "exclusion";
        last_word = word;
        continue;
      }

      /* number ---------------------------------------- */

      if (number) {
        // it's a number
        this.game.log("log", "high", "parseInput > number: " + word, "Parser");
        count.number++;
        count.phrase++;
        // store the typed words in their original order
        this_turn.pushParsedWord({
          type: "number",
          word: word,
          properties: properties,
        });

        last_word_type = "number";
        last_word = word;
        continue;
      }

      /* adjective ---------------------------------------- */

      if (adjective) {
        // it's an adjective
        this.game.log(
          "log",
          "high",
          "parseInput > adjective: " + word,
          "Parser"
        );
        count.adjective++;
        this_turn.pushParsedWord({
          type: "adjective",
          word: word,
          properties: properties,
        });

        last_word_type = "adjective";
        last_word = word;
        continue;
      }

      /* unknown ---------------------------------------- */

      // it's unknown
      this.game.log("log", "high", "parseInput > unknown: " + word, "Parser");
      last_word_type = "unknown";
      this_turn.pushParsedWord({
        type: "unknown",
        word: word,
        properties: properties,
      });

      last_word = word;
    } // for position_in_parsed_input loop

    return true;
  }; // parseSentence
})();