// getRoomExits.js
(function () {
/* global AdventureJS A */
var p = AdventureJS.Game.prototype;
/**
*
* @memberOf AdventureJS.Game
* @method AdventureJS.Game#getRoomExits
* @returns {String} A formatted list of exits.
* @param {Object} room A room to get exits of. Defaults to current room.
*/
p.getRoomExits = function Game_getRoomExits(
room = this.world[this.world._room]
) {
// loop through exits, which are nested objects
// we need index/length to handle our punctuation logic
// but we don't get that by enumerating properties
// so instead we use object.keys
var exits = Object.keys(room.exits);
var exit_id, destination;
var closed = [];
var output = "";
if (room.hasDescription("exits")) {
let exits_description = A.FX.getSAF.call(
this.game,
room.descriptions.exits
);
if (room.hasDescription("append_exits")) {
exits_description =
exits_description +
A.FX.getSAF.call(this.game, room.descriptions.append_exits);
}
return `<span class="ajs-room-exits">${exits_description}</span>`;
}
const print_named =
room.print_named_exits === true ||
(room.print_named_exits !== false &&
this.game.settings.print_named_exits === true);
const print_directional =
room.print_directional_exits === true ||
(room.print_directional_exits !== false &&
this.game.settings.print_directional_exits === true);
for (var i = exits.length - 1; i > -1; i--) {
const exit = this.game.getAsset(room.exits[exits[i]]);
const dest = this.game.getAsset(exit.destination);
// don't list exits without destinations
if (!dest) {
exits.splice(i, 1);
continue;
}
// follow settings for printing named exits
if (exit.is.named && !print_named) {
exits.splice(i, 1);
continue;
}
// follow settings for printing directional exits
if (exit.is.directional && !print_directional) {
exits.splice(i, 1);
continue;
}
// move closed exits to separate list
if (exit.is.closed) {
closed.push(exit);
exits.splice(i, 1);
continue;
}
}
// no exits?
if (!exits.length && !closed.length) {
return false;
}
// this will need to be more sophisticated,
// checking against visibility and knowledge
if (exits.length) output += "{We} can go ";
for (var i = 0; i < exits.length; i++) {
const exit = this.game.getAsset(room.exits[exits[i]]);
destination = this.game.getAsset(exit.destination);
// last item in the list
if (exits.length > 1 && i === exits.length - 1) {
output += "or ";
}
// depending on settings, we're going to want
// a custom label
// just the direction name
// or the direction name + name of destination
let label = A.FX.getSAF.call(this.game, exit.descriptions.label);
// author provided a description
if (label) {
// add <a>?
if (
this.game.settings.print_exits_links &&
this.game.settings.prints_exits_links_around_custom_labels
) {
// label = `<a href="#"
// onclick="window.${this.game.game_name}.sendToParser('${exit.direction}')">${label.trim()}</a>`;
label = `
<a href="#"
class="ajs-exit-link"
data-destination = "${exit.direction}"
>${label.trim()}</a>
`;
} else if (this.game.settings.print_exits_links) {
// `<span class="ajs-exit-direction"><a href="#"
// onclick="window.${this.game.game_name}.sendToParser('${exit.direction}')">`
label = label
.replace(
"<a>",
`<span
class="ajs-exit-direction"
><a href="#"
class="ajs-exit-link"
data-destination = "${exit.direction}"
>`
)
.replace("</a>", `</a></span>`);
}
output += `<span class="ajs-custom-exit-name">${label}</span>`;
}
// get exit name and if logic permits,
// also get preposition, article, destination name
else {
label = `<span class="ajs-extended-exit-name">${this.getExtendedExitName(
exit,
destination
)}</span>`;
output += label;
} // else
if (i === exits.length - 1) {
output += ". ";
} else {
output += ", ";
}
}
let apertures = [];
if (closed.length) {
for (let i = closed.length - 1; i > -1; i--) {
const aperture = this.game.getAsset(closed[i].aperture);
if (aperture) {
apertures.push(aperture);
closed.splice(i);
}
}
}
if (apertures.length) {
let sentence = "";
for (var i = 0; i < apertures.length; i++) {
let aperture = apertures[i];
let direction = aperture.direction;
if (this.game.settings.print_exits_links) {
// direction = `<a href="#"
// onclick="window.${this.game.game_name}.sendToParser('${direction}')">${direction}</a>`;
direction = `
<a href="#"
class="ajs-exit-link"
data-destination = "${direction}"
>${direction}</a>`;
}
sentence += `${aperture.article_name} leading ${direction}`;
if (i === 0) sentence += ` is closed`;
if (apertures.length > 1 && i === 0) {
sentence += `, as ${apertures.length > 2 ? "are" : "is"} `;
}
if (apertures.length > 2 && i > 0 && i < apertures.length - 2)
sentence += `, `;
if (apertures.length > 2 && i === apertures.length - 2)
sentence += `, and `;
}
sentence = A.FX.capitalize(sentence);
sentence += `. `;
output += sentence;
}
// What remains in closed is exits without apertures.
// We don't expect exits without apertures to be closed
// but there's nothing stopping an author from doing it.
if (closed.length) {
output += `${closed.length > 1 ? "Ways " : "A way "} `;
for (var i = 0; i < closed.length; i++) {
let lookup = this.game.dictionary.direction_lookup[closed[i].direction];
if (i > 0 && i < closed.length - 1) {
output += ", ";
}
if (closed.length > 1 && i === closed.length - 1) {
output += " and ";
}
if (i === 0 && lookup.article) output += `to ${lookup.article} `;
output += closed[i].direction;
}
output += `${closed.length > 1 ? " are" : " is"} blocked. `;
}
if (room.hasDescription("append_exits")) {
output =
output + A.FX.getSAF.call(this.game, room.descriptions.append_exits);
}
return `<span class="ajs-room-exits">${output}</span>`;
};
})();