// untie.js
(function () {
/*global adventurejs A*/
/**
* @augments {adventurejs.Verb}
* @class untie
* @ajsnode game.dictionary.verbs.untie
* @ajsconstruct MyGame.createVerb({ "name": "untie", [...] });
* @ajsconstructedby adventurejs.Dictionary#createVerb
* @hideconstructor
* @ajsinstanceof Verb
* @ajsnavheading ManipulationVerbs
* @summary Verb meaning untie, as in "untie string from finger".
* @tutorial Scripting_VerbSubscriptions
* @tutorial Verbs_VerbAnatomy
* @tutorial Verbs_VerbProcess
* @tutorial Verbs_ModifyVerbs
* @tutorial Verbs_WriteVerbs
* @classdesc
* <pre class="display border outline">
* <span class="input">> untie shoelace</span>
* You untie your shoelace. Hung from the tree branch by your shoe
* as you are, this promptly results in you resuming your fall
* toward the ground. Yoink! Your parachute catches in the same branch
* and you're caught again, but thankfully only a couple of feet off
* the ground this time.
* </pre>
* <p>
* <strong>Untie</strong> a {@link adventurejs.Tangible|Tangible}
* {@link adventurejs.Asset|Asset}.
* Requires that the asset has
* <code>asset.dov.untie.enabled</code> set to true. If the asset also has
* its <code>asset.dov.tie.enabled</code> property set true and asset.is.tied
* is true, asset.is.tied will be set to false. If the asset is connected to
* another asset by tie, the connection will be broken.
* </p>
* <p>
* To apply untie to a non-rope asset such as a shoe
* or a bowtie, set its
* <code class="property">asset.dov.tie.with_params.with_nothing</code>
* to true.
* </p>
* <h3 class="example">Example</h3>
* <pre class="display"><code class="language-javascript">MyGame.createAsset({
* class: "Clothing",
* name: "shoe"
* dov: {
* untie: true,
* },
* is: { tied: true },
* });
* <p>
* If a rope is being tied to another asset, the other asset must have its
* <code class="property">asset.iov.tie.enabled</code> set to true.
* This is true even if a player inputs the other asset as a direct object.
* For example, "tie rope to zebra" and "tie zebra with rope" will both be
* parsed with the rope as the direct object and the zebra as the indirect object.
* (Instances of the {@link adventurejs.Rope|Rope} class will inherit
* a direct object subscription, though you may redefine it in order
* to set custom parameters.)
* </p>
* <pre class="display"><code class="language-javascript">MyGame.createAsset({
* class: "Rope",
* name: "sisal rope"
* dov: {
* tie: {
* with_assets: [ "balustrade" ],
* },
* untie: true,
* },
* });
* MyGame.createAsset({
* class: "Thing",
* name: "balustrade",
* dov: { climb: true },
* iov: {
* tie: {
* with_assets: [ "sisal rope" ],
* },
* untie: true,
* },
* });
* </code></pre>
* @ajsverbreactions doRemoveThisFromThat, doRemoveThatFromThis, doMoveThisToThat, doMoveThatToThis
* @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
*/
A.Preverbs.untie = {
name: "untie",
synonyms: ["untie"],
past_tense: "untied",
prettyname: "untie",
gerund: "untying",
unstate: "tied",
/**
* @ajsverbstructures
* @memberof untie
*/
accepts_structures: [
"verb noun", // untie rope, untie shoelace
"verb noun preposition noun",
// untie rope from thing, untie rope with thing?
// "verb noun preposition noun preposition noun",
// untie rope from thing with thing?
],
/**
* @memberof untie
* @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 untie
* @ajsverbphrase
* phrase2:
* {
* accepts_noun: true,
* requires_noun: true,
* noun_must_be:
* {
* known: true,
* tangible: true,
* present: true,
* visible: true,
* reachable: 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,
accepts_these_prepositions: ["from", "with", "in"],
},
/**
* @memberof untie
* @ajsverbparams
* with_params: {},
*/
with_params: {},
doTry: function () {
var input = this.game.getInput();
var verb_phrase = input.verb_phrase;
var player = this.game.getPlayer();
var direct_object = input.getAsset(1);
var indirect_object = input.getAsset(2);
var indirect_preposition = input.getPreposition(2);
var results;
var msg = "";
// example: untie rope (from thing)
// example: untie table (untie rope from table)
// sentence structure: verb noun
if (input.hasStructure("verb noun")) {
// does it have state?
// only applies to non-ropes such as a shoe or a bowtie
// which don't require an indirect object
if (direct_object.is.tied) {
return true;
}
// did player try to untie a rope without specifying
// the thing it's tied to?
if (
direct_object.isDOV("tie") &&
direct_object.getVerbConnectionCount("tie", "to_iov")
) {
// get the first thing the rope is tied to
// not currently accounting for multiple targets
input.setAsset(
2,
this.game.getAsset(
direct_object.getVerbConnections("tie", "to_iov")[0]
)
);
input.setPreposition(2, "from");
indirect_object = input.getAsset(2);
indirect_preposition = "from";
input.setStructure("verb noun preposition noun");
}
// did player try to untie a thing a rope is tied to
// rather than the rope?
if (
direct_object.isIOV("tie") &&
direct_object.getVerbConnectionCount("tie", "to_dov")
) {
// get the first rope that is tied to this thing
// not currently accounting for multiple ropes
input.setAsset(
2,
this.game.getAsset(
direct_object.getVerbConnections("tie", "to_dov")[0]
)
);
input.swapNouns(1, 2);
input.setPreposition(2, "from");
direct_object = input.getAsset(1);
indirect_object = input.getAsset(2);
indirect_preposition = "from";
input.setStructure("verb noun preposition noun");
}
} // verb noun
// @TODO handling for "untie knots in/from rope"
// can't tie to or tie with
if (!direct_object.isDOV(this.name) && !direct_object.isIOV(this.name)) {
this.game.debug(
`D1482 | ${this.name}.js | ${direct_object.id}.dov.untie and .iov.untie are unset `
);
msg += `${direct_object.Articlename} can't be untied. `;
this.handleFailure(msg);
return null;
}
if (input.hasStructure("verb noun preposition noun")) {
if (indirect_preposition === "") {
}
}
// explicitly separate iov/dov check here because
// ropes may have both, leading to false results
if (direct_object.isDOV("tie")) {
// if object is rope but not tied to anything
if (!direct_object.getVerbConnectionCount("tie", "to_iov")) {
// is another rope tied to this rope? that is a real thing
if (
direct_object.isIOV("tie") &&
direct_object.getVerbConnectionCount("tie", "to_dov")
) {
let other_rope = this.game.getAsset(
direct_object.getVerbConnections("tie", "to_dov")[0]
);
if (other_rope) {
input.setAsset(1, other_rope);
direct_object = other_rope;
}
} else {
// rope isn't tied to anything
this.game.debug(
`D1484 | ${this.name}.js | ${direct_object.id}.is.connected_by.tie.to_iov is unset `
);
msg += `${direct_object.Articlename_isnt} tied to anything. `;
this.handleFailure(msg);
return null;
}
}
} else if (direct_object.isIOV("tie")) {
// if object can have rope tied to it but doesn't
if (!direct_object.getVerbConnectionCount("tie", "to_dov")) {
this.game.debug(
`D1485 | ${this.name}.js | ${direct_object.id}.is.connected_by.tie.to_dov is empty`
);
if (direct_object.allowVerbWithNothing("tie", "dov")) {
msg += `${direct_object.Articlename_is} already ${this.past_tense}. `;
} else {
msg += `Nothing is tied to ${direct_object.articlename}. `;
}
this.handleFailure(msg);
return null;
}
}
return true;
},
doSuccess: function () {
var input = this.game.getInput();
var verb_phrase = input.verb_phrase;
var player = this.game.getPlayer();
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 = "";
if (input.hasStructure("verb noun")) {
// if we got here without an indirect object
// it means none is required
// apply state changes
direct_object.is.tied = false;
// compose output
msg = `$(We) ${this.name} ${direct_object.articlename}. `;
// print output
this.handleSuccess(msg, direct_object);
return true;
}
// apply state changes
let tie = this.game.dictionary.verbs.tie;
if (tie) {
tie.unsetVerbConnection(direct_object, indirect_object);
}
// compose output
msg +=
`$(We) ${this.name}` +
`${direct_preposition ? " " + direct_preposition : ""}` +
`${direct_object ? " " + direct_object.articlename : ""}` +
`${indirect_preposition ? " " + indirect_preposition : ""}` +
`${indirect_object ? " " + indirect_object.articlename : ""}`;
if (direct_object.getVerbConnectionCount("tie", "dov")) {
msg += `, leaving it tied to ${this.game.getPrintableObjectList({
objects: direct_object.getVerbConnections("tie", "to_iov"),
})}`;
}
msg += `. `;
if (
this.game.parser.isParsingMultiple() &&
-1 === input.output_class.indexOf("concatenate_output")
) {
input.output_class += " concatenate_output ";
}
// print output
return this.handleSuccess(msg, direct_object);
},
};
})(); // untie