// drink.js
(function () {
/*global adventurejs A*/
"use strict";
/**
* @augments {adventurejs.Verb}
* @class drink
* @ajsnode game.dictionary.verbs.drink
* @ajsconstruct MyGame.createVerb({ "name": "drink", [...] });
* @ajsconstructedby adventurejs.Dictionary#createVerb
* @hideconstructor
* @ajsinstanceof Verb
* @ajsnavheading ConsumptionVerbs
* @summary Verb meaning drink substance.
* @todo finish writing
* @tutorial Scripting_VerbSubscriptions
* @tutorial Verbs_VerbAnatomy
* @tutorial Verbs_VerbProcess
* @tutorial Verbs_ModifyVerbs
* @tutorial Verbs_WriteVerbs
* @classdesc
* <pre class="display border outline">
* <span class="input">> drink milk</span>
* You drink milk from the carton. It does a body good.
* </pre>
* <p>
* <strong>Drink</strong> a {@link adventurejs.Substance|Substance}
* {@link adventurejs.Asset|Asset}.
* Requires that a quantity of the Substance be present and reachable.
* Parser will search for the specified Substance among available
* Assets.
* </p>
* @ajsverbphases doBeforeTry, doAfterTry, doBeforeSuccess, doAfterSuccess
*/
A.Preverbs.drink = {
name: "drink",
prettyname: "drink",
past_tense: "drank",
synonyms: ["drink", "sip"],
/**
* @ajsverbstructures
* @memberof drink
*/
accepts_structures: [
"verb noun",
"verb preposition noun",
"verb noun preposition noun",
],
/**
* @memberof drink
* @ajsverbphrase
* phrase1:
* {
* accepts_noun:true,
* requires_noun:true,
* noun_must_be:
* {
* known: true,
* matter: true,
* present_if_tangible: true,
* reachable_if_tangible: true,
* },
* accepts_preposition: true,
* accepts_these_prepositions: ["from"],
* },
*/
phrase1: {
accepts_noun: true,
requires_noun: true,
noun_must_be: {
known: true,
matter: true,
present_if_tangible: true,
reachable_if_tangible: true,
},
accepts_preposition: true,
accepts_these_prepositions: ["from"],
},
/**
* @memberof drink
* @ajsverbphrase
* phrase2:
* {
* accepts_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" ],
* },
*/
phrase2: {
accepts_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"],
},
/**
* @memberof drink
* @ajsverbparams
* with_params: {},
*/
with_params: {},
doTry: function () {
var input = this.game.getInput();
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 currentRoom = this.game.getCurrentRoom();
var containers;
var msg = "";
var results, hook;
var find_container_for_direct_object = false;
var find_substance_for_direct_object = false;
// parsed sentence structure: verb
if (input.hasStructure("verb")) {
}
// parsed sentence structure: verb noun
if (input.hasStructure("verb noun")) {
} // verb noun
if (input.hasStructure("verb preposition noun")) {
}
// has player entered "drink asset"?
if (
input.hasStructure("verb noun") ||
input.hasStructure("verb preposition noun")
) {
// is asset a substance? > get container
if (direct_object instanceof adventurejs.Substance) {
find_container_for_direct_object = true;
} else if (direct_object.doesContainAnySubstance()) {
find_substance_for_direct_object = true; // check open / reachable etc
} else if (direct_object.canContainAnySubstance()) {
this.game.debug(
`F1575 | ${this.name}.js | ${direct_object.id} is empty `,
);
msg += `${direct_object.Articlename} is empty. `;
this.handleFailure(msg);
return null;
} else if (direct_object.isDOV("drink")) {
// is player carrying the thing?
if (direct_object.isDOV("take") && !direct_object.isIn(player)) {
this.game.debug(
`F1748 | ${this.name}.js | ${direct_object.id} is not in player `,
);
msg += `$(We're) not carrying ${direct_object.articlename}. `;
this.handleFailure(msg);
return null;
}
// special handling for things that are not substance containers
// but which can be drunk, as in a case like "drink potion"
// where potion asset responds directly to drink
input.verb_params.can_be_drunk = true;
return true;
} else {
this.game.debug(
`F1171 | ${this.name}.js | ${direct_object.id}.dov.drink.enabled is false `,
);
msg += `${direct_object.Articlename} can't be drunk from. `;
this.handleFailure(msg);
return null;
}
} // verb noun
// player input "drink substance" and we need to infer container
if (find_container_for_direct_object) {
containers = this.game.findSubstanceContainers(direct_object.id, [
"Present",
"Known",
"Visible",
"Reachable",
]);
switch (containers.length) {
case 0:
this.game.debug(`F1576 | ${this.name}.js | no containers found `);
msg += `There's no ${direct_object.name} available. `;
this.handleFailure(msg);
return null;
case 1:
// set indirect object to the container
// ie "drink water" becomes "drink water from bowl"
indirect_object = this.game.getAsset(containers[0]);
input.setAsset(2, indirect_object);
input.setPreposition(2, "from");
input.setAssumed(2, true);
input.setStructure("verb noun preposition noun");
break;
default:
var asset, room;
for (var i = 0; i < containers.length; i++) {
asset = this.game.getAsset(containers[i]);
if (asset.id === currentRoom.id) {
room = true;
break;
}
}
// if room is among multiple sources, always prefer room
// meant for environmental substances, like standing by a lake
if (room) {
// set indirect object to the room
// ie "drink water" becomes "drink water from room"
indirect_object = asset;
input.setAsset(2, indirect_object);
input.setPreposition(2, "from");
input.setAssumed(2, true);
input.verb_params.drink_from_room = true;
input.setStructure("verb noun preposition noun");
break;
} else {
// disambiguate - set parsedNoun.matches for next turn
this.game.debug(
`F1578 | ${this.name}.js | multiple containers found, disambiguate `,
);
// set preposition to "from" for disambiguation
// because we're asking player to choose a container
input.setPreposition(1, "from");
// save containers back to input for next turn disambiguation
input.setParsedNounMatchesQualified(1, containers);
this.game.parser.printNounDisambiguation({
parsedNoun: input.getParsedNoun(1),
nounIndex: 1,
});
return null;
}
} // switch
} // find_container_for_direct_object
// player input "drink container" and we need to infer substance
if (find_substance_for_direct_object) {
indirect_object = direct_object;
direct_object = this.game.getAsset(
indirect_object.getAnySubstanceThisContains(),
);
input.setAsset(1, direct_object);
input.setPreposition(1, "");
input.setAsset(2, indirect_object);
input.setPreposition(2, "from");
input.setStructure("verb noun preposition noun");
} // find_substance_for_direct_object
// now we can get into verb noun preposition noun
if (input.hasStructure("verb noun preposition noun")) {
// is substance unpotable? for instance could be sand
if (!direct_object.isDOV("drink")) {
this.game.debug(
`F1577 | ${this.name}.js | ${direct_object.id}.dov.drink.enabled is false `,
);
msg += `$(We) can't drink ${direct_object.name}. `;
this.handleFailure(msg);
return null;
}
// can indirect object contain substance?
if (!indirect_object.canContainAnySubstance()) {
this.game.debug(
`F1582 | ${this.name}.js | ${indirect_object.id} has no substance container `,
);
msg += `${indirect_object.Articlename} can't be drunk from. `;
this.handleFailure(msg);
return null;
}
// DOES indirect object contain substance?
if (!indirect_object.doesContainAnySubstance()) {
if (indirect_object instanceof adventurejs.SubstanceEmitter) {
this.game.debug(
`F1580 | ${this.name}.js | "+${indirect_object.id}+" is class SubstanceEmitter and .is_emitting is false `,
);
msg += `Nothing is coming out of ${indirect_object.articlename}. `;
} else {
this.game.debug(
`F1581 | ${this.name}.js | ${indirect_object.id}.aspects.in.vessel.volume is 0 `,
);
msg += `${indirect_object.Articlename} is empty. `;
}
this.handleFailure(msg);
return null;
}
// can indirect object be drunk from?
if (!indirect_object.can.drink_from) {
this.game.debug(
`F1173 | ${this.name}.js | ${indirect_object.id}.can.drink_from is false `,
);
msg += `$(We) can't drink from ${indirect_object.articlename}. `;
this.handleFailure(msg);
return null;
}
// Is indirect object takeable but not in player?
if (indirect_object.isDOV("take") && !indirect_object.isIn(player)) {
this.game.debug(
`F1579 | ${this.name}.js | ${indirect_object.id} is not in player `,
);
msg += `$(We're) not holding ${indirect_object.articlename}. `;
this.handleFailure(msg);
return null;
}
// Is indirect object closed?
if (
indirect_object.getAspectWithVessel() === "in" &&
indirect_object.isDOV("open")
) {
this.game.debug(
`F1571 | ${this.name}.js | ${indirect_object.id}.is.closed `,
);
msg += `${indirect_object.Articlename} is closed. `;
this.handleFailure(msg);
return null;
}
if (!indirect_object.doesContainSubstance(direct_object.id)) {
this.game.debug(
`F1583 | ${this.name}.js | ${indirect_object.id} does not contain "+${direct_object.id}+" `,
);
msg += `${indirect_object.Articlename} contains ${
this.game.getAsset(indirect_object.getAnySubstanceThisContains())
.name
}. `;
this.handleFailure(msg);
return null;
}
} // verb noun preposition noun
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 msg = "";
var results;
var source_aspect;
var source_vessel;
var substance;
if (input.verb_params.can_be_drunk) {
this.game.debug(
`F1172 | ${this.name}.js | doSuccess ${direct_object.name}.dov.drink.enabled `,
);
// we only arrive here if the object can be direct object of drink but
// no substance involved. For simple things like "drink potion"
// parsed sentence structure: verb
if (input.hasStructure("verb")) {
}
// parsed sentence structure: verb noun
if (input.hasStructure("verb noun")) {
} // verb noun
msg += `$(We) drink ${direct_object.articlename}. `;
if (direct_object && direct_object.on_drink_destroy) {
direct_object.destroy();
}
} else if (input.hasStructure("verb noun")) {
// shouldn't happen because we inferred verb noun preposition noun
} else if (input.hasStructure("verb preposition noun")) {
// shouldn't happen because we inferred verb noun preposition noun
} else if (input.hasStructure("verb noun preposition noun")) {
this.game.debug(
`F1170 | ${this.name}.js | doSuccess dObj = ${direct_object.name}, iObj = ${indirect_object?.name} `,
);
source_aspect = indirect_object.getAspectWithVessel();
source_vessel = indirect_object.getVesselAt(source_aspect);
substance = this.game.getAsset(source_vessel.substance_id);
if (indirect_object.on_drink_empty) {
source_vessel.setVolume(0);
} else {
source_vessel.subtractVolume(this.game.settings.mouthful);
}
msg += `$(We) drink some ${substance.name} from ${indirect_object.articlename}`;
if (0 >= source_vessel.getVolume()) {
msg += `, emptying it in one gulp`;
}
msg += `. `;
}
// print output
this.handleSuccess(msg, direct_object);
return true;
},
};
})(); // drink