// remove.js
(function () {
/* global adventurejs A */
/**
* @augments {adventurejs.Verb}
* @class remove
* @ajsnode game.dictionary.verbs.remove
* @ajsredirectverb untie, detach, take
* @ajsconstruct MyGame.createVerb({ "name": "remove", [...] });
* @ajsconstructedby adventurejs.Dictionary#createVerb
* @hideconstructor
* @ajsinstanceof Verb
* @ajsnavheading ManipulationVerbs
* @summary Verb meaning remove, as in "remove cap from toothpaste".
* @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">> remove hat from frog</span>
* You try to remove the top hat from the singing frog. He leans neatly away without moving from his spot on the piano, causing you to miss and plunge hands first into the taut piano strings. You leap backwards with strings wrapped around you and crash into the drum set, trodding loudly upon the snare drum.
*
* The sudden cacophony draws the conductor, who whacks you about the head and shoulders with his baton and chases you into the stage curtains. You wrestle with the curtains, which tear and fall heavily down upon you. You climb to your feet, wrapped in twisted curtains and piano strings, one foot stuck in a drum, and find yourself on stage, bathed in spotlight, facing the shocked crowd.
* </pre>
* <p>
* <strong>Remove</strong> may be interpreted ambiguously. It tries to respond
* contextually depending on the properties of the objects provided.
* Remove may redirect to
* {@link untie},
* {@link detach}, or
* {@link take}.
* Remove may also remove items worn by the subject or
* {@link adventurejs.NPC|NPCs}, automatically unzipping or unbuttoning them if needed.
* </p>
* @ajsverbreactions doRemoveThisFromThat, doRemoveThatFromThis, doMoveThisToThat, doMoveThatToThis
* @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
*/
A.Preverbs.remove = {
name: "remove",
prettyname: "remove",
past_tense: "removed",
synonyms: ["remove"],
gerund: "removing",
/**
* @ajsverbstructures
* @memberof remove
*/
accepts_structures: ["verb noun", "verb noun preposition noun"],
/**
* @memberof remove
* @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 remove
* @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,
* preposition_must_be: [ 'from' ],
* },
*/
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,
preposition_must_be: ["from"],
},
/**
* @memberof remove
* @ajsverbparams
* with_params: {},
*/
with_params: {},
doTry: function () {
var input = this.game.getInput();
var subject = input.getSubject();
var direct_object = input.getAsset(1);
var indirect_object = input.getAsset(2);
var msg = "";
// if (!direct_object.isDOV("remove")) {
// this.game.debug(
// `D1923 | ${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;
// }
// sentence structure: verb noun
if (input.hasStructure("verb noun")) {
var parent = direct_object.getPlaceAsset();
input.setAsset(2, parent);
input.setPreposition(2, "from");
input.setInferred(2);
input.setStructure("verb noun preposition noun");
indirect_object = parent;
this.game.printInferred(`from ${parent.articlename}`);
}
// sentence structure: verb noun preposition noun
if (input.hasStructure("verb noun preposition noun")) {
// if direct_object is tied, redirect to untie
if (
direct_object.getVerbConnectionCount("tie", "to_iov") &&
direct_object.isDOV("untie")
) {
this.game.debug(
`D1254 | ${this.name}.js | ${direct_object.id}.dov.tie, infer untie `
);
return this.game.dictionary.doVerb("untie");
}
// if direct_object is attached, redirect to detach
if (
direct_object.isPlacedAtAspect("attached") &&
this.game.hasVerb("detach")
) {
this.game.debug(
`D1254 | ${this.name}.js | ${direct_object.id} is attached, infer detach `
);
return this.game.dictionary.doVerb("detach");
}
// thing not in other thing
if (!direct_object.isWithin(indirect_object)) {
this.game.debug(
`D1255 | ${this.name}.js | ${direct_object.id} place is not ${indirect_object.id} `
);
msg += `${direct_object.Articlename_isnt} in ${indirect_object.articlename}. `;
this.handleFailure(msg);
return null;
}
// if direct_object is worn & can be removed, take it off
if (
direct_object.is.worn &&
direct_object.isDOV("remove") &&
indirect_object.id === subject.id
) {
return true;
}
// direct_object is worn by subject but can't be removed
// handcuffs for instance
if (
direct_object.is.worn &&
!direct_object.isDOV("remove") &&
indirect_object.id === subject.id
) {
this.game.debug(
`D1256 | ${this.name}.js | ${direct_object.id}.dov.remove.enabled is false `
);
msg += `{We} can't remove ${direct_object.articlename}. `;
this.handleFailure(msg);
return null;
}
// direct_object is worn by other char but can't be removed
if (
direct_object.is.worn &&
indirect_object !== subject.id &&
(!direct_object.isDOV("remove") || !indirect_object.isIOV("take"))
) {
this.game.debug(
`D1257 | ${this.name}.js | ${direct_object.id}.dov.remove is unset or ${indirect_object.id}.iov.take is unset`
);
msg += `{We} can't remove ${direct_object.articlename} from ${indirect_object.articlename}. `;
this.handleFailure(msg);
return null;
}
// worn by a character like a pet that you can take from?
// as in "remove collar from cat"
if (
direct_object.is.worn &&
indirect_object.id !== subject.id &&
direct_object.isDOV("remove") &&
indirect_object.isIOV("take")
) {
// any conditions that would prevent removing clothing?
// none at the moment so just proceed to success
return true;
}
// try taking a thing from a character
// who can't be taken from
// authors will probably want some control over this interation
if (!indirect_object.isIOV("take")) {
this.game.debug(
`D1258 | ${this.name}.js | ${indirect_object.id}.iov.take is unset`
);
msg += `{We} can't take anything from ${indirect_object.articlename}. `;
this.handleFailure(msg);
return null;
}
if (direct_object.is.worn && !direct_object.isDOV("remove")) {
this.game.debug(
`D1259 | ${this.name}.js | ${direct_object.id}.dov.remove.enabled is false`
);
msg += `{We} can't remove ${direct_object.articlename} from ${indirect_object.articlename}. `;
this.handleFailure(msg);
return null;
}
}
// if it's none of these things, redirect to take
if (this.game.hasVerb("take")) {
this.game.debug(`D1260 | ${this.name}.js | infer take`);
return this.game.dictionary.doVerb("take");
}
},
doSuccess: function () {
var input = this.game.getInput();
var subject = input.getSubject();
var direct_object = input.getAsset(1);
var indirect_object = input.getAsset(2);
var parent = direct_object.getPlaceAsset();
var msg = "";
var closedAnscestors = [];
var results;
// open any containers if necessary
// we only do this for items nested in inventory
if (
direct_object.isWithin(subject) &&
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;
}
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 += ". ";
}
}
// if direct_object is worn, take it off
if (direct_object.is.worn && indirect_object.id == subject.id) {
results = direct_object.unfasten();
msg += results ? `{We} ${results}, then remove, ` : `{We} remove `;
msg += `${direct_object.articlename}. `;
direct_object.is.worn = false;
}
// worn by a character like a pet that you can take from
// what if it's sexy sex? removing clothes from a partner
if (
direct_object.is.worn &&
indirect_object.id !== subject.id &&
indirect_object.isIOV("take")
) {
results = direct_object.unfasten();
msg += results ? `{We} ${results}, then remove, ` : `{We} remove `;
msg += `${direct_object.articlename} from ${indirect_object.articlename}. `;
direct_object.is.worn = false;
}
if (indirect_object.id !== subject.id && direct_object.takeable) {
// remove thing from its current container
results = parent.onRemoveThatFromThis(direct_object);
if ("undefined" !== typeof results) return results;
// add thing to subject's contents
results = subject.onMoveThatToThis(direct_object, "in");
if ("undefined" !== typeof results) return results;
}
// --------------------------------------------------
// print output
// --------------------------------------------------
return this.handleSuccess(msg);
},
};
})(); // remove