// selectVisible.js
(function () {
/* global adventurejs A */
var p = adventurejs.Parser.prototype;
/**
* Exclude from a list of assets all assets that are not visible to subject.
* @method adventurejs.Parser#selectVisible
* @memberOf adventurejs.Parser
* @param {Array} list
* @returns {Array}
* @todo consider global darkness
*/
p.selectVisible = function Parser_selectVisible(list) {
if ("string" === typeof list) list = [list];
if (!Array.isArray(list)) {
this.game.log(
"L1090",
"error",
"critical",
["[selectVisible.js] selectVisible() received non-array", list],
"Parser"
);
return [];
}
this.game.log(
"L1179",
"log",
"high",
`[selectVisible.js] selectVisible() receive:\n${list}`,
"Parser"
);
// we already know it's present
var input = this.game.getInput();
var subject = input.getSubject();
var room = this.game.getRoom();
var foundObjects = [];
var roomObjects = [];
var containers = [];
for (var i = 0; i < list.length; i++) {
var object = this.game.getAsset(list[i]); // may return substance
if (!object) continue;
// abstractions are always visible
if (object.is.abstract) {
foundObjects.push(list[i]);
continue;
}
// global objects are always visible, barring darkness
// @TODO probably some complexities to explore here,
// like seeing sun, moon, sky from underground
if (object.is.global) {
foundObjects.push(list[i]);
continue;
}
// if object is a plug, test against its parent
if (object.isConnectedToAsset("plug", object.getPlaceAsset(), "to_dov")) {
object = object.getPlaceAsset();
}
// check if input is unparsed substance
if (object instanceof adventurejs.Substance) {
// this version automatically returns substances as present
// foundObjects.push( list[i] );
// continue;
// this version looks for substance containers
if (!roomObjects.length) {
roomObjects = [room.id].concat(room.getAllNestedContents());
}
for (var j = 0; j < roomObjects.length; j++) {
var roomObject = this.game.getAsset(roomObjects[j]);
if (!subject.knowsAbout(roomObject)) continue;
var preposition = roomObject.containsSubstance(object.id);
if (preposition) {
// becomes for ex: bowl:in:water which can be handled by verbs
if (!subject.knowsAbout(`${roomObject.id}|${preposition}|vessel`))
continue;
containers.push(
roomObject.id + ":" + preposition + ":" + object.id
);
}
}
if (containers.length) {
containers = this.selectVisible(containers);
if (containers.length) {
foundObjects = foundObjects.concat(containers);
}
}
continue;
}
/*
// TODO selectVisible
get ambient light level
- get light provided by all lightsources?
get object's min_light_required_to_see
hidden in a container - visible? or reachable?
also consider container's opacity
*/
if (object.is.hidden) {
continue;
}
// if it has no parent, and it's not a room,
// then it's not present in the world
if (
!object.hasClass("Substance") &&
!object.getPlaceAsset() &&
!(object instanceof adventurejs.Room)
) {
continue;
}
/**
* If object's anscestor is closed we'll consider it not visible
* unless it's nested in subject inventory. We'll be nice and
* let subject access their inventory without having to
* open every damned container.
*
* In theory we could do the same for any nested & known objects,
* but that could raise unpredictable problems in situations like taking
* objects from NPCs, or inadvertently triggering custom functions.
*/
//console.warn( 'selectVisible > areAnscestorsClosed()',object.areAnscestorsClosed() );
if (
!object.isWithin(subject) &&
object.areAnscestorsClosed &&
object.areAnscestorsClosed()
) {
continue;
}
/**
* Omit if any of object's
* anscestors are unknown. It's possible for a known
* object to be inside an unknown object, but this state
* is unlikely to happen by accident, so we'll take unknown
* anscestors to mean the object was deliberately hidden.
*/
if (object.areAnscestorsUnknown && object.areAnscestorsUnknown()) {
continue;
}
// TODO is parent transparent?
// drain with plug
// bottle with plug
foundObjects.push(list[i]);
}
//console.log( "selectVisible returned " + JSON.stringify(foundObjects) );
return foundObjects;
};
})();