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

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

  /**
   * @augments {adventurejs.Verb}
   * @class pull
   * @ajsnode game.dictionary.verbs.pull
   * @ajsconstruct MyGame.createVerb({ "name": "pull", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading ManipulationVerbs
   * @summary Verb meaning pull 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; pull mask</span>
   * You don't tug on Superman's cape.
   * You don't spit into the wind.
   * You don't pull the mask off that old Lone Ranger.
   * And you don't mess around with Jim.
   * </pre>
   * <p>
   * <strong>Pull</strong> requires that the
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset} to be pulled has
   * asset.dov.pull.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.pull = {
    name: "pull",
    prettyname: "pull",
    past_tense: "pulled",
    synonyms: ["pull"],
    gerund: "pulling",

    /**
     * @ajsverbstructures
     * @memberof pull
     */
    accepts_structures: [
      "verb noun", // ie 'pull wagon'
      "verb noun noun", // ie 'pull wagon north'

      "verb preposition noun", // ie 'pull up bucket'
      "verb noun preposition", // ie 'pull drawer open', 'pull bucket up'

      "verb noun preposition noun", // ie 'pull wagon over hill'
      "verb noun preposition noun preposition noun", // ie 'pull wagon from dingle to hill'
    ],

    /**
     * @memberof pull
     * @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 pull
     * @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,
      accepts_preposition_without_noun: true,
    },

    /**
     * @memberof pull
     * @ajsverbphrase
     * phrase3:
     * {
     *   // only supports form: pull 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 pull
     * @ajsverbparams
     * with_params: {},
     */
    with_params: {},

    doTry: function () {
      var input = this.game.getInput();
      var subject = input.getSubject();
      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 results;
      var msg = "";

      // sentence structure: verb noun preposition
      // ex: pull drawer open
      if (input.hasStructure("verb noun preposition")) {
        input.setPreposition(1, indirect_preposition);
        input.deletePhrase(2);
        input.setStructure("verb preposition noun");
      } // verb noun preposition

      // sentence structure: verb preposition noun
      // ex: pull open drawer, pull on shirt, pull up bucket, pull in rope
      if (input.hasStructure("verb preposition noun")) {
        if (
          direct_object.allowVerbWithPreposition(
            this.name,
            direct_preposition,
            "dov"
          )
        ) {
          return true;
        }
      } // verb preposition noun

      if (
        direct_object.hasQuirk("pull_means_open") &&
        direct_object.isDOV("open")
      ) {
        this.game.debug(
          `D1672 | ${this.name}.js | ${direct_object.id}.quirks.pull_means_open is true, doVerb open`
        );
        if (input.hasStructure("verb preposition noun")) {
          input.setPreposition(1, "");
          input.setStructure("verb noun");
        } // verb preposition noun
        return this.game.dictionary.doVerb("open");
      }

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

      if (!direct_object.isDOV(this.name)) {
        this.game.debug(
          `D1380 | ${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(
          `D2019 | ${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: pull bed north
      if (input.hasStructure("verb noun noun")) {
        if (!indirect_object.direction) {
          this.game.debug(
            `D2020 | ${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: pull 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(
            `D2021 | ${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(
            `D2022 | ${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: pull pram across lawn
      if (input.hasStructure("verb noun preposition noun")) {
        if (direct_object === indirect_object) {
          this.game.debug(
            `D2023 | ${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) nudge ${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(
            `D2024 | ${this.name}.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;
        }

        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(
              `D2025 | ${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(
              `D2026 | ${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(
            `D2027 | ${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(
            `D2028 | ${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 subject = input.getSubject();
      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 msg = "";
      var results;
      var results1, results2;

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

      if (indirect_object && indirect_object.direction) {
        // @TODO reconsider whether "pull 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.agree()} ${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.agree()} ${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.agree()} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          }
        } // off
        else if (["to", "toward", "near"].includes(indirect_preposition)) {
          msg += `$(We) ${this.agree()} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        } // to toward near
      } // verb noun preposition noun

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