Listing room exits manually

I have the default global setting for listing room exits turned off for my game as I have a specific room type that shouldn't display them and other more traditional rooms that should.

How would I go about doing something like I'm seeing in http://textadventures.co.uk/forum/quest/topic/spp_ltyb7e2d82dp3i88eq/changing-room-desciptions-when-multiple-items-are-removed but for exits as well?


The function ScopeExits() returns a list of exits in the current room. Or ScopeExitsForRoom(room) if you want the exits of another room.

So if you're putting it in the room description,, you could do You can go {=FormatList(ScopeExits(), ", ", ", or", "nowhere")}.

Or using the function from that other thread:

{=FancyObjectList("There are exits leading ", ScopeExits(), ".", "There is no way out!")}

You could also use GetExitsList() instead of ScopeExits() if you want to list only exits which aren't look-only or scenery.

Or if there's only one room that shouldn't display them, you could turn the default room description on, and just disable the "You can go:" line for that one room. You can put game.autodescription_youcango = 0 in that room's "before enter" script, and game.autodescription_youcango = 3 (or whatever it was initially set to) in the room's exit script.


I got this error for my only exit "out":

Error running script: Expected 1 parameter(s) in script 'msg ("You can go out")'

msg ("You begin inside a dark cave, you cannot see anything without the use of your phone's flashlight. You've been travelling in a general forward direction for what seems like forever until you notice a light in the distance that you hope is the exit.")
msg ("You can go {=FormatList(ScopeExits(), ", ", ", or", "nowhere")}")

Or using that FancyObjectList function:

Error running script: Error compiling expression '"You can go out."': SyntaxError: Unexpected token "You___SPACE___can___SPACE___go"

msg ("You begin inside a dark cave, you cannot see anything without the use of your phone's flashlight. You've been travelling in a general forward direction for what seems like forever until you notice a light in the distance that you hope is the exit.")
msg ("{=FancyObjectList ("You can go ", ScopeExits(), ".", "There is no way out!")}")


  <function name="FancyObjectList" parameters="preList, objects, postList, empty" type="string">
    if (TypeOf (objects) = "object") {
      objects = GetDirectChildren (objects)
    }
    if (ListCount (objects) = 0) {
      if (IsDefined ("empty")) {
        return (empty)
      }
      else {
        return ("")
      }
    }
    else if (ListCount (objects) = 2) {
      return (preList + FormatList (objects, ", ", " and ", "") + postList)
    }
    else {
      return (preList + FormatList (objects, ", ", ", and ", "") + postList)
    }
  </function>

If you're passing that string to msg, you need to put a \ before each ", so Quest knows it's not marking the end of the string. If you were including it in the room description, or in some other text field, the GUI would do that for you.

So this line:

msg ("{=FancyObjectList ("You can go ", ScopeExits(), ".", "There is no way out!")}")

should be:

msg ("{=FancyObjectList (\"You can go \", ScopeExits(), \".\", \"There is no way out!\")}")

or because there's no real need to encapsulate this if you're not putting it in a textual description field, you could use:

msg (FancyObjectList ("You can go ", ScopeExits(), ".", "There is no way out!"))

Okay so that works to display it as text but what about providing an actual link to the exit that the user can click rather than use the compass? So changing FancyObjectList as a whole to provide links to the objects/exits it spits out.


Ah… does FormatList only work with objects?
In that case, something like…

<function name="FancyObjectList" parameters="preList, objects, postList, empty, joiner" type="string">
  if (not IsDefined ("joiner")) {
    joiner = "and"
  }
  if (TypeOf (objects) = "object") {
    objects = GetDirectChildren (objects)
  }
  if (ListCount (objects) = 0) {
    if (IsDefined ("empty")) {
      return (empty)
    }
    else {
      return ("")
    }
  }
  else {
    result = ""
    itemsLeft = ListCount(objects)
    foreach (item, objects) {
      switch (TypeOf(item)) {
        case ("object", "exit") {
          result = result + GetDisplayNameLink(item, TypeOf(item))
        }
        case ("string") {
          result = result + item
        }
        default {
          result = result + ToString (item)
        }
      }
      itemsLeft = itemsLeft - 1
      if (itemsLeft > 0) {
        if (itemsLeft > 1 or (GetBoolean (game, "oxfordcomma") and not ListCount (objects) = 2)) {
          result = result + ", "
        }
        else {
          result = result + " "
        }
        if (itemsLeft = 1) {
          result = result + joiner + " "
        }
      }
    }
    return (Trim (result))
  }
</function>

(this version will look for a boolean attribute game.oxfordcomma, so you can make it use one or not as you see fit)


I'm getting this error:

You begin inside a dark cave, you cannot see anything without the use of your phone's flashlight. You've been travelling in a general forward direction for what seems like forever until you notice a light in the distance that you hope is the exit.
Error running script: Error compiling expression 'and': SyntaxError: Unexpected token "and"; expected one of "NOT", "-",

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="RPG Battle Engine Test">
    <gameid>9606deb8-fcbe-4076-bbf4-de25c7066f4b</gameid>
    <version>1.0</version>
    <firstpublished>2019</firstpublished>
    <customstatuspane />
    <feature_advancedscripts />
    <statusandcompassattop type="boolean">false</statusandcompassattop>
    <commandpane type="boolean">false</commandpane>
    <roomenter type="script"><![CDATA[
      // Attacks
      s = "<style>.button {background-color: red; color: white; padding: 10px 32px; border: 1px solid black; text-align: center; font-size: 14px; width:100%}</style>"
      s = s + "<style>.button2 {background-color: red; padding: 10px 32px; border: 1px solid black; text-align: center; font-size: 14px; width:100%} .button2 a { color:white }</style>"
      s = s + "<table style=\"border-collapse: separate;\" width=\"100%\">"
      s = s + "<tr><td style=\"text-align:center; text-decoration: underline;\" width=\"100%\"><p>Attacks</p></td></tr>"
      s = s + "<tr><td class=\"button\" onclick=\"ASLEvent('StatusLinkAttacks', 'Attack');\" style=\";cursor:pointer;\" title=\"Attack\">Attack</td></tr>"
      s = s + "<tr><td class=\"button\" onclick=\"ASLEvent('StatusLinkAttacks', 'Defend');\" style=\";cursor:pointer;\" title=\"Defend\">Defend</td></tr>"
      s = s + "<tr><td class=\"button\" onclick=\"ASLEvent('StatusLinkAttacks', 'Item');\" style=\";cursor:pointer;\" title=\"Item\">Item</td></tr>"
      s = s + "<tr><td class=\"button\" onclick=\"ASLEvent('StatusLinkAttacks', 'Flee');\" style=\";cursor:pointer;\" title=\"Flee\">Flee</td></tr>"
      s = s + "</table>"
      JS.setCustomStatus (s)
    ]]></roomenter>
    <start type="script">
    </start>
    <showdescriptiononenter type="boolean">false</showdescriptiononenter>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <usedefaultprefix type="boolean">false</usedefaultprefix>
    <description type="string"></description>
    <isroom />
    <enter type="script">
      msg ("You begin inside a dark cave, you cannot see anything without the use of your phone's flashlight. You've been travelling in a general forward direction for what seems like forever until you notice a light in the distance that you hope is the exit.")
      msg (FancyObjectList ("You can go ", ScopeExits(), ".", "There is no way out!"))
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit alias="in" to="room2">
      <inherit name="indirection" />
    </exit>
    <exit alias="out" to="room3">
      <inherit name="outdirection" />
    </exit>
  </object>
  <object name="room2">
    <inherit name="editor_room" />
    <exit alias="out" to="room">
      <inherit name="outdirection" />
    </exit>
  </object>
  <object name="room3">
    <inherit name="editor_room" />
  </object>
  <function name="StatusLinkAttacks" parameters="AttackName">
    AttackTheEnemy (player, AttackName)
  </function>
  <function name="AttackTheEnemy" parameters="player, attack" type="boolean">
    ClearScreen
    switch (attack) {
      case ("Attack") {
        msg ("The Player attacks")
      }
      case ("Defend") {
        msg ("The Player defends")
      }
      case ("Item") {
        msg ("The Player uses an item")
      }
      case ("Flee") {
        msg ("You fled the battle")
      }
    }
  </function>
  <function name="FancyObjectList" parameters="preList, objects, postList, empty, joiner" type="string"><![CDATA[
    if (not IsDefined ("joiner")) {
      joiner = AND
    }
    if (TypeOf (objects) = "object") {
      objects = GetDirectChildren (objects)
    }
    if (ListCount (objects) = 0) {
      if (IsDefined ("empty")) {
        return (empty)
      }
      else {
        return ("")
      }
    }
    else {
      result = ""
      itemsLeft = ListCount(list)
      foreach (item, list) {
        switch (TypeOf(item)) {
          case ("object", "exit") {
            result = result + GetDisplayNameLink(item, TypeOf(item))
          }
          case ("string") {
            result = result + item
          }
          default {
            result = result + ToString (item)
          }
        }
        itemsLeft = itemsLeft - 1
        if (itemsLeft > 0) {
          if (itemsLeft > 1 or (GetBoolean (game, "oxfordcomma") AND ListCount (objects) = 2)) {
            result = result + ", "
          }
          if (itemsLeft = 1) {
            result = result + joiner + " "
          }
        }
      }
      return (Trim (result))
    }
  ]]></function>
</asl>

Sorry, for some reason I had a missing quote.
I assume you already found this error, as you'd changed joiner = and to joiner = AND.
But as we're setting a string, it should be joiner = "AND"


Okay so adding the quotes to AND I now get this:

Error running script: Error compiling expression 'ListCount(list)': Unknown object or variable 'list'
Error running script: Object reference not set to an instance of an object.

There's a 'preList' and 'postList' parameter but not a 'list' one


Sorry, guess I was really not thinking straight when I wrote this. That should be ListCount (objects).


How would this line work too?

foreach (item, list)

Yeah, should be foreach (item, objects) { too.
I've updated the code in my post above. Hopefully there's no more silly mistakes I missed.


It works as plain text but not as a hyperlink despite the game.hyperlink, you also forgot the preList and postList usage.

https://imgur.com/a/89xXPHB

FancyObjectList (fixed)

<function name="FancyObjectList" parameters="preList, objects, postList, empty, joiner" type="string">
  if (not IsDefined ("joiner")) {
    joiner = "and"
  }
  if (TypeOf (objects) = "object") {
    objects = GetDirectChildren (objects)
  }
  if (ListCount (objects) = 0) {
    if (IsDefined ("empty")) {
      return (empty)
    }
    else {
      return ("")
    }
  }
  else {
    result = ""
    itemsLeft = ListCount(objects)
    foreach (item, objects) {
      switch (TypeOf(item)) {
        case ("object", "exit") {
          result = result + GetDisplayNameLink(item, TypeOf(item))
        }
        case ("string") {
          result = result + item
        }
        default {
          result = result + ToString (item)
        }
      }
      itemsLeft = itemsLeft - 1
      if (itemsLeft > 0) {
        if (itemsLeft > 1 or (GetBoolean(game, "oxfordcomma") and not ListCount (objects) = 2)) {
          result = result + ", "
        }
        else {
          result = result + " "
        }
        if (itemsLeft = 1) {
          result = result + joiner + " "
        }
      }
    }
	result = preList + result + postList
    return (Trim (result))
  }
</function>

It works as plain text but not as a hyperlink

Are you sure that game.enablehyperlinks is true?

Also, double check that the exits are visible; if they're not, then the scripts called by FinishTurn will cause the javascript to remove links again.


All exits are visible as well as the game.enablehyperlinks, you can check from the full game code I posted earlier, obviously replacing the broken version of the FancyObjectList with the one I posted before this.


https://imgur.com/a/ltoFbLa

Update: I think there's a way to do it with CommandLink(GetDisplayName(item),GetDisplayName(item)) but it's a bit of a hack and according to the documentation GetDisplayNameLink() should have worked but it's broken.


Ugh… can't believe I missed a dumb mistake so many times. TypeOf (item) is "object" for exits.

So

        case ("object", "exit") {
          result = result + GetDisplayNameLink(item, TypeOf(item))
        }

should be:

        case ("object") {
          if (DoesInherit (item, "defaultexit")) {
            result = result + GetDisplayNameLink(item, "exit")
          }
          else {
            result = result + GetDisplayNameLink(item, "object")
          }
        }

Excellent, that works a treat now.


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums