Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// unlock.js
// OK 09 2023
(function () {
  /* global adventurejs A */

  /**
   * @augments {adventurejs.Verb}
   * @class unlock
   * @ajsnode game.dictionary.verbs.unlock
   * @ajsredirectverb pick
   * @ajsconstruct MyGame.createVerb({ "name": "unlock", [...] });
   * @ajsconstructedby adventurejs.Dictionary#createVerb
   * @hideconstructor
   * @ajsinstanceof Verb
   * @ajsnavheading OpenCloseVerbs
   * @ajscaninferindirect true
   * @summary Verb meaning unlock, as in "unlock door with key".
   * @tutorial Verbs_Subscriptions
   * @tutorial AdvancedVerbs_VerbAnatomy
   * @tutorial AdvancedVerbs_VerbProcess
   * @tutorial AdvancedVerbs_ModifyVerbs
   * @tutorial AdvancedVerbs_ModifyVerbs
   * @classdesc
   * <pre class="display border outline">
   * <span class="ajs-player-input">&gt; unlock heart with love</span>
   * You unlock the heart stone with the loving key. The chamber's dim lighting immediately brightens into a pulsating glow. The sense of forboding that had descended upon you lifts too. You feel yourself buoyed with positive emotion. In fact... whoa... you look down to find your feet rising from the ground.
   * </pre>
   *
   * <p>
   * <strong>Unlock</strong> a
   * {@link adventurejs.Tangible|Tangible}
   * {@link adventurejs.Asset|Asset}.
   * Requires that the lock has
   * asset.dov.unlock.enabled set to true and its
   * <a class="code" href="/doc/adventurejs.Tangible.html#property_is_locked">is.locked</a>
   * property set to true.
   * If the lock requires a key, verb will soft prompt for one.
   * </p>
   *
   * tryUnlockThis
   * tryUnlockThisWithThat
   * tryUnlockThatWithThis
   * doUnlockThis
   * doUnlockThisWithThat
   * doUnlockThatWithThis
   * @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
   * @ajsdemo OpenDemo, SittingRoom, Library, Playground, Objects, Scorecard
   */
  A.Preverbs.unlock = {
    name: "unlock",
    prettyname: "unlock",
    past_tense: "unlocked",
    synonyms: ["unlock"],
    unstate: "locked",
    related: ["lock", "pick"],
    gerund: "unlocking",

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

    /**
     * @memberof unlock
     * @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 unlock
     * @ajsverbphrase
     * phrase2:
     * {
     *   accepts_noun: true,
     *   noun_must_be:
     *   {
     *     in_inventory: true,
     *     known: true,
     *   },
     *   accepts_preposition: true,
     *   requires_preposition: true,
     *   preposition_must_be: ["with"],
     * },
     */
    phrase2: {
      accepts_noun: true,
      noun_must_be: {
        in_inventory: true,
        known: true,
      },
      accepts_preposition: true,
      requires_preposition: true,
      preposition_must_be: ["with"],
    },

    /**
     * @memberof unlock
     * @ajsverbparams
     * with_params: {},
     */
    with_params: { on_unlock_open: true },

    doTry: function () {
      var input = this.game.getInput();
      var subject = input.getSubject();
      var direct_object = input.getAsset(1);
      var indirect_object = input.getAsset(2);
      var indirect_preposition = input.getPreposition(2);
      var indirect_inferred;
      var results;
      var msg = "";

      // be nice and redirect to pick if appropriate
      if (
        direct_object?.isDOV("pick") &&
        indirect_object &&
        direct_object.allowVerbWithAsset({
          verb: "pick",
          asset: indirect_object.id,
          ov: "dov",
        })
      ) {
        return this.game.dictionary.doVerb("pick");
      }

      // can be direct object of verb?
      if (!direct_object.isDOV(this.name)) {
        if (direct_object.isDOV("pick")) {
          return this.game.dictionary.doVerb("pick");
        }
        this.game.debug(
          `D1464 | ${this.name}.js | ${direct_object.id}.dov.${this.name}.enabled is false `
        );
        msg += `${direct_object.Articlename} can't be ${this.past_tense}. `;
        this.handleFailure(msg);
        return false;
      }

      // verb state?
      if (this.hasState() && direct_object.isVerbState(this.name)) {
        this.game.debug(
          `D1465 | ${this.name}.js | ${
            direct_object.id
          }.is.${this.getState()} is false`
        );
        msg += `${direct_object.Articlename_isnt}  ${this.getState()}. `;
        this.handleFailure(msg);
        return false;
      }

      // single use direct object?
      if (
        direct_object.allowVerbOnce(this.name, "dov") &&
        direct_object.didVerb(this.name, "dov")
      ) {
        this.game.debug(
          `D1831 | ${this.name}.js | ${direct_object.id}.dov.${this.name}.once and ${direct_object.id}.did.${this.name}.directly `
        );
        msg += `${direct_object.Articlename} has already been ${this.past_tense}. `;
        this.handleFailure(msg);
        return false;
      }

      // sentence structure: verb noun
      if (input.hasStructure("verb noun")) {
        // indirect objects available?
        if (
          !direct_object.hasIndirectObjects(this.name) &&
          !direct_object.allowVerbWithNothing(this.name, "dov")
        ) {
          this.game.debug(
            `D1466 | ${this.name}.js | ${direct_object.id}.dov.${this.name}.with_nothing is false `
          );
          msg += `{We} {don't} know of anything that unlocks ${direct_object.articlename}. `;
          this.handleFailure(msg);
          return false;
        }

        // infer indirect object?
        results = this.tryToInferIndirectObject({
          direct_object: direct_object,
          context: subject,
          handle_input: true,
        });
        if (results.prompt) {
          // indirect object required?
          if (direct_object.allowVerbWithNothing(this.name, "dov")) {
            return true;
          }

          this.game.debug(`D1757 | ${this.name}.js | soft prompt for noun2 `);
          msg += input.verb_params.auto_open
            ? `${direct_object.Articlename_is} locked. `
            : ``;
          msg += `What would {we} like to ${this.name} ${direct_object.articlename} with? `;
          this.handleFailure(msg);
          return false;
        } else if (results.success) {
          indirect_object = results.indirect_object;
          indirect_preposition = "with";
          indirect_inferred = true;
          input.setAsset(2, indirect_object);
          input.setPreposition(2, indirect_preposition);
          input.setStructure("verb noun preposition noun");
        }
      } // verb noun

      // sentence structure: verb noun preposition noun
      if (input.hasStructure("verb noun preposition noun")) {
        // works with any indirect object?
        if (direct_object.allowVerbWithAnything(this.name, "dov")) {
          return true;
        }

        // indirect object not required?
        // if (direct_object.allowVerbWithNothing(this.name, "dov")) {
        //   this.game.debug(
        //     ` | ${this.name}.js | ${direct_object.id}.dov.${this.name}.with_nothing `
        //   );
        //   msg += `{We} can't ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
        //   this.handleFailure(msg);
        //   return null;
        // }

        // indirect object usable with direct object?
        if (
          !direct_object.allowVerbWithAsset({
            verb: this.name,
            asset: indirect_object,
            ov: "dov",
          })
        ) {
          this.game.debug(
            `D1698 | ${this.name}.js | ${direct_object.id}.dov.${this.name}.with_assets/with_classes does not include ${indirect_object.id} `
          );
          msg += `{We} can't ${this.name} ${direct_object.articlename} ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return null;
        }

        // can indirect object be used?
        if (!indirect_object.isIOV(this.name)) {
          this.game.debug(
            `D1913 | ${this.name}.js | ${indirect_object.id}.iov.${this.name}.enabled is false `
          );
          msg += `{We} can't ${this.name} anything ${indirect_preposition} ${indirect_object.articlename}. `;
          this.handleFailure(msg);
          return false;
        }

        // single use indirect object?
        if (
          indirect_object.allowVerbOnce(this.name, "iov") &&
          indirect_object.iDidVerb(this.name, "iov")
        ) {
          this.game.debug(
            `D1817 | ${this.name}.js | ${indirect_object.id}.iov.${
              this.name
            }.once and ${indirect_object.id}.did.${this.name}.indirectly is ${
              indirect_object.did[this.name].indirectly
            } `
          );
          msg += `${indirect_object.Articlename} has already been used to ${this.name} something. `;
          this.handleFailure(msg);
          return null;
        }
      } // verb noun preposition noun

      return true;
    },

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

      if (input.verb_params.auto_open) {
        direct_object.setIs("closed", false);
        direct_object.incrementDoVerbCount("open", "dov");
        auto_open = true;
      }

      // apply state changes
      this.setState(direct_object, false);

      // compose output
      msg += `{We} ${this.agree()}${
        direct_preposition ? " " + direct_preposition : ""
      }${direct_object ? " " + direct_object.articlename : ""}${
        indirect_preposition ? " " + indirect_preposition : ""
      }${
        indirect_object ? " " + indirect_object.articlename : ""
      }${auto_open ? " and open it" : ""}. `;

      // printable contents?
      if (auto_open && direct_object.hasContentsAtAspect("in")) {
        msg += direct_object.getPrintableListOfContentsAt("in");
      }

      // --------------------------------------------------
      // print output
      // --------------------------------------------------
      return this.handleSuccess(msg);
    },
  };
})(); // unlock