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

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

  /**
   * @augments {adventurejs.Verb}
   * @class move
   * @ajsnode game.dictionary.verbs.move
   * @ajsconstruct MyGame.createVerb({ "name": "move", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading ManipulationVerbs
   * @summary Verb meaning move an asset.
   * @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; move sofa north</span>
   * You move the sofa north, into the parlor. Yup, it
   * definitely looks better there against the sunny window.
   * </pre>
   * <p>
   * <strong>Move</strong> a
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset} in a direction.
   * Requires that the Asset has
   * asset.dov.move.enabled set to true.
   * If successful, will move
   * player and Asset to new
   * {@link adventurejs.Room|Room}.
   * </p>
   * @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
   */
  A.Preverbs.move = {
    name: "move",
    prettyname: "move",
    past_tense: "moved",
    synonyms: ["move", "slide"],

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

    /**
     * @memberof move
     * @ajsverbphrase
     * phrase1:
     * {
     *   accepts_noun:true,
     *   requires_noun: true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *   },
     * },
     */
    phrase1: {
      accepts_noun: true,
      requires_noun: true,
      noun_must_be: {
        known: true,
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
      },
    },

    /**
     * @memberof move
     * @ajsverbphrase
     * phrase2:
     * {
     *   accepts_noun:true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *     // direction: true,
     *   },
     *   accepts_preposition: true,
     * },
     */
    phrase2: {
      accepts_noun: true,
      noun_must_be: {
        known: true,
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
      },
      accepts_preposition: true,
    },

    /**
     * @memberof move
     * @ajsverbphrase
     * phrase3:
     * {
     *   // only supports form: move asset from asset to asset
     *   accepts_noun:true,
     *   accepts_preposition: true,
     *   requires_preposition: true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *   },
     * },
     */
    phrase3: {
      accepts_noun: true,
      accepts_preposition: true,
      requires_preposition: true,
      noun_must_be: {
        known: true,
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
      },
    },

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

    doTry: 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 indirect_object2 = input.getAsset(3);
      var indirect_preposition2 = input.getPreposition(3);
      var player = this.game.getPlayer();
      var results;
      var msg = "";

      if (!direct_object.isDOV("move") && !direct_object.isDOV("take")) {
        // if you can take it, you can move it
        this.game.debug(
          `F1351 | move.js | ${direct_object.id}.dov.move.enabled is false `
        );
        msg += `$(We) can't move ${direct_object.articlename}. `;
        this.handleFailure(msg);
        return null;
      }

      if (
        indirect_object &&
        indirect_object.direction &&
        !direct_object.can.push_from_room &&
        !direct_object.isDOV("take")
      ) {
        this.game.debug(
          `F1352 | move.js | ${direct_object.id}.can.push_from_room is false `
        );
        msg += `$(We) can't move ${direct_object.articlename} out of the room. `;
        this.handleFailure(msg);
        return null;
      }

      if (input.hasStructure("verb noun noun")) {
        if (!indirect_object.direction) {
          // player input "move asset asset"
          this.game.debug(
            `F1675 | move.js | ${indirect_object.id} is not direction `
          );
          msg += this.game.parser.getUnparsedMessage(input.input);
          this.handleFailure(msg);
          return null;
        }
      }

      if (input.hasStructure("verb noun preposition noun preposition noun")) {
        // did player input "move a from b to c"?
        if (indirect_preposition === "from" && indirect_preposition2 === "to") {
          // if so swap to/from because we're going to drop from at a later step
          input.swapPhrases(2, 3);
          indirect_preposition = "to";
          indirect_preposition2 = "from";
          indirect_object = input.getAsset(2);
          indirect_object2 = input.getAsset(3);
        }

        if (indirect_preposition !== "to" || indirect_preposition2 !== "from") {
          // we don't handle any other phrases in this structure
          this.game.debug(
            `F1686 | push.js | sentence structure is 'verb noun preposition noun preposition noun' but phrase is not handled`
          );
          msg += this.game.parser.getUnparsedMessage(input.input);
          this.handleFailure(msg);
          return null;
        }

        // is asset at the "from" location?
        if (direct_object.getPlaceAssetId() !== indirect_object2.id) {
          this.game.debug(
            `F1687 | move.js | ${direct_object.id} is not ${indirect_object2.default_aspect} ${indirect_object2.id}`
          );
          msg += `${direct_object.Articlename} is not ${indirect_object2.default_aspect} ${indirect_object2.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        // simplify this down to 'verb noun preposition noun'
        input.setStructure("verb noun preposition noun");
      } // verb noun preposition noun preposition noun

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

        // is prep across, over, or match direct object's position?
        // but not in same place as asset?
        if (
          [direct_object.getPlacePreposition(), "across", "over"].indexOf(
            indirect_preposition
          ) > -1 &&
          direct_object.getPlaceAsset().id !== indirect_object.id
        ) {
          this.game.debug(
            `F1677 | move.js | ${direct_object.id} is not ${indirect_preposition} ${indirect_object.id} `
          );
          msg += `${direct_object.Articlename} is not on ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        } // across over

        // is prep across, over, or match direct object's position?
        // and is in same place as asset?
        if (
          [direct_object.getPlacePreposition(), "across", "over"].indexOf(
            indirect_preposition
          ) > -1 &&
          direct_object.getPlaceAsset().id === indirect_object.id
        ) {
          // ok
        } else if ("off" === indirect_preposition) {
          if (
            "on" !== direct_object.getPlacePreposition() ||
            direct_object.getPlaceAssetId() !== indirect_object.id
          ) {
            this.game.debug(
              `F1678 | move.js | ${direct_object.id} is not on ${indirect_object.id} `
            );
            msg += `${direct_object.Articlename} isn't on ${indirect_object.articlename}. `;
            this.handleFailure(msg);
            return null;
          }
        } // off
        else if ("to" === indirect_preposition) {
          // is player holding direct object and not indirect object?
          // redirect to put
          if (direct_object.isIn(player)) {
            this.game.debug(`F1683 | move.js | infer 'put', doVerb put`);
            input.setPreposition(2, indirect_object.default_aspect);
            this.game.dictionary.doVerb("put");
            return null;
          }

          // is asset already at target?
          if (direct_object.getPlaceAssetId() === indirect_object.id) {
            this.game.debug(
              `F1685 | move.js | ${direct_object.id} is already ${indirect_preposition} ${indirect_object.id} `
            );
            msg += `${
              direct_object.Articlename
            } is already ${direct_object.getPlacePreposition()} ${
              indirect_object.articlename
            }. `;
            this.handleFailure(msg);
            return null;
          }
        } // to
        else if (["toward", "near"].indexOf(indirect_preposition) > -1) {
          // are both things in the same place?
          if (
            direct_object.getPlaceAssetId() !==
            indirect_object.getPlaceAssetId()
          ) {
            this.game.debug(
              `F1682 | move.js | ${direct_object.id} is not in the same place as ${indirect_object.id} `
            );
            msg += `$(We) can't move ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
            this.handleFailure(msg);
            return null;
          }
        } // toward near
        else if (!indirect_object.hasAspectAt(indirect_preposition)) {
          this.game.debug(
            `F1679 | move.js | ${indirect_object.id} has no aspect at ${indirect_preposition} `
          );
          msg += `$(We) can't move ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (
          -1 !== "in on under behind".indexOf(indirect_preposition) &&
          !indirect_object.hasAspectAt(indirect_preposition)
        ) {
          this.game.debug(
            `F1680 | move.js | ${indirect_object.id} has no aspect at ${indirect_preposition} `
          );
          msg += `$(We) can't move anything ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (indirect_object.hasAspectAt(indirect_preposition)) {
          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 results1, results2;

      this.game.debug(`F1684 | move.js | print doSuccess `);

      // parsed sentence structure: verb
      if (input.hasStructure("verb")) {
      }

      // parsed sentence structure: verb noun
      if (input.hasStructure("verb noun")) {
        msg += `$(We) nudge ${direct_object.articlename}. `;
      }

      if (indirect_object && indirect_object.direction) {
        results = this.game.tryTravel(indirect_object.direction, {
          with: [direct_object.id],
        });
        if (A.isFalseOrNull(results)) return results;
        // no msg because tryTravel handled it
      }

      if (input.hasStructure("verb noun noun")) {
      }

      if (input.hasStructure("verb noun preposition noun")) {
        if (
          [direct_object.getPlacePreposition(), "across", "over"].indexOf(
            indirect_preposition
          ) > -1 &&
          direct_object.getPlaceAsset().id === indirect_object.id
        ) {
          msg += `$(We) nudge ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        } // across over
        else if (
          -1 < "in on under behind".indexOf(indirect_preposition) &&
          indirect_object.hasAspectAt(indirect_preposition)
        ) {
          results1 = direct_object
            .getPlaceAsset()
            .onRemoveThatFromThis(direct_object);
          if (!A.isFalseOrNull(results1)) {
            results2 = indirect_object.onMoveThatToThis(
              direct_object,
              "behind"
            );
          }
          if (A.isFalseOrNull(results1) || A.isFalseOrNull(results2)) {
            msg = `$(We're) prevented from moving ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          }
        } // in on under behind
        else if ("off" === indirect_preposition) {
          results1 = indirect_object.onRemoveThatFromThis(direct_object);
          if (!A.isFalseOrNull(results1)) {
            results2 = indirect_object
              .getPlaceAsset()
              .onMoveThatToThis(
                direct_object,
                indirect_object.getPlacePreposition()
              );
          }
          if (A.isFalseOrNull(results1) || A.isFalseOrNull(results2)) {
            msg = `$(We're) prevented from moving ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          } else {
            msg = `$(We) move ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          }
        } // off
        else if ("to" === indirect_preposition) {
          // move one thing to another implies picking it up
          // which means it passes through player
          // this might be overkill, can we skip the player passthrough?
          var oldlocation = direct_object.getPlaceAsset();

          // remove direct object from indirect object
          results = oldlocation.onRemoveThatFromThis(direct_object);
          if ("undefined" !== typeof results) return results;

          // player has to pick this up
          // set direct object's temporary location to player
          results = player.onMoveThatToThis(direct_object);
          if ("undefined" !== typeof results) return results;

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

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

          msg = `$(We) move ${direct_object.articlename} from ${oldlocation.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        } // to
        else if (["toward", "near"].indexOf(indirect_preposition) > -1) {
          // no status changes at the moment
          msg += `$(We) move ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        } // toward near
      } // verb noun preposition noun

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