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

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

  /**
   * @augments {adventurejs.Verb}
   * @class push
   * @ajsnode game.dictionary.verbs.push
   * @ajsconstruct MyGame.createVerb({ "name": "push", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading ManipulationVerbs
   * @summary Verb meaning push an asset.
   * @ajssynonyms shove, push
   * @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; push builder</span>
   * You push the builder up the hill. He complains loudly.
   * "Hey! Whatsamatta you?!? Is you a'crazy?" He rolls back
   * down the hill and resumes the very important building
   * project that you interrupted. Meanwhile, a deformed
   * buzzard has landed on you. It begins plucking out your
   * intestines. "You don't mind, do ya chum? My momma don'tol'
   * me, bring something for dinner." Gruesome, isn't it?
   * Really makes you wish you had spellcheck.
   * </pre>
   * <p>
   * <strong>Push</strong> a
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset}.
   * Requires that the Asset has
   * asset.dov.push.enabled set to true.
   * By default, no special results will occur.
   * Authors wanting to make use of it may need to use a method such
   * as verb hooks. See
   * <a href="/doc/Scripting_VerbPhases.html">Verb Phases</a>
   * to learn more.
   * </p>
   * @ajsverbreactions
   * @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
   */
  A.Preverbs.push = {
    name: "push",
    prettyname: "push",
    past_tense: "pushed",
    synonyms: ["push", "shove"],
    gerund: "pushing",

    /**
     * @ajsverbstructures
     * @memberof push
     */
    accepts_structures: [
      "verb noun", // ie 'push boulder'
      "verb noun noun", // ie 'push boulder north'
      "verb noun preposition noun", // ie 'push boulder over hill'
      "verb noun preposition noun preposition noun", // ie 'push boulder from dingle to hill'
    ],

    /**
     * @memberof push
     * @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 push
     * @ajsverbphrase
     * phrase2:
     * {
     *   accepts_noun:true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: 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 push
     * @ajsverbphrase
     * phrase3:
     * {
     *   // only supports form: push asset from asset to asset
     *   accepts_noun:true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *   },
     *   accepts_preposition: true,
     *   requires_preposition: true,
     * },
     */
    phrase3: {
      accepts_noun: true,
      noun_must_be: {
        known: true,
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
      },
      accepts_preposition: true,
      requires_preposition: true,
    },

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

    doTry: function () {
      var input = this.game.getInput();
      var verb_phrase = input.verb_phrase;
      var direct_object = input.getAsset(1);
      var direct_preposition = input.getPreposition(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.hasQuirk("push_means_press") &&
        direct_object.isDOV("press")
      ) {
        this.game.debug(
          `D2029 | ${this.name}.js | ${direct_object.id}.quirks.push_means_press is true, doVerb press `
        );
        return this.game.dictionary.doVerb("press");
      }

      if (
        direct_object.hasQuirk("push_means_toggle") &&
        direct_object.isDOV("toggle")
      ) {
        this.game.debug(
          `D2043 | ${this.name}.js | ${direct_object.id}.quirks.push_means_toggle is true, doVerb toggle `
        );
        return this.game.dictionary.doVerb("toggle");
      }

      if (!direct_object.isDOV(this.name)) {
        this.game.debug(
          `D1384 | ${this.name}.js | ${direct_object.id}.dov.${this.name} is unset `
        );
        msg += `${direct_object.Articlename} can't be ${this.past_tense}. `;
        this.handleFailure(msg);
        return null;
      }

      if (
        indirect_object &&
        indirect_object.direction &&
        !direct_object.can.move_between_rooms &&
        !direct_object.isDOV("take")
      ) {
        this.game.debug(
          `D1386 | ${this.name}.js | ${direct_object.id}.can.move_between_rooms is false `
        );
        msg += `$(We) try to ${this.name} ${direct_object.articlename} ${
          indirect_object.direction
        }, but ${direct_object.getPronoun("we're")} not going anywhere. `;
        this.handleFailure(msg);
        return null;
      }

      // sentence structure: verb noun noun
      // ex: push chair north
      if (input.hasStructure("verb noun noun")) {
        if (!indirect_object.direction) {
          this.game.debug(
            `D1385 | ${this.name}.js | ${indirect_object.id} is not direction `
          );
          msg += this.game.parser.getUnparsedMessage(input.getInput());
          this.handleFailure(msg);
          return null;
        }
      } // verb noun noun

      // sentence structure: verb noun preposition noun preposition noun
      // ex: push a from b to c
      if (input.hasStructure("verb noun preposition noun preposition noun")) {
        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(
            `D1688 | ${this.name}.js | sentence structure is 'verb noun preposition noun preposition noun' but phrase is not handled`
          );
          msg += this.game.parser.getUnparsedMessage(input.getInput());
          this.handleFailure(msg);
          return null;
        }

        // is asset at the "from" location?
        if (direct_object.getPlaceAssetId() !== indirect_object2.id) {
          this.game.debug(
            `D1689 | ${this.name}.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

      // sentence structure: verb noun preposition noun
      // ex: push pram across lawn
      if (input.hasStructure("verb noun preposition noun")) {
        if (direct_object === indirect_object) {
          this.game.debug(
            `D1673 | ${this.name}.js | direct_object ${direct_object.id} is indirect_object ${indirect_object.id} `
          );
          msg += `$(We) can't ${this.name} ${direct_object.articlename} ${indirect_preposition} itself. `;
          this.handleFailure(msg);
          return null;
        }

        // if( [direct_object.getPlacePreposition(), "across", "over"].includes( indirect_preposition )
        // && direct_object.getPlaceAsset().id === indirect_object.id )
        // {
        //   this.game.debug(` | ${this.name}.js | ${direct_object.id} is ${indirect_preposition} ${indirect_object.id} `);
        //   msg += `$(We) ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        //   this.handleFailure(msg);
        //   return null;
        // }

        if (
          [direct_object.getPlacePreposition(), "across", "over"].includes(
            indirect_preposition
          ) &&
          direct_object.getPlaceAsset().id !== indirect_object.id
        ) {
          this.game.debug(
            `D1674 | ${this.name}.js | ${direct_object.id} is not ${indirect_preposition} ${indirect_object.id} `
          );
          msg += `$(We) can't ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (
          [direct_object.getPlacePreposition(), "across", "over"].includes(
            indirect_preposition
          ) &&
          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(
              `D1138 | ${this.name}.js | ${direct_object.id} is not on ${indirect_object.id} `
            );
            msg += `${direct_object.Articlename_isnt}  on ${indirect_object.articlename}. `;
            this.handleFailure(msg);
            return null;
          }
        } else if (["to", "toward", "near"].includes(indirect_preposition)) {
          // is direct in same place as indirect?
          if (
            direct_object.getPlaceAssetId() !==
              indirect_object.getPlaceAssetId() ||
            direct_object.getPlacePreposition() !==
              indirect_object.getPlacePreposition()
          ) {
            this.game.debug(
              `D1681 | ${this.name}.js | ${direct_object.id} isn't in same parent as ${indirect_object.id} `
            );
            msg += `$(We) can't ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
            this.handleFailure(msg);
            return null;
          }
        } else if (!indirect_object.hasAspectAt(indirect_preposition)) {
          this.game.debug(
            `D1204 | ${this.name}.js | ${indirect_object.id} has no aspect at ${indirect_preposition} `
          );
          msg += `$(We) can't ${this.name} ${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(
            `D1188 | ${this.name}.js | ${indirect_object.id} has no aspect at ${indirect_preposition} `
          );
          msg += `$(We) can't ${this.name} 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 verb_phrase = input.verb_phrase;
      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;

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

      if (indirect_object && indirect_object.direction) {
        // @TODO reconsider whether "move east" does tryTravel
        // results = this.game.tryTravel(indirect_object.direction, {
        //   with: [direct_object.id],
        // });
        // if (A.isFalseOrNull(results)) return results;
        // no msg because tryTravel handled it
        msg += `$(We) ${this.name} ${direct_object.articlename} a bit to the ${indirect_object.direction}. `;
      }

      // sentence structure: verb noun preposition noun
      if (input.hasStructure("verb noun preposition noun")) {
        if (
          [direct_object.getPlacePreposition(), "across", "over"].includes(
            indirect_preposition
          ) &&
          direct_object.getPlaceAsset().id === indirect_object.id
        ) {
          msg += `$(We) ${this.name} ${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 ${this.gerund} ${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 ${this.gerund} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          } else {
            msg += `$(We) ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          }
        } // off
        else if (["to", "toward", "near"].includes(indirect_preposition)) {
          msg += `$(We) ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        } // to toward near
      } // verb noun preposition noun

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