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

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

  /**
   * @augments {adventurejs.Verb}
   * @class hang
   * @ajsnode game.dictionary.verbs.hang
   * @ajsconstruct MyGame.createVerb({ "name": "hang", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading PositionVerbs
   * @summary Verb meaning hang, as in "hang hat on hook" or "hang from branch".
   * @todo make bridge and ledge examples
   * @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; hang from catwalk</span>
   * You crawl over the railing and hang from the catwalk,
   * dangling over the vat of bubbling green chemicals below.
   * Oh no! You're slipping... SPLASH.
   *
   * AHH, IT BURNS! AHH... AHHHH...
   *
   * AHH HAH HAH HAAH HAAH HAAAAH!
   * </pre>
   * <p>
   * <strong>Hang on</strong>, or also (and more likely)
   * <strong>hang from</strong>,
   * understands the player to mean that they want to hang from a
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset} such as a
   * {@link adventurejs.Stalactite|Stalactite} or a branch or ledge.
   * The results are similar to {@link climb_to}.
   * </p>
   * @ajsverbreactions
   * @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
   */
  A.Preverbs.hang = {
    name: "hang",
    prettyname: "hang",
    past_tense: "hung",
    synonyms: [],

    /**
     * @ajsverbstructures
     * @memberof hang
     */
    accepts_structures: [
      "verb", // player can hang from nest
      "verb preposition", // hang on, hang out - both meaning wait?
      "verb preposition noun", // hang from branch, hang on tree, hang up painting
      "verb noun preposition noun", // hang painting on wall
    ],

    player_must_be: {
      not_constrained: true,
    },

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

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

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

    doTry: function () {
      var input = this.game.getInput();
      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 player = this.game.getPlayer();
      var nest_preposition = player.getNestPreposition();
      var nest_parent_id = player.getNestId();
      var nest_asset = player.getNestAsset();
      var msg = "";
      var results;

      if ("from" === direct_preposition) {
        input.setPreposition(1, "on");
        direct_preposition = "on";
      }

      if ("from" === indirect_preposition) {
        input.setPreposition(2, "on");
        indirect_preposition = "on";
      }

      // sentence structure: verb
      // ex: hang
      if (input.hasStructure("verb")) {
        // can player hang here?
        let parent = player.getNestOrPlaceAsset();
        direct_object = parent;
        direct_preposition = player.getNestOrPlacePreposition();
        input.setAsset(1, direct_object);
        input.setPreposition(1, direct_preposition);
        input.setStructure("verb preposition noun");
      }

      // sentence structure: verb preposition
      // ex: hang out, hang on - both mean wait
      if (input.hasStructure("verb preposition")) {
        if (["out", "on"].indexOf(direct_preposition) > -1) {
          return true;
        }
        if ("up" === direct_preposition) {
          let phones = player.findClassInThis("Phone");
          if (!phones.length) {
            this.game.debug(
              `F1303 | ${this.name}.js | ${player.id} has no phone `
            );
            msg += `$(We) slam down $(our) imaginary phone. `;
            this.handleFailure(msg);
            return null;
          }
          if (phones.length) {
            for (let i = 0; i < phones.length; i++) {
              let phone = this.game.getAsset(phones[i]);
              if (phone && phone.is.connected) {
                direct_object = phone;
                input.setAsset(1, direct_object);
                input.setStructure("verb preposition noun");
              }
            }
            if (!direct_object) {
              this.game.debug(
                `F1262 | ${this.name}.js | ${player.id} has phone but no connection `
              );
              msg += `$(We) don't appear to be on a call. `;
              this.handleFailure(msg);
              return null;
            }
          }
        } else {
          this.game.debug(
            `F1245 | ${this.name}.js | ${this.name} ${direct_preposition} is unsupported `
          );
          msg += `$(We) don't know how to ${input.input_verb} ${direct_preposition}. `;
          this.handleFailure(msg);
          return null;
        }
      }

      // sentence structure: verb preposition noun
      // ex: hang from rope, hang up phone
      if (input.hasStructure("verb preposition noun")) {
        // can't hang on
        if (!direct_object.isDOV("hang")) {
          this.game.debug(
            `F1305 | ${this.name}.js | ${direct_object.id}.dov.hang is unset `
          );
          msg += `$(We) see no way to hang ${direct_preposition} ${direct_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (
          "up" === direct_preposition &&
          direct_object instanceof adventurejs.Phone
        ) {
          this.game.debug(
            `F1246 | ${this.name}.js | ${direct_object.id} is ${
              direct_object.is.connected ? "" : "un"
            }connected phone `
          );
          if (!direct_object.is.connected) {
            msg += `${direct_object.Articlename} doesn't appear to be connected. `;
            this.handleFailure(msg);
            return null;
          }
          return true;
        }

        // is player already on it?
        if (
          nest_asset &&
          direct_object.id === nest_asset.id &&
          direct_preposition === nest_preposition
        ) {
          // @TODO posture check for hanging
          this.game.debug(
            `F1338 | ${this.name}.js | player is ${direct_preposition} ${direct_object.id} `
          );
          msg += `$(We're) already ${direct_preposition} ${direct_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (direct_object.is.climbable) {
          `F1285 | ${this.name}.js | ${direct_object.id}.is.climbable, doVerb climb `;
          this.game.dictionary.doVerb("climb");
          return null;
        }

        // if you can hang on it, you should be able to climb it,
        // and so we're done, but just in case

        // figure out y overlap
        var range = direct_object.getYRange();

        // is player close enough on y?
        if (player.position.y > range.max || player.position.y < range.min) {
          this.game.debug(
            `F1306 | ${this.name}.js | ${player.id}.position.y out of range of ${direct_object.id} `
          );
          msg += `${direct_object.Articlename} is too far ${
            player.position.y > range.max ? "below" : "above"
          } your position on ${
            player.isNested() ? nest_asset.articlename : "the floor"
          }. `;
          this.handleFailure(msg);
          return null;
        }
      }

      // sentence structure: verb noun preposition noun
      // ex: hang portrait on wall
      if (input.hasStructure("verb noun preposition noun")) {
        if (!indirect_object.isIOV("hang")) {
          this.game.debug(
            `F1298 | ${this.name}.js | ${indirect_object.id}.iov.hang is unset `
          );
          msg += `$(We) can't hang anything ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        if (!indirect_object.hasAspectAt(indirect_preposition)) {
          this.game.debug(
            `F1299 | ${this.name}.js | ${indirect_object.id}.aspects.${indirect_preposition} is unset `
          );
          msg += `$(We) can't hang anything ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        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;
        }
      }

      return true;
    },

    doSuccess: function () {
      var input = this.game.getInput();
      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 player = this.game.getPlayer();
      var nest_parent_id = player.getNestId();
      var nest_asset = player.getNestAsset();
      var msg = "";
      var results;

      this.game.debug(`F1304 | ${this.name}.js | print doSuccess `);

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

      // sentence structure: verb preposition
      // ex: hang out, hang on - both mean wait
      if (input.hasStructure("verb preposition")) {
        if ("out" === direct_preposition) {
          msg += `$(We) chillax for a moment. `;
        }
        if ("on" === direct_preposition) {
          msg += `$(We) cling desperately to life. `;
        }
        if ("up" === direct_preposition) {
          msg += `$(We) do have $(ours). `;
        }
        msg += ``;
      }

      // sentence structure: verb preposition noun
      // ex: hang from rope, hang up phone
      if (input.hasStructure("verb preposition noun")) {
        // hang up phone
        if (
          "up" === direct_preposition &&
          direct_object instanceof adventurejs.Phone
        ) {
          // compose output
          msg += `$(We) hang up ${direct_object.articlename}. `;

          // apply state changes
          direct_object.is.connected = false;
        } else {
          // compose output
          msg += `$(We) hang ${direct_preposition} ${direct_object.articlename}. `;

          // if player is nested, unnest
          if (nest_asset && nest_asset.id !== direct_object.id) {
            results = player.onUnnestThisFromThat(nest_asset);
            if ("undefined" !== typeof results) return results;
          }
          results = player.onNestThisToThat(direct_object, direct_preposition);
          if ("undefined" !== typeof results) return results;

          // apply state changes
          player.posture = "hang";
        }
      }

      // sentence structure: verb noun preposition noun
      // ex: hang portrait on wall
      if (input.hasStructure("verb noun preposition noun")) {
        // remove noun1 from player
        results = player.onRemoveThatFromThis(direct_object);
        if ("undefined" !== typeof results) return results;

        results = indirect_object.onMoveThatToThis(direct_object, "on");
        if ("undefined" !== typeof results) return results;

        // compose output
        msg += `$(We) hang ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;

        // apply state changes
        direct_object.posture_position = this.game.dictionary.getStringLookup(
          "posture_positions",
          "hanging"
        );
      }

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