Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// addAssetToLookup.js
(function () {
  /* global adventurejs A */

  var p = adventurejs.Game.prototype;

  /**
   * <strong>addAssetToLookup()</strong> adds an asset's
   * vocabulary to the world lookup table.
   * <br/><br/>
   * Because we're not doing natural language processing
   * and everything is indexed, we want to increase the chances
   * that the parser understands player input that is partial or
   * has words jumbled. We add a lookup entry for every
   * combination of an object's adjectives with its noun(s).
   * For example we have a "green colored pencil", and we want
   * the parser to understand "green pencil" or "colored pencil".
   * If there are other colored pencils, we want the parser to
   * understand "colored pencils". If there are colored pencils
   * in three shades of green, we want the parser to understand
   * "green pencils". We store all of these combinations to the lookup.
   * @method adventurejs.Game#addWordsToLookup
   * @memberOf adventurejs.Game
   * @param {Object} asset
   * @param {Array} words
   * @param {String} type
   */
  p.addAssetToLookup = function Game_addAssetToLookup(asset) {
    let id = "";
    let name = "";
    let names = [];
    let pairs = [];
    let synonyms = [];
    let adjectives = [];
    let group = [];
    let normalized_group = [];
    let proper_name = "";
    let propernames = [];

    if (asset.adjectives) {
      for (let a = 0; a < asset.adjectives.length; a++) {
        let adjective = asset.adjectives[a].trim();
        for (let i = 0; i < asset.singularPluralPairs.length; i++) {
          if ("" === adjective || " " === adjective) {
            continue;
          }
          pairs.push([
            // example: brass lantern
            A.denormalize(`${adjective} ${asset.singularPluralPairs[i][0]}`),
            // example: brass lanterns
            A.denormalize(`${adjective} ${asset.singularPluralPairs[i][1]}`),
          ]);

          // does world_lookup really need serialized entries?
          // pairs.push(
          //   [
          //     // example: brass_lantern
          //     A.normalize( adjective + "_" + asset.singularPluralPairs[i][0] ),
          //     // example: brass_lanterns
          //     A.normalize( adjective + "_" + asset.singularPluralPairs[i][1] )
          //   ]
          // );
        }
      }
    }

    if (asset.singularPluralPairs) {
      asset.singularPluralPairs = asset.singularPluralPairs.concat(pairs);
    }

    // Most objects will be listed in world_lookup.
    // zones are excluded
    if (asset.exclude_from_lookup) {
    } else {
      // There shouldn't be any spaces by this point, but just in case.
      if (asset.id) id = asset.id.toLowerCase().split(" ");
      if (asset.name) name = [asset.name].slice(0);
      if (asset.proper_name) proper_name = [asset.proper_name].slice(0);

      /**
       * By default we add the name, each word of the name
       * and each pair of words in the name.
       * Possibly excessive, but helps catch
       * typos in long names for use with "oops".
       * Can be disabled per asset by setting
       * asset.split_name_for_world_lookup = false.
       */
      if (asset.split_name_for_world_lookup && "string" === typeof asset.name) {
        // add each word of the name
        names = asset.name.toLowerCase().split(" ");
        if (2 <= names.length) {
          for (let i = names.length - 1; i > 0; i--) {
            // add each pair of words in the name
            // ie for "tiny silver key" we add "tiny silver" and "silver key"
            let wordPair = `${names[i - 1]} ${names[i]}`;
            if (-1 === names.indexOf(wordPair)) {
              names.push(wordPair);
            }
          }
          let morenames = asset.name.toLowerCase().split(" ");
          for (let i = morenames.length; i > 1; i--) {
            names.push(morenames.slice(0, i).join(" "));
          }
        }

        propernames = asset.proper_name.toLowerCase().split(" ");
        if (2 <= propernames.length) {
          for (let i = propernames.length - 1; i > 0; i--) {
            // add each pair of words in the propernames
            // ie for "tiny silver key" we add "tiny silver" and "silver key"
            let wordPair = `${propernames[i - 1]} ${propernames[i]}`;
            if (-1 === propernames.indexOf(wordPair)) {
              propernames.push(wordPair);
            }
          }
          let morenames = asset.proper_name.toLowerCase().split(" ");
          for (let i = morenames.length; i > 1; i--) {
            propernames.push(morenames.slice(0, i).join(" "));
          }
        }
      }

      /**
       * We're going to pass these properties through addWordsToLookup which
       * is destructive, so we use copies in order to retain the originals.
       */
      if (asset.synonyms) synonyms = asset.synonyms.slice(0);
      if (asset.adjectives) adjectives = asset.adjectives.slice(0);
      if (asset.group) {
        group = asset.group.slice(0);
        // added this because non-serialized group words
        // were being omitted from lookup
        normalized_group = asset.group.slice(0);
        normalized_group = A.normalizeArray(normalized_group);
      }
      this.game.addWordsToLookup(asset, ["all"], "plural");
      if (id) this.game.addWordsToLookup(asset, id, "id");
      if (name) this.game.addWordsToLookup(asset, name, "name");
      if (names?.length) this.game.addWordsToLookup(asset, names, "name");
      if (synonyms?.length)
        this.game.addWordsToLookup(asset, synonyms, "synonym");
      if (adjectives?.length)
        this.game.addWordsToLookup(asset, adjectives, "adjective");
      if (group?.length) this.game.addWordsToLookup(asset, group, "group");
      if (normalized_group?.length)
        this.game.addWordsToLookup(asset, normalized_group, "group");
      // this.game.addWordsToLookup(asset, serialized_adjectives, "group" );
      if (proper_name)
        this.game.addWordsToLookup(asset, proper_name, "proper_name");
      if (propernames?.length)
        this.game.addWordsToLookup(asset, propernames, "proper_name");

      if (asset.singularPluralPairs?.length) {
        for (let i = 0; i < asset.singularPluralPairs.length; i++) {
          let singular = asset.singularPluralPairs[i][0];
          let plural = asset.singularPluralPairs[i][1];

          // is this unneccessarily indirect?
          this.game.addWordsToLookup(asset, [singular], "singular");
          this.game.addWordsToLookup(asset, [plural], "plural");

          /*
           * Add lookup entry for "all [plural]"
           * which is really the same as just "[plural]"
           * Example:
           *  take keys
           *  take all keys
           * Are the same.
           * And don't add "all all".
           */
          if (false === asset instanceof adventurejs.All) {
            this.game.addWordsToLookup(
              asset,
              [A.denormalize("all " + plural)],
              "plural"
            );
            // does world_lookup really need serialized entries?
            //this.game.addWordsToLookup(asset, [ A.normalize( "all_" + plural ) ], "plural" );
          }

          // i'm not sure the singular needs a reference to the plural
          this.game.world_lookup[singular].plural = plural;

          // the plural word def needs a reference to the singular
          this.game.world_lookup[plural].singular = singular;

          if (false === asset instanceof adventurejs.All) {
            // all plural
            this.game.world_lookup[A.denormalize("all " + plural)].singular =
              singular;
            // does world_lookup really need serialized entries?
            //this.game.world_lookup[ A.normalize( "all_" + plural ) ].singular = singular;
          }
        }
      }
    }

    return this;
  };
})();