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

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

  /**
   * @augments {adventurejs.Verb}
   * @class take
   * @ajsnode game.dictionary.verbs.take
   * @ajsconstruct MyGame.createVerb({ "name": "take", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading ManipulationVerbs
   * @summary Verb meaning take, as in "take lantern".
   * @ajssynonyms take, pick up
   * @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; take nap</span>
   * You take a nap from the dish on the console table,
   * but you're not sure what to do with it.
   * </pre>
   * <p>
   * <strong>Take</strong> a
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset}.
   * Requires that
   * <code>asset.dov.take.enabled</code> is true.
   * </p>
   * @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
   */
  A.Preverbs.take = {
    name: "take",
    prettyname: "take",
    past_tense: "took",
    synonyms: ["take"],
    enqueue_collections: true,

    /**
     * @ajsverbstructures
     * @memberof take
     */
    accepts_structures: [
      "verb noun",
      "verb preposition noun", // take off jacket
      "verb noun preposition", // take jacket off
      "verb noun preposition noun",
    ],

    /**
     * @memberof take
     * @ajsverbphrase
     * phrase1:
     * {
     *   accepts_noun: true,
     *   requires_noun: true,
     *   accepts_plural_noun: true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     not_global: true,
     *     not_scenery: true,
     *     not_exit: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *     takeable: true,
     *     not_in_hands: true,
     *     not_worn: true,
     *     not_nested_inventory_if_all: true,
     *   },
     * },
     */
    phrase1: {
      accepts_noun: true,
      requires_noun: true,
      accepts_plural_noun: true,
      noun_must_be: {
        known: true,
        not_global: true,
        not_scenery: true,
        not_exit: true,
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
        takeable: true,
        not_in_hands: true,
        //not_worn: true,
        not_nested_inventory_if_all: true,
      },
      accepts_preposition: true,
      //accepts_these_prepositions: ["off"],
    },

    /**
     * @memberof take
     * @ajsverbphrase
     * phrase2:
     * {
     *   accepts_noun: true,
     *   noun_must_be:
     *   {
     *     known: true,
     *     not_global: true,
     *     not_scenery: true,
     *     not_exit: true,
     *     tangible: true,
     *     present: true,
     *     visible: true,
     *     reachable: true,
     *   },
     *   accepts_preposition: true,
     *   accepts_these_prepositions: [],
     * },
     */
    phrase2: {
      accepts_noun: true,
      noun_must_be: {
        known: true,
        not_global: true,
        not_scenery: true,
        not_exit: true,
        tangible: true,
        present: true,
        visible: true,
        reachable: true,
      },
      accepts_preposition: true,
      accepts_preposition_without_noun: true,
      //accepts_these_prepositions: [],
    },

    /**
     * @memberof take
     * @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 direct_preposition = input.getPreposition(1);
      var indirect_preposition = input.getPreposition(2);
      var closedAnscestors = [];
      var player = this.game.getPlayer();
      var msg = "";
      var takefrom = "";
      var substance;
      var results;

      //console.warn(`doTry take ${direct_object.id}`);

      if (!direct_object.isDOV("take")) {
        this.game.debug(
          `F1922 | ${this.name}.js | ${direct_object.id}.dov.${this.name} not enabled `,
        );
        msg += `$(We) can't ${this.name} ${direct_object.articlename}. `;
        this.handleFailure(msg);
        return null;
      }

      if (input.hasStructure("verb noun preposition")) {
        if (["off"].indexOf(indirect_preposition) > -1) {
          // ex: take jacket off
          if (direct_object.is.worn) {
            direct_preposition = indirect_preposition;
            input.setPreposition(1, indirect_preposition);
            input.deletePhrase(2);
            input.setStructure("verb preposition noun");
          } else {
            // otherwise just take it
            indirect_preposition = "";
            input.setStructure("verb noun");
            input.deletePhrase(2);
          }
        } else if (["down"].indexOf(indirect_preposition) > -1) {
          // ex: take curtain down
          indirect_preposition = "";
          input.deletePhrase(2);
          input.setStructure("verb 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 === "off") {
          // ex: take off jacket
          if (direct_object.is.worn) {
            direct_preposition = "";
            input.setPreposition(1, "");
            input.setStructure("verb noun");
            this.game.debug(
              `F1927 | ${this.name}.js | take off, doVerb remove `,
            );
            this.game.dictionary.doVerb("remove");
            return null;
          } else {
            // otherwise just take it
            direct_preposition = "";
            input.setStructure("verb noun");
            input.deletePhrase(2);
          }
        } else if (direct_preposition === "down") {
          // ex: take down curtain
          input.setStructure("verb noun");
        } else {
          this.game.debug(
            `F1928 | ${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;
        }
      }

      // sentence structure: verb noun
      if (input.hasStructure("verb noun")) {
        indirect_object = direct_object.getPlaceAsset();
        indirect_preposition = "from";
        input.setAsset(2, indirect_object);
        input.setPreposition(2, indirect_preposition);
        input.setStructure("verb noun preposition noun");
      } // verb noun

      if ("from" === indirect_preposition || "out" === indirect_preposition) {
        takefrom = "from";
      }
      if ("fromin" === indirect_preposition) {
        takefrom = "in";
      } else if ("fromon" === indirect_preposition) {
        takefrom = "on";
      } else if (
        "fromunder" === indirect_preposition ||
        "outfromunder" === indirect_preposition
      ) {
        takefrom = "under";
      } else if (
        "frombehind" === indirect_preposition ||
        "outfrombehind" === indirect_preposition
      ) {
        takefrom = "behind";
      }

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

      // we're handling take and hold distinctly though there is clear crossover
      // mind this because there is also an opportunity for hold to redirect to take
      if (direct_object.quirks.take_means_hold && direct_object.isDOV("hold")) {
        if ("all" !== input.parsedNoun1.deserialized_input) {
          this.game.debug(
            `F1422 | ${this.name}.js | ${direct_object.id}.quirks.take_means_hold, doVerb hold `,
          );
          this.game.dictionary.doVerb("hold");
        }
        return null;
      }

      // can't take exits
      if (direct_object instanceof adventurejs.Exit) {
        this.game.debug(
          `F1425 | ${this.name}.js | ${direct_object.id} is exit `,
        );
        msg += "Pity $(we) can't take direction.";
        this.handleFailure(msg);
        return null;
      }

      // can't take substances
      substance = input.getParsedNoun(1).matches.substance;
      if (substance) {
        this.game.debug(
          `F1372 | ${this.name}.js | substance ${substance} can only be carried in a vessel `,
        );
        msg +=
          this.game.getAsset(substance).Articlename +
          " slips through $(our) fingers. ";
        this.handleFailure(msg);
        return null;
      }

      // already carrying
      if (direct_object.getPlaceAssetId() === this.game.getPlayer().id) {
        this.game.debug(
          `F1426 | ${this.name}.js | ${direct_object.id} is in player `,
        );
        msg += `$(We're) already ${
          direct_object.is.worn ? "wearing" : "carrying"
        } ${direct_object.articlename}. `;
        this.handleFailure(msg);
        return null;
      }

      // can't "take" it...
      if (
        direct_object.isDOV("tie") &&
        !direct_object.DOVhasMaxConnections("tie")
      ) {
        // but might be able to "hold" it...?
        if (
          direct_object.isDOV("hold") &&
          !player.IOVisConnectedToAsset(this.name, direct_object) &&
          !player.IOVhasMaxConnections(this.name)
        ) {
          this.game.debug(
            `F1427 | ${this.name}.js | ${direct_object.id} is tied to things and .dov.hold.enabled, doVerb hold `,
          );
          this.game.dictionary.doVerb("hold");
          return null;
        }

        if (player.IOVisConnectedToAsset("hold", direct_object)) {
          this.game.debug(
            `F1428 | ${this.name}.js | ${direct_object.id} is in ${player.id}.iov.hold.with_params.connections `,
          );
          msg += `$(We're) holding ${direct_object.articlename} already. `;
        }

        this.game.debug(
          `F1429 | ${this.name}.js | ${direct_object.id} is tied to things `,
        );
        msg += `$(We) can't take ${direct_object.articlename} while it's tied to
            this.game.getPrintableObjectList({ objects: direct_object.DOVgetConnections('tie') }). `;
        this.handleFailure(msg);
        return null;
      }

      if (indirect_object) {
        if (!direct_object.isIn(indirect_object)) {
          this.game.debug(
            `F1512 | ${this.name}.js | ${direct_object.id} is not in ${indirect_object.id} `,
          );
          if (indirect_object instanceof adventurejs.Character) {
            msg += `${indirect_object.Articlename} hasn't got ${direct_object.articlename}. `;
          } else {
            msg += `There's no ${direct_object.name} 
              ${
                takefrom && takefrom !== "from"
                  ? takefrom
                  : indirect_object.default_aspect
              } ${indirect_object.articlename}. `;
          }
          this.handleFailure(msg);
          return null;
        }

        // takefrom
        if (takefrom && takefrom !== "from") {
          if (direct_object.getPlacePreposition() !== takefrom) {
            this.game.debug(
              `F1513 | ${this.name}.js | ${direct_object.id} is not ${takefrom} ${indirect_object.id} `,
            );
            msg += `There's no ${direct_object.name} ${takefrom} ${indirect_object.articlename}. `;
            this.handleFailure(msg);
            return null;
          }
        }

        if (!indirect_object.isIOV("take")) {
          this.game.debug(
            `F1929 | ${this.name}.js | ${indirect_object.id}.iov.take is unset `,
          );
          msg += `$(We) can't take ${direct_object.articlename} from ${
            direct_object.getPlaceAsset().articlename
          }. `;
          this.handleFailure(msg);
          return null;
        }

        if (direct_object.is.worn && !direct_object.isDOV("remove")) {
          this.game.debug(
            `F1930 | ${this.name}.js | ${direct_object.id}.dov.remove is unset `,
          );
          msg += `$(We) can't remove ${direct_object.articlename} from ${
            direct_object.getPlaceAsset().articlename
          }. `;
          this.handleFailure(msg);
          return null;
        }
      }

      return true;
    },

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

      this.game.debug(`F1424 | ${this.name}.js | print doSuccess `);
      // open any containers if necessary
      // we only do this for items nested in inventory
      if (direct_object.isIn(player) && direct_object.areAnscestorsClosed()) {
        closedAnscestors = direct_object.getClosedAnscestors();

        for (var i = 0; i < closedAnscestors.length; i++) {
          this.game.getAsset(closedAnscestors[i]).is.closed = false;
          closedAnscestors[i] = this.game.getAsset(closedAnscestors[i]).name;
        }
      }

      // remove thing from its current container
      //results = indirect_object.onRemoveThatFromThis( direct_object );
      results = direct_object.moveFrom(indirect_object);
      if ("undefined" !== typeof results) return results;

      // add thing to player's contents
      //results = player.onMoveThatToThis( direct_object, "in" );
      results = direct_object.moveTo("in", player);
      if ("undefined" !== typeof results) return results;

      if (closedAnscestors.length > 0) {
        msg += `$(We) open the `;
        for (var i = 0; i < closedAnscestors.length; i++) {
          if (closedAnscestors.length > 2 && i < closedAnscestors.length - 2) {
            msg += `, `;
          }
          if (
            closedAnscestors.length > 1 &&
            i === closedAnscestors.length - 1
          ) {
            msg += ` and the `;
          }
          msg += closedAnscestors[i];
        }
        msg += `. `;
      }

      msg += `$(We) take ${direct_object.articlename}`;
      msg += !(indirect_object instanceof adventurejs.Room)
        ? ` ${indirect_preposition} ${indirect_object.articlename}`
        : ``;
      msg += `. `;

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

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