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

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

  var p = adventurejs.Parser.prototype;

  /**
   * Handle multi-word input.
   * @memberOf adventurejs.Parser
   * @method adventurejs.Parser#handleSentence
   */
  p.handleSentence = function Parser_handleSentence() {
    this.game.log(
      "L1198",
      "log",
      "high",
      "handleSentence.js > BEGIN",
      "Parser"
    );
    var this_turn = this.input_history[0];
    var last_turn = this.input_history[1];
    var parsed_verb_name = "",
      dictionary_verb = null,
      dictionary_verb_name = "",
      nouns = [],
      containers = [],
      exclusions = [],
      prepositions = [],
      parsedNouns = [],
      count = { phrase: 0 },
      msg = "";

    // --------------------------------------------------
    // parsed one word
    // --------------------------------------------------

    if (this_turn.parsed_word.enabled) {
      // we've arrived here via handleWord and
      // we're probably amending last turn's input
      // so copy that to start with
      this_turn.verified_sentence = A.clone.call(
        this.game,
        last_turn.verified_sentence
      );

      // get verb + nouns from last turn prompt,
      // which may differ from last turn's input
      if (this_turn.parsed_word.verb) {
        this_turn.setVerb(1, this_turn.parsed_word.verb);
      }
      for (let i = 1; i <= 3; i++) {
        if (this_turn.parsed_word[`noun${i}`]) {
          this_turn.setNoun(i, this_turn.parsed_word[`noun${i}`]);
        }
        if (this_turn.parsed_word[`parsedNoun${i}`]) {
          this_turn.setParsedNoun(i, this_turn.parsed_word[`parsedNoun${i}`]);
        }
        if (this_turn.parsed_word[`container${i}`]) {
          this_turn.setContainer(i, this_turn.parsed_word[`container${i}`]);
        }
        if (this_turn.parsed_word[`preposition${i}`]) {
          this_turn.setPreposition(i, this_turn.parsed_word[`preposition${i}`]);
        }
      }
    } // parsed_word

    // --------------------------------------------------
    // get verb and nouns
    // --------------------------------------------------

    if (this_turn.hasInput()) {
      // we've got fresh input from parseInput
      if (this_turn.hasVerb()) {
        parsed_verb_name = this_turn.getVerb();
      }

      for (let i = 1; i <= 3; i++) {
        if (this_turn.hasPhrase(i)) {
          prepositions[i] = this_turn.getPreposition(i);
          nouns[i] = this_turn.getNoun(i);
          containers[i] = this_turn.getContainer(i);
          exclusions[i] = this_turn.getExclusion(i);
        }
      }
    } else {
      // we shouldn't arrive here but may need an error message
      this.game.debug(`D1207 | handleSentence.js | didn't receive words `);
      msg += this.getUnparsedMessage(this_turn.input);
      this.game.print(msg, this_turn.output_class);
    }

    // --------------------------------------------------
    // oops
    // --------------------------------------------------

    if ("oops " === this_turn.input.substring(0, 5)) {
      this.game.printInput(this_turn.input);
      return this.game.dictionary.doVerb("oops");
    }

    // --------------------------------------------------
    // verify verb
    // --------------------------------------------------

    if (!parsed_verb_name || !this.dictionary.verbs[parsed_verb_name]) {
      // if no verb, did we get a two-word response to a soft prompt?
      if (
        this_turn.verified_sentence_structure === "preposition noun" &&
        last_turn.soft_prompt.enabled
      ) {
        for (let i = 1; i <= 3; i++) {
          if (
            last_turn.soft_prompt[`noun${i}`] &&
            last_turn.soft_prompt[`preposition${i}`]
          ) {
            let new_phrase = Object.assign(
              {},
              this_turn.verified_sentence.phrase1
            );
            this_turn.verified_sentence = A.clone.call(
              this.game,
              last_turn.verified_sentence
            );
            this_turn.setPhrase(i, new_phrase);
            this_turn.verified_sentence_structure =
              last_turn.soft_prompt.structure ||
              last_turn.verified_sentence_structure;
            parsed_verb_name = this_turn.getVerb();
          }
        }
      }
    }

    // check for a verb again
    if (!parsed_verb_name || !this.dictionary.verbs[parsed_verb_name]) {
      let err = `parser.handleSentence > Verb not found. This may happen if a compound phrase is improperly found. Original input: ${this_turn.input} Parsed input: ${this_turn.parsed_input}`;
      this.game.log("L1199", "warn", "high", err, "Parser");
      this.game.debug(
        `D1721 | handleSentence.js | verb not found. Check the console for more info. `
      );
      msg += this.getUnparsedMessage(this_turn.input);
      this.game.print(msg, this_turn.output_class);
      return false;
    }

    // if verb.let_verb_handle_remaining_input, bypass handleSentence
    // originally used for oops and left in for future cases

    if (
      this.dictionary.verbs[parsed_verb_name].let_verb_handle_remaining_input
    ) {
      this.dictionary.doVerb(parsed_verb_name);
      return false;
    }

    // --------------------------------------------------
    // qualify verb
    // --------------------------------------------------

    // Check verb against circumstances that prevent its use,
    // such as if player is constrained, lying on the floor, etc.

    dictionary_verb = this.qualifyParsedVerb({
      parsed_verb_name: parsed_verb_name,
    });
    // If qualifyParsedVerb returned false, then it already
    // printed an error msg to the player, so we can just...
    if (!dictionary_verb) return false;

    // --------------------------------------------------
    // get phrase count
    // --------------------------------------------------

    for (const key in this_turn.verified_sentence) {
      if (key.startsWith("phrase")) {
        count.phrase++;
      }
    }

    // --------------------------------------------------
    // for each phrase
    // --------------------------------------------------

    for (let n = 1; n <= count.phrase; n++) {
      var phrase = this_turn.verified_sentence[`phrase${n}`];
      var noun = phrase.noun;
      var preposition = phrase.preposition;
      var exclusion = phrase.exclusion;

      this.game.log(
        "L1200",
        "log",
        "high",
        `parser.handleSentence > handle phrase ${n}`,
        "Parser"
      );

      // this shouldn't happen
      if (!noun && !preposition) {
        this.game.debug(
          `D1034 | handleSentence.js | ${dictionary_verb.name} didn't receive a noun or preposition`
        );
        msg += `How did $(we) want to ${this_turn.input}? `;
        this.game.print(msg, this_turn.output_class);
        return false;
      }

      // --------------------------------------------------
      // unsupported noun?
      // --------------------------------------------------

      if (noun && !dictionary_verb[`phrase${n}`].accepts_noun) {
        this.game.debug(
          `D2018 | handleSentence.js | ${dictionary_verb.name} received a noun it can't handle`
        );
        msg += this.getUnparsedMessage(this_turn.input);
        this.game.print(msg, this_turn.output_class);
        return false;
      }

      // --------------------------------------------------
      // unsupported preposition without noun?
      // --------------------------------------------------

      if (
        preposition &&
        !noun &&
        !dictionary_verb[`phrase${n}`].accepts_preposition_without_noun
      ) {
        this.game.debug(
          `D1033 | handleSentence.js | ${dictionary_verb.name} received preposition without noun, soft prompt noun${n}`
        );
        msg += `What would $(we) like to ${this_turn.input}? `;
        this_turn.setSoftPrompt({
          index: n,
          type: "noun",
          [`noun${n}`]: true,
          verb: this_turn.input_verb,
          verb_phrase: this_turn.verb_phrase,
        });
        this.game.print(msg, this_turn.output_class);
        return false;
      }

      // --------------------------------------------------
      // noun
      // --------------------------------------------------

      if (noun) {
        // --------------------------------------------------
        // plural
        // --------------------------------------------------

        // "this and that" is parsed as "this&that"
        let split_noun = noun.split("&");

        // "all keys" might be parsed as "key=keya,keyb,keyc"
        // we deliberately do not handle that here as
        // it conflicts with a later disambiguation handler

        let noun_is_plural = "all" === noun || split_noun.length > 1;

        if (
          noun_is_plural &&
          !dictionary_verb[`phrase${n}`].accepts_plural_noun
        ) {
          this.game.debug(
            `D1032 | handleSentence.js | ${dictionary_verb.name}.phrase${n}.accepts_plural_noun is false`
          );
          msg += `$(We) can't ${dictionary_verb.prettyname} more than one thing at a time. `;
          this.game.print(msg, this_turn.output_class);
          return false;
        }

        // Split noun string and queue verb-noun inputs for each item
        if (split_noun.length > 1) {
          for (let i = 1; i < split_noun.length; i++) {
            this.input_queue.push({
              input: this_turn.parsed_input.replace(noun, split_noun[i]),
              printInput: false,
            });
          }
          noun = split_noun[0];
        } // plural

        // write a parsedNoun back to the phrase
        // it's possible that one was already set by a disambiguation
        // so check for existing
        if (!phrase.parsedNoun) phrase.parsedNoun = this.parseNoun(noun);
      } // noun

      // --------------------------------------------------
      // unsupported noun without preposition?
      // --------------------------------------------------

      if (
        noun &&
        !preposition &&
        dictionary_verb[`phrase${n}`].requires_preposition
      ) {
        this.game.debug(
          `D1041 | handleSentence.js | ${dictionary_verb.name} received noun without preposition, soft prompt preposition${n}`
        );
        // msg += `How did $(we) want to ${this_turn.input_verb} ${phrase.noun}? `;
        switch (n) {
          case 1:
            msg += `Where in relation to ${
              this.game.getAsset(
                this_turn.verified_sentence.phrase1.parsedNoun.object_id
              ).articlename
            } did $(we) want to ${dictionary_verb.prettyname}? `;
            break;
          case 2:
            msg += `Where in relation to ${
              this.game.getAsset(
                this_turn.verified_sentence.phrase2.parsedNoun.object_id
              ).articlename
            } did $(we) want to ${dictionary_verb.prettyname} ${
              this.game.getAsset(
                this_turn.verified_sentence.phrase1.parsedNoun.object_id
              ).articlename
            }? `;
            break;
          case 3:
            msg += `That seems to be missing a preposition. Can $(we) try phrasing that another way? `;
            break;
        }

        this_turn.setSoftPrompt({
          index: 2,
          type: "preposition",
          [`preposition${n}`]: true,
          verb: this_turn.input_verb,
          verb_phrase: this_turn.verb_phrase,
        });
        this.game.print(msg, this_turn.output_class);
        return false;
      }

      // --------------------------------------------------
      // unsupported preposition?
      // --------------------------------------------------

      if (
        preposition &&
        dictionary_verb[`phrase${n}`].accepts_these_prepositions.length &&
        -1 ===
          dictionary_verb[`phrase${n}`].accepts_these_prepositions.indexOf(
            preposition
          )
      ) {
        this.game.debug(
          `D1222 | handleSentence.js | ${
            dictionary_verb.name
          }.phrase${n}.accepts_these_prepositions: ${dictionary_verb[
            `phrase${n}`
          ].accepts_these_prepositions.join(", ")}`
        );
        msg += `$(We) don't seem to know how to ${
          dictionary_verb.name
        } anything ${preposition} ${noun ? noun : ""}. `;
        this.game.print(msg, this_turn.output_class);
        return false;
      }

      // --------------------------------------------------
      // parsedNoun empty?
      // --------------------------------------------------

      if (phrase.parsedNoun && !phrase.parsedNoun.matches.all.length) {
        this.game.log(
          "L1201",
          "log",
          "high",
          [
            "handleSentence.js > input: " +
              this_turn.input +
              `, phrase${n}.parsedNoun: `,
            phrase.parsedNoun,
          ],
          "Parser"
        );

        // save record for "oops"
        this_turn.unknown_word = noun;

        this.game.debug(
          `D1035 | handleSentence.js | ${noun} isn't recognized `
        );

        // can we return the original string?
        if (this_turn.replacements[noun]) {
          msg += `$(We) don't know of any ${this_turn.replacements[noun].source}. `;
        }
        // does the unrecognized input match a class name?
        else if (adventurejs[A.propercase(noun)]) {
          msg += `$(We) don't know of any ${noun}. `;
        }
        // as last resort use if_parser_has_no_response_print_this
        else {
          msg += this.getUnparsedMessage(this_turn.unparsed_input);
        }

        this.game.print(msg, this_turn.output_class);
        return false;
      } // parsedNoun
      this.game.log(
        "L1202",
        "log",
        "medium",
        [`handleSentence.js > phrase${n}.parsedNoun:`, phrase.parsedNoun],
        "Parser"
      );

      // --------------------------------------------------
      // in means on?
      // --------------------------------------------------

      // Replace 'in' with 'on' where applicable such as 'sit in chair'
      if (phrase.parsedNoun && !dictionary_verb[`phrase${n}`].accepts_noun) {
        this.game.debug(
          `D1036 | handleSentence.js | ${dictionary_verb.name} received a noun it can't handle`
        );
        msg += this.getUnparsedMessage(this_turn.input);
        this.game.print(msg, this_turn.output_class);
        return false;
      }
      if (
        phrase.parsedNoun &&
        "in" === preposition &&
        this.game.getAsset(phrase.parsedNoun.object_id).quirks.in_means_on &&
        dictionary_verb.in_can_mean_on
      ) {
        this_turn.setInPhrase(n, "preposition", "on");
      }

      // --------------------------------------------------
      // exclusion (aka but)
      // --------------------------------------------------

      // examples of exclusions:
      //  "take all but sword"
      //  "take all gems but green gem"
      //  "take all gems but green gem and blue gem"

      if (exclusion && "string" === typeof exclusion) {
        var exclusion_split = exclusion.split("&");

        for (let x = 0; x < exclusion_split.length; x++) {
          var excluded_noun = exclusion_split[x];
          var excluded_parsed_noun = this.parseNoun(excluded_noun);

          this.game.log(
            "L1203",
            "log",
            "medium",
            ["handleSentence.js > Exclude:", excluded_parsed_noun],
            "Parser"
          );

          if (excluded_parsed_noun) {
            for (let i = 0; i < excluded_parsed_noun.matches.all.length; i++) {
              let excluded_id = excluded_parsed_noun.matches.all[i];
              // remove excluded_id from parsedNoun.matches.all
              phrase.parsedNoun.matches.all.splice(
                phrase.parsedNoun.matches.all.indexOf(excluded_id),
                1
              );
              // remove excluded_id from parsedNoun.matches.qualified
              phrase.parsedNoun.matches.qualified.splice(
                phrase.parsedNoun.matches.qualified.indexOf(excluded_id),
                1
              );
              // remove excluded_id from parsedNoun.matches.unambiguous
              if (phrase.parsedNoun.matches.unambiguous === excluded_id)
                phrase.parsedNoun.matches.unambiguous = "";
            } // for excluded_parsed_noun.matches.all
          } // excluded_parsed_noun
        } // for exclusion_split

        this.game.log(
          "L1204",
          "log",
          "medium",
          [
            `handleSentence.js > phrase${n}.parsedNoun minus exclusions: `,
            phrase.parsedNoun,
          ],
          "Parser"
        );
      } // exclusion

      // --------------------------------------------------
      // exclude from prior
      // --------------------------------------------------

      if (n > 1) {
        let first_phrase = this_turn.getPhrase(1);
        let last_split_noun = [];
        last_split_noun = first_phrase.noun && first_phrase.noun.split("&");
        let last_noun_is_plural =
          first_phrase.noun === "all" || last_split_noun.length > 1;
        let exclude_from_plural =
          dictionary_verb[`phrase${n}`].not_in_prior_plural;
        if (last_noun_is_plural && exclude_from_plural) {
          // was there an unambiguous match for this?
          if (phrase.parsedNoun.matches.unambiguous) {
            // remove unambiguous from prior noun's matches
            let excluded_id = phrase.parsedNoun.matches.unambiguous;
            let allindex =
              first_phrase.parsedNoun.matches.all.indexOf(excluded_id);
            let qualindex =
              first_phrase.parsedNoun.matches.qualified.indexOf(excluded_id);
            // remove excluded_id from parsedNoun.matches.all
            first_phrase.parsedNoun.matches.all.splice(allindex, 1);
            // remove excluded_id from parsedNoun.matches.qualified
            first_phrase.parsedNoun.matches.qualified.splice(qualindex, 1);
            // remove excluded_id from parsedNoun.matches.unambiguous
            if (first_phrase.parsedNoun.matches.unambiguous === excluded_id)
              first_phrase.parsedNoun.matches.unambiguous = "";
            if (allindex > -1 || qualindex > -1) {
              // we might need to re-qualify the last noun
              if (first_phrase.parsedNoun) {
                first_phrase.parsedNoun = this.qualifyParsedNoun({
                  parsedNoun: first_phrase.parsedNoun,
                  parsedVerb: dictionary_verb.name,
                  nounIndex: n - 1,
                });
                // If qualifyParsedNoun returned false, then it already
                // printed an error msg to the player, so we can just...
                if (!phrase.parsedNoun) return false;
              }
            }
          }
        }

        // remove iobj from dobj collection ----------
        // @TODO reexamine - this seems like it should be caught in prior block
        if (
          phrase.parsedNoun &&
          phrase.parsedNoun.object_id &&
          first_phrase.parsedNoun.object_id &&
          first_phrase.parsedNoun.matches.qualified.length > 1
        ) {
          for (
            var i = first_phrase.parsedNoun.matches.qualified.length - 1;
            i > -1;
            i--
          ) {
            if (
              phrase.parsedNoun.qualified_object_id ===
              first_phrase.parsedNoun.matches.qualified[i]
            ) {
              first_phrase.parsedNoun.matches.qualified.splice(i, 1);
            }
          }
        } // remove iobj from dobj collection
      } // n>1 / exclude from prior

      // --------------------------------------------------
      // qualify noun
      // --------------------------------------------------

      if (phrase.parsedNoun) {
        phrase.parsedNoun = this.qualifyParsedNoun({
          parsedNoun: phrase.parsedNoun,
          parsedVerb: dictionary_verb.name,
          nounIndex: n,
        });
        // If qualifyParsedNoun returned false, then it already
        // printed an error msg to the player, so we can just...
        if (!phrase.parsedNoun) return false;
      }

      // --------------------------------------------------
      // redirectVerb
      // --------------------------------------------------

      // Has author used redirectVerb for this verb on direct_object?
      if (
        n === 1 &&
        phrase.parsedNoun &&
        phrase.parsedNoun.qualified_object_id
      ) {
        let direct_object = this.game.getAsset(
          phrase.parsedNoun.qualified_object_id
        );
        if (direct_object.redirected_verbs[dictionary_verb.name]) {
          // requalify verb
          dictionary_verb = this.qualifyParsedVerb({
            parsed_verb_name:
              direct_object.redirected_verbs[dictionary_verb_name],
          });
          if (!dictionary_verb) return false;
        }
      } // redirectVerb
    } // for each phrase

    // --------------------------------------------------
    // each phrase redux
    // --------------------------------------------------

    // I think this is reiterating to account for changes made during the first pass
    for (let n = 1; n <= count.phrase; n++) {
      var phrase = this_turn.verified_sentence[`phrase${n}`];
      var parsedNoun = phrase.parsedNoun;
      if (!parsedNoun) continue;

      this.game.log(
        "L1205",
        "log",
        "high",
        `handleSentence.js > final check on phrase ${n}`,
        "Parser"
      );

      if (parsedNoun.matches.qualified.length > 1) {
        var lookup = this.game.world_lookup[parsedNoun.serialized_input];
        var is_plural = false;
        if (1 < parsedNoun.original_input.split("&").length) {
          is_plural = true;
        }
        if (lookup) {
          if ("plural" === lookup.type || "group" === lookup.type) {
            is_plural = true;
          }
        }

        if (is_plural) {
          if (!dictionary_verb[`phrase${n}`].accepts_plural_noun) {
            // verb doesn't accept a plural noun

            // can we exclude any for not being dov?
            let q = parsedNoun.matches.qualified.slice();
            for (let index = q.length - 1; index > -1; index--) {
              let qid = q[index];
              let qasset = this.game.getAsset(qid);
              if (!qasset.isDOV(dictionary_verb.name)) {
                q.splice(index, 1);
              }
            }
            if (q.length === 1) {
              parsedNoun.matches.qualified = q.slice();
            }

            // ask again
            if (parsedNoun.matches.qualified.length > 1) {
              this.game.debug(
                `D1202 | handleSentence.js | ${dictionary_verb.name} doesn't handle multiple objects `
              );
              this.game.log(
                "L1206",
                "warn",
                "high",
                "handleSentence.js > " +
                  dictionary_verb.name +
                  " doesn't handle multiple objecs: " +
                  parsedNoun.original_input,
                "Parser"
              );
              this.printNounDisambiguation({
                parsedNoun: parsedNoun,
                nounIndex: n,
              });
              return false;
            }
          }
        } // is_plural

        // we found multiple assets, meaning, parsedNoun.matches.qualified.length > 1
        // but verb doesn't handle plurals
        if (!is_plural && !dictionary_verb.let_verb_handle_disambiguation) {
          if (parsedNoun.matches.substance) {
            this.game.debug(
              `D1447 | handleSentence.js | phrase${n}.parsedNoun found multiple substance containers `
            );
            let found = false;

            if (this.game.settings.disambiguation_considers_last_turn) {
              // did last turn refer to a container of this substance?
              // if so infer that container
              for (
                let phrase = 1;
                phrase < last_turn.getPhraseCount();
                phrase++
              ) {
                let last_turn_asset = last_turn.getAsset(phrase);
                if (last_turn_asset.contains === parsedNoun.matches.substance) {
                  // asset contains substance but is it one of the qualified matches?
                  for (
                    let container = 0;
                    container < parsedNoun.matches.qualified.length;
                    container++
                  ) {
                    let match = parsedNoun.matches.qualified[container];
                    let asset = this.game.getAsset(match);
                    if (asset.id === last_turn_asset.id) {
                      parsedNoun.matches.qualified = [match];
                      parsedNoun.qualified_object_id = match;
                      found = true;
                    }
                  }
                }
              }
            }

            // prefer reservoir?
            if (
              !found &&
              this.game.settings.infer_containers_prefers_reservoir
            ) {
              for (
                let container = 0;
                container < parsedNoun.matches.qualified.length;
                container++
              ) {
                let match = parsedNoun.matches.qualified[container];
                let asset = this.game.getAsset(match);
                if (asset.$is("reservoir")) {
                  parsedNoun.matches.qualified = [match];
                  //parsedNoun.matches.qualifiedIndex = container;
                  parsedNoun.qualified_object_id = match;
                }
              }
            }

            // automatically pick?
            if (!found && parsedNoun.matches.qualified.length > 1) {
              if (this.game.settings.infer_containers_automatically_picks) {
                parsedNoun.matches.qualified = [
                  parsedNoun.matches.qualified[0],
                ];
              }
            }
          } // parsedNoun.matches.substance

          // prefer_present_if_ambiguous?
          // for verbs like "go to asset" where we can handle a non-present
          // asset but prefer a present asset if there's ambiguity
          else if (
            dictionary_verb[`phrase${n}`].noun_must_be
              .prefer_present_if_ambiguous
          ) {
            let present_assets = [];
            for (
              let qualified = 0;
              qualified < parsedNoun.matches.qualified.length;
              qualified++
            ) {
              let match = parsedNoun.matches.qualified[qualified];
              let asset = this.game.getAsset(match);
              if (asset.$is("present")) {
                present_assets.push(match);
              }
            }
            if (present_assets.length === 1) {
              parsedNoun.matches.qualified = present_assets;
              //parsedNoun.matches.qualifiedIndex = qualified;
              parsedNoun.qualified_object_id = present_assets[0];
            }
          } // prefer_present_if_ambiguous

          // ask this again now
          if (parsedNoun.matches.qualified.length > 1) {
            this.game.debug(
              `D1201 | handleSentence.js | phrase${n}.parsedNoun needs disambiguation `
            );
            this.game.log(
              "L1207",
              "log",
              "high",
              "handleSentence.js > parsedNoun" +
                n +
                " needs disambiguation: " +
                parsedNoun.matches.qualified,
              "Parser"
            );

            let found = false;
            if (this.game.settings.disambiguation_considers_last_turn) {
              // did last turn's input refer to an asset that could resolve
              // this ambiguity? if so infer that asset
              for (
                let phrase = 1;
                phrase < last_turn.getPhraseCount();
                phrase++
              ) {
                let last_turn_asset = last_turn.getAsset(phrase);
                if (parsedNoun.matches.qualified.includes(last_turn_asset.id)) {
                  this.game.debug(
                    `D1589 | handleSentence.js | disambiguation defaulting to last turn's ${last_turn_asset.name}`
                  );
                  parsedNoun.matches.qualified = [last_turn_asset.id];
                  parsedNoun.qualified_object_id = last_turn_asset.id;
                  found = true;
                }
              }
            }

            if (!found) {
              this.printNounDisambiguation({
                parsedNoun: parsedNoun,
                nounIndex: n,
              });
              return false;
            }
          }
        }
      } // more than one qualified
    } // each phrase redux

    // --------------------------------------------------
    // do the thing!
    // --------------------------------------------------

    this.game.log("L1208", "log", "high", "handleSentence.js > END", "Parser");
    let direct_object = this_turn.getAsset(1);
    if (direct_object?.is.collection && dictionary_verb.enqueue_collections) {
      this.game.debug(
        `D1091 | handleSentence.js | ${
          this_turn.getAsset(1).name
        }.is.collection, enqueueing collection`
      );
      this.game.print(msg);
      dictionary_verb.enqueueCollection(direct_object);
    } else {
      this.game.log(
        "L1209",
        "log",
        "high",
        `handleSentence.js > doVerb ${dictionary_verb.name}`,
        "Parser"
      );
      return dictionary_verb.do();
    }

    return true;
  }; // handleSentence
})();