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

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

  /**
   * @augments {adventurejs.Verb}
   * @class put
   * @ajsnode game.dictionary.verbs.put
   * @ajsconstruct MyGame.createVerb({ "name": "put", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading ManipulationVerbs
   * @summary Verb meaning put, as in 'put sword' or 'put sword in scabbard'.
   * @ajssynonyms put
   * @tutorial Scripting_VerbSubscriptions
   * @tutorial Verbs_VerbAnatomy
   * @tutorial Verbs_VerbProcess
   * @tutorial Verbs_ModifyVerbs
   * @tutorial Verbs_WriteVerbs
   * @classdesc
   * <pre class="display border outline">
   * <span class="input">&gt; put paper behind painting</span>
   * You put the slip of paper on which is written the Illuminati
   * password behind the painted portrait of Grover Cleveland.
   * </pre>
   * <pre class="display border outline">
   * <span class="input">&gt; put sword in stone</span>
   * You put the sword in the stone. The stone begins to glow
   * with a soft purple light. The glow brightens slowly,
   * growing gradually into incandescence. You shield your eyes
   * with your hands. There is a loud WHUMPF followed by cool
   * darkness. You lower your hands. The sword and the stone are gone.
   * </pre>
   * <pre class="display border outline">
   * <span class="input">&gt; put syrup on pancakes</span>
   * You can't put anything on the pancakes.
   *
   * Kidding! The game understands that you actually meant
   * "pour syrup on pancakes". The game is not cruel or dumb
   * or inflexible. The game loves you, and accommodates
   * you, and only wants you to enjoy a healthy nutritious
   * breakfast. You pour some syrup on the pancakes. Mmmm.
   * </pre>
   * <pre class="display border outline">
   * <span class="input">&gt; put lizard under rock</span>
   * You put the lizard back under the hot rock. It wriggles its
   * legs and burrows in contentedly.
   * </pre>
   * <p>
   * <strong>Put</strong> one
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset} behind/in/on/under another Tangible Asset.
   * Requires that the destination Asset has a
   * {@link adventurejs.Aspect|Aspect}
   * there..
   * To learn about Aspects, see
   * <a href="/doc/Tangibles_Aspects.html">How to Use Aspects</a>.
   * </p>
   * @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
   */
  A.Preverbs.put = {
    name: "put",
    prettyname: "put",
    past_tense: "put",
    synonyms: ["put", "place", "set"],
    enqueue_collections: true,

    /**
     * @ajsverbstructures
     * @memberof put
     */
    accepts_structures: [
      "verb noun",
      "verb noun preposition",
      "verb preposition noun",
      "verb noun preposition noun",
    ],

    /**
     * @memberof put
     * @ajsverbphrase
     * phrase1:
     * {
     *   accepts_noun: true,
     *   requires_noun: true,
     *   accepts_plural_noun: true,
     *   noun_must_be:
     *   {
     *     in_inventory: true,
     *     not_worn_if_all: true,
     *     not_nested_inventory_if_all: true,
     *   },
     * },
     */
    phrase1: {
      accepts_noun: true,
      requires_noun: true,
      accepts_plural_noun: true,
      noun_must_be: {
        in_inventory: true,
        not_worn_if_all: true,
        not_nested_inventory_if_all: true,
      },
    },

    /**
     * @memberof put
     * @ajsverbphrase
     * phrase2:
     * {
     *   accepts_noun: true,
     *   noun_must_be:
     *   {
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *     known: true,
     *     not_in_prior_plural: true,
     *   },
     *   accepts_preposition: true,
     *   requires_preposition: true,
     * },
     */
    phrase2: {
      accepts_noun: true,
      noun_must_be: {
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
        known: true,
        not_in_prior_plural: true,
      },
      accepts_preposition: true,
      requires_preposition: true,
    },

    /**
     * @memberof put
     * @ajsverbparams
     * with_params: {},
     */
    with_params: {},

    doTry: function () {
      var input = this.game.getInput();
      var player = this.game.getPlayer();
      var direct_object = input.getAsset(1);
      var indirect_object = input.getAsset(2);
      var direct_preposition = input.getPreposition(1);
      var indirect_preposition = input.getPreposition(2);
      var indirect_aspect;
      var msg = "";
      var results;

      // can be direct object of verb?
      if (!direct_object.isDOV(this.name)) {
        this.game.debug(
          `F1722 | ${this.name}.js | ${direct_object.id}.dov.${this.name}.enabled is unset `
        );
        msg += `${direct_object.Articlename} can't be ${this.past_tense}. `;
        this.handleFailure(msg);
        return null;
      }

      if (input.hasStructure("verb noun")) {
        // we've arrived here without an indirect_object, which is legit,
        // player can "put thing", in which case we just want to drop
        this.game.debug(
          `F1161 | ${this.name}.js | no indirect object, doVerb drop `
        );
        this.game.dictionary.doVerb("drop");
        return null;
      }

      if (input.hasStructure("verb noun preposition")) {
        if (["on", "down"].indexOf(indirect_preposition) > -1) {
          input.setPreposition(1, indirect_preposition);
          input.deletePhrase(2);
          input.setStructure("verb preposition noun");
        } else {
          this.game.debug(
            `F1925 | ${this.name}.js | ${this.name} ${indirect_preposition} not handled `
          );
          msg += `$(We) don't know how to ${this.name} ${direct_object.articlename} ${indirect_preposition}. `;
          this.handleFailure(msg);
          return null;
        }
      }

      if (input.hasStructure("verb preposition noun")) {
        if (direct_preposition === "down") {
          this.game.debug(`F1926 | ${this.name}.js | put down, doVerb drop `);
          this.game.dictionary.doVerb("drop");
          return null;
        }
        if (direct_preposition === "on" && direct_object.isDOV("wear")) {
          this.game.debug(`F1891 | ${this.name}.js | put on, doVerb wear `);
          this.game.dictionary.doVerb("wear");
          return null;
        }
        // @TODO what about "put in key"? prompt for indirect object? assume from context?
        this.game.debug(
          `F1927 | ${this.name}.js | ${this.name} ${direct_preposition} not handled `
        );
        msg += `$(We) don't know how to ${this.name} ${direct_preposition} ${direct_object.articlename}. `;
        this.handleFailure(msg);
        return null;
      }

      if (input.hasStructure("verb noun preposition noun")) {
        if (direct_object === indirect_object) {
          this.game.debug(
            `F1154 | ${this.name}.js | direct_object ${direct_object.id} is indirect_object ${indirect_object.id} `
          );
          msg += `$(We) can't put ${direct_object.articlename} ${indirect_preposition} itself. `;
          this.handleFailure(msg);
          return null;
        }

        if (
          indirect_object instanceof adventurejs.Floor &&
          indirect_preposition === "on"
        ) {
          this.game.debug(
            `F1162 | ${this.name}.js | indirect_object is floor, doVerb drop `
          );
          this.game.dictionary.doVerb("drop");
          return null;
        }

        // in some cases "put on" can mean "attach to"
        // ex "put cap on pen"
        // so see if we can attach these things
        if (
          indirect_preposition === "on" &&
          !indirect_object.hasAspectAt(indirect_preposition) &&
          (direct_object.canBePut("attached", indirect_object) ||
            indirect_object.canBePut("attached", direct_object))
        ) {
          input.setPreposition(2, "attached");
          this.game.debug(
            `F1155 | ${this.name}.js | ${direct_object.id} and ${indirect_object.id} can attach, doVerb attach `
          );
          this.game.dictionary.doVerb("attach");
          return null;
        }

        if (!indirect_object.hasAspectAt(indirect_preposition)) {
          this.game.debug(
            `F1156 | ${this.name}.js | ${indirect_object.id} has no ${indirect_preposition} aspect `
          );
          msg += `$(We) can't put anything ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (
          direct_object.getPlacePreposition() === indirect_preposition &&
          direct_object.getPlaceAssetId() === indirect_object.id
        ) {
          this.game.debug(
            `F1163 | ${this.name}.js | ${indirect_object.id} is ${indirect_preposition} ${indirect_object.id}`
          );
          msg += `${direct_object.Articlename} is already ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (
          "in" === indirect_preposition &&
          indirect_object.isDOV("close") &&
          indirect_object.is.closed
        ) {
          // @TODO automatically open the thing, if context allows it
          this.game.debug(
            `F1157 | ${this.name}.js | ${indirect_object.id}.is.closed `
          );
          msg += `${indirect_object.Articlename} is closed. `;
          this.handleFailure(msg);
          return false;
        }

        results = this.tryToPutThisInThatAspect(
          direct_object,
          indirect_preposition,
          indirect_object
        );
        if (results.fail) {
          msg = results.msg;
          this.handleFailure(msg);
          if (results.end_turn) return false;
          return null;
        }
      } // verb noun preposition noun

      return true;
    },

    doSuccess: function () {
      var input = this.game.getInput();
      var direct_object = input.getAsset(1);
      var indirect_object = input.getAsset(2);
      var indirect_preposition = input.getPreposition(2);
      var player = this.game.getPlayer();
      var msg = "";
      var results;
      var moved = false;

      // sentence structure: verb noun preposition noun
      if (input.hasStructure("verb noun preposition noun")) {
        this.game.debug(`F1164 | ${this.name}.js | doSuccess `);
        msg += `$(We)`;
        if (direct_object.getPlaceAssetId() !== player.id) {
          msg += ` take ${direct_object.articlename} from ${
            direct_object.getPlaceAsset().articlename
          } and `;
          moved = true;
        }
        msg += ` put ${
          moved ? direct_object.pronoun : direct_object.articlename
        } ${indirect_preposition} ${indirect_object.articlename}. `;

        // remove noun1 from player
        results = player.onRemoveThatFromThis(direct_object);
        if ("undefined" !== typeof results) return results;

        // set noun1's new location to noun2
        // add noun1 to noun2's contents
        results = indirect_object.onMoveThatToThis(
          direct_object,
          indirect_preposition
        );
        if ("undefined" !== typeof results) return results;

        if (
          input.parsedNoun1.matches.qualified.length > 1 &&
          -1 === input.output_class.indexOf("concatenate_output")
        ) {
          input.output_class += " concatenate_output";
        }
      }

      // print output
      this.handleSuccess(msg, direct_object);
      return true;
    },
  };
})(); // put