// Tangible_Is.js
(function () {
/*global adventurejs A*/
"use strict";
var p = adventurejs.Tangible.prototype;
/**
* <strong>$is()</strong> is a convenience method for authors that
* provides an easy way to test for various conditions.
* <ul>
* <li><dt>assetA.$is("body")</dt> <dd>asking, is this asset a body of substance such as a lake or sandy desert?</li>
* <li><dt>assetA.$is("closed")</dt> <dd>asking, is this asset closed?</li>
* <li><dt>assetA.$is("held", assetB)</dt> <dd>asking, is this asset held by that asset, as in a bannister held by player?</dd></li>
* <li><dt>assetA.$is("holding", assetB)</dt> <dd>asking, is this asset holding that asset, as in player holding a rope?</dd></li>
* <li><dt>assetA.$is("in", assetB)</dt> <dd>accepts any preposition, asking, is this asset in that aspect of that asset?</dd> </li>
* <li><dt>assetA.$is("locked")</dt> <dd>asking, is this asset locked?</li>
* <li><dt>assetA.$is("nested in", assetB)</dt> <dd>nested in, specific to character classes, asking, is this asset nested in that asset?</dd></li>
* <li><dt>assetA.$is("open")</dt> <dd>asking, is this asset open?</li>
* <li><dt>assetA.$is("plugged")</dt> <dd>asking, is this asset plugged?</li>
* <li><dt>assetA.$is("sealed")</dt> <dd>asking, is this asset sealed?</li>
* <li><dt>assetA.$is("takeable")</dt> <dd>asking, can this asset be taken?</li>
* <li><dt>assetA.$is("unlocked")</dt> <dd>asking, is this asset unlocked?</li>
* <li><dt>assetA.$is("unplugged")</dt> <dd>asking, is this asset unplugged?</li>
* <li><dt>assetA.$is("unsealed")</dt> <dd>asking, is this asset unsealed?</li>
* <li><dt>assetA.$is("worn")</dt> <dd>asking, is this asset being worn?</li>
* <li><dt>assetA.$is("zipped")</dt> <dd>asking, is this asset zipped?</li>
* </ul>
* @memberOf adventurejs.Tangible
* @method adventurejs.Tangible#$is
* @param {String} property
* @param {Object} asset
* @todo Leaving open the possibility for other params.
*/
p.$is = function Tangible_$is(property, asset) {
var msg = "";
// property is required, asset is optional
let shadow_props = {
open: "closed",
unlocked: "locked",
unplugged: "plugged",
unsealed: "sealed",
};
if ("string" !== typeof property) {
msg = "Tangible_is received a value for property that is not a string. ";
this.game.log("warn", "high", msg, "Tangible");
return false;
}
if ("string" === typeof asset) {
asset = this.game.getAsset(asset);
}
// shadow props are properties we don't actually track
// but which are opposites of props we do track
// ie we track asset.is.sealed and using this we allow
// authors to ask if asset.is.unsealed
if (!asset && shadow_props[property]) {
// only return true if opposite property is explicitly
// set to false, vs null or undefined,
// so we don't get false positives, ie returning
// open === true for a thing that doesn't actually open
return false === asset.is[shadow_props[property]];
}
if (!asset && "undefined" !== typeof this.is[property]) {
// we understand this to mean that author is asking for
// something like asset.$is('closed') where we can return
// asset.is.closed
return this.is[property];
}
// check for preposition aka aspect
if (this.game.dictionary.isPreposition(property)) {
// property is a preposition
// we take this to mean that author is asking
// something like MyGame.$('comb').is('on','dresser')
if (!asset) return false;
// characters are special because they have two ways to be children
// we have to check place and nest
if (asset instanceof adventurejs.Character) {
if (property !== this.getNestOrPlacePreposition()) return false;
if (asset.id !== this.getNestOrPlaceAsset().id) return false;
return true;
}
// for anything other than character, just check place
if (property !== this.getPlacePreposition()) return false;
if (asset.id !== this.getPlaceAssetId()) return false;
return true;
}
// otherwise we got some random property that we may or may not support
switch (property) {
case "body":
if (
this.hasVessel() &&
this.getVesselAt(this.getAspectWithVessel()).is_body_of_substance
) {
return true;
}
return false;
case "takeable":
return asset.isDOV("take");
case "holding":
msg = `Is ${this.id} holding ${asset.id}? `;
this.game.log("log", "high", msg, "Tangible");
return this.IOVisConnectedToAsset("hold", asset);
case "held":
msg = `Is ${this.id} held by ${asset.id}? `;
this.game.log("log", "high", msg, "Tangible");
return this.DOVisConnectedToAsset("hold", asset);
case "nested in":
msg = `Is ${this.id} nested in ${asset.id}? `;
this.game.log("log", "high", msg, "Tangible");
if (this.getNestId) {
return this.getNestId() === asset.id;
}
return false;
default:
// no property
if ("undefined" === typeof this[property]) {
msg = `Tangible.$is() couldn't find a property ${property} on ${this.name}. `;
this.game.log("warn", "high", msg, "Tangible");
return false;
}
// property is object
if ("object" === typeof this[property]) {
msg = `Tangible.$is() is meant to return a boolean. ${this.name}'s ${property} is an object, which isn't handled by asset.$is(). `;
this.game.log("warn", "high", msg, "Tangible");
return false;
}
// property is something else
if ("boolean" !== typeof this[property]) {
// we'll return a string or a number with a warning
msg = `Tangible.$is() is meant to return a boolean. ${
this.name
}'s ${property} is ${typeof this[
property
]}, which isn't handled by asset.$is(). `;
this.game.log("warn", "high", msg, "Tangible");
return false;
}
return this[property];
} // switch
}; // adventurejs.Tangible.prototype.is
})();