Pre-release
AdventureJS Docs Downloads Bundler Devlog Score: 0 Moves: 0
// 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>`;
  };
})();