Pre-release
Adventure.js Docs Downloads
Score: 0 Moves: 0
// Input.js
(function () {
  /*global adventurejs A*/
  "use strict";

  /**
   * @class adventurejs.Input
   * @ajsinternal
   * @ajsnavheading FrameworkReference
   * @summary Framework class, used as a property of the parser instance, that stores a turn's parsed input.
   * @classdesc
   * <p>
   * <strong>Input</strong> is a special class constructed by
   * {@link adventurejs.Parser#parseInput|Parser.parseInput()},
   * and used to store each turn's input and all of
   * the metadata that is generated for it, including the verb and noun(s)
   * that were parsed, whether a disambiguation was called for,
   * whether a soft prompt was made, whether a noun was assumed
   * based upon context, and other data. This is an internal class
   * that authors should not need to construct.
   * </p>
   */
  class Input {
    constructor(params) {
      this.game_name = params.game_name || "";

      this.game.log("log", "high", "Input.js > new input created", "Parser");

      /**
       * Save the original input string for later reference.
       * @var {String} adventurejs.Input#input
       * @default ""
       */
      this.input = ""; // original input

      /**
       * The end result of parsing is a set of verified words -
       * verbs, nouns and prepositions - which can be used by verbs.
       * @var {Object} adventurejs.Input#verified_sentence
       * @default {}
       */
      this.verified_sentence = {};

      /**
       * Property used by handleWord() to pass data to
       * parseMultipleInputs().
       * @var {Array} adventurejs.Input#parsed_word
       * @default { 'enabled':false }
       */
      this.parsed_word = { enabled: false };

      /**
       * We use this as an intermediary step to store the
       * parsed, typed input before we verify it.
       * @var {Array} adventurejs.Input#parsed_sentence
       * @default []
       */
      this.parsed_sentence = [];

      /**
       * This is a simple representation of the parsed input
       * for comparison purposes. Verbs may have their
       * accepts_structures property set to a list of valid
       * sentence structures. This gives us another way to
       * validate input, by comparing it to a verb's capabilities.
       * @var {Array} adventurejs.Input#verified_sentence_structure
       * @default ""
       */
      this.verified_sentence_structure = "";

      /**
       * Object for managing strings that author appends/overrides/prepends
       * to native output.
       * @var {Object} adventurejs.Input#printer
       * @default {append:[],prepend:[],override:[],appended:[],prepended:[],overridden:[]}
       */
      // this.append_to_next_print = [];
      this.printer = {
        append: [],
        prepend: [],
        override: [],
        appended: [],
        prepended: [],
        overriden: [],
      };

      /**
       * The original unparsed player's input string.
       * @var {String} adventurejs.Input#unparsed_input
       * @default ""
       */
      this.unparsed_input = "";

      /**
       * The parsed version of the player's input string.
       * @var {String} adventurejs.Input#parsed_input
       * @default
       */
      this.parsed_input = "";

      /**
       * Optional string containing a space delimited list of
       * CSS classes to apply to the printed output.
       * @var {String} adventurejs.Input#output_class
       * @default ""
       */
      this.output_class = "";

      /**
       * If player only input one word, store that here,
       * because we parse single words differently from multiple words.
       * @var {String} adventurejs.Input#found_word
       * @default ""
       */
      this.found_word = "";

      /**
       * A string representing the verb that was found in player input.
       * @var {String} adventurejs.Input#input_verb
       * @default ""
       */
      this.input_verb = "";

      /**
       * If parser found an unknown word, store it here.
       * @var {String} adventurejs.Input#unknown_word
       * @default undefined
       */
      this.unknown_word = undefined;

      /**
       * We're making a soft prompt with this turn, asking for clarification of a verb or noun.
       * @var {Boolean} adventurejs.Input#soft_prompt
       * @default { 'verb':null, 'noun1':false, 'noun2':false, 'noun3':false, 'enabled':false, 'satisfied':false }
       */
      this.soft_prompt = {
        verb: null,
        input_verb: null,
        noun1: false,
        noun2: false,
        noun3: false,
        nouns: [],
        preposition1: false,
        preposition2: false,
        preposition3: false,
        prepositions: [],
        enabled: false,
        satisfied: false,
        structure: "",
      };

      /**
       * When we call for disambiguation, we ask for noun1, noun2, or noun3.
       * We save the index here so we can refer to, for ex: "disambiguate["noun"+disambiguate.index].
       * @var {int} adventurejs.Input#disambiguate
       * @default { 'index':null, 'noun1':false, 'noun2':false, 'noun3':false }
       */
      this.disambiguate = {
        index: null,
        noun1: false,
        noun2: false,
        noun3: false,
        enabled: false,
        nouns: [],
      };

      /**
       * It's possible to redirect from one verb to another within a
       * single turn. We save each verb's id in verb_chain, to check
       * that we're not stuck in a circular loop.
       * @var {Array} adventurejs.Input#verb_chain
       * @default []
       */
      this.verb_chain = [];

      /**
       * In some instances we want to allow a verb to be reused, such as
       * when we're redirecting between nouns rather than verbs.
       * @var {Boolean} adventurejs.Input#allow_circular_verb
       * @default false
       * @todo Should this also be an Array and sync indexes with verb_chain?
       */
      this.allow_circular_verb = false;

      /**
       * A method for passing arbitrary properties along with a verb redirect.
       * For ex: close_with may redirect to lock_with, and we may want to pass
       * a param such as "autoClose=true".
       * @var {Object} adventurejs.Input#verb_params
       * @default {}
       */
      this.verb_params = {};

      /**
       * During parsing we replace substrings with other substrings.
       * Here we keep a record of the source substrings.
       * @var {Object} adventurejs.Input#replacements
       * @default {}
       */
      this.replacements = {};

      /**
       * If player inputs quoted strings, we save them here. Ex:
       * 'type "foo" on typewriter', we save "foo" as an unparsed string.
       * @var {Array} adventurejs.Input#strings
       * @default []
       */
      this.strings = [];

      /**
       * During parse we perform regex to join verb phrases.
       * For example, if player inputs
       * "write name on paper with pencil",
       * joinVerbNounPrepNounPrepNouns() would find and join
       * "write_on_with paper pencil".
       * When we do a replacement, we're saving the original
       * string and the original verb. Here we save the fomr
       * of the verb phrase, ie verb_noun_prep_noun_prep_noun,
       * for use in verb logic.
       * @var {Array} adventurejs.Input#joint
       * @default []
       */
      this.joint = "";

      // on startup we want to establish a populated turn before the first turn
      // we're probably just setting it to "wait"
      if (params && params.verb) {
        this.input = params.verb;
        this.found_word = params.verb;
        this.input_verb = params.verb;
        this.parsed_input = params.verb;
        this.unparsed_input = params.verb;
        this.setVerb(params.verb);
      }
    }

    /**
     * Getter function that returns the top level game object. Use <code class="property">this.game</code>.
     * @var {Getter} adventurejs.Input#game
     * @returns {adventurejs.Game}
     */
    get game() {
      return window[this.game_name] || false;
    }

    /**
     * Lets author append an arbitrary string to this turn's output.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#appendToOutput
     * @param {String} msg Arbitrary string to append to next print.
     * @returns {boolean}
     */
    appendToOutput(msg) {
      if ("string" !== typeof msg) return false;
      this.printer.append.push(msg);
      return true;
    }

    /**
     * Lets author override this turn's output.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#overrideOutput
     * @param {String} msg Arbitrary string to override next print.
     * @returns {boolean}
     */
    overrideOutput(msg) {
      if ("string" !== typeof msg) return false;
      this.printer.override.push(msg);
      return true;
    }

    /**
     * Lets author prepend an arbitrary string to this turn's output.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#prependToOutput
     * @param {String} msg Arbitrary string to prepend to next print.
     * @returns {boolean}
     */
    prependToOutput(msg) {
      if ("string" !== typeof msg) return false;
      this.printer.prepend.push(msg);
      return true;
    }

    /**
     * Get verb from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#hasVerb
     * @param {int} index
     * @returns {Object|Boolean}
     */
    hasVerb(index) {
      var bool = false;
      if (!index) index = 1;
      if (this.verified_sentence["verb" + index]) {
        bool = true;
      }
      return bool;
    }

    /**
     * Get verb from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getVerb
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getVerb(index) {
      var verb = false;
      if (!index) index = 1;
      if (this.verified_sentence["verb" + index]) {
        verb = this.verified_sentence["verb" + index].verb;
      }
      return verb;
    }

    /**
     * Get dictionary verb from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getDictionaryVerb
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getDictionaryVerb(index) {
      var verb = false;
      if (!index) index = 1;
      if (this.verified_sentence["verb" + index]) {
        verb = this.verified_sentence["verb" + index].verb;
      }
      verb = this.game.getVerb(verb);
      return verb;
    }

    /**
     * Set the specified verb in the verified sentence.
     * We're only ever taking one verb, but provisioning
     * for more in the future in the case of structures
     * such as "tell person to go north".
     * @method adventurejs.Input#setVerb
     * @param {String} value
     */
    setVerb(index, value) {
      if (!index) index = 1;
      if (!this.verified_sentence["verb" + index]) {
        this.verified_sentence["verb" + index] = {};
      }
      this.verified_sentence["verb" + index].verb = value;
    }

    /**
     * Set the specified phrase in the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setPhrase
     * @param {int} index
     * @param {string} type
     * @param {string} value
     */
    setPhrase(index, phrase) {
      this.verified_sentence["phrase" + index] = A.clone.call(
        this.game,
        phrase,
      );
    }

    /**
     * Delete the specified phrase in the verified sentence
     * and renumber any higher numbered phrases.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#deletePhrase
     * @param {int} index
     */
    deletePhrase(index) {
      if (!this.verified_sentence["phrase" + index]) return;
      delete this.verified_sentence["phrase" + index];
      if (this.getPhraseCount() > index) {
        for (let i = index + 1; i <= this.getPhraseCount(); i++) {
          this.verified_sentence["phrase" + (i - 1)] =
            this.verified_sentence["phrase" + i];
          delete this.verified_sentence["phrase" + i];
        }
      }
      this.resetStructure();
      return true;
    }

    /**
     * Reset the verified sentence structure (after revising verified_sentence).
     * @memberof adventurejs.Input
     * @method adventurejs.Input#resetStructure
     */
    resetStructure(index) {
      this.verified_sentence_structure = "";
      if (this.verified_sentence.verb1?.verb) {
        this.verified_sentence_structure += "verb";
      }
      for (let i = 1; i < 4; i++) {
        let phrase = this.verified_sentence["phrase" + i];
        if (phrase && phrase.preposition)
          this.verified_sentence_structure += " preposition";
        if (phrase && phrase.noun) this.verified_sentence_structure += " noun";
      }
      return true;
    }

    /**
     * Get the specified phrase from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getPhrase
     * @param {int} index
     * @returns {Object}
     */
    getPhrase(index) {
      var phrase = this.verified_sentence["phrase" + index];
      return phrase || {};
    }

    /**
     * Get a count of nouns.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getNounCount
     * @returns {int}
     */
    getNounCount() {
      var count = 0;
      for (var i = 1; i <= 3; i++) {
        if (
          this.verified_sentence["phrase" + i] &&
          (this.verified_sentence["phrase" + i].noun ||
            this.verified_sentence["phrase" + i].parsedNoun)
        ) {
          count++;
        }
      }
      return count;
    }

    /**
     * Does the specified phrase exist in the verified sentence?
     * @memberof adventurejs.Input
     * @method adventurejs.Input#hasPhrase
     * @param {int} index
     * @returns {Boolean}
     */
    hasPhrase(index) {
      if (this.verified_sentence["phrase" + index]) return true;
      return false;
    }

    /**
     * Try to get a noun string from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getNoun
     * @param {int} index
     * @returns {String|Boolean}
     */
    getNoun(index) {
      return this.getInPhrase(index, "noun");
    }

    /**
     * Set a noun string from the verified sentence.
     * Be careful to avoid letting noun and parsedNoun
     * fall out of sync.
     * By contrast, setAsset() will set both noun and
     * parsedNoun.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setNoun
     * @param {int} index
     * @param {String} value
     * @returns {String|Boolean}
     */
    setNoun(index, value) {
      return this.setInPhrase(index, "noun", value);
    }

    /**
     * Try to get an exclusion string from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getExclusion
     * @param {int} index
     * @returns {String|Boolean}
     */
    getExclusion(index) {
      return this.getInPhrase(index, "exclusion");
    }

    /**
     * Set an exclusion string in the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setExclusion
     * @param {int} index
     * @param {String} value
     * @returns {String|Boolean}
     */
    setExclusion(index, value) {
      return this.setInPhrase(index, "exclusion", value);
    }

    /**
     * Try to get an asset from the parsedNoun in the
     * specified phrase in the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getAsset
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getAsset(index) {
      var asset = null;
      var parsedNoun = this.getInPhrase(index, "parsedNoun");

      // qualified_object_id is only available when a singular match is found
      //if(parsedNoun) asset = this.game.getAsset( parsedNoun.qualified_object_id );

      // object_id is available when multiple matches are found
      // it doesn't seem we should want multiple matches here,
      // but some verbs for example "take all keys but blue key"
      // result not only in multiple matches but in stacked input
      // @TODO reexamine this
      if (parsedNoun) asset = this.game.getAsset(parsedNoun.object_id);

      return asset;
    }

    /**
     * Set the asset in the specified phrase. Asset means
     * Asset-classed object, but we store here a ParsedNoun
     * which is its own classed object that includes metadata
     * about the Asset object.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setAsset
     * @param {Int} index
     * @param {Object} parsedNoun
     */
    setAsset(index, asset) {
      if (!this.verified_sentence["phrase" + index]) {
        this.verified_sentence["phrase" + index] = {};
      }
      this.verified_sentence["phrase" + index].parsedNoun =
        new adventurejs.ParsedNoun(asset);
      this.verified_sentence["phrase" + index].noun = asset.id;
    }

    /**
     * When player refers to a substance, some verbs will try
     * to identify a vessel containing that substance.
     * Save that vessel id here.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setVessel
     * @param {Int} index
     * @param {Object} asset
     */
    setVessel(index, asset) {
      if (!this.verified_sentence["phrase" + index]) {
        this.verified_sentence["phrase" + index] = {};
      }
      this.verified_sentence["phrase" + index].vessel = asset.id;
    }

    /**
     * When player refers to a substance, some verbs will try
     * to identify a vessel containing that substance.
     * Get that vessel id. Returns null if not found.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setVessel
     * @param {Int} index
     * @param {Object} asset
     */
    getVessel(index) {
      return this.getInPhrase(index, "vessel");
    }

    /**
     * Create a new phrase at the lowest available phrase number.
     * Assumed is always true.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setNewPhrase
     * @param {Object} params
     * @returns {Int}
     */
    setNewPhrase(params) {
      var index = 1;
      if (this.hasPhrase(1)) index = 2;
      if (this.hasPhrase(2)) index = 3;
      if (this.hasPhrase(3)) index = 4; // @TODO throw error
      this.verified_sentence["phrase" + index] = {};
      if (params.preposition) {
        this.verified_sentence_structure += " preposition";
        this.verified_sentence["phrase" + index].preposition =
          params.preposition;
      }
      if (params.asset) {
        this.verified_sentence_structure += " noun";
        this.verified_sentence["phrase" + index].parsedNoun =
          new adventurejs.ParsedNoun(params.asset);
        this.verified_sentence["phrase" + index].noun = params.asset.id;
      }
      this.verified_sentence["phrase" + index].assumed = true;
      return index;
    }

    /**
     * Get the number of phrases in the input.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getPhraseCount
     */
    getPhraseCount() {
      var index = 0;
      if (this.hasPhrase(1)) index = 1;
      if (this.hasPhrase(2)) index = 2;
      if (this.hasPhrase(3)) index = 3;
      // we don't handle 4 phrases yet, but maybe in future?
      return index;
    }

    /**
     * Try to get a preposition from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getPreposition
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getPreposition(index) {
      return this.getInPhrase(index, "preposition");
    }

    /**
     * Set verified preposition.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setPreposition
     * @param {int} index
     * @param {string} value
     */
    setPreposition(index, value) {
      return this.setInPhrase(index, "preposition", value);
    }

    /**
     * Try to get a direction from the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getDirection
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getDirection(index) {
      return this.getInPhrase(index, "direction");
    }

    /**
     * Set verified direction.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setDirection
     * @param {int} index
     * @param {Object} value
     */
    setDirection(index, value) {
      return this.setInPhrase(index, "direction", value);
    }

    /**
     * Try to get a parsedNoun in the
     * specified phrase in the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getParsedNoun
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getParsedNoun(index) {
      return this.getInPhrase(index, "parsedNoun");
    }

    /**
     * Set a parsedNoun in the
     * specified phrase in the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setParsedNoun
     * @param {int} index
     * @param {Object} parsedNoun
     */
    setParsedNoun(index, parsedNoun) {
      this.setInPhrase(index, "parsedNoun", parsedNoun);
    }

    /**
     * Set a parsedNoun in the
     * specified phrase in the verified sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setParsedNoun
     * @param {int} index
     * @param {Object} parsedNoun
     */
    setParsedNounMatchesQualified(index, value) {
      if (
        this.verified_sentence["phrase" + index] &&
        this.verified_sentence["phrase" + index].parsedNoun
      ) {
        this.verified_sentence["phrase" + index].parsedNoun.matches.qualified =
          value;
      }
    }

    /**
     * Ask if verified noun has been set assumed.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getAssumed
     * @param {int} index
     * @returns {Object|Boolean}
     */
    getAssumed(index) {
      return this.getInPhrase(index, "assumed");
    }

    /**
     * Set verified noun assumed.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setAssumed
     * @param {int} index
     * @returns {Object|Boolean}
     */
    setAssumed(index, value) {
      if (typeof value === "undefined") value = true;
      this.setInPhrase(index, "assumed", value);
    }

    /**
     * Swap two phrases
     * @memberof adventurejs.Input
     * @method adventurejs.Input#swapPhrases
     * @param {int} index1
     * @param {int} index2
     * @returns {Object|Boolean}
     */
    swapPhrases(index1, index2) {
      if (!this.getPhrase(index1)) this[`phrase${index1}`] = {};
      if (!this.getPhrase(index2)) this[`phrase${index2}`] = {};
      var swap1 = A.clone.call(this.game, this.getPhrase(index1));
      var swap2 = A.clone.call(this.game, this.getPhrase(index2));
      this.setPhrase(index1, swap2);
      this.setPhrase(index2, swap1);
    }

    /**
     * Swap two nouns
     * @memberof adventurejs.Input
     * @method adventurejs.Input#swapNouns
     * @param {int} index1
     * @param {int} index2
     * @returns {Object|Boolean}
     */
    swapNouns(index1, index2) {
      var noun1 = String(this.getInPhrase(index1, "noun"));
      var noun2 = String(this.getInPhrase(index2, "noun"));
      var parsedNoun1 = A.clone.call(
        this.game,
        this.getInPhrase(index1, "parsedNoun"),
      );
      var parsedNoun2 = A.clone.call(
        this.game,
        this.getInPhrase(index2, "parsedNoun"),
      );
      this.setInPhrase(index1, "noun", noun2);
      this.setInPhrase(index2, "noun", noun1);
      this.setInPhrase(index1, "parsedNoun", parsedNoun2);
      this.setInPhrase(index2, "parsedNoun", parsedNoun1);
    }

    /**
     * Swap two prepositions
     * @memberof adventurejs.Input
     * @method adventurejs.Input#swapPrepositions
     * @param {int} index1
     * @param {int} index2
     * @returns {Object|Boolean}
     */
    swapPrepositions(index1, index2) {
      var swap1 = String(this.getPreposition(index1));
      var swap2 = String(this.getPreposition(index2));
      this.setPreposition(index1, swap2);
      this.setPreposition(index2, swap1);
    }

    /**
     * Try to get a property from the specified phrase.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getInPhrase
     * @param {String} position
     * @param {String} property
     * @returns {*}
     */
    getInPhrase(index, property) {
      if (
        this.verified_sentence["phrase" + index] &&
        this.verified_sentence["phrase" + index][property]
      ) {
        return this.verified_sentence["phrase" + index][property];
      }
      return null;
    }

    /**
     * Try to get a property from the specified phrase.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setInPhrase
     * @param {String} position
     * @param {String} property
     * @returns {*}
     */
    setInPhrase(index, property, value) {
      if (!this.verified_sentence["phrase" + index]) {
        this.verified_sentence["phrase" + index] = {};
      }
      this.verified_sentence["phrase" + index][property] = value;
    }

    /**
     * Does the input object have verified input?
     * @memberof adventurejs.Input
     * @method adventurejs.Input#hasInput
     * @returns {Boolean}
     */
    hasInput() {
      var bool = Object.keys(this.verified_sentence).length ? true : false;
      return bool;
    }

    /**
     * Set a soft prompt for next turn.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setSoftPrompt
     * @param {Object} params
     */
    setSoftPrompt(params) {
      this.soft_prompt.enabled = true;
      for (var key in params) {
        this.soft_prompt[key] = params[key];
      }
    }

    /**
     * Indicate that this turn parsed one word, which
     * may satisfy a disambiguation prompt.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setOneWord
     * @param {Object} params
     */
    setOneWord(params) {
      console.warn("setOneWord", params);
      this.parsed_word.enabled = true;
      for (var key in params) {
        this.parsed_word[key] = params[key];
      }
    }

    /**
     * Indicate that this turn parsed one word, which
     * may satisfy a disambiguation prompt.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setDisambiguate
     * @param {Object} params
     */
    setDisambiguate(params) {
      this.disambiguate.enabled = true;
      for (var key in params) {
        this.disambiguate[key] = params[key];
      }
    }

    /**
     * Returns the parsed sentence structure.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getStructure
     * @TODO replace with verified sentence structure
     */
    getStructure() {
      return this.verified_sentence_structure;
    }

    /**
     * Set the parsed sentence structure.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#setStructure
     * @TODO replace with verified sentence structure
     */
    setStructure(value) {
      this.verified_sentence_structure = value;
    }

    /**
     * Returns the parsed sentence structure.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#getStructure
     * @param {String} value
     * @returns {boolean}
     * @TODO replace with verified sentence structure
     */
    hasStructure(value) {
      return this.verified_sentence_structure === value;
    }

    /**
     * Push a parsed word to parsed_sentence.
     * @memberof adventurejs.Input
     * @method adventurejs.Input#pushParsedWord
     * @param {Object} params
     */
    pushParsedWord(params) {
      this.parsed_sentence.push(params);
    }

    // TEMPORARY ----------

    /**
     * A bridge between the old and new input systems.
     * @var {Getter|Setter} adventurejs.Input#preposition1
     */
    get preposition1() {
      return this.getInPhrase(1, "preposition");
    }
    set preposition1(value) {
      this.setInPhrase(1, "preposition", value);
    }

    /**
     * A temporary bridge between the old and new input systems.
     * @var {Getter|Setter} adventurejs.Input#preposition2
     */
    get preposition2() {
      return this.getInPhrase(2, "preposition");
    }
    set preposition2(value) {
      this.setInPhrase(2, "preposition", value);
    }

    /**
     * A temporary bridge between the old and new input systems.
     * @var {Getter|Setter} adventurejs.Input#preposition3
     */
    get preposition3() {
      return this.getInPhrase(3, "preposition");
    }
    set preposition3(value) {
      this.setInPhrase(3, "preposition", value);
    }

    /**
     * A bridge between the old and new input systems.
     * A parsed noun object for the first noun found in player input.
     * @var {Getter|Setter} adventurejs.Input#parsedNoun1
     */
    get parsedNoun1() {
      return this.getInPhrase(1, "parsedNoun");
    }
    set parsedNoun1(value) {
      this.setInPhrase(1, "parsedNoun", value);
    }
    /**
     * A bridge between the old and new input systems.
     * @var {Getter|Setter} adventurejs.Input#parsedNoun2
     */
    get parsedNoun2() {
      return this.getInPhrase(2, "parsedNoun");
    }
    set parsedNoun2(value) {
      this.setInPhrase(2, "parsedNoun", value);
    }

    /**
     * A bridge between the old and new input systems.
     * @var {Getter|Setter} adventurejs.Input#parsedNoun3
     */
    get parsedNoun3() {
      return this.getInPhrase(3, "parsedNoun");
    }
    set parsedNoun3(value) {
      this.setInPhrase(3, "parsedNoun", value);
    }

    /**
     * A bridge between the old and new input systems.
     * Player did not input a noun, but we extrapolated one from context.
     * @var {Getter|Setter} adventurejs.Input#parsedNoun1_is_assumed
     */
    get parsedNoun1_is_assumed() {
      return this.getInPhrase(1, "assumed");
    }
    set parsedNoun1_is_assumed(value) {
      this.setInPhrase(1, "assumed", value);
    }

    /**
     * A bridge between the old and new input systems.
     * Player did not input a noun, but we extrapolated one from context.
     * @var {Getter|Setter} adventurejs.Input#parsedNoun2_is_assumed
     */
    get parsedNoun2_is_assumed() {
      return this.getInPhrase(2, "assumed");
    }
    set parsedNoun2_is_assumed(value) {
      this.setInPhrase(2, "assumed", value);
    }

    /**
     * A bridge between the old and new input systems.
     * Player did not input a noun, but we extrapolated one from context.
     * @var {Getter|Setter} adventurejs.Input#parsedNoun3_is_assumed
     */
    get parsedNoun3_is_assumed() {
      return this.getInPhrase(3, "assumed");
    }
    set parsedNoun3_is_assumed(value) {
      this.setInPhrase(3, "assumed", value);
    }

    /**
     * A shortcut method for setting a number of properties on the instance.
     * @memberOf adventurejs.Verb
     * @method adventurejs.Input#set
     * @param {Object} props A generic object containing properties to copy to the DisplayObject instance.
     * @returns {adventurejs.Input} Returns the instance the method is called on (useful for chaining calls.)
     * @chainable
     */
    set(props) {
      return A.deepSet.call(this.game, props, this);
    }
  }

  adventurejs.Input = Input;
})();