KV's Old Nautical Directions Library? [[paranormally solved?]]

Anyone have a copy of it that I could copy? It used to be available here (now just a 404 error):

http://textadventures.co.uk/forum/samples/topic/45kehg8oz0_7eumput3cag/nautical-directions

Does it even work with ASLX version 580?


Mister Pixie made one too

https://github.com/ThePix/quest/wiki/Library:-Port-and-starboard


It is there for me.

It is better than mine as it allows you to swap between the two.


The link posted by Dcoder works for me too.

Is there any way to take advantage of that library when working with the web editor?


There have been unsubstantiated rumors of KV-like poltergeist sightings. One such report has it that a mysterious entity has updated the Nautical Directions link that I referred to earlier. Thank you ghost!


  • "...KV-like poltergeist sightings."

It was probably Richard Headkid. See below...

hit RH
Your hand goes right through him. "Pseudonym," says RH, pointing a thumb at himself.

hit RH
"You can't hit me. Just give up," says RH.

hit RH
"How many times do you think I'll give a different response?" asks RH.

hit RH
"This is fun, isn't it?" sighs RH.

hit RH
"Why do you keep trying to hit me, man? That's not very Fonzie-like." RH shakes his head and goes back to work on the group project.

http://textadventures.co.uk/games/view/jymfhimg00c5cvrdqna7xa/pixies-quest


So is there any way to take advantage of that library when working with the web editor?


No. The web editor has a few restrictions, and these libraries use pretty much all of them: type, aliases for exits, templates, embedded JavaScript. I will have a think about whether there is an alternative approach.


If you figure something out, I'd love to take advantage of it. I am using the web editor to create a game set on a ship, so using starboard/port would be much cooler.


So far the ideas I had came to nothing. It may not be possible.


I tried a few things online, too. Nothing worked. (I still have a couple of ideas, though.)


I didn't even know we can't set a non-directional exit's alias in the GUI online (and I just now noticed that Pixie mentioned this in a previous post in this thread). Even if we name the exit, the alias of the room the exit leads to is what is displayed in the exit list.

I had to name the exit then change the alias of that exit in the start script to add an alias.


Okay... I made it work online, but it works a little differently.

...and this will not be over quickly.

For online users:


Add this line of code to your start script in code view:

SetupNautical

image


Turn on the advanced scripts for the game object.

image


Add this to the User Interface Initialisation script in code view:

SendToJsEval (js.description)
JS.changeCompass ()

image


Create a turn script named nautical_buttons_turnscript.

Paste this in for the script in code view:

// Version 2
if (ListCount(FilterByAttribute (ListParents(game.pov), "shiptype", true)) > 0) {
  list = NewStringList()
  foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
    list add (list, exit.alias)
  }
  JS.updateShipCompass (Join(list, "/"))
}

image


Create a room named js.

Past this into the description as text (NOT in code view):

var onBoard = false;
var shipButtons = '<div id="dir-holder" style="display:none;"><div id="ship-nav"><table id="ship-directions"><tr><td></td><td>';
shipButtons += '<button id="cmdCompassF" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="fore" onclick="compassClick(\'fore\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-n" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';
shipButtons += '<tr><td><button id="cmdCompassP" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="port" onclick="compassClick(\'port\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-w" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></td><td></td><td></button>';
shipButtons += '<button id="cmdCompassSB" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="starboard" onclick="compassClick(\'starboard\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-e" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';
shipButtons += '<tr><td></td><td><button id="cmdCompassA" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="aft" onclick="compassClick(\'aft\');" role="button" ><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-s" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr></table>';
shipButtons += '</div></div>';
function changeCompass(){
  $('body').append(shipButtons);
  $("#ship-directions").css("border-spacing","0");
  $("#cmdCompassNW").parent().parent().parent().attr('id','def-nav');
  $('#ship-nav').hide();$('#def-nav').parent().append($('#dir-holder').html());
  $(".shipcompassbutton").each(function(){
    $(this).button().button("enable").button("disable");
    $(".shipcompassbutton span").css("left", "0.8em");$(".shipcompassbutton .ui-button-text").css('padding','.8em .8em');
  });
};
function toggleNav(){
  $("#def-nav, #ship-nav").toggle()
};
function updateShipCompass(data){
  var exits = data.split("/");
  $(".shipcompassbutton").each(function(){
    for (var exit in exits){
      if($(this).attr('title') === exits[exit]){
        $(this).button("enable");
        break;
      }else{
        $(this).button("disable");
      }
    }
  });
};

image


Create a function named SetupNautical

(It has no parameters, nor does it have a return type.)

Paste this in for the script in code view:

game.compassdirections = ListExclude (game.compassdirections, "")
list add (game.compassdirections, "fore")
list add (game.compassdirections, "port")
list add (game.compassdirections, "starboard")
list add (game.compassdirections, "aft")
list add (game.compassdirections, "f")
list add (game.compassdirections, "p")
list add (game.compassdirections, "sb")
list add (game.compassdirections, "a")
request (SetCompassDirections, Join(game.compassdirections, ";"))
go.pattern = "^go to (?"+Chr(60)+"exit>.*)$|^go (?"+Chr(60)+"exit>.*)$|^(?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
lookdir.pattern = "^look (?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
foreach (exit, AllExits()) {
  if (StartsWith (exit.name, "fore")) {
    exit.alias = "fore"
    exit.alt = Split("f;forward")
  }
  if (StartsWith (exit.name, "aft")) {
    exit.alias = "aft"
    exit.alt = Split("a")
  }
  if (StartsWith (exit.name, "port")) {
    exit.alias = "port"
    exit.alt = Split("p")
  }
  if (StartsWith (exit.name, "starboard")) {
    exit.alias = "starboard"
    exit.alt = Split("sb")
  }
}

image


Create a function named SendToJsEval

Add the parameter data

(It has no return value.)

Paste this in for the script in code view:

regEx = "//"
s = Chr(60) + "br/>"
js = Split(data,s)
notes = NewStringList()
foreach (line, js) {
  if (StartsWith(line,"//")) {
    list add (notes, line)
  }
}
js = ListExclude(js,notes)
finaljs = NewStringList()
foreach (line, js) {
  code = line
  if (IsRegExMatch(regEx,line)) {
    list = Split(line,"//")
    code = list[0]
  }
  list add (finaljs, code)
}
js = Join(finaljs,"")
js = Replace(js, "[br]", s)
js = Replace(js, "[br/]", s)
js = Replace(js, "[break]", s)
js = Replace(js, "[linebreak]", s)
js = Replace(js, "[line break]", s)
JS.eval (js)

image


Now, the way this works is....

A turn script checks to see if the game.pov object's parent object's parent has the boolean attribute "shiptype" set to true.

So, create a room which symbolizes an entire ship (mine is called ship). Then, go to the "Features" tab and select "Run an initialisation script for this object."

image


Now go to the new "Initialisation script" tab of that new ship object, and paste this into code view:

this.shiptype = true

image


From this point,

Each time you create a room that will be part of the ship, just use the "Move" button to move each room to a ship once the new room is created.

image


For exits which lead in and out of ships

You'll need to set up a script on any exit that leads in and/or out of a ship.

Paste this into code view for the script:

JS.toggleNav ()
MoveObject (player, this.to)

image


If your game begins onboard a ship (as my example does)

You'll want to paste this into the first room's "After entering for the first time" script:

JS.toggleNav ()
do (nautical_buttons_turnscript, "script")

image


For the nautical exits

UPDATE This function will save you from doing the stuff in this section.

You will need to create each exit as a non-directional exit. (This means you will have to create each exit, without being able to create the exit from the opposite direction at the same time.)

You can't set the alias online, so you have to use the exit's name. And this is where it gets taxing. If you have more than one exit which will lead aft, you can only actually name one of the exits "aft". But, with this setup, as long as your exit's name begins with "aft", my function will set the exit's alias to "aft". (The same goes for "fore", "port", and "starboard".)

So, you can do it like: "aft", "aft1", "fore"

Or you could do it like: "aft_to_bridge", "aft_to_cabin", "fore_to_bridge"


I made this test game online:

http://textadventures.co.uk/games/view/nc_b5jyqoksm2q_4zdefjg/online-ship

Here's the entire code:

<!--Saved by Quest 5.7.6615.29455-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Online Ship">
    <gameid>85e47918-aea4-4e27-82c3-67454a3ac51a</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <menufont>Georgia, serif</menufont>
    <attr name="feature_advancedwearables" type="boolean">false</attr>
    <feature_advancedscripts />
    <start type="script">
      SetupNautical
    </start>
    <inituserinterface type="script">
      SendToJsEval (js.description)
      JS.changeCompass ()
    </inituserinterface>
  </game>
  <turnscript name="nautical_buttons_turnscript">
    <enabled />
    <script>
      if (HasAttribute (game.pov.parent, "parent")) {
        if (GetBoolean(game.pov.parent.parent,"shiptype")) {
          list = NewStringList()
          foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
            list add (list, exit.alias)
          }
          JS.updateShipCompass (Join(list, "/"))
        }
      }
    </script>
  </turnscript>
  <object name="ship">
    <inherit name="editor_object" />
    <feature_startscript />
    <attr name="_initialise_" type="script">
      this.shiptype = true
    </attr>
    <object name="cabin">
      <inherit name="editor_room" />
      <firstenter type="script">
        JS.toggleNav ()
        do (nautical_buttons_turnscript, "script")
      </firstenter>
      <object name="player">
        <inherit name="editor_object" />
        <inherit name="editor_player" />
      </object>
      <exit name="fore" to="bridge" />
      <exit name="port1" to="entry bay" />
    </object>
    <object name="bridge">
      <inherit name="editor_room" />
      <exit name="aft" to="cabin" />
      <exit name="fore1" to="engine room" />
    </object>
    <object name="storage">
      <inherit name="editor_room" />
      <exit name="starboard" to="engine room" />
    </object>
    <object name="engine room">
      <inherit name="editor_room" />
      <exit name="aft1" to="bridge" />
      <exit name="port" to="storage" />
    </object>
    <object name="entry bay">
      <inherit name="editor_room" />
      <exit name="starboard1" to="cabin" />
      <exit alias="down" to="landing pad">
        <inherit name="downdirection" />
        <runscript />
        <script type="script">
          JS.toggleNav ()
          MoveObject (player, this.to)
        </script>
      </exit>
    </object>
  </object>
  <object name="js">
    <inherit name="editor_room" />
    <description><![CDATA[var onBoard = false;<br/>var shipButtons = '<div id="dir-holder" style="display:none;"><div id="ship-nav"><table id="ship-directions"><tr><td></td><td>';<br/>shipButtons += '<button id="cmdCompassF" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="fore" onclick="compassClick(\'fore\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-n" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td><button id="cmdCompassP" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="port" onclick="compassClick(\'port\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-w" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></td><td></td><td></button>';<br/>shipButtons += '<button id="cmdCompassSB" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="starboard" onclick="compassClick(\'starboard\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-e" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td></td><td><button id="cmdCompassA" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="aft" onclick="compassClick(\'aft\');" role="button" ><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-s" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr></table>';<br/>shipButtons += '</div></div>';<br/>function changeCompass(){<br/>  $('body').append(shipButtons);<br/>  $("#ship-directions").css("border-spacing","0");<br/>  $("#cmdCompassNW").parent().parent().parent().attr('id','def-nav');<br/>  $('#ship-nav').hide();$('#def-nav').parent().append($('#dir-holder').html());<br/>  $(".shipcompassbutton").each(function(){<br/>    $(this).button().button("enable").button("disable");<br/>    $(".shipcompassbutton span").css("left", "0.8em");$(".shipcompassbutton .ui-button-text").css('padding','.8em .8em');<br/>  });<br/>};<br/>function toggleNav(){<br/>  $("#def-nav, #ship-nav").toggle()<br/>};<br/>function updateShipCompass(data){<br/>  var exits = data.split("/");<br/>  $(".shipcompassbutton").each(function(){<br/>    for (var exit in exits){<br/>      if($(this).attr('title') === exits[exit]){<br/>        $(this).button("enable");<br/>        break;<br/>      }else{<br/>        $(this).button("disable");<br/>      }<br/>    }<br/>  });<br/>};]]></description>
  </object>
  <object name="landing pad">
    <inherit name="editor_room" />
    <exit alias="up" to="entry bay">
      <inherit name="updirection" />
      <runscript />
      <script type="script">
        JS.toggleNav ()
        MoveObject (player, this.to)
      </script>
    </exit>
  </object>
  <function name="SetupNautical"><![CDATA[
    game.compassdirections = ListExclude (game.compassdirections, "")
    list add (game.compassdirections, "fore")
    list add (game.compassdirections, "port")
    list add (game.compassdirections, "starboard")
    list add (game.compassdirections, "aft")
    list add (game.compassdirections, "f")
    list add (game.compassdirections, "p")
    list add (game.compassdirections, "sb")
    list add (game.compassdirections, "a")
    request (SetCompassDirections, Join(game.compassdirections, ";"))
    go.pattern = "^go to (?"+Chr(60)+"exit>.*)$|^go (?"+Chr(60)+"exit>.*)$|^(?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    lookdir.pattern = "^look (?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    foreach (exit, AllExits()) {
      if (StartsWith (exit.name, "fore")) {
        exit.alias = "fore"
        exit.alt = Split("f;forward")
      }
      if (StartsWith (exit.name, "aft")) {
        exit.alias = "aft"
        exit.alt = Split("a")
      }
      if (StartsWith (exit.name, "port")) {
        exit.alias = "port"
        exit.alt = Split("p")
      }
      if (StartsWith (exit.name, "starboard")) {
        exit.alias = "starboard"
        exit.alt = Split("sb")
      }
    }
  ]]></function>
  <function name="SendToJsEval" parameters="data"><![CDATA[
    regEx = "//"
    s = Chr(60) + "br/>"
    js = Split(data,s)
    notes = NewStringList()
    foreach (line, js) {
      if (StartsWith(line,"//")) {
        list add (notes, line)
      }
    }
    js = ListExclude(js,notes)
    finaljs = NewStringList()
    foreach (line, js) {
      code = line
      if (IsRegExMatch(regEx,line)) {
        list = Split(line,"//")
        code = list[0]
      }
      list add (finaljs, code)
    }
    js = Join(finaljs,"")
    js = Replace(js, "[br]", s)
    js = Replace(js, "[br/]", s)
    js = Replace(js, "[break]", s)
    js = Replace(js, "[linebreak]", s)
    js = Replace(js, "[line break]", s)
    JS.eval (js)
  ]]></function>
</asl>

PS

ONLINE USERS

You could also use this and just select north, south, west, or east for the exits for rooms onboard a ship. This will change north to fore, south to aft, west to port, and east to starboard:


Create a function named ChangeDirToNautical.

(It needs no parameters, nor does it need a return type.)

Paste this into the script in code view:

foreach (exit, AllExits()) {
  if (ListCount(FilterByAttribute (ListParents(exit), "shiptype", true)) > 0) {
    if (exit.alias = "north") {
      exit.visible = false
      newname = "" + GetUniqueElementName("fore")
      create exit (newname, "fore", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("f;forward")
    }
    else if (exit.alias = "south") {
      exit.visible = false
      newname = "" + GetUniqueElementName("aft")
      create exit (newname, "aft", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("a")
    }
    else if (exit.alias = "west") {
      exit.visible = false
      newname = "" + GetUniqueElementName("port")
      create exit (newname, "port", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("p")
    }
    else if (exit.alias = "east") {
      exit.visible = false
      newname = "" + GetUniqueElementName("starboard")
      create exit (newname, "starboard", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("sb")
    }
  }
}

At the very, very end of the SetupNautical function, add this line:

ChangeDirToNautical

image


I have added a spa room to my ship object. I created an exit to the east from the cabin to the spa, and I selected "Also create exit in the other direction."

This function changes the exit from the cabin to the spa to "starboard" and the exit from the spa to the cabin (which begins as west) to "port".

image



...and this will not be over quickly.

Boy, you weren't kidding about that!

Sorry to butt in, but on a different note...

KV, I could not get your latest Nautical Library (2018/6/20) to work. I made a barebones TA desktop game with Pixie's latest update 5.8 beta10. I added a "shiptype" type to the game's Advanced --> Object Types (needed for game to work with library), and then added your library. I followed all of the instructions:

I'm not using the NPC library.

All rooms are in a parent room having the "shiptype" type.

All exits have inherited the correct nautical direction type.

These two lines have been added to the IUI tab:

SendToJsEval (js.description)
JS.changeCompass ()

The game doesn't show the nautical directions, just the standard ones. I tried changing the exit aliases to their nautical names, but of course then the compass buttons don't work.

Barebones game:

<!--Saved by Quest 5.8.6747.20202-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <include ref="NauticalDirectionsLib.aslx" />
  <game name="Nautical Map">
    <gameid>1339903a-f9a3-492d-b0b9-fd5bfa31414b</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <inituserinterface type="script">
      SendToJsEval (js.description)
      JS.changeCompass ()
    </inituserinterface>
  </game>
  <object name="INSIDE">
    <inherit name="editor_room" />
    <inherit name="shiptype" />
    <object name="room1">
      <inherit name="editor_room" />
      <inherit name="shiptype" />
      <object name="player">
        <inherit name="editor_object" />
        <inherit name="editor_player" />
      </object>
      <exit name="R1toR2" alias="south" to="room2">
        <inherit name="aftdirection" />
        <inherit name="southdirection" />
      </exit>
    </object>
    <object name="room2">
      <inherit name="editor_room" />
      <inherit name="shiptype" />
      <exit name="R2toR1" alias="north" to="room1">
        <inherit name="foredirection" />
        <inherit name="northdirection" />
      </exit>
    </object>
  </object>
  <type name="shiptype" />
</asl>

Your latest Nautical Library that I used:

<?xml version="1.0"?>
<library>

<!--

NauticalDirectionsLib
Version: 1.2
By: KV
Quest version: 5.8
Special thanks: Doctor Agon and The Pixie


INSTRUCTIONS:

If you are using NpcLib, this should be included AFTER it in the game's code for this NiceDirection() mod to work!

All rooms on a ship need to have a parent object which inherits "shiptype".

In order for the shortcut commands to work, you must add the appropriate type to the exit.

You do not need to change your exits' names or aliases. The script will turn the alias of each exit which is in a "shiptype" object to a nautical exit alias, as long as the exit inherits one of the nautical direction types.

Types:
"foredirection"
"portdirection"
"starboarddirection"
"aftdirection"

The shortcut commands:
fore, forward, f, port, p, starboard, sb, s, aft, a


IMPORTANT:

	ADD THE FOLLOWING 2 LINES TO THE GAME OBJECT'S inituserinterface
		
		SendToJsEval (js.description)
		JS.changeCompass ()

-->




  <turnscript name="nautical_buttons">
    <enabled />
    <script>
      if (DoesInherit(game.pov.parent.parent,"shiptype")) {
        list = NewStringList()
        foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
          list add (list, exit.alias)
        }
        JS.updateShipCompass (Join(list, "/"))
      }
    </script>
  </turnscript>

  <object name="js">
    <description><![CDATA[var onBoard = false;<br/><br/>var shipButtons = '<div id="dir-holder" style="display:none;"><div id="ship-nav"><table id="ship-directions"><tr><td></td><td>';<br/>shipButtons += '<button id="cmdCompassF" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="fore" onclick="compassClick(\'fore\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-n" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td><button id="cmdCompassP" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="port" onclick="compassClick(\'port\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-w" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></td><td></td><td></button>';<br/>shipButtons += '<button id="cmdCompassSB" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="starboard" onclick="compassClick(\'starboard\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-e" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td></td><td><button id="cmdCompassA" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="aft" onclick="compassClick(\'aft\');" role="button" ><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-s" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr></table>';<br/>shipButtons += '</div></div>';<br/><br/>function changeCompass(){<br/>  addText(shipButtons);$("#ship-directions").css("border-spacing","0");<br/>  $("#cmdCompassNW").parent().parent().parent().attr('id','def-nav');<br/>  $('#ship-nav').hide();$('#def-nav').parent().append($('#dir-holder').html());<br/>  $(".shipcompassbutton").each(function(){<br/>    $(this).button().button("enable").button("disable");<br/>    $(".shipcompassbutton span").css("left", "0.8em");$(".shipcompassbutton .ui-button-text").css('padding','.8em .8em');<br/>  });<br/>};<br/><br/>function toggleNav(){<br/>  $("#def-nav, #ship-nav").toggle()<br/>};<br/><br/>function updateShipCompass(data){<br/>  var exits = data.split("/");<br/>  $(".shipcompassbutton").each(function(){<br/>    for (var exit in exits){<br/>      if($(this).attr('title') === exits[exit]){<br/>        $(this).button("enable");<br/>        break;<br/>      }else{<br/>        $(this).button("disable");<br/>      }<br/>    }<br/>  });<br/>};<br/>]]></description>
  </object>

  <type name="shiptype">
    <compassTableShip />
    <captain type="object"></captain>
    <ramp type="object"></ramp>
    <destination type="object"></destination>
    <attr name="_initialise_" type="script">
      SetNauticalExitAliases
    </attr>
    <attr name="locations_visited" type="objectlist"></attr>
    <course type="objectlist"></course>
    <shipDirs type="stringdictionary">
      <item>
        <key>north</key>
        <value>fore</value>
      </item>
      <item>
        <key>east</key>
        <value>starboard</value>
      </item>
      <item>
        <key>west</key>
        <value>port</value>
      </item>
      <item>
        <key>south</key>
        <value>aft</value>
      </item>
    </shipDirs>
  </type>

  <type name="foredirection">
    <inherit name="compassdirection" />
    <alias>fore</alias>
    <alt type="stringlist">
      <value>f</value>
      <value>forward</value>
    </alt>
  </type>

  <type name="portdirection">
    <inherit name="compassdirection" />
    <alias>port</alias>
    <alt type="stringlist">
      <value>p</value>
    </alt>
  </type>

  <type name="starboarddirection">
    <inherit name="compassdirection" />
    <alias>starboard</alias>
    <alt type="stringlist">
      <value>sb</value>
    </alt>
  </type>

  <type name="aftdirection">
    <inherit name="compassdirection" />
    <alias>aft</alias>
    <alt type="stringlist">
      <value>a</value>
    </alt>
  </type>

  <function name="SetNauticalExitAliases"><![CDATA[
    ship.compassdirections = ListExclude(ship.compassdirections,"")
    list add (game.compassdirections, "fore")
    list add (game.compassdirections, "port")
    list add (game.compassdirections, "starboard")
    list add (game.compassdirections, "aft")
    list add (game.compassdirections, "f")
    list add (game.compassdirections, "p")
    list add (game.compassdirections, "sb")
    list add (game.compassdirections, "a")
    request (SetCompassDirections, Join(game.compassdirections, ";"))
    go.pattern = "^go to (?<exit>.*)$|^go (?<exit>.*)$|^(?<exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
      lookdir.pattern = "^look (?<exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    foreach (exit, AllExits()) {
      if (DoesInherit(exit.parent.parent, "shiptype")) {
        alias = exit.alias
        if (DictionaryContains(game.shipDirs, alias)) {
          repl = StringDictionaryItem(game.shipDirs,alias)
          exit.alias = repl
        }
      }
    }
  ]]></function>

  <function name="SendToJsEval" parameters="data"><![CDATA[
    regEx = "//"
    js = Split(data,"<br/>")
    notes = NewStringList()
    foreach (line, js) {
      if (StartsWith(line,"//")) {
        list add (notes, line)
      }
    }
    js = ListExclude(js,notes)
    finaljs = NewStringList()
    foreach (line, js) {
      code = line
      if (IsRegExMatch(regEx,line)) {
        list = Split(line,"//")
        code = list[0]
      }
      list add (finaljs, code)
    }
    js = Join(finaljs,"")
    js = Replace(js, "[br]", "<br/>")
    js = Replace(js, "[br/]", "<br/>")
    js = Replace(js, "[break]", "<br/>")
    js = Replace(js, "[linebreak]", "<br/>")
    js = Replace(js, "[line break]", "<br/>")
    JS.eval (js)
  ]]></function>


  <!--
  
  TODO: 
	Add tabs so simplify setup.
	
	Fix the CSS on the compass. The buttons are a little too far apart.
  -->

<!-- Fix ReverseDirection() and NiceDirection() -->

  <function name="ReverseDirection" parameters="dir" type="string">
    list1 = Split("north;northeast;east;southeast;south;southwest;west;northwest;up;down;in;out;fore;port;starboard;aft", ";")
    list2 = Split("south;southwest;west;northwest;north;northeast;east;southeast;down;up;out;in;aft;starboard;port;fore", ";")
    n = IndexOf(list1, dir)
    if (not n = -1) {
      return (StringListItem(list2, n))
    }
    return (dir)
  </function>

	<function name="NiceDirection" parameters="exit, addthe" type="string">
	   switch (exit.alias) {
		 case ("in") { s = "inside" }
		 case ("out") { s = "outside" }
		 case ("up") { s = "above" }
		 case ("down") { s = "below" }
		  //Added by KV for Nautical Directions:
		  case ("starboard") {
			s = "port"
			addthe = false
		  }
		  case ("port") {
			s = "starboard"
			addthe = false
		  }
		  case ("aft") {
			s = "fore"
			addthe = false
		  }
		  case ("fore") {
			s = "aft"
			addthe = false
		  }
		  // End of KV's addition
		 default {
		   if (addthe) {
			 s = "the " + exit.alias
		   }
		   else {
			 s = exit.alias
		   }
		 }
	   }
	   return (s)
	 </function>
  
  </library>

UPDATE: Finally got the "details" tag to work. Just trying to conserve space to help tired eyes and wrists.


Technically speaking, you can set up whatever needs to be done to see JavaScript in the regular view in the game's code, instead of code view. Then you either paste or type the rest of the code in. I think I did that once.

Just saying, you do not need the room description. I think.
But your thing does make it easier to paste in fast, I'll give you that.


I added a "shiptype" type to the game's Advanced --> Object Types (needed for game to work with library)

That's already in the library. You shouldn't have to add that type.

Oh... I had some game-specific attributes (captain, destination, etc) which were throwing errors.

Revised library:
http://textadventures.co.uk/games/view/tc6_kfxsteafa-ecf7sqew/nauticaldirectionslib


Also note that the library stuff behaves differently than the online stuff.

So mixing and matching code from one to the other would more than likely cause problems.


How well are you doing so far?

Honestly, I think it would be easier if KV adapted The Pixie's nautical directions code to the online version.


First of all, a big thank you to Richard Headkid for all of this code! I've finally finished adding all of it to my game. I had already created all of the rooms and exits, so I've moved the rooms into a new 'ship' object (although I named it differently).

Unfortunately, all of the exits remain north, west, etc... The compass arrows are disabled.

Maybe this is complicated by the fact that my first room is actually an 'Object and/or room' with the only exit being 'out'. I've moved the lines below from that room to the room that contains it.

JS.toggleNav ()
do (nautical_buttons_turnscript, "script")

That didn't help. Of course, that room's exits are 'in' and 'down', so the first room where the nautical directions would matter is actually the 3rd room the player encounters. I moved the above lines to that room instead, but still no change...


Send me a link to your game (or post the code), and I'll see what I can do to help.


Here it is (I noticed that I hadn't enabled the nautical_buttons_turnscript after I posted this, so I fixed that):

<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Red Alert">
    <gameid>5d168f57-b215-43fb-b260-9d2c82c05bfc</gameid>
    <version>1.1</version>
    <firstpublished>2018</firstpublished>
    <author>Eric Caillibot</author>
    <category>Sci-Fi</category>
    <showscore />
    <menufont>Georgia, serif</menufont>
    <feature_limitinventory />
    <attr name="feature_lightdark" type="boolean">false</attr>
    <attr name="feature_asktell" type="boolean">false</attr>
    <attr name="feature_annotations" type="boolean">false</attr>
    <attr name="feature_advancedwearables" type="boolean">false</attr>
    <feature_advancedscripts />
    <appendobjectdescription />
    <showcommandbar type="boolean">false</showcommandbar>
    <gridmap type="boolean">false</gridmap>
    <mapscale type="int">1</mapscale>
    <mapsize type="int">1</mapsize>
    <respondtogridclicks type="boolean">false</respondtogridclicks>
    <attr name="autodescription_youarein_useprefix" type="boolean">false</attr>
    <attr name="autodescription_youcansee" type="int">3</attr>
    <attr name="autodescription_youcango" type="int">4</attr>
    <attr name="autodescription_description" type="int">2</attr>
    <commandpane />
    <statusandcompassattop />
    <turnoffplacesandobjects />
    <description>You were supposed to remain in cryo sleep until the Scion reached orbit around your target world in the Alpha Centauri system. So why are you awake now? And why are you alone?</description>
    <cover>red-space.jpeg</cover>
    <subtitle>Adrift in Space</subtitle>
    <povstatusattributes type="stringdictionary" />
    <menufontsize type="int">11</menufontsize>
    <turnoffinventory type="boolean">false</turnoffinventory>
    <turnoffcompass type="boolean">false</turnoffcompass>
    <showpanes />
    <pov type="object">player</pov>
    <inituserinterface type="script"><![CDATA[
      JS.setCommands ("Computer;Look")
      SetTimeout (2) {
        cmds = ProcessText("{command:Computer}&emsp;{command:Look}&emsp;{command:Inventory}" + Chr(60) + "span id=\"custom-score-div\">" + Chr(60) + "br/>Score: {game.score}" + Chr(60) + "/span>")
        s = Chr(60) + "div style=\\\"padding-top:6px;\\\" id=\\\"mobile-cmds\\\">"
        s = s + Replace(cmds, Chr(34), Chr(92) + Chr(34))
        s = s + Chr(60) + "/div>"
        JS.eval ("if (typeof (currentTab) === 'string'){var s = \""+s+"\";$('body').append(s);$('#mobile-cmds').insertAfter($('#txtCommandDiv'));}")
        JS.
      }
      SendToJsEval (js.description)
      JS.changeCompass ()
    ]]></inituserinterface>
    <start type="script">
      set (captain, "state", "asleep")
      set (hypospray, "med", "empty")
      set (game, "power", "low")
      js = "function isMobilePlayer(){"
        js = js + "if (typeof(currentTab) === 'string'){return true;}return false;};"
      JS.eval (js)
      SetupNautical
    </start>
  </game>
  <verb>
    <property>ask/tell</property>
    <pattern>ask/tell</pattern>
    <defaultexpression>"You can't ask/tell " + object.article + "."</defaultexpression>
  </verb>
  <object name="space_cargo_bay">
    <inherit name="editor_room" />
    <usedefaultprefix type="boolean">false</usedefaultprefix>
    <alias>In Space (Outside Cargo Bay)</alias>
    <description type="script">
      msg ("The cold blackness of space is visible in every direction, perforated by innumerable, distant stars. The hull of the Scion stretches out below you, illuminated only by your suit's lights.")
      firsttime {
        msg ("The only sound is your own breathing. Using the grappling equipment integrated into your suit, you are able to move around the hull. The lack of gravity makes it virtually effortless, but the process is awkward and slow.")
      }
    </description>
    <exit name="airlock_in" alias="in" to="cargo_bay">
      <inherit name="indirection" />
      <runscript />
      <script type="script">
        msg ("You glide into the airlock and seal the outer door behind you. Air is automatically pumped into the room and once the air pressure matches the interior of the Scion, the inner door automatically slides open. You climb through the inner door, sealing it behind you. Once free of the airlock, you carefully remove the space suit.")
        MoveObject (player, cargo_bay)
        space_suit.worn = false
      </script>
    </exit>
    <exit alias="southeast" to="space_engine_room">
      <inherit name="southeastdirection" />
    </exit>
    <exit alias="northeast" to="space_mess_deck">
      <inherit name="northeastdirection" />
    </exit>
  </object>
  <command name="computer">
    <pattern>Computer</pattern>
    <script>
      queries = listComputerQueries()
      computerFunction (queries)
    </script>
  </command>
  <verb>
    <property>suitup</property>
    <pattern>suit up</pattern>
    <defaultexpression>"You can't suit up " + object.article + "."</defaultexpression>
  </verb>
  <object name="space_engine_room">
    <inherit name="editor_room" />
    <alias>In Space (Outside Engine Room)</alias>
    <description>You approach the aft section of the ship and you can see the enormous engine nacelles sticking out of the Scion. You can't help but feel awed by the sight.</description>
    <exit alias="northwest" to="space_cargo_bay">
      <inherit name="northwestdirection" />
    </exit>
    <exit alias="north" to="space_mess_deck">
      <inherit name="northdirection" />
    </exit>
    <object name="hull">
      <inherit name="editor_object" />
      <inherit name="container_closed" />
      <alias>hull</alias>
      <feature_usegive />
      <feature_container />
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Use</value>
      </displayverbs>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <inroomdescription type="string"></inroomdescription>
      <prefix>the</prefix>
      <look type="script">
        msg ("The hull outside the Engine Room shows damage that could only have been caused by some kind of weapons fire. Luckily, the damage seems to be minor.")
        if (hull.isopen = true and eng_door.locked = true) {
          msg ("A long thin gash runs along the hull, where you cut in with your plasma torch.")
        }
        else if (hull.isopen=true and eng_door.locked = false) {
          msg ("You admire your handiwork, noting that the cut you made previously has been expertly sealed.")
        }
      </look>
      <use type="script">
        if (plasma_torch.parent = player) {
          if (not hull.isopen) {
            msg ("Using the plasma torch, you begin cutting through the Scion's hull. As soon as you pierce through, a jet of air begins spraying out through the gap. You continue cutting until the atmosphere from the Engine Room has completely vented into space. Without any air left inside, the fire won't be able to sustain itself.")
            HelperOpenObject (hull)
            IncreaseScore (1)
          }
          else {
            firsttime {
              msg ("With all of the air vented into space and the fire extinguished, you use the plasma torch to seal the cut you made.")
              UnlockExit (eng_door)
              IncreaseScore (1)
            }
            otherwise {
              msg ("The hull remains well sealed. No further work is required.")
            }
          }
        }
        else {
          msg ("You don't have any tool that would let you work on the hull.")
        }
      </use>
    </object>
  </object>
  <object name="space_mess_deck">
    <inherit name="editor_room" />
    <description>You make your way around the hull to the section outside the Mess Deck. The ship was clearly fired upon by some kind of energy weapon. Minor damage is visible in several locations.</description>
    <alias>In Space (Outside Mess Deck)</alias>
    <exit alias="southwest" to="space_cargo_bay">
      <inherit name="southwestdirection" />
    </exit>
    <exit alias="south" to="space_engine_room">
      <inherit name="southdirection" />
    </exit>
    <object name="hull_breach">
      <inherit name="editor_object" />
      <alias>gaping tear in the hull</alias>
      <inroomdescription>The worst of the damage caused a hull breach, running parallel to the Scion's long axis.</inroomdescription>
      <look>A long, but very narrow gash. You're confident that you could repair the damage, if you had the right tool. Assuming you don't get fired on while you are helplessly exposed...</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Use</value>
      </displayverbs>
      <feature_usegive />
      <use type="script">
        if (plasma_torch.parent = player) {
          msg ("Carefully bracing yourself against the hull, you begin welding the gash closed with the plasma torch. Your visor automatically darkens to protect your eyes from the intense light. Despite your suit's insulated gloves, your hands heat up and become sweaty in short order. It is slow going, but you persevere and succeed in sealing the breach.")
          RemoveObject (hull_breach)
          UnlockExit (mess_door)
          IncreaseScore (1)
        }
        else {
          msg ("You can't do much about the breach without the right tool.")
        }
      </use>
    </object>
    <object name="alien_ship">
      <inherit name="editor_object" />
      <alias>Unidentified Object</alias>
      <inroomdescription>In the distance, a twinkling light catches your eye. </inroomdescription>
      <look>It is much too faint to be a star or planet. It could be another spaceship.</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
    </object>
  </object>
  <verb>
    <property>exitsuit</property>
    <pattern>exit suit</pattern>
    <defaultexpression>"You can't exit suit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>removesuit</property>
    <pattern>remove suit</pattern>
    <defaultexpression>"You can't remove suit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>dropsuit</property>
    <pattern>drop suit</pattern>
    <defaultexpression>"You can't drop suit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>stand</property>
    <pattern>stand</pattern>
    <defaultexpression>"You can't stand " + object.article + "."</defaultexpression>
  </verb>
  <turnscript name="mobileScore">
    <enabled />
    <script><![CDATA[
      JS.eval ("$('#custom-score-div').html('" + Chr(60) + "br/>Score: " + ProcessText("{game.score}") + "');")
    ]]></script>
  </turnscript>
  <turnscript name="nautical_buttons_turnscript">
    <script>
      if (HasAttribute (game.pov.parent, "parent")) {
        if (GetBoolean(game.pov.parent.parent,"shiptype")) {
          list = NewStringList()
          foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
            list add (list, exit.alias)
          }
          JS.updateShipCompass (Join(list, "/"))
        }
      }
    </script>
  </turnscript>
  <object name="js">
    <inherit name="editor_room" />
    <description><![CDATA[var onBoard = false;<br/>var shipButtons = '<div id="dir-holder" style="display:none;"><div id="ship-nav"><table id="ship-directions"><tr><td></td><td>';<br/>shipButtons += '<button id="cmdCompassF" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="fore" onclick="compassClick(\'fore\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-n" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td><button id="cmdCompassP" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="port" onclick="compassClick(\'port\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-w" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></td><td></td><td></button>';<br/>shipButtons += '<button id="cmdCompassSB" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="starboard" onclick="compassClick(\'starboard\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-e" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td></td><td><button id="cmdCompassA" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="aft" onclick="compassClick(\'aft\');" role="button" ><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-s" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr></table>';<br/>shipButtons += '</div></div>';<br/>function changeCompass(){<br/>  $('body').append(shipButtons);<br/>  $("#ship-directions").css("border-spacing","0");<br/>  $("#cmdCompassNW").parent().parent().parent().attr('id','def-nav');<br/>  $('#ship-nav').hide();$('#def-nav').parent().append($('#dir-holder').html());<br/>  $(".shipcompassbutton").each(function(){<br/>    $(this).button().button("enable").button("disable");<br/>    $(".shipcompassbutton span").css("left", "0.8em");$(".shipcompassbutton .ui-button-text").css('padding','.8em .8em');<br/>  });<br/>};<br/>function toggleNav(){<br/>  $("#def-nav, #ship-nav").toggle()<br/>};<br/>function updateShipCompass(data){<br/>  var exits = data.split("/");<br/>  $(".shipcompassbutton").each(function(){<br/>    for (var exit in exits){<br/>      if($(this).attr('title') === exits[exit]){<br/>        $(this).button("enable");<br/>        break;<br/>      }else{<br/>        $(this).button("disable");<br/>      }<br/>    }<br/>  });<br/>};]]></description>
  </object>
  <object name="scion">
    <feature_startscript />
    <attr name="_initialise_" type="script">
      this.shiptype = true
    </attr>
    <object name="cryo_quarters">
      <inherit name="editor_room" />
      <description>Row upon row of pods, each housing a crew member in cryogenic suspension, surrounds you. Even outside the pods, the room is cold. The sound of dripping water can be heard in the distance. A ladder leads down to the Crew Quarters.</description>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <descprefix type="string"></descprefix>
      <alias>Cryo Quarters</alias>
      <dropdestination type="object">cryo_quarters</dropdestination>
      <firstenter type="script">
      </firstenter>
      <exit name="ladder down" alias="down" to="crew_quarters">
        <inherit name="downdirection" />
      </exit>
      <object name="cryo_pod">
        <inherit name="container_closed" />
        <inroomdescription>Your cryo pod stands out from the rows of identical, but sealed and occupied, pods nearby.</inroomdescription>
        <feature_container />
        <isopen type="boolean">false</isopen>
        <displayverbs type="stringlist">
          <value>Look at</value>
        </displayverbs>
        <transparent type="boolean">false</transparent>
        <openmsg>The cylindrical glass cover rotates with a hiss, opening the cryo pod. As the pod interior is exposed to the room, a cloud of vapour floats out and quickly dissipates.</openmsg>
        <closemsg>The glass cover rotates into place, sealing the cryo pod. A quiet hum is audible as the pod activates its cryo sleep cycle.</closemsg>
        <listchildren />
        <visible type="boolean">false</visible>
        <alias>cryo pod</alias>
        <close type="boolean">false</close>
        <look>A cylindrical capsule with a sliding glass cover, sized to contain a single person. Inside is a variety of vital sign sensors used to adjust the cryogenic stasis of its occupant.</look>
        <dropdestination type="object">cryo_pod</dropdestination>
        <openscript type="script">
          msg ("The cylindrical glass cover rotates with a hiss. As the pod opens to the surrounding room, a cloud of vapour floats out and quickly dissipates.")
          firsttime {
            create exit ("pod door", cryo pod, Cryo Quarters, out)
            msg ("You climb out of the pod carefully, making sure not to overexert your sluggish muscles. You still feel woozy from the effects of cryo sleep, but your senses are slowly returning to normal.")
            MoveObject (player, Cryo Quarters)
          }
        </openscript>
        <closescript type="script">
          msg ("The cylindrical glass cover rotates, sealing the cryo pod.")
        </closescript>
        <onopen type="script">
          HelperOpenObject (cryo_pod)
        </onopen>
        <description type="script">
          firsttime {
            msg ("You awake from a deep slumber, struggling to make sense of your perceptions. You are lying on your back, inside a small container. It is dark, and cold. As your consciousness returns, you manage to identify your surroundings as a cryo pod. You begin to remember climbing into it, in preparation for a long cryo sleep, while the Scion travelled to the Alpha Centauri system. Why have you been awakened? Has the Scion reached its destination? Is it time to begin founding a new colony?")
          }
          otherwise {
            msg ("The cryo pod still feels cold, even though the cryo sleep function has clearly been disabled. ")
          }
        </description>
        <onclose type="script">
          HelperCloseObject (cryo_pod)
        </onclose>
        <firstenter type="script">
        </firstenter>
        <object name="player">
          <inherit name="editor_object" />
          <inherit name="editor_player" />
          <inherit name="namedmale" />
          <alias>Crewman Shepherd</alias>
          <usedefaultprefix />
          <look type="string"></look>
          <visible type="boolean">false</visible>
          <attr name="pov_look">You're dressed in a standard-issue jump suit, with the Scion's mission crest over your left pectoral.</attr>
          <maxvolume type="int">1</maxvolume>
          <containerfullmessage>You can't carry any more. Your jumpsuit doesn't have any pockets.</containerfullmessage>
        </object>
        <exit alias="out" to="cryo_quarters">
          <inherit name="outdirection" />
          <locked type="boolean">false</locked>
          <lockmessage>The cryo pod is sealed. </lockmessage>
          <runscript />
          <script type="script">
            if (not ListContains(ScopeVisible(), cryo_pod)) {
              if (not cryo_pod.isopen) {
                msg ("Your mind still fuzzy from the effects of prolonged cryo sleep, you push against the cryo pod's glass cover to no avail. As you slowly regain your faculties, you remember your training. Opening the cryo pod, as well as perfoming many other actions aboard the Scion, requires issuing verbal commands to the ship's computer.")
                SetTimeout (2) {
                  JS.eval ("if (typeof (currentTab) !== 'string') {$('#divOutput').append(\"TUTORIAL: Click on the Computer link at the top right to issue verbal commands to the ship's computer.\");} else {$('#divOutput').append(\"TUTORIAL: Click on the Computer link at the bottom to issue verbal commands to the ship's computer.\");}")
                  JS.scrollToEnd ()
                }
              }
              else {
                firsttime {
                  msg ("You climb out of the pod carefully, making sure not to overexert your sluggish muscles. You still feel woozy from the effects of cryo sleep, but your senses are slowly returning to normal.")
                  IncreaseScore (1)
                }
                otherwise {
                  msg ("")
                }
                MakeObjectVisible (cryo_pod)
                MoveObject (player, cryo_quarters)
              }
            }
            else {
              MoveObject (player, cryo_quarters)
            }
          </script>
        </exit>
      </object>
      <exit alias="in" to="cryo_pod">
        <inherit name="indirection" />
      </exit>
      <object name="captain_pod">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <inherit name="container_lockable" />
        <feature_container />
        <close type="boolean">false</close>
        <listchildren />
        <inroomdescription>You are also able to identify Captain Picker's cryo pod.</inroomdescription>
        <look>A cylindrical capsule with a sliding glass cover, identical to the one you crawled out of.</look>
        <alias>Captain Picker's cryo pod</alias>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Open</value>
        </displayverbs>
        <listchildrenprefix>Inside is</listchildrenprefix>
        <openmsg>The cylindrical glass cover rotates with a hiss, opening the cryo pod. As the pod interior is exposed to the room, a cloud of vapour floats out and quickly dissipates.</openmsg>
        <closemsg>The glass cover rotates into place, sealing the cryo pod. A quiet hum is audible as the pod activates its cryo sleep cycle.</closemsg>
        <autounlock type="boolean">false</autounlock>
        <autoopen type="boolean">false</autoopen>
        <transparent />
        <hidechildren />
        <feature_startscript />
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <attr name="_initialise_" type="script"><![CDATA[
          captain_pod.openscript => {
            if (not this.locked and not this.isopen) {
              captain_pod.isopen = true
              captain.state = "awake"
              MoveObject (captain, cryo_quarters)
              msg ("The cylindrical glass cover rotates with a hiss, opening the cryo pod. As the pod interior is exposed to the room, a cloud of vapour floats out. As it dissipates, you can see {object:captain} slowly climbing out of his pod.")
            }
            else if (not this.locked and this.isopen) {
              msg ("It is already open.")
            }
            else {
              msg ("An error chimes sounds from the ship's computer.<br/>\"Life support at critical levels. Restore main power in order to revive additional crew members.\"")
            }
          }
        ]]></attr>
        <object name="captain">
          <inherit name="editor_object" />
          <inherit name="namedmale" />
          <alias>Captain Picker</alias>
          <displayverbs type="stringlist">
            <value>Look at</value>
          </displayverbs>
          <look type="script">
            switch (captain.state) {
              case ("asleep") {
                msg ("You examine Captain Picker as he sleeps. He is in his fifties, bald, with sharp, angular features and a stern demeanour which is not diminished by his peaceful state.")
              }
              case ("awake") {
                msg ("Captain Picker rubs his face groggily with boths hands. He is in his fifties, bald, with sharp, angular features and a stern demeanour.")
              }
              case ("hurt") {
                msg ("Captain Picker lays in a heap on the floor. He appears to have been knocked unconscious and you see an angry red mark on his bald head.")
              }
              case ("combat") {
                msg ("Captain Picker is scanning the instrumentation output on the console integrated into the Captain's Chair and braking commands at the ship's computer to evade the hostile vessel incoming fire and mitigate damage.")
              }
            }
          </look>
          <speak type="script">
            talkToCaptain
          </speak>
          <ask type="scriptdictionary">
            <item key="health">
            </item>
          </ask>
        </object>
      </object>
    </object>
    <object name="crew_quarters">
      <inherit name="editor_room" />
      <description>Dozens of rows of bunk beds fill the room, all unnoccupied. The beds are made and ready for use. Once the crew is awakened from cryogenic sleep, this will become their new sleeping area. The cold air from the cryo quarters above can be felt drifting down the ladder.</description>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <descprefix type="string"></descprefix>
      <alias>Crew Quarters</alias>
      <dropdestination type="object">crew_quarters</dropdestination>
      <firstenter type="script">
        JS.toggleNav ()
        do (nautical_buttons_turnscript, "script")
      </firstenter>
      <exit name="ladder up" alias="up" to="cryo_quarters">
        <inherit name="updirection" />
      </exit>
      <exit alias="west" to="aft_corridor">
        <inherit name="westdirection" />
      </exit>
      <object name="locker">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <feature_container />
        <inroomdescription>A row of lockers lines the far wall. </inroomdescription>
        <look>You recognize the locker designated for your use.</look>
        <listchildren />
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
          <value>Open</value>
          <value>Close</value>
        </inventoryverbs>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Open</value>
          <value>Close</value>
        </displayverbs>
        <openmsg>The locker opens with a metallic squeak.</openmsg>
        <object name="space_suit">
          <inherit name="editor_object" />
          <inherit name="wearable" />
          <alias>space suit</alias>
          <feature_wearable />
          <take />
          <attr name="wear_layer" type="int">0</attr>
          <wearmsg>You climb into the suit, piece by piece. You painstakingly verify every joint and seal, completing the pre-EVA checklist drilled into you during your training.</wearmsg>
          <removemsg>You remove the suit, struggling your way out of each section, until you are down to just your jump suit once again.</removemsg>
          <inventoryverbs type="stringlist">
            <value>Look at</value>
            <value>Suit Up</value>
            <value>Remove Suit</value>
            <value>Drop Suit</value>
          </inventoryverbs>
          <volume type="int">0</volume>
          <look type="script">
            msg ("It is a Mark IV, extra vehicular activity suit, with integrated grappling harness and air supply. ")
            if (air_tank.isopen = true) {
              msg ("The air tank is currently empty.")
            }
            else {
              msg ("The air tank is full.")
            }
          </look>
          <suitup type="script">
            if (air_tank.isopen = true) {
              msg ("Putting on the space suit with no air in the tank would doom you to suffocation.")
            }
            else {
              msg ("You climb into the suit, piece by piece. You painstakingly verify every joint and seal, completing the pre-EVA checklist drilled into you during your training.")
              space_suit.worn = true
            }
          </suitup>
          <dropsuit type="script">
            if (space_suit.worn = true) {
              msg ("You must remove the suit before dropping it.")
            }
            else {
              msg ("You drop it.")
              MoveObjectHere (space_suit)
            }
          </dropsuit>
          <removesuit type="script">
            if (player.parent=space_cargo_bay or player.parent=space_mess_deck or player.parent=space_engine_room) {
              msg ("Removing your space suit while in space would be suicide.")
            }
            else {
              msg ("You remove the suit, struggling your way out of each section, until you are down to just your jump suit once again.")
              SetObjectFlagOff (space_suit, "worn")
            }
          </removesuit>
          <object name="air_tank">
            <inherit name="editor_object" />
            <inherit name="container_limited" />
            <scenery type="boolean">false</scenery>
            <visible type="boolean">false</visible>
            <feature_container />
          </object>
        </object>
      </object>
    </object>
    <object name="aft_corridor">
      <inherit name="editor_room" />
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <alias>Aft Corridor</alias>
      <dropdestination type="object">aft_corridor</dropdestination>
      <description type="script">
        msg ("The corridor in the aft section of the Scion is wide enough for several people to walk side by side. Off to port is the Cargo Bay, the Crew Quarters are starboard, heading aft leads to the engine room, while the rest of the ship is to the fore.")
        if (eng_door.locked = true) {
          msg ("You can smell smoke coming from the aft direction.")
        }
      </description>
      <exit alias="east" to="crew_quarters">
        <inherit name="eastdirection" />
      </exit>
      <exit name="eng_door" alias="south" to="engine_room">
        <inherit name="southdirection" />
        <locked />
        <lockmessage>As you approach the engine room, the door does not slide open automatically. Thin tendrils of smoke are seeping around the door seal and you can feel intense heat coming from the other side.</lockmessage>
      </exit>
      <exit alias="west" to="cargo_bay">
        <inherit name="westdirection" />
      </exit>
      <exit alias="north" to="fore_corridor">
        <inherit name="northdirection" />
      </exit>
    </object>
    <object name="engine_room">
      <inherit name="editor_room" />
      <alias>Engine Room</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description type="script"><![CDATA[
        firsttime {
          msg ("As the door to the Engine Room begins to slide open, you brace yourself. If the fire damage was bad enough, you may be walking into a radioactive disaster zone. Even if you aren't immediately killed, a damaged engine could mean the Scion is about to become dead in space, dooming you and the sleeping crew to float in a cold, lonely grave for centuries. <br/><br/>When the door does open, you are relieved to see the shining blue light of the containment field. Everything within it, crucially including the engine itself, was spared from the fire. The damage to the rest of the room is extensive, but you can't worry about that right now.")
        }
        msg ("The room is peppered with black soot and the acrid smell of smoke is almost overpowering.")
      ]]></description>
      <exit alias="north" to="aft_corridor">
        <inherit name="northdirection" />
      </exit>
      <object name="containment_field">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <look>The translucent field shimmers as you inspect it. It is holding steady, at full strength.</look>
        <inroomdescription>A glowing, blue containment field protects a cynlindrical volume within the Engine Room. Everything inside the field appears pristine, having been untouched by the fire.</inroomdescription>
        <feature_container />
        <open type="boolean">false</open>
        <close type="boolean">false</close>
        <transparent />
        <alias>containment field</alias>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Open</value>
        </displayverbs>
        <openmsg type="string"></openmsg>
        <nokeymessage>Lowering the containment field would instantly expose you to dangerous radiation from the engine. </nokeymessage>
        <listchildren />
        <autounlock type="boolean">false</autounlock>
        <autoopen type="boolean">false</autoopen>
        <feature_startscript />
        <listchildrenprefix>Within it are </listchildrenprefix>
        <attr name="_initialise_" type="script"><![CDATA[
          containment_field.openscript => {
            if (not this.locked and not this.isopen) {
              msg ("Lowering the containment field would instantly expose you to dangerous radiation from the engine. ")
            }
          }
        ]]></attr>
        <object name="engine">
          <inherit name="editor_object" />
          <inherit name="container_closed" />
          <feature_container />
          <isopen type="boolean">false</isopen>
          <transparent type="boolean">false</transparent>
          <inroomdescription>The advanced fission engine sits in the centre of the containment field.</inroomdescription>
          <feature_switchable />
          <listchildren type="boolean">false</listchildren>
          <displayverbs type="stringlist">
            <value>Look at</value>
          </displayverbs>
          <look type="script">
            if (old_rods.parent = engine) {
              msg ("The engine is operational, but its power output is very low.")
            }
            else if (new_rods.parent = engine) {
              msg ("The engine is operating at full capacity. Power output is nominal.")
            }
            else {
              msg ("Without any control rods inside, the plasma reactor is offline.")
            }
          </look>
          <object name="old_rods">
            <inherit name="editor_object" />
            <alias>depleted control rods</alias>
          </object>
        </object>
        <object name="RAT">
          <inherit name="editor_object" />
          <alias>RAT</alias>
          <inroomdescription>A robotacized, automated transport (RAT) is in standby mode.</inroomdescription>
          <displayverbs type="stringlist">
            <value>Look at</value>
            <value>Use</value>
          </displayverbs>
          <feature_usegive />
          <look type="script">
            msg ("The RAT has a four wheeled base, designed for navigating rough terrain. It features a long, flat bed for transporting heavy equipment and a robotic arm for loading and unloading.")
            if (old_rods.parent = RAT) {
              msg ("The used control rods sit on top of the RAT's flat bed.")
            }
            else if (new_rods.parent = RAT) {
              msg ("The new control rods sit on top of the RAT's flat bed.")
            }
          </look>
          <use type="script"><![CDATA[
            RATQueries = NewStringList()
            RATQueries = listRATQueries()
            if (ListCount(RATQueries) = 0) {
              msg ("\"Roboticised Automated Transports will respond to verbal commands issued to the ship's computer,\" explains the ship's computer. \"RAT units can be used to service the Scion's plasma reactor. Verifying current reactor status...\"<br/>")
              engineStatus
            }
            else {
              computerFunction (RATQueries)
            }
          ]]></use>
        </object>
      </object>
      <object name="broken_rat">
        <inherit name="editor_object" />
        <inroomdescription>A robot stands just outside the field, its tires melted and its chassis warped and blackened by the fire. </inroomdescription>
        <look>A quick glance is enough to tell you that extensive reconstruction would be necessary to get this RAT working again.</look>
        <displayverbs type="stringlist">
          <value>Look at</value>
        </displayverbs>
        <alias>damaged robot</alias>
      </object>
    </object>
    <object name="cargo_bay">
      <inherit name="editor_room" />
      <alias>Cargo Bay</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The bay is packed with equipment from floor to ceiling. The mission organizer's tried to include everything needed to establish a new colony on a distant, unknown alien world. Any damage to the equipment in here could threaten the success of the mission. At the far end of the cargo bay is an airlock. </description>
      <exit alias="east" to="aft_corridor">
        <inherit name="eastdirection" />
      </exit>
      <exit name="airlock" alias="out" to="space_cargo_bay">
        <inherit name="outdirection" />
        <locked type="boolean">false</locked>
        <lockmessage type="string"></lockmessage>
        <runscript />
        <script type="script">
          if (space_suit.worn = true) {
            msg ("You open the airlock's inner door and walk inside. The inner door seals itself automatically and the air is quickly sucked out of the room. You check your space suit's systems, and they are all within normal operating parameters. The outer door slides open silently and you cautiously step out into the void.")
            JS.toggleNav ()
            MoveObject (player, space_cargo_bay)
          }
          else {
            msg ("Stepping into an airlock without wearing a space suit would be suicide.")
          }
        </script>
      </exit>
      <object name="huge_crate">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <inherit name="container_lockable" />
        <alias>huge crate</alias>
        <feature_container />
        <listchildren />
        <nokeymessage>The crate can't be opened with your bare hands.</nokeymessage>
        <unlockmessage>The laser cut through the crate's seals with ease.</unlockmessage>
        <takemsg>The crate is much too massive to be picked up by even the strongest human.</takemsg>
        <close type="boolean">false</close>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Take</value>
          <value>Open</value>
        </displayverbs>
        <keycount type="int">1</keycount>
        <autounlock />
        <autoopen />
        <openmsg>With a solid shove, the top of the crate slides away.</openmsg>
        <key type="object">laser_opener</key>
        <look type="script">
          if (huge_crate.isopen = false) {
            msg ("The crate is tightly sealed. A label reads \"plasma reactor control rods\".")
          }
          else {
            msg ("The crate has been cut open. The lid lies discarded on the floor nearby. ")
          }
        </look>
        <object name="new_rods">
          <inherit name="editor_object" />
          <inherit name="plural" />
          <alias>new control rods</alias>
          <look>The rods are long, thin cylinders, gunmetal grey in colour. They are in pristine condition and ready for use.</look>
          <takemsg>The rods are too heavy and too numerous for you to handle unaided.</takemsg>
        </object>
      </object>
      <object name="plasma_torch">
        <inherit name="editor_object" />
        <alias>plasma torch</alias>
        <look>A heavy duty tool, able to cut through or seal metal plating up to a metre thick.</look>
        <take />
        <volume type="int">1</volume>
        <feature_usegive />
        <use type="script">
          if (plasma_torch.parent = player and player.parent = space_mess_deck and hull_breach.parent = space_mess_deck) {
            msg ("Carefully bracing yourself against the hull, you begin welding the gash closed with the plasma torch. Your visor automatically darkens to protect your eyes from the intense light. Despite your suit's insulated gloves, your hands heat up and become sweaty in short order. It is slow going, but you persevere and succeed in sealing the breach.")
            RemoveObject (hull_breach)
            UnlockExit (mess_door)
            IncreaseScore (1)
          }
          else if (plasma_torch.parent = player and player.parent = space_engine_room) {
            if (not hull.isopen) {
              msg ("Using the plasma torch, you begin cutting through the Scion's hull. As soon as you pierce through, a jet of air begins spraying out through the gap. You continue cutting until the atmosphere from the Engine Room has completely vented into space. Without any air left inside, the fire won't be able to sustain itself.")
              HelperOpenObject (hull)
              IncreaseScore (1)
            }
            else {
              firsttime {
                msg ("With all of the air vented into space and the fire extinguished, you use the plasma torch to seal the cut you made.")
                UnlockExit (eng_door)
                IncreaseScore (1)
              }
              otherwise {
                msg ("The hull remains well sealed. No further work is required.")
              }
            }
          }
          else {
            msg ("You don't see any obvious use for it here.")
          }
        </use>
      </object>
    </object>
    <object name="fore_corridor">
      <inherit name="editor_room" />
      <alias>Forward Corridor</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The corridor narrows toward the fore of the Scion, allowing only a pair of passengers to walk abreast as it reaches the bridge at the far end. The Med Bay is on the port side, with the Mess Deck to starboard. Following the corridor aft leads into the Aft Corridor.</description>
      <exit alias="south" to="aft_corridor">
        <inherit name="southdirection" />
      </exit>
      <exit alias="north" to="bridge">
        <inherit name="northdirection" />
        <runscript />
        <script type="script"><![CDATA[
          if (captain.parent = captain_chair) {
            msg ("As you walk into the Bridge, you see that Captain Picker has already taken up his post in the Captain's Chair. The viewscreen shows a magnified image of the enemy vessel. You've never seen anything like it--it looks like a collection of haphazardly arranged spheres, variously glowing in incomprehensible patterns.<br/><br/>\"Shepherd!\" shouts the Captain as you walk in. \"I'm having the Scion perform evasive maneuvers. I need you to man the weapons and return fire! Step to it man!\"")
            MoveObject (player, bridge)
          }
          else {
            MoveObject (player, bridge)
          }
        ]]></script>
      </exit>
      <exit alias="west" to="med_bay">
        <inherit name="westdirection" />
      </exit>
      <exit name="mess_door" alias="east" to="mess_deck">
        <inherit name="eastdirection" />
        <locked />
        <lockmessage>As you approach the door to the Mess Deck, it does not slide open automatically.</lockmessage>
      </exit>
    </object>
    <object name="med_bay">
      <inherit name="editor_room" />
      <alias>Med Bay</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The walls are lined with empty gurneys, ready to receive patients. A variety of medical equipment and robotics are installed in the middle of the room. Medicine is not your area of expertise, so you recognize very few of the devices and know how to operate fewer still.</description>
      <exit alias="east" to="fore_corridor">
        <inherit name="eastdirection" />
      </exit>
      <object name="air_compressor">
        <inherit name="editor_object" />
        <alias>air compressor</alias>
        <look>A hefty machine, the air compressor features a hose with a high pressure nozzle and locking mechanism.</look>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </inventoryverbs>
        <feature_usegive />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <use type="script">
          if (space_suit.parent = player and air_tank.isopen = true) {
            msg ("You connect the air compressor's nozzle to the space suit's air tank and activate the machine. It takes several minutes, but the tank's supply indicator finally goes from red to green.")
            air_tank.isopen = false
            IncreaseScore (1)
          }
          else if (space_suit.parent=player and air_tank.isopen = false) {
            msg ("The space suit's air supply is sufficient for several hours of operation and doesn't require any topping up.")
          }
          else {
            msg ("You have nothing to use the air compressor on.")
          }
        </use>
      </object>
      <object name="dispensary">
        <inherit name="editor_object" />
        <inherit name="container_open" />
        <alias>medication dispensary</alias>
        <look>The dispensary fills an entire wall of the Med Bay. You remember being taught that it contains an enormous variety of medication, intended to sustain the new colony until new treatments can be developed from the native flora and fauna of your new home. It features a small rectangular opening with a circular receptacle. </look>
        <feature_usegive />
        <feature_container />
        <open type="boolean">false</open>
        <close type="boolean">false</close>
        <transparent />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <listchildren />
        <listchildrenprefix>Docked in the receptacle is </listchildrenprefix>
        <use type="script">
          if (hypospray.parent = player) {
            fillHypo
          }
          else {
            msg ("You don't have anything to store medication from the dispensary.")
          }
        </use>
      </object>
    </object>
    <object name="bridge">
      <inherit name="editor_room" />
      <alias>Bridge</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The nerve center of the Scion, the Bridge is dominated by a viewscreen covering the entire curved surface at the front of the room. The captain's chair sits on a slightly raised dais in the rear with a commanding view of the entire Bridge. Between the captain's chair and the screen are several control stations, each one intended to be manned by a senior officer.</description>
      <exit alias="south" to="fore_corridor">
        <inherit name="southdirection" />
      </exit>
      <object name="captain_chair">
        <inherit name="surface" />
        <inherit name="editor_object" />
        <feature_container />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Stand</value>
        </displayverbs>
        <look>It features the most advanced ergonomics ever developed by humanity, and is made from the most advanced materials, making it comfortable for extended periods of time. It features a control panel built into the right armrest. It also includes a safety harness to ensure its occupant cannot be inadvertently ejected. It is one excellent chair.</look>
        <alias>Captain's Chair</alias>
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <prefix>the</prefix>
        <sit type="script">
          if (captain.parent = captain_chair) {
            msg ("The Captain gives you a brief, but eloquent look. You quickly back away from the chair.")
          }
          else {
            msg ("Looking over your shoulder despite yourself, you take a seat in the Captain's Chair. It feels good. You could definitely get used to this.")
            game.gridmap = false
            MoveObject (player, captain_chair)
          }
        </sit>
        <stand type="script">
          if (player.parent = captain_chair) {
            msg ("Reluctantly, you stand up, leaving the comfort of the Captain's Chair behind.")
            MoveObject (player, bridge)
            game.gridmap = true
          }
          else {
            msg ("You cannot stand up from the chair unless you sit down first.")
          }
        </stand>
      </object>
      <object name="weapon_controls">
        <inherit name="editor_object" />
        <alias>weapons control station</alias>
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <prefix>the </prefix>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <feature_usegive />
        <look type="script">
          msg ("The panel displays status information regarding the Scion's complement of defensive weaponry. The ship's mission may be colonization of a new world, but the mission planners were not so naïve as to think that peaceful intentions would preclude the occasional need for force.")
          if (new_rods.parent = engine) {
            msg ("With full power restored, the Scion's full array of weapons is available and ready for use.")
          }
          else {
            msg ("With main power at critical, all weapon functions have been disabled.")
          }
        </look>
        <use type="script"><![CDATA[
          if (captain.parent = captain_chair) {
            play sound ("tos_phasersstrikingdeflectorshields.mp3", false, false)
            msg ("You take control of the panel and with the computer's help, you acquire the enemy vessel.<br/><br/>\"Target acquired!\" you shout over the sound of the Scion taking another hit.<br/><br/>\"Fire!\" Picker shouts back at you.<br/><br/>You jab the control panel and immediately hear and feel the vibrations throughout the Scion as the heavy lasers are activated. Searing red lines appear on the viewscreen, connecting with the enemy vessel. It attempts to maneouvre away, but the tracking sensors keep the lasers on target. Explosions blossom across the vessel's hull and in a dazzling display of colours, the ship's breaks apart.<br/><br/>\"Target neutralized,\" you announce with relief.<br/><br/>\"Well done,\" replies Captain Picker. \"You've earned yourself a field promotion for saving the Scion. Now let's wake up the rest of the crew and complete our mission.\"<br/><br/>Congratulations!")
            RemoveObject (alien_ship)
            IncreaseScore (5)
            finish
          }
          else if (new_rods.parent = engine and player.parent <> captain_chair) {
            play sound ("computerbeep_1.mp3", false, false)
            msg ("As soon as you begin to manipulate the controls, an error chime sounds.<br/><br/>\"Unauthorized use of weapons systems detected. Senior officer approval is required.\"")
          }
          else if (player.parent = captain_chair) {
            msg ("You can't reach the weapons control panel from the Captain's Chair.")
          }
          else {
            msg ("The panel displays only a warning about the main power levels being critical.")
          }
        ]]></use>
      </object>
      <object name="sensors">
        <inherit name="editor_object" />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <feature_usegive />
        <alias>sensors control station</alias>
        <look type="script">
          msg ("The panel displays internal and external sensor readings. Sensor logs can also be retrieved.")
        </look>
        <use type="script"><![CDATA[
          if (player.parent = captain_chair) {
            msg ("You can't reach the sensors panel from the Captain's Chair.")
          }
          else {
            readings = NewStringList()
            list add (readings, "Internal Sensor Array")
            list add (readings, "External Sensor Array")
            list add (readings, "Sensor Logs")
            ShowMenu ("\"Select sensor information to display,\" the computer asks in response to you activating the panel.", readings, true) {
              switch (result) {
                case ("Internal Sensor Array") {
                  internalStatus
                }
                case ("External Sensor Array") {
                  play sound ("alarm03.mp3", false, false)
                  msg ("\"Warning: hostile vessel detected,\" states the computer.<br/><br/>The Scion's passive sensors are detecting intermittent energy readings from the direction of the unknown vessel. Although it is hard to be sure, given the ship's unknown origins, it would seem that it is not operating at normal capacity.<br/><br/>Active sensors show the unknown ship's size to be smaller than the Scion. Its hull design resembles a collection of spheres welded together without any clear pattern. <br/><br/>Sensors also show a planet, approximately one light month away.")
                }
                case ("Sensor Logs") {
                  ClearScreen
                  msg ("You skim through years of automated log entries detailing normal ship functions and minor glitches. Eventually, you discover today's log entry.")
                  TextFX_Typewriter ("Unknown energy signature detected.<br>Incoming weapons fire detected.<br>Damage to aft hull detected. Initiating defensive counter measures. <br>Hull breach detected on Mess Deck. Innervating Chief Engineer Dawson.<br>Power surge detected. Chief Engineer Dawson life signs failing. Innervating Crewman Shepherd.<br>Explosive discharge detected aboard hostile vessel. <br>Power surge detected in plasma reactor. Fire detected in engine room. Unable to continue defensive countermeasures.", 50)
                  ShowRoomDescription
                  IncreaseScore (1)
                }
                default {
                  play sound ("computerbeep_1.mp3", false, false)
                  msg ("\"Invalid selection,\" the computer replies.")
                }
              }
            }
          }
        ]]></use>
      </object>
      <object name="propulsion_controls">
        <inherit name="editor_object" />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <feature_usegive />
        <alias>propulsion controls station</alias>
        <look type="script">
          msg ("The panel displays status information regarding the Scion's propulsion systems.")
          if (new_rods.parent = engine) {
            msg ("With full power restored, the Scion's propulsion systems are active.")
          }
          else {
            msg ("With main power at critical, the Scion is adrift.")
          }
        </look>
        <use type="script"><![CDATA[
          if (new_rods.parent = engine and player.parent <> captain_chair) {
            msg ("The Scion's propulsion systems are active.")
          }
          else if (player.parent = captain_chair) {
            msg ("You can't reach the propulsion control panel from the Captain's Chair.")
          }
          else {
            msg ("The panel displays only a warning about the main power levels being critical.")
          }
        ]]></use>
      </object>
    </object>
    <object name="mess_deck">
      <inherit name="editor_room" />
      <alias>Mess Deck</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The large open area was designed to give the crew a break from the functional, confined spaces of the rest of the ship. Floor to ceiling windows line the deck, giving an incredible view of the stars. Recent exposure to vacuum has left the deck in a sorry state, with whatever objects that were unable to fit through the hull breach now strewn across the deck. Only the bar and the tables, which are bolted to the deck, remain where they belong.</description>
      <exit alias="west" to="fore_corridor">
        <inherit name="westdirection" />
      </exit>
      <object name="laser_opener">
        <inherit name="editor_object" />
        <alias>laser cutter</alias>
        <look>A low-power, handheld laser cutter. Looks like its batteries are included.</look>
        <volume type="int">1</volume>
        <take />
        <feature_usegive />
        <use type="script">
          if (laser_opener.parent=player and player.parent=cargo_bay) {
            msg ("The laser cut through the crate's seals with ease.")
            huge_crate.locked = false
            HelperOpenObject (huge_crate)
          }
          else {
            msg ("A laser cutter must be used with care, especially on a space ship. There is no useful target for it here.")
          }
        </use>
      </object>
      <object name="coffee">
        <inherit name="editor_object" />
        <alias>instant coffee canister</alias>
        <volume type="int">1</volume>
        <look>One of the modern wonders of the world: an apparatus containing instant coffee, water and a mechanism able to combine and heat them into a ready-to-serve beverage with a simple twist of the wrist and a few moments of patience. If only they could make it taste good... </look>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Drop</value>
          <value>Give</value>
        </inventoryverbs>
        <usestandardverblist />
        <take />
        <feature_usegive />
        <givesingle type="script">
          if (player.parent = bridge and captain.parent = captain_chair or player.parent = cryo_quarters and captain.parent = captain_pod) {
            RemoveObject (coffee)
            msg ("You twist the container's top, instantly mixing and heating its contents into passable coffee, and hand it to the Captain. He glances at you and grabs the container, favouring you with a half smile.")
            IncreaseScore (1)
          }
          else {
            msg ("There is no one to give this too. ")
          }
        </givesingle>
      </object>
      <object name="hypospray">
        <inherit name="editor_object" />
        <look>A glass and metal cylinder the size of your hand. You remember from your training that it can be used to administer any kind of medication.</look>
        <take />
        <volume type="int">1</volume>
        <feature_usegive />
        <use type="script"><![CDATA[
          if (hypospray.parent = player and player.parent = med_bay) {
            fillHypo
          }
          else if (hypospray.parent = player and player.parent = cryo_quarters and captain.state = "hurt" and hypospray.med <> "empty") {
            msg ("You kneel and administer the hypospray to the unconscious form of Captain Picker.")
            if (hypospray.med = "stimulant") {
              msg ("His eyes flutter and finally open. He props himself up, rubbing his head. <br/><br/>\"What happened?\" he asks, wincing as he touches his bruised head.")
              captain.state = "healed"
              IncreaseScore (1)
              talkToCaptain
            }
            else {
              msg ("The medication does not seem to have any effect.")
            }
            hypospray.med = "empty"
          }
          else if (hypospray.med = "empty") {
            msg ("The hypospray won't do anyone much good while it is empty.")
          }
          else {
            msg ("You consider injecting yourself, but then decide it wouldn't be advisable under the circumstances.")
          }
        ]]></use>
      </object>
    </object>
  </object>
  <function name="shipStatus">
    if (alien_ship.parent = space_mess_deck) {
      play sound ("alarm03.mp3", false, false)
      msg ("Warning: hostile vessel detected")
    }
    internalStatus
  </function>
  <function name="listComputerQueries" type="stringlist">
    queries = NewStringList()
    list add (queries, "State ship status")
    if (player.parent = cryo_pod) {
      list add (queries, "Open cryo pod")
    }
    if (eng_door.locked = true and player.parent = aft_corridor) {
      list add (queries, "Extinguish fire in Engine Room")
    }
    if (player.parent = fore_corridor) {
      list add (queries, "Override door to Mess Deck")
    }
    if (player.parent=engine_room) {
      list add (queries, "State engine status")
    }
    queries = ListCombine(queries, listRATQueries())
    return (queries)
  </function>
  <function name="walkthrough">
    msg ("Starting test...")
    UnlockExit (eng_door)
    HelperOpenObject (huge_crate)
    MoveObject (player, cryo_quarters)
    RemoveObject (old_rods)
    MoveObject (new_rods, engine)
    MoveObject (hypospray, player)
    hypospray.med = "stimulant"
    captain_pod.locked = false
    mess_door.locked = false
    msg ("Test completed")
  </function>
  <function name="computerFunction" parameters="queries"><![CDATA[
    if (ListCount(queries) = 0) {
      msg ("You hear an error chime sound from the ship's computer.")
      play sound ("computerbeep_1.mp3", false, false)
    }
    else {
      play sound ("computerbeep_10.mp3", false, false)
      ShowMenu ("\"Computer,\" you call loudly. <br> \"Specify query\", says a feminine robotic voice.", queries, true) {
        switch (result) {
          case ("State ship status") {
            shipStatus
          }
          case ("Open cryo pod") {
            if (cryo_pod.isopen = false) {
              msg ("\"Opening cryo pod 352,\" replies the computer.")
              HelperOpenObject (cryo_pod)
            }
            else {
              msg ("\"Crewmen Shepherd's cryo pod is already open,\" replies the computer with an error chime.")
              play sound ("computerbeep_1.mp3", false, false)
            }
          }
          case ("Extinguish fire in Engine Room") {
            msg ("\"Unable to comply,\" replies the computer with an error tone. \"Fire countermeasure systems are inoperative.\"")
            play sound ("computerbeep_1.mp3", false, false)
          }
          case ("Override door to Mess Deck") {
            msg ("\"Unable to comply,\" replies the computer with an error tone. \"No atmosphere present on Mess Deck. Warning: hull breach detected on Mess Deck.\"")
            play sound ("alarm03.mp3", false, false)
          }
          case ("State engine status") {
            engineStatus
          }
          case ("Command the RAT to remove degraded control rods from the engine") {
            ClearScreen
            msg ("\"Executing command,\" replies the computer.<br/><br/>The RAT's robotic arm begins to move, reaching out toward the engine. The depleted rods are removed smoothly and loaded on to the RAT's flat bed, ready for transport.<br/>")
            MoveObject (old_rods, RAT)
            ShowRoomDescription
          }
          case ("Move RAT") {
            destinations = NewStringList()
            list add (destinations, "Bridge")
            list add (destinations, "Medical Bay")
            list add (destinations, "Mess Deck")
            list add (destinations, "Cargo Bay")
            list add (destinations, "Crew Quarters")
            list add (destinations, "Engine Room")
            if (player.parent = RAT.parent or player.parent=engine_room and RAT.parent=containment_field) {
              ShowMenu ("\"Specify destination,\" replies the computer.", destinations, true) {
                switch (result) {
                  case ("Bridge") {
                    MoveObject (RAT, bridge)
                  }
                  case ("Medical Bay") {
                    MoveObject (RAT, med_bay)
                  }
                  case ("Mess Deck") {
                    MoveObject (RAT, mess_deck)
                  }
                  case ("Cargo Bay") {
                    MoveObject (RAT, cargo_bay)
                  }
                  case ("Crew Quarters") {
                    MoveObject (RAT, crew_quarters)
                  }
                  case ("Engine Room") {
                    MoveObject (RAT, engine_room)
                  }
                  default {
                    msg ("Unable to comply.")
                    play sound ("computerbeep_1.mp3", false, false)
                  }
                }
                msg ("\"Executing command,\" replies the computer.<br/><br/>Its motors whirring loudly, the RAT rolls out through the door.<br/>")
                ShowRoomDescription
              }
            }
            else {
              msg ("\"Unable to comply,\" replies the computer with an error chime. \"Safety protocols prohibit commanding a RAT unit without an operator present in the same room.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
          }
          case ("Command the RAT to load the new control rods") {
            if (new_rods.parent = huge_crate and old_rods.parent <> RAT and huge_crate.isopen = true) {
              ClearScreen
              msg ("\"Executing command,\" replies the computer.<br/><br/>The RAT's robotic arm begins to move, reaching into the crate. The new control rods are carefully extracted and loaded on to the RAT's flat bed, ready for transport.<br/>")
              MoveObject (new_rods, RAT)
              ShowRoomDescription
            }
            else if (huge_crate.isopen = false) {
              play sound ("computerbeep_1.mp3", false, false)
              msg ("\"Unable to comply,\" replies the computer. \"RAT unit is unable to access control rods inside sealed cargo container.\"")
            }
            else if (new_rods.parent = RAT or old_rods.parent = RAT) {
              play sound ("computerbeep_1.mp3", false, false)
              msg ("\"Unable to comply,\" replies the computer. \"Roboticized Automated Transport is at maximum capacity.\"")
            }
          }
          case ("Unload RAT") {
            if (RAT.parent = cargo_bay and player.parent = cargo_bay and old_rods.parent = RAT) {
              ClearScreen
              msg ("\"Executing command,\" replies the computer.<br/><br/>The airlock inner door slides open and the RAT moves inside. It unloads the degraded control rods and returns to the Cargo Bay. The airlock inner door slides closed behind it.<br/><br/>\"Jettisoning degraded control rods,\" explains the computer as the airlock's outer door opens and the rods are sucked into space, along with the atmosphere inside the airlock.<br/>")
              IncreaseScore (1)
              RemoveObject (old_rods)
              ShowRoomDescription
            }
            else if (RAT.parent = containment_field and player.parent = engine_room) {
              msg ("\"Unable to comply,\" replies the computer. \"Installing degraded control rods into plasma reactor violates safety protocols.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else if (old_rods.parent = RAT and player.parent = RAT.parent) {
              msg ("\"Unable to comply,\" replies the computer. \"Degraded control rods cannot be stored in " + RAT.parent.name + ". Exposure to degraded control rods is a severe hazard to crew health.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else if (new_rods.parent = RAT and player.parent = engine_room and RAT.parent = engine_room) {
              msg ("The RAT rolls through the containment field and over to the engine. Its robotic arm carefully loads each new control rod into place inside the reactor. Once the process is complete, the engine roars into life.<br/><br/>\"Power levels nominal,\" reports the ship's computer. ''Additional crew members may now be innervated.\"")
              MoveObject (RAT, containment_field)
              MoveObject (new_rods, engine)
              HelperCloseObject (engine)
              captain_pod.locked = false
              IncreaseScore (2)
              game.power = "normal"
              DisableTimer (lights)
              DisableTimer (powerWarning)
              DisableTimer (powerFailure)
            }
            else if (new_rods.parent = RAT) {
              msg ("\"Unable to comply,\" replies the computer. \"New control rods can be damaged if not stored in accordance with usage guidelines.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else if (player.parent <> RAT.parent) {
              msg ("\"Unable to comply,\" replies the computer with an error chime. \"Safety protocols prohibit commanding a RAT unit without an operator present in the same room.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else {
              msg ("\"Unable to comply,\" replies the computer unhelpfully.")
              play sound ("computerbeep_1.mp3", false, false)
            }
          }
          case ("Run test") {
            walkthrough
          }
          default {
            msg ("Unable to comply.")
            play sound ("computerbeep_1.mp3", false, false)
          }
        }
      }
    }
    JS.scrollToEnd ()
  ]]></function>
  <function name="listRATQueries" type="stringlist">
    RATqueries = NewStringList()
    if (engine.isopen=true and player.parent = engine_room and old_rods.parent=engine) {
      list add (RATqueries, "Command the RAT to remove degraded control rods from the engine")
    }
    if (old_rods.parent = RAT or new_rods.parent = RAT) {
      list add (RATqueries, "Move RAT")
      list add (RATqueries, "Unload RAT")
    }
    if (player.parent = cargo_bay and RAT.parent = cargo_bay and new_rods.parent = huge_crate) {
      list add (RATqueries, "Command the RAT to load the new control rods")
    }
    return (RATqueries)
  </function>
  <function name="listCaptainTopics" type="stringlist">
    dialogue = NewStringList()
    switch (captain.state) {
      case ("asleep") {
        msg ("Captain Picker is asleep.")
      }
      case ("awake") {
        msg ("\"Captain Picker,\" you begin. ")
        list add (dialogue, "\"How do you feel?\"")
        list add (dialogue, "\"Let me catch you up on what's been going on.\"")
      }
      case ("hurt") {
        msg ("The Captain is unconscious and unresponsive.")
      }
      case ("healed") {
        list add (dialogue, "The Scion is under attack!")
        list add (dialogue, "Sleeping on the job again")
      }
      case ("combat") {
        list add (dialogue, "What are your orders?")
        list add (dialogue, "We need to return fire!")
      }
    }
    return (dialogue)
  </function>
  <function name="fillHypo"><![CDATA[
    msg ("You plug the hypospray into the medication dispensary.")
    MoveObject (hypospray, dispensary)
    if (hypospray.med <> "empty") {
      msg ("An error chime sounds. The hypospray cannot be refilled until it is emptied.")
    }
    else {
      meds = NewStringList()
      list add (meds, "antibiotics")
      list add (meds, "sedative")
      list add (meds, "stimulant")
      list add (meds, "multi-vitamin")
      ShowMenu ("\"Select medication to dispense,\" says the ship's computer.", meds, false) {
        ClearScreen
        msg ("You hear the hum of machinery within the dispensary, followed by a faint hiss. A small indicator light on the hypospray changes from red to green.<br/>")
        hypospray.med = result
        ShowRoomDescription
      }
    }
  ]]></function>
  <function name="talkToCaptain"><![CDATA[
    dialogue = listCaptainTopics()
    ShowMenu ("", dialogue, false) {
      switch (result) {
        case ("\"How do you feel?\"") {
          msg ("Captain Picker sits up in his cryo pod and rubs his eyes.<br/><br/>\"I'm fine,\" he says. \"Just a bit groggy.\"")
        }
        case ("\"Let me catch you up on what's been going on.\"") {
          ClearScreen
          msg ("You relate everything that has happened since you awoke in your cryo pod. The Captain interjects with questions occasionally, but mostly furrows his brow in concentration as he absorbs the situation.<br/><br/>\"I see,\" he says simply as you finish. <br/>")
          play sound ("largeexplosion1.mp3", false, false)
          msg ("Just then, the Scion is rocked violently. You are thrown to the floor and hear a loud thud as the Captain is thrown into the bulkhead next to you. You scramble back to your feet.<br/>")
          captain.state = "hurt"
          MoveObject (captain, cryo_quarters)
          EnableTimer (attack)
          EnableTimer (shipDestroyed)
          ShowRoomDescription
        }
        case ("The Scion is under attack!") {
          msg ("\"What?\" exlaims the Captain. \"We need to get to the Bridge!\"<br/><br/>He struggles to his feet and without waiting for a response, he slides down the ladder to the Crew Quarters.")
          MoveObject (captain, captain_chair)
          captain.state = "combat"
        }
        case ("What are your orders?") {
          msg ("\"Take control of the weapon systems and destroy that ship!\" Captain Picker shouts.")
        }
        case ("We need to return fire!") {
          msg ("\"I know that! I already ordered you to fire on that ship! Get to it!\" Captain Picker shouts angrily.")
        }
        default {
          msg ("Captain Picker fixes you with a withering stare.")
        }
      }
    }
    JS.scrollToEnd ()
  ]]></function>
  <function name="internalStatus"><![CDATA[
    if (old_rods.parent <> engine and new_rods.parent <> engine) {
      msg ("Warning: plasma reactor is offline. Operating on auxiliary power.")
    }
    if (hull_breach.parent = space_mess_deck) {
      msg ("Warning: hull breach detected on Mess Deck.")
    }
    if (hull.isopen = false and eng_door.locked = true) {
      msg ("Warning: fire detected in Engine Room.")
    }
    else if (hull.isopen = true and eng_door.locked = true) {
      msg ("Warning: hull breach detected in Engine Room")
    }
    if (new_rods.parent <> engine) {
      msg ("Warning: power levels critical.<br/><br/>Immediate intervention is recommended to avoid loss of ship and all hands aboard.")
    }
    JS.scrollToEnd ()
  ]]></function>
  <function name="engineStatus">
    if (old_rods.parent = engine) {
      msg ("\"Plasma reactor is operational,\" replies the computer. \"Power output is limited due to degraded control rods.\"")
      HelperOpenObject (engine)
    }
    else if (new_rods.parent = engine) {
      msg ("\"Plasma reactor is operational,\" replies the computer. \"Power output within nominal operating parameters.\"")
    }
    else {
      msg ("\"Warning: plasma reactor is offline,\" replies the computer with a danger chime. \"Operating on auxiliary power.\"")
      play sound ("alarm03.mp3", false, false)
    }
    JS.scrollToEnd ()
  </function>
  <function name="SetupNautical"><![CDATA[
    game.compassdirections = ListExclude (game.compassdirections, "")
    list add (game.compassdirections, "fore")
    list add (game.compassdirections, "port")
    list add (game.compassdirections, "starboard")
    list add (game.compassdirections, "aft")
    list add (game.compassdirections, "f")
    list add (game.compassdirections, "p")
    list add (game.compassdirections, "sb")
    list add (game.compassdirections, "a")
    request (SetCompassDirections, Join(game.compassdirections, ";"))
    go.pattern = "^go to (?"+Chr(60)+"exit>.*)$|^go (?"+Chr(60)+"exit>.*)$|^(?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    lookdir.pattern = "^look (?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    foreach (exit, AllExits()) {
      if (StartsWith (exit.name, "fore")) {
        exit.alias = "fore"
        exit.alt = Split("f;forward")
      }
      if (StartsWith (exit.name, "aft")) {
        exit.alias = "aft"
        exit.alt = Split("a")
      }
      if (StartsWith (exit.name, "port")) {
        exit.alias = "port"
        exit.alt = Split("p")
      }
      if (StartsWith (exit.name, "starboard")) {
        exit.alias = "starboard"
        exit.alt = Split("sb")
      }
    }
    ChangeDirToNautical
  ]]></function>
  <function name="SendToJsEval" parameters="data"><![CDATA[
    regEx = "//"
    s = Chr(60) + "br/>"
    js = Split(data,s)
    notes = NewStringList()
    foreach (line, js) {
      if (StartsWith(line,"//")) {
        list add (notes, line)
      }
    }
    js = ListExclude(js,notes)
    finaljs = NewStringList()
    foreach (line, js) {
      code = line
      if (IsRegExMatch(regEx,line)) {
        list = Split(line,"//")
        code = list[0]
      }
      list add (finaljs, code)
    }
    js = Join(finaljs,"")
    js = Replace(js, "[br]", s)
    js = Replace(js, "[br/]", s)
    js = Replace(js, "[break]", s)
    js = Replace(js, "[linebreak]", s)
    js = Replace(js, "[line break]", s)
    JS.eval (js)
  ]]></function>
  <function name="ChangeDirToNautical">
    foreach (exit, AllExits()) {
      if (HasAttribute (exit.parent, "parent")) {
        if (GetBoolean (exit.parent.parent, "shiptype")) {
          if (exit.alias = "north") {
            exit.visible = false
            newname = "" + GetUniqueElementName("fore")
            create exit (newname, "fore", exit.parent, exit.to, "")
            newexit = GetObject(newname)
            newexit.to = exit.to
            newexit.alt = Split("f;forward")
          }
          else if (exit.alias = "south") {
            exit.visible = false
            newname = "" + GetUniqueElementName("aft")
            create exit (newname, "aft", exit.parent, exit.to, "")
            newexit = GetObject(newname)
            newexit.to = exit.to
            newexit.alt = Split("a")
          }
          else if (exit.alias = "west") {
            newname = "" + GetUniqueElementName("port")
            create exit (newname, "port", exit.parent, exit.to, "")
            newexit = GetObject(newname)
            newexit.to = exit.to
            newexit.alt = Split("p")
          }
          else if (exit.alias = "east") {
            exit.visible = false
            newname = "" + GetUniqueElementName("starboard")
            create exit (newname, "starboard", exit.parent, exit.to, "")
            newexit = GetObject(newname)
            newexit.to = exit.to
            newexit.alt = Split("sb")
          }
        }
      }
    }
  </function>
  <timer name="lights">
    <interval>120</interval>
    <enabled />
    <script><![CDATA[
      if (player.parent <> space_cargo_bay and player.parent <> space_engine_room and player.parent <> space_mess_deck) {
        switch (game.power) {
          case ("low") {
            msg ("<br/>The lights in the room flicker for a few moments before turning on again.")
          }
          case ("critical") {
            msg ("<br/>The lights in the room switch off, leaving you in perfect blackness for a few moments before they turn on again. You shiver as you notice that the ambient temperature has dropped a few degrees.")
          }
          case ("normal") {
          }
        }
      }
      JS.scrollToEnd ()
    ]]></script>
  </timer>
  <timer name="powerFailure">
    <interval>900</interval>
    <enabled type="boolean">false</enabled>
    <script><![CDATA[
      ClearScreen
      if (new_rods.parent <> engine and space_suit.worn = false) {
        play sound ("alarm03.mp3", false, false)
        msg ("\"Plasma reactor failure,\" announces the computer. \"Unable to maintain minimal life support functions.\"<br/><br/>You feel the temperature dropping rapidly around you and you struggle to draw breath in the increasingly thin atmosphere. Within moments, you see bright spots appear before your eyes and then... darkness...<br/><br/>You failed to save the Scion!")
        DecreaseScore (-5)
        finish
      }
      else if (new_rods.parent <> engine and space_suit.worn = true) {
        play sound ("alarm03.mp3", false, false)
        msg ("\"Plasma reactor failure,\" announces the computer. \"Unable to maintain minimal life support functions.\"<br/><br/>From within the confines of your space suit, you watch the Scion's systems shut down around you. Your air supply keeps you alive a short time longer, but with nowhere to go and no way to resurrect the Scion, you drop to your knees in despair.<br/><br/>You failed to save the Scion!")
        DecreaseScore (-3)
        finish
      }
    ]]></script>
  </timer>
  <timer name="powerWarning">
    <interval>900</interval>
    <enabled />
    <script><![CDATA[
      if (new_rods.parent <> engine) {
        EnableTimer (powerFailure)
        game.power = "critical"
        play sound ("alarm03.mp3", false, false)
        msg ("\"Warning: plasma reactor power levels have dropped to critical levels,\" the computer states flatly. \"Life support failure in 15 minutes.\"")
      }
    ]]></script>
  </timer>
  <timer name="attack">
    <interval>60</interval>
    <script><![CDATA[
      play sound ("largeexplosion1.mp3", false, false)
      msg ("<br/>You stagger as the ship is rocked by another direct hit. You're not sure how much more the Scion can take...")
      JS.scrollToEnd ()
    ]]></script>
  </timer>
  <timer name="shipDestroyed">
    <interval>600</interval>
    <script><![CDATA[
      play sound ("largeexplosion1.mp3", false, false)
      msg ("You are thrown to the deck as the Scion is blasted yet again. Secondary explosions quickly follow the initial impact and you can hear explosive decompression occuring all around you. After another few moments of violence, you have just enough time to realize that the Scion is doomed before a bright flash fills your senses.<br/><br/>You have failed to save the Scion!")
      DecreaseScore (-3)
      finish
    ]]></script>
  </timer>
</asl>```

</details>

That was my error. (Sorry!)

The start script runs before the objects' initialisation scripts, so "scion" doesn't have the "shiptype" attribute set yet when the SetupNautical function is called.

To fix that, delete the initialisation script on scion, then replace your start script with this:

set (captain, "state", "asleep")
set (hypospray, "med", "empty")
set (game, "power", "low")
js = "function isMobilePlayer(){"
  js = js + "if (typeof(currentTab) === 'string'){return true;}return false;};"
JS.eval (js)
scion.shiptype = true
SetupNautical

Also add this to the starting room's "Before entering for the first time" script:

JS.toggleNav ()
do (nautical_buttons_turnscript, "script")

Let me know if it works, please!


@Richard

if (typeof(currentTab) === 'string'){return true;}return false;

This seems to be a rather wordy way of saying:

return (typeof(currentTab) === 'string');

If you want to return true if the expression is true, and false if the expression is false, then just return the value of the expression. In JS sometimes you might want to convert a truthy/falsey value to actual true/false, in which case you'd do return (!!expression);, but that shouldn't be necessary here as the equality operators return an actual true or false.


I made the changes, including adding to the cryo_pod's "Before entering for the first time" script.

The result is that when the player arrives in the Crew Quarters (3rd room but first where nautical directions should appear), I see the following:

  1. port is listed as an exit (hurray!)
  2. west is still listed as an exit (both exits work and lead to the same place)
  3. mousing over the compass direction shows west
  4. moving into the Aft Corridor (west/port of the Crew Quarters), the compass shows the Crew Quarters exits, not the Aft Corridor exits
  5. The Aft Corridor exits in the output show up as nautical (hurray!) but west is also in the list

I have a funny situation where my starting room (Cryo Pod) is a room inside the Cryo Quarters (which is inside scion, the ship). So nautical_buttons_turnscript will find that cryo_pod.parent.parent does not have shiptype when it runs "Before entering for the first time" in cryo pod.

I tried moving those 2 lines to Cryo Quarters (2nd room) instead of Cryo Pod, but that didn't solve the problem. It did seem to help a little though, as the compass now changes when moving from Crew Quarters to Aft Corridor (the up exit disappears, but the compass is otherwise still not updated correctly).


@mrangel

Thanks! I'll change that.


@Gizmodeus

I left one line out of the ChangeDirToNautical function. That's why the normal directions were still showing up.

I fixed that, then changed the way it checks if you're on a ship. Now it checks all the parents of an exit, all the way to the top level.

Replace ChangeDirToNautical with this:

foreach (exit, AllExits()) {
  if (ListCount(FilterByAttribute (ListParents(exit), "shiptype", true)) > 0) {
    if (exit.alias = "north") {
      exit.visible = false
      newname = "" + GetUniqueElementName("fore")
      create exit (newname, "fore", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("f;forward")
    }
    else if (exit.alias = "south") {
      exit.visible = false
      newname = "" + GetUniqueElementName("aft")
      create exit (newname, "aft", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("a")
    }
    else if (exit.alias = "west") {
      exit.visible = false
      newname = "" + GetUniqueElementName("port")
      create exit (newname, "port", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("p")
    }
    else if (exit.alias = "east") {
      exit.visible = false
      newname = "" + GetUniqueElementName("starboard")
      create exit (newname, "starboard", exit.parent, exit.to, "")
      newexit = GetObject(newname)
      newexit.to = exit.to
      newexit.alt = Split("sb")
    }
  }
}

...and don't forget to add this to the "Before entering for the first time" script on your starting room if the room is on board a ship:

JS.toggleNav ()
do (nautical_buttons_turnscript, "script")

President Grue

This looks really, really good. Every good text adventure needs a ship.

I can really tell that this will make text adventures great again!


I also updated the turn script to this to handle any room which is on board a ship (no matter how deeply nested):

// Version 2
if (ListCount(FilterByAttribute (ListParents(game.pov), "shiptype", true)) > 0) {
  list = NewStringList()
  foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
    list add (list, exit.alias)
  }
  JS.updateShipCompass (Join(list, "/"))
}

@PG

This looks really, really good. Every good text adventure needs a ship.

I can really tell that this will make text adventures great again!

Thank you (I think).


Progress! The latest changes have fixed the directions links in the output. This now works perfectly!

However, the compass directions are all disabled (except for up, down, in, out).


Can you post your current code one more time?


The updated code is below. Note that there seem to be two problems:

  1. Compass buttons are disabled, but after clicking around for a while, they became enabled (not sure what I did exactly, need to spend more time testing)
  2. I have two exits that are locked at the beginning of the game (eng_door and mess_door) which are replaced with unlocked doors by ChangeDirToNautical
<!--Saved by Quest 5.7.6615.29455-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Red Alert">
    <gameid>5d168f57-b215-43fb-b260-9d2c82c05bfc</gameid>
    <version>1.2</version>
    <firstpublished>2018</firstpublished>
    <author>Eric Caillibot</author>
    <category>Sci-Fi</category>
    <showscore />
    <menufont>Georgia, serif</menufont>
    <feature_limitinventory />
    <attr name="feature_lightdark" type="boolean">false</attr>
    <attr name="feature_asktell" type="boolean">false</attr>
    <attr name="feature_annotations" type="boolean">false</attr>
    <attr name="feature_advancedwearables" type="boolean">false</attr>
    <feature_advancedscripts />
    <appendobjectdescription />
    <showcommandbar type="boolean">false</showcommandbar>
    <gridmap type="boolean">false</gridmap>
    <mapscale type="int">1</mapscale>
    <mapsize type="int">1</mapsize>
    <respondtogridclicks type="boolean">false</respondtogridclicks>
    <attr name="autodescription_youarein_useprefix" type="boolean">false</attr>
    <attr name="autodescription_youcansee" type="int">3</attr>
    <attr name="autodescription_youcango" type="int">4</attr>
    <attr name="autodescription_description" type="int">2</attr>
    <commandpane />
    <statusandcompassattop />
    <turnoffplacesandobjects />
    <description>You were supposed to remain in cryo sleep until the Scion reached orbit around your target world in the Alpha Centauri system. So why are you awake now? And why are you alone?</description>
    <cover>red-space.jpeg</cover>
    <subtitle>Adrift in Space</subtitle>
    <povstatusattributes type="stringdictionary" />
    <menufontsize type="int">11</menufontsize>
    <turnoffinventory type="boolean">false</turnoffinventory>
    <turnoffcompass type="boolean">false</turnoffcompass>
    <showpanes />
    <pov type="object">player</pov>
    <inituserinterface type="script"><![CDATA[
      JS.setCommands ("Computer;Look")
      SetTimeout (2) {
        cmds = ProcessText("{command:Computer}&emsp;{command:Look}&emsp;{command:Inventory}" + Chr(60) + "span id=\"custom-score-div\">" + Chr(60) + "br/>Score: {game.score}" + Chr(60) + "/span>")
        s = Chr(60) + "div style=\\\"padding-top:6px;\\\" id=\\\"mobile-cmds\\\">"
        s = s + Replace(cmds, Chr(34), Chr(92) + Chr(34))
        s = s + Chr(60) + "/div>"
        JS.eval ("if (typeof (currentTab) === 'string'){var s = \""+s+"\";$('body').append(s);$('#mobile-cmds').insertAfter($('#txtCommandDiv'));}")
        JS.
      }
      SendToJsEval (js.description)
      JS.changeCompass ()
    ]]></inituserinterface>
    <start type="script">
      set (captain, "state", "asleep")
      set (hypospray, "med", "empty")
      set (game, "power", "low")
      js = "function isMobilePlayer(){"
        js = js + "return (typeof(currentTab) === 'string');"
        JS.eval (js)
        scion.shiptype = true
        SetupNautical
    </start>
  </game>
  <verb>
    <property>ask/tell</property>
    <pattern>ask/tell</pattern>
    <defaultexpression>"You can't ask/tell " + object.article + "."</defaultexpression>
  </verb>
  <object name="space_cargo_bay">
    <inherit name="editor_room" />
    <usedefaultprefix type="boolean">false</usedefaultprefix>
    <alias>In Space (Outside Cargo Bay)</alias>
    <description type="script">
      msg ("The cold blackness of space is visible in every direction, perforated by innumerable, distant stars. The hull of the Scion stretches out below you, illuminated only by your suit's lights.")
      firsttime {
        msg ("The only sound is your own breathing. Using the grappling equipment integrated into your suit, you are able to move around the hull. The lack of gravity makes it virtually effortless, but the process is awkward and slow.")
      }
    </description>
    <exit name="airlock_in" alias="in" to="cargo_bay">
      <inherit name="indirection" />
      <runscript />
      <script type="script">
        msg ("You glide into the airlock and seal the outer door behind you. Air is automatically pumped into the room and once the air pressure matches the interior of the Scion, the inner door automatically slides open. You climb through the inner door, sealing it behind you. Once free of the airlock, you carefully remove the space suit.")
        MoveObject (player, cargo_bay)
        space_suit.worn = false
      </script>
    </exit>
    <exit alias="southeast" to="space_engine_room">
      <inherit name="southeastdirection" />
    </exit>
    <exit alias="northeast" to="space_mess_deck">
      <inherit name="northeastdirection" />
    </exit>
  </object>
  <command name="computer">
    <pattern>Computer</pattern>
    <script>
      queries = listComputerQueries()
      computerFunction (queries)
    </script>
  </command>
  <verb>
    <property>suitup</property>
    <pattern>suit up</pattern>
    <defaultexpression>"You can't suit up " + object.article + "."</defaultexpression>
  </verb>
  <object name="space_engine_room">
    <inherit name="editor_room" />
    <alias>In Space (Outside Engine Room)</alias>
    <description>You approach the aft section of the ship and you can see the enormous engine nacelles sticking out of the Scion. You can't help but feel awed by the sight.</description>
    <exit alias="northwest" to="space_cargo_bay">
      <inherit name="northwestdirection" />
    </exit>
    <exit alias="north" to="space_mess_deck">
      <inherit name="northdirection" />
    </exit>
    <object name="hull">
      <inherit name="editor_object" />
      <inherit name="container_closed" />
      <alias>hull</alias>
      <feature_usegive />
      <feature_container />
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Use</value>
      </displayverbs>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <inroomdescription type="string"></inroomdescription>
      <prefix>the</prefix>
      <look type="script">
        msg ("The hull outside the Engine Room shows damage that could only have been caused by some kind of weapons fire. Luckily, the damage seems to be minor.")
        if (hull.isopen = true and eng_door.locked = true) {
          msg ("A long thin gash runs along the hull, where you cut in with your plasma torch.")
        }
        else if (hull.isopen=true and eng_door.locked = false) {
          msg ("You admire your handiwork, noting that the cut you made previously has been expertly sealed.")
        }
      </look>
      <use type="script">
        if (plasma_torch.parent = player) {
          if (not hull.isopen) {
            msg ("Using the plasma torch, you begin cutting through the Scion's hull. As soon as you pierce through, a jet of air begins spraying out through the gap. You continue cutting until the atmosphere from the Engine Room has completely vented into space. Without any air left inside, the fire won't be able to sustain itself.")
            HelperOpenObject (hull)
            IncreaseScore (1)
          }
          else {
            firsttime {
              msg ("With all of the air vented into space and the fire extinguished, you use the plasma torch to seal the cut you made.")
              UnlockExit (eng_door)
              IncreaseScore (1)
            }
            otherwise {
              msg ("The hull remains well sealed. No further work is required.")
            }
          }
        }
        else {
          msg ("You don't have any tool that would let you work on the hull.")
        }
      </use>
    </object>
  </object>
  <object name="space_mess_deck">
    <inherit name="editor_room" />
    <description>You make your way around the hull to the section outside the Mess Deck. The ship was clearly fired upon by some kind of energy weapon. Minor damage is visible in several locations.</description>
    <alias>In Space (Outside Mess Deck)</alias>
    <exit alias="southwest" to="space_cargo_bay">
      <inherit name="southwestdirection" />
    </exit>
    <exit alias="south" to="space_engine_room">
      <inherit name="southdirection" />
    </exit>
    <object name="hull_breach">
      <inherit name="editor_object" />
      <alias>gaping tear in the hull</alias>
      <inroomdescription>The worst of the damage caused a hull breach, running parallel to the Scion's long axis.</inroomdescription>
      <look>A long, but very narrow gash. You're confident that you could repair the damage, if you had the right tool. Assuming you don't get fired on while you are helplessly exposed...</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Use</value>
      </displayverbs>
      <feature_usegive />
      <use type="script">
        if (plasma_torch.parent = player) {
          msg ("Carefully bracing yourself against the hull, you begin welding the gash closed with the plasma torch. Your visor automatically darkens to protect your eyes from the intense light. Despite your suit's insulated gloves, your hands heat up and become sweaty in short order. It is slow going, but you persevere and succeed in sealing the breach.")
          RemoveObject (hull_breach)
          UnlockExit (mess_door)
          IncreaseScore (1)
        }
        else {
          msg ("You can't do much about the breach without the right tool.")
        }
      </use>
    </object>
    <object name="alien_ship">
      <inherit name="editor_object" />
      <alias>Unidentified Object</alias>
      <inroomdescription>In the distance, a twinkling light catches your eye. </inroomdescription>
      <look>It is much too faint to be a star or planet. It could be another spaceship.</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
    </object>
  </object>
  <verb>
    <property>exitsuit</property>
    <pattern>exit suit</pattern>
    <defaultexpression>"You can't exit suit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>removesuit</property>
    <pattern>remove suit</pattern>
    <defaultexpression>"You can't remove suit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>dropsuit</property>
    <pattern>drop suit</pattern>
    <defaultexpression>"You can't drop suit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>stand</property>
    <pattern>stand</pattern>
    <defaultexpression>"You can't stand " + object.article + "."</defaultexpression>
  </verb>
  <turnscript name="mobileScore">
    <enabled />
    <script><![CDATA[
      JS.eval ("$('#custom-score-div').html('" + Chr(60) + "br/>Score: " + ProcessText("{game.score}") + "');")
    ]]></script>
  </turnscript>
  <turnscript name="nautical_buttons_turnscript">
    <enabled />
    <script><![CDATA[
      // Version 2
      if (ListCount(FilterByAttribute (ListParents(game.pov), "shiptype", true)) > 0) {
        list = NewStringList()
        foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
          list add (list, exit.alias)
        }
        JS.updateShipCompass (Join(list, "/"))
      }
    ]]></script>
  </turnscript>
  <object name="js">
    <inherit name="editor_room" />
    <description><![CDATA[var onBoard = false;<br/>var shipButtons = '<div id="dir-holder" style="display:none;"><div id="ship-nav"><table id="ship-directions"><tr><td></td><td>';<br/>shipButtons += '<button id="cmdCompassF" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="fore" onclick="compassClick(\'fore\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-n" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td><button id="cmdCompassP" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="port" onclick="compassClick(\'port\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-w" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></td><td></td><td></button>';<br/>shipButtons += '<button id="cmdCompassSB" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="starboard" onclick="compassClick(\'starboard\');" role="button"><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-e" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr>';<br/>shipButtons += '<tr><td></td><td><button id="cmdCompassA" class="shipcompassbutton compassbutton ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button" title="aft" onclick="compassClick(\'aft\');" role="button" ><span class="ui-button-icon-primary ui-icon ui-icon-arrowthick-1-s" style="left: 0.8em;"></span><span class="ui-button-text" style="left: 0.8em;"></span></button></td></tr></table>';<br/>shipButtons += '</div></div>';<br/>function changeCompass(){<br/>  $('body').append(shipButtons);<br/>  $("#ship-directions").css("border-spacing","0");<br/>  $("#cmdCompassNW").parent().parent().parent().attr('id','def-nav');<br/>  $('#ship-nav').hide();$('#def-nav').parent().append($('#dir-holder').html());<br/>  $(".shipcompassbutton").each(function(){<br/>    $(this).button().button("enable").button("disable");<br/>    $(".shipcompassbutton span").css("left", "0.8em");$(".shipcompassbutton .ui-button-text").css('padding','.8em .8em');<br/>  });<br/>};<br/>function toggleNav(){<br/>  $("#def-nav, #ship-nav").toggle()<br/>};<br/>function updateShipCompass(data){<br/>  var exits = data.split("/");<br/>  $(".shipcompassbutton").each(function(){<br/>    for (var exit in exits){<br/>      if($(this).attr('title') === exits[exit]){<br/>        $(this).button("enable");<br/>        break;<br/>      }else{<br/>        $(this).button("disable");<br/>      }<br/>    }<br/>  });<br/>};]]></description>
  </object>
  <object name="scion">
    <attr name="feature_startscript" type="boolean">false</attr>
    <attr name="_initialise_" type="script">
    </attr>
    <object name="cryo_quarters">
      <inherit name="editor_room" />
      <description>Row upon row of pods, each housing a crew member in cryogenic suspension, surrounds you. Even outside the pods, the room is cold. The sound of dripping water can be heard in the distance. A ladder leads down to the Crew Quarters.</description>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <descprefix type="string"></descprefix>
      <alias>Cryo Quarters</alias>
      <dropdestination type="object">cryo_quarters</dropdestination>
      <firstenter type="script">
      </firstenter>
      <beforeenter type="script">
      </beforeenter>
      <exit name="ladder down" alias="down" to="crew_quarters">
        <inherit name="downdirection" />
      </exit>
      <object name="cryo_pod">
        <inherit name="container_closed" />
        <inroomdescription>Your cryo pod stands out from the rows of identical, but sealed and occupied, pods nearby.</inroomdescription>
        <feature_container />
        <isopen type="boolean">false</isopen>
        <displayverbs type="stringlist">
          <value>Look at</value>
        </displayverbs>
        <transparent type="boolean">false</transparent>
        <openmsg>The cylindrical glass cover rotates with a hiss, opening the cryo pod. As the pod interior is exposed to the room, a cloud of vapour floats out and quickly dissipates.</openmsg>
        <closemsg>The glass cover rotates into place, sealing the cryo pod. A quiet hum is audible as the pod activates its cryo sleep cycle.</closemsg>
        <listchildren />
        <visible type="boolean">false</visible>
        <alias>cryo pod</alias>
        <close type="boolean">false</close>
        <look>A cylindrical capsule with a sliding glass cover, sized to contain a single person. Inside is a variety of vital sign sensors used to adjust the cryogenic stasis of its occupant.</look>
        <dropdestination type="object">cryo_pod</dropdestination>
        <openscript type="script">
          msg ("The cylindrical glass cover rotates with a hiss. As the pod opens to the surrounding room, a cloud of vapour floats out and quickly dissipates.")
          firsttime {
            create exit ("pod door", cryo pod, Cryo Quarters, out)
            msg ("You climb out of the pod carefully, making sure not to overexert your sluggish muscles. You still feel woozy from the effects of cryo sleep, but your senses are slowly returning to normal.")
            MoveObject (player, Cryo Quarters)
          }
        </openscript>
        <closescript type="script">
          msg ("The cylindrical glass cover rotates, sealing the cryo pod.")
        </closescript>
        <onopen type="script">
          HelperOpenObject (cryo_pod)
        </onopen>
        <description type="script">
          firsttime {
            msg ("You awake from a deep slumber, struggling to make sense of your perceptions. You are lying on your back, inside a small container. It is dark, and cold. As your consciousness returns, you manage to identify your surroundings as a cryo pod. You begin to remember climbing into it, in preparation for a long cryo sleep, while the Scion travelled to the Alpha Centauri system. Why have you been awakened? Has the Scion reached its destination? Is it time to begin founding a new colony?")
          }
          otherwise {
            msg ("The cryo pod still feels cold, even though the cryo sleep function has clearly been disabled. ")
          }
        </description>
        <onclose type="script">
          HelperCloseObject (cryo_pod)
        </onclose>
        <firstenter type="script">
        </firstenter>
        <beforeenter type="script">
          JS.toggleNav ()
          do (nautical_buttons_turnscript, "script")
        </beforeenter>
        <object name="player">
          <inherit name="editor_object" />
          <inherit name="editor_player" />
          <inherit name="namedmale" />
          <alias>Crewman Shepherd</alias>
          <usedefaultprefix />
          <look type="string"></look>
          <visible type="boolean">false</visible>
          <attr name="pov_look">You're dressed in a standard-issue jump suit, with the Scion's mission crest over your left pectoral.</attr>
          <maxvolume type="int">1</maxvolume>
          <containerfullmessage>You can't carry any more. Your jumpsuit doesn't have any pockets.</containerfullmessage>
        </object>
        <exit alias="out" to="cryo_quarters">
          <inherit name="outdirection" />
          <locked type="boolean">false</locked>
          <lockmessage>The cryo pod is sealed. </lockmessage>
          <runscript />
          <script type="script">
            if (not ListContains(ScopeVisible(), cryo_pod)) {
              if (not cryo_pod.isopen) {
                msg ("Your mind still fuzzy from the effects of prolonged cryo sleep, you push against the cryo pod's glass cover to no avail. As you slowly regain your faculties, you remember your training. Opening the cryo pod, as well as perfoming many other actions aboard the Scion, requires issuing verbal commands to the ship's computer.")
                SetTimeout (2) {
                  JS.eval ("if (typeof (currentTab) !== 'string') {$('#divOutput').append(\"TUTORIAL: Click on the Computer link at the top right to issue verbal commands to the ship's computer.\");} else {$('#divOutput').append(\"TUTORIAL: Click on the Computer link at the bottom to issue verbal commands to the ship's computer.\");}")
                  JS.scrollToEnd ()
                }
              }
              else {
                firsttime {
                  msg ("You climb out of the pod carefully, making sure not to overexert your sluggish muscles. You still feel woozy from the effects of cryo sleep, but your senses are slowly returning to normal.")
                  IncreaseScore (1)
                }
                otherwise {
                  msg ("")
                }
                MakeObjectVisible (cryo_pod)
                MoveObject (player, cryo_quarters)
                JS.toggleNav ()
                MoveObject (player, this.to)
              }
            }
            else {
              MoveObject (player, cryo_quarters)
            }
          </script>
        </exit>
      </object>
      <exit alias="in" to="cryo_pod">
        <inherit name="indirection" />
      </exit>
      <object name="captain_pod">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <inherit name="container_lockable" />
        <feature_container />
        <close type="boolean">false</close>
        <listchildren />
        <inroomdescription>You are also able to identify Captain Picker's cryo pod.</inroomdescription>
        <look>A cylindrical capsule with a sliding glass cover, identical to the one you crawled out of.</look>
        <alias>Captain Picker's cryo pod</alias>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Open</value>
        </displayverbs>
        <listchildrenprefix>Inside is</listchildrenprefix>
        <openmsg>The cylindrical glass cover rotates with a hiss, opening the cryo pod. As the pod interior is exposed to the room, a cloud of vapour floats out and quickly dissipates.</openmsg>
        <closemsg>The glass cover rotates into place, sealing the cryo pod. A quiet hum is audible as the pod activates its cryo sleep cycle.</closemsg>
        <autounlock type="boolean">false</autounlock>
        <autoopen type="boolean">false</autoopen>
        <transparent />
        <hidechildren />
        <feature_startscript />
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <attr name="_initialise_" type="script"><![CDATA[
          captain_pod.openscript => {
            if (not this.locked and not this.isopen) {
              captain_pod.isopen = true
              captain.state = "awake"
              MoveObject (captain, cryo_quarters)
              msg ("The cylindrical glass cover rotates with a hiss, opening the cryo pod. As the pod interior is exposed to the room, a cloud of vapour floats out. As it dissipates, you can see {object:captain} slowly climbing out of his pod.")
            }
            else if (not this.locked and this.isopen) {
              msg ("It is already open.")
            }
            else {
              msg ("An error chimes sounds from the ship's computer.<br/>\"Life support at critical levels. Restore main power in order to revive additional crew members.\"")
            }
          }
        ]]></attr>
        <object name="captain">
          <inherit name="editor_object" />
          <inherit name="namedmale" />
          <alias>Captain Picker</alias>
          <displayverbs type="stringlist">
            <value>Look at</value>
          </displayverbs>
          <look type="script">
            switch (captain.state) {
              case ("asleep") {
                msg ("You examine Captain Picker as he sleeps. He is in his fifties, bald, with sharp, angular features and a stern demeanour which is not diminished by his peaceful state.")
              }
              case ("awake") {
                msg ("Captain Picker rubs his face groggily with boths hands. He is in his fifties, bald, with sharp, angular features and a stern demeanour.")
              }
              case ("hurt") {
                msg ("Captain Picker lays in a heap on the floor. He appears to have been knocked unconscious and you see an angry red mark on his bald head.")
              }
              case ("combat") {
                msg ("Captain Picker is scanning the instrumentation output on the console integrated into the Captain's Chair and braking commands at the ship's computer to evade the hostile vessel incoming fire and mitigate damage.")
              }
            }
          </look>
          <speak type="script">
            talkToCaptain
          </speak>
          <ask type="scriptdictionary">
            <item key="health">
            </item>
          </ask>
        </object>
      </object>
    </object>
    <object name="crew_quarters">
      <inherit name="editor_room" />
      <description>Dozens of rows of bunk beds fill the room, all unnoccupied. The beds are made and ready for use. Once the crew is awakened from cryogenic sleep, this will become their new sleeping area. The cold air from the cryo quarters above can be felt drifting down the ladder.</description>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <descprefix type="string"></descprefix>
      <alias>Crew Quarters</alias>
      <dropdestination type="object">crew_quarters</dropdestination>
      <firstenter type="script">
      </firstenter>
      <beforeenter type="script">
      </beforeenter>
      <exit name="ladder up" alias="up" to="cryo_quarters">
        <inherit name="updirection" />
      </exit>
      <exit alias="west" to="aft_corridor">
        <inherit name="westdirection" />
      </exit>
      <object name="locker">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <feature_container />
        <inroomdescription>A row of lockers lines the far wall. </inroomdescription>
        <look>You recognize the locker designated for your use.</look>
        <listchildren />
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
          <value>Open</value>
          <value>Close</value>
        </inventoryverbs>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Open</value>
          <value>Close</value>
        </displayverbs>
        <openmsg>The locker opens with a metallic squeak.</openmsg>
        <object name="space_suit">
          <inherit name="editor_object" />
          <inherit name="wearable" />
          <alias>space suit</alias>
          <feature_wearable />
          <take />
          <attr name="wear_layer" type="int">0</attr>
          <wearmsg>You climb into the suit, piece by piece. You painstakingly verify every joint and seal, completing the pre-EVA checklist drilled into you during your training.</wearmsg>
          <removemsg>You remove the suit, struggling your way out of each section, until you are down to just your jump suit once again.</removemsg>
          <inventoryverbs type="stringlist">
            <value>Look at</value>
            <value>Suit Up</value>
            <value>Remove Suit</value>
            <value>Drop Suit</value>
          </inventoryverbs>
          <volume type="int">0</volume>
          <look type="script">
            msg ("It is a Mark IV, extra vehicular activity suit, with integrated grappling harness and air supply. ")
            if (air_tank.isopen = true) {
              msg ("The air tank is currently empty.")
            }
            else {
              msg ("The air tank is full.")
            }
          </look>
          <suitup type="script">
            if (air_tank.isopen = true) {
              msg ("Putting on the space suit with no air in the tank would doom you to suffocation.")
            }
            else {
              msg ("You climb into the suit, piece by piece. You painstakingly verify every joint and seal, completing the pre-EVA checklist drilled into you during your training.")
              space_suit.worn = true
            }
          </suitup>
          <dropsuit type="script">
            if (space_suit.worn = true) {
              msg ("You must remove the suit before dropping it.")
            }
            else {
              msg ("You drop it.")
              MoveObjectHere (space_suit)
            }
          </dropsuit>
          <removesuit type="script">
            if (player.parent=space_cargo_bay or player.parent=space_mess_deck or player.parent=space_engine_room) {
              msg ("Removing your space suit while in space would be suicide.")
            }
            else {
              msg ("You remove the suit, struggling your way out of each section, until you are down to just your jump suit once again.")
              SetObjectFlagOff (space_suit, "worn")
            }
          </removesuit>
          <object name="air_tank">
            <inherit name="editor_object" />
            <inherit name="container_limited" />
            <scenery type="boolean">false</scenery>
            <visible type="boolean">false</visible>
            <feature_container />
          </object>
        </object>
      </object>
    </object>
    <object name="aft_corridor">
      <inherit name="editor_room" />
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <alias>Aft Corridor</alias>
      <dropdestination type="object">aft_corridor</dropdestination>
      <description type="script">
        msg ("The corridor in the aft section of the Scion is wide enough for several people to walk side by side. Off to port is the Cargo Bay, the Crew Quarters are starboard, heading aft leads to the engine room, while the rest of the ship is to the fore.")
        if (eng_door.locked = true) {
          msg ("You can smell smoke coming from the aft direction.")
        }
      </description>
      <exit alias="east" to="crew_quarters">
        <inherit name="eastdirection" />
      </exit>
      <exit name="eng_door" alias="south" to="engine_room">
        <locked />
        <lockmessage>As you approach the engine room, the door does not slide open automatically. Thin tendrils of smoke are seeping around the door seal and you can feel intense heat coming from the other side.</lockmessage>
      </exit>
      <exit alias="west" to="cargo_bay">
        <inherit name="westdirection" />
      </exit>
      <exit alias="north" to="fore_corridor">
        <inherit name="northdirection" />
      </exit>
    </object>
    <object name="engine_room">
      <inherit name="editor_room" />
      <alias>Engine Room</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description type="script"><![CDATA[
        firsttime {
          msg ("As the door to the Engine Room begins to slide open, you brace yourself. If the fire damage was bad enough, you may be walking into a radioactive disaster zone. Even if you aren't immediately killed, a damaged engine could mean the Scion is about to become dead in space, dooming you and the sleeping crew to float in a cold, lonely grave for centuries. <br/><br/>When the door does open, you are relieved to see the shining blue light of the containment field. Everything within it, crucially including the engine itself, was spared from the fire. The damage to the rest of the room is extensive, but you can't worry about that right now.")
        }
        msg ("The room is peppered with black soot and the acrid smell of smoke is almost overpowering.")
      ]]></description>
      <exit alias="north" to="aft_corridor">
        <inherit name="northdirection" />
      </exit>
      <object name="containment_field">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <look>The translucent field shimmers as you inspect it. It is holding steady, at full strength.</look>
        <inroomdescription>A glowing, blue containment field protects a cynlindrical volume within the Engine Room. Everything inside the field appears pristine, having been untouched by the fire.</inroomdescription>
        <feature_container />
        <open type="boolean">false</open>
        <close type="boolean">false</close>
        <transparent />
        <alias>containment field</alias>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Open</value>
        </displayverbs>
        <openmsg type="string"></openmsg>
        <nokeymessage>Lowering the containment field would instantly expose you to dangerous radiation from the engine. </nokeymessage>
        <listchildren />
        <autounlock type="boolean">false</autounlock>
        <autoopen type="boolean">false</autoopen>
        <feature_startscript />
        <listchildrenprefix>Within it are </listchildrenprefix>
        <attr name="_initialise_" type="script"><![CDATA[
          containment_field.openscript => {
            if (not this.locked and not this.isopen) {
              msg ("Lowering the containment field would instantly expose you to dangerous radiation from the engine. ")
            }
          }
        ]]></attr>
        <object name="engine">
          <inherit name="editor_object" />
          <inherit name="container_closed" />
          <feature_container />
          <isopen type="boolean">false</isopen>
          <transparent type="boolean">false</transparent>
          <inroomdescription>The advanced fission engine sits in the centre of the containment field.</inroomdescription>
          <feature_switchable />
          <listchildren type="boolean">false</listchildren>
          <displayverbs type="stringlist">
            <value>Look at</value>
          </displayverbs>
          <look type="script">
            if (old_rods.parent = engine) {
              msg ("The engine is operational, but its power output is very low.")
            }
            else if (new_rods.parent = engine) {
              msg ("The engine is operating at full capacity. Power output is nominal.")
            }
            else {
              msg ("Without any control rods inside, the plasma reactor is offline.")
            }
          </look>
          <object name="old_rods">
            <inherit name="editor_object" />
            <alias>depleted control rods</alias>
          </object>
        </object>
        <object name="RAT">
          <inherit name="editor_object" />
          <alias>RAT</alias>
          <inroomdescription>A robotacized, automated transport (RAT) is in standby mode.</inroomdescription>
          <displayverbs type="stringlist">
            <value>Look at</value>
            <value>Use</value>
          </displayverbs>
          <feature_usegive />
          <look type="script">
            msg ("The RAT has a four wheeled base, designed for navigating rough terrain. It features a long, flat bed for transporting heavy equipment and a robotic arm for loading and unloading.")
            if (old_rods.parent = RAT) {
              msg ("The used control rods sit on top of the RAT's flat bed.")
            }
            else if (new_rods.parent = RAT) {
              msg ("The new control rods sit on top of the RAT's flat bed.")
            }
          </look>
          <use type="script"><![CDATA[
            RATQueries = NewStringList()
            RATQueries = listRATQueries()
            if (ListCount(RATQueries) = 0) {
              msg ("\"Roboticised Automated Transports will respond to verbal commands issued to the ship's computer,\" explains the ship's computer. \"RAT units can be used to service the Scion's plasma reactor. Verifying current reactor status...\"<br/>")
              engineStatus
            }
            else {
              computerFunction (RATQueries)
            }
          ]]></use>
        </object>
      </object>
      <object name="broken_rat">
        <inherit name="editor_object" />
        <inroomdescription>A robot stands just outside the field, its tires melted and its chassis warped and blackened by the fire. </inroomdescription>
        <look>A quick glance is enough to tell you that extensive reconstruction would be necessary to get this RAT working again.</look>
        <displayverbs type="stringlist">
          <value>Look at</value>
        </displayverbs>
        <alias>damaged robot</alias>
      </object>
    </object>
    <object name="cargo_bay">
      <inherit name="editor_room" />
      <alias>Cargo Bay</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The bay is packed with equipment from floor to ceiling. The mission organizer's tried to include everything needed to establish a new colony on a distant, unknown alien world. Any damage to the equipment in here could threaten the success of the mission. At the far end of the cargo bay is an airlock. </description>
      <exit alias="east" to="aft_corridor">
        <inherit name="eastdirection" />
      </exit>
      <exit name="airlock" alias="out" to="space_cargo_bay">
        <inherit name="outdirection" />
        <locked type="boolean">false</locked>
        <lockmessage type="string"></lockmessage>
        <runscript />
        <script type="script">
          if (space_suit.worn = true) {
            msg ("You open the airlock's inner door and walk inside. The inner door seals itself automatically and the air is quickly sucked out of the room. You check your space suit's systems, and they are all within normal operating parameters. The outer door slides open silently and you cautiously step out into the void.")
            JS.toggleNav ()
            MoveObject (player, space_cargo_bay)
          }
          else {
            msg ("Stepping into an airlock without wearing a space suit would be suicide.")
          }
        </script>
      </exit>
      <object name="huge_crate">
        <inherit name="editor_object" />
        <inherit name="container_closed" />
        <inherit name="container_lockable" />
        <alias>huge crate</alias>
        <feature_container />
        <listchildren />
        <nokeymessage>The crate can't be opened with your bare hands.</nokeymessage>
        <unlockmessage>The laser cut through the crate's seals with ease.</unlockmessage>
        <takemsg>The crate is much too massive to be picked up by even the strongest human.</takemsg>
        <close type="boolean">false</close>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Take</value>
          <value>Open</value>
        </displayverbs>
        <keycount type="int">1</keycount>
        <autounlock />
        <autoopen />
        <openmsg>With a solid shove, the top of the crate slides away.</openmsg>
        <key type="object">laser_opener</key>
        <look type="script">
          if (huge_crate.isopen = false) {
            msg ("The crate is tightly sealed. A label reads \"plasma reactor control rods\".")
          }
          else {
            msg ("The crate has been cut open. The lid lies discarded on the floor nearby. ")
          }
        </look>
        <object name="new_rods">
          <inherit name="editor_object" />
          <inherit name="plural" />
          <alias>new control rods</alias>
          <look>The rods are long, thin cylinders, gunmetal grey in colour. They are in pristine condition and ready for use.</look>
          <takemsg>The rods are too heavy and too numerous for you to handle unaided.</takemsg>
        </object>
      </object>
      <object name="plasma_torch">
        <inherit name="editor_object" />
        <alias>plasma torch</alias>
        <look>A heavy duty tool, able to cut through or seal metal plating up to a metre thick.</look>
        <take />
        <volume type="int">1</volume>
        <feature_usegive />
        <use type="script">
          if (plasma_torch.parent = player and player.parent = space_mess_deck and hull_breach.parent = space_mess_deck) {
            msg ("Carefully bracing yourself against the hull, you begin welding the gash closed with the plasma torch. Your visor automatically darkens to protect your eyes from the intense light. Despite your suit's insulated gloves, your hands heat up and become sweaty in short order. It is slow going, but you persevere and succeed in sealing the breach.")
            RemoveObject (hull_breach)
            UnlockExit (mess_door)
            IncreaseScore (1)
          }
          else if (plasma_torch.parent = player and player.parent = space_engine_room) {
            if (not hull.isopen) {
              msg ("Using the plasma torch, you begin cutting through the Scion's hull. As soon as you pierce through, a jet of air begins spraying out through the gap. You continue cutting until the atmosphere from the Engine Room has completely vented into space. Without any air left inside, the fire won't be able to sustain itself.")
              HelperOpenObject (hull)
              IncreaseScore (1)
            }
            else {
              firsttime {
                msg ("With all of the air vented into space and the fire extinguished, you use the plasma torch to seal the cut you made.")
                UnlockExit (eng_door)
                IncreaseScore (1)
              }
              otherwise {
                msg ("The hull remains well sealed. No further work is required.")
              }
            }
          }
          else {
            msg ("You don't see any obvious use for it here.")
          }
        </use>
      </object>
    </object>
    <object name="fore_corridor">
      <inherit name="editor_room" />
      <alias>Forward Corridor</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The corridor narrows toward the fore of the Scion, allowing only a pair of passengers to walk abreast as it reaches the Bridge at the far end. The Med Bay is on the port side, with the Mess Deck to starboard. Following the corridor aft leads into the Aft Corridor.</description>
      <exit alias="south" to="aft_corridor">
        <inherit name="southdirection" />
      </exit>
      <exit alias="north" to="bridge">
        <inherit name="northdirection" />
        <runscript />
        <script type="script"><![CDATA[
          if (captain.parent = captain_chair) {
            msg ("As you walk into the Bridge, you see that Captain Picker has already taken up his post in the Captain's Chair. The viewscreen shows a magnified image of the enemy vessel. You've never seen anything like it--it looks like a collection of haphazardly arranged spheres, variously glowing in incomprehensible patterns.<br/><br/>\"Shepherd!\" shouts the Captain as you walk in. \"I'm having the Scion perform evasive maneuvers. I need you to man the weapons and return fire! Step to it man!\"")
            MoveObject (player, bridge)
          }
          else {
            MoveObject (player, bridge)
          }
        ]]></script>
      </exit>
      <exit alias="west" to="med_bay">
        <inherit name="westdirection" />
      </exit>
      <exit name="mess_door" alias="east" to="mess_deck">
        <locked />
        <lockmessage>As you approach the door to the Mess Deck, it does not slide open automatically.</lockmessage>
      </exit>
    </object>
    <object name="med_bay">
      <inherit name="editor_room" />
      <alias>Med Bay</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The walls are lined with empty gurneys, ready to receive patients. A variety of medical equipment and robotics are installed in the middle of the room. Medicine is not your area of expertise, so you recognize very few of the devices and know how to operate fewer still.</description>
      <exit alias="east" to="fore_corridor">
        <inherit name="eastdirection" />
      </exit>
      <object name="air_compressor">
        <inherit name="editor_object" />
        <alias>air compressor</alias>
        <look>A hefty machine, the air compressor features a hose with a high pressure nozzle and locking mechanism.</look>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </inventoryverbs>
        <feature_usegive />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <use type="script">
          if (space_suit.parent = player and air_tank.isopen = true) {
            msg ("You connect the air compressor's nozzle to the space suit's air tank and activate the machine. It takes several minutes, but the tank's supply indicator finally goes from red to green.")
            air_tank.isopen = false
            IncreaseScore (1)
          }
          else if (space_suit.parent=player and air_tank.isopen = false) {
            msg ("The space suit's air supply is sufficient for several hours of operation and doesn't require any topping up.")
          }
          else {
            msg ("You have nothing to use the air compressor on.")
          }
        </use>
      </object>
      <object name="dispensary">
        <inherit name="editor_object" />
        <inherit name="container_open" />
        <alias>medication dispensary</alias>
        <look>The dispensary fills an entire wall of the Med Bay. You remember being taught that it contains an enormous variety of medication, intended to sustain the new colony until new treatments can be developed from the native flora and fauna of your new home. It features a small rectangular opening with a circular receptacle. </look>
        <feature_usegive />
        <feature_container />
        <open type="boolean">false</open>
        <close type="boolean">false</close>
        <transparent />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <listchildren />
        <listchildrenprefix>Docked in the receptacle is </listchildrenprefix>
        <use type="script">
          if (hypospray.parent = player) {
            fillHypo
          }
          else {
            msg ("You don't have anything to store medication from the dispensary.")
          }
        </use>
      </object>
    </object>
    <object name="bridge">
      <inherit name="editor_room" />
      <alias>Bridge</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The nerve center of the Scion, the Bridge is dominated by a viewscreen covering the entire curved surface at the front of the room. The captain's chair sits on a slightly raised dais in the rear with a commanding view of the entire Bridge. Between the captain's chair and the screen are several control stations, each one intended to be manned by a senior officer.</description>
      <exit alias="south" to="fore_corridor">
        <inherit name="southdirection" />
      </exit>
      <object name="captain_chair">
        <inherit name="surface" />
        <inherit name="editor_object" />
        <feature_container />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Stand</value>
        </displayverbs>
        <look>It features the most advanced ergonomics ever developed by humanity, and is made from the most advanced materials, making it comfortable for extended periods of time. It features a control panel built into the right armrest. It also includes a safety harness to ensure its occupant cannot be inadvertently ejected. It is one excellent chair.</look>
        <alias>Captain's Chair</alias>
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <prefix>the</prefix>
        <sit type="script">
          if (captain.parent = captain_chair) {
            msg ("The Captain gives you a brief, but eloquent look. You quickly back away from the chair.")
          }
          else {
            msg ("Looking over your shoulder despite yourself, you take a seat in the Captain's Chair. It feels good. You could definitely get used to this.")
            game.gridmap = false
            MoveObject (player, captain_chair)
          }
        </sit>
        <stand type="script">
          if (player.parent = captain_chair) {
            msg ("Reluctantly, you stand up, leaving the comfort of the Captain's Chair behind.")
            MoveObject (player, bridge)
            game.gridmap = true
          }
          else {
            msg ("You cannot stand up from the chair unless you sit down first.")
          }
        </stand>
      </object>
      <object name="weapon_controls">
        <inherit name="editor_object" />
        <alias>weapons control station</alias>
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <prefix>the </prefix>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <feature_usegive />
        <look type="script">
          msg ("The panel displays status information regarding the Scion's complement of defensive weaponry. The ship's mission may be colonization of a new world, but the mission planners were not so naïve as to think that peaceful intentions would preclude the occasional need for force.")
          if (new_rods.parent = engine) {
            msg ("With full power restored, the Scion's full array of weapons is available and ready for use.")
          }
          else {
            msg ("With main power at critical, all weapon functions have been disabled.")
          }
        </look>
        <use type="script"><![CDATA[
          if (captain.parent = captain_chair) {
            play sound ("tos_phasersstrikingdeflectorshields.mp3", false, false)
            msg ("You take control of the panel and with the computer's help, you acquire the enemy vessel.<br/><br/>\"Target acquired!\" you shout over the sound of the Scion taking another hit.<br/><br/>\"Fire!\" Picker shouts back at you.<br/><br/>You jab the control panel and immediately hear and feel the vibrations throughout the Scion as the heavy lasers are activated. Searing red lines appear on the viewscreen, connecting with the enemy vessel. It attempts to maneouvre away, but the tracking sensors keep the lasers on target. Explosions blossom across the vessel's hull and in a dazzling display of colours, the ship's breaks apart.<br/><br/>\"Target neutralized,\" you announce with relief.<br/><br/>\"Well done,\" replies Captain Picker. \"You've earned yourself a field promotion for saving the Scion. Now let's wake up the rest of the crew and complete our mission.\"<br/><br/>Congratulations!")
            RemoveObject (alien_ship)
            IncreaseScore (5)
            finish
          }
          else if (new_rods.parent = engine and player.parent <> captain_chair) {
            play sound ("computerbeep_1.mp3", false, false)
            msg ("As soon as you begin to manipulate the controls, an error chime sounds.<br/><br/>\"Unauthorized use of weapons systems detected. Senior officer approval is required.\"")
          }
          else if (player.parent = captain_chair) {
            msg ("You can't reach the weapons control panel from the Captain's Chair.")
          }
          else {
            msg ("The panel displays only a warning about the main power levels being critical.")
          }
        ]]></use>
      </object>
      <object name="sensors">
        <inherit name="editor_object" />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <feature_usegive />
        <alias>sensors control station</alias>
        <look type="script">
          msg ("The panel displays internal and external sensor readings. Sensor logs can also be retrieved.")
        </look>
        <use type="script"><![CDATA[
          if (player.parent = captain_chair) {
            msg ("You can't reach the sensors panel from the Captain's Chair.")
          }
          else {
            readings = NewStringList()
            list add (readings, "Internal Sensor Array")
            list add (readings, "External Sensor Array")
            list add (readings, "Sensor Logs")
            ShowMenu ("\"Select sensor information to display,\" the computer asks in response to you activating the panel.", readings, true) {
              switch (result) {
                case ("Internal Sensor Array") {
                  internalStatus
                }
                case ("External Sensor Array") {
                  play sound ("alarm03.mp3", false, false)
                  msg ("\"Warning: hostile vessel detected,\" states the computer.<br/><br/>The Scion's passive sensors are detecting intermittent energy readings from the direction of the unknown vessel. Although it is hard to be sure, given the ship's unknown origins, it would seem that it is not operating at normal capacity.<br/><br/>Active sensors show the unknown ship's size to be smaller than the Scion. Its hull design resembles a collection of spheres welded together without any clear pattern. <br/><br/>Sensors also show a planet, approximately one light month away.")
                }
                case ("Sensor Logs") {
                  ClearScreen
                  msg ("You skim through years of automated log entries detailing normal ship functions and minor glitches. Eventually, you discover today's log entry.")
                  TextFX_Typewriter ("Unknown energy signature detected.<br>Incoming weapons fire detected.<br>Damage to aft hull detected. Initiating defensive counter measures. <br>Hull breach detected on Mess Deck. Innervating Chief Engineer Dawson.<br>Power surge detected. Chief Engineer Dawson life signs failing. Innervating Crewman Shepherd.<br>Explosive discharge detected aboard hostile vessel. <br>Power surge detected in plasma reactor. Fire detected in engine room. Unable to continue defensive countermeasures.", 50)
                  ShowRoomDescription
                  IncreaseScore (1)
                }
                default {
                  play sound ("computerbeep_1.mp3", false, false)
                  msg ("\"Invalid selection,\" the computer replies.")
                }
              }
            }
          }
        ]]></use>
      </object>
      <object name="propulsion_controls">
        <inherit name="editor_object" />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Use</value>
        </displayverbs>
        <feature_usegive />
        <alias>propulsion controls station</alias>
        <look type="script">
          msg ("The panel displays status information regarding the Scion's propulsion systems.")
          if (new_rods.parent = engine) {
            msg ("With full power restored, the Scion's propulsion systems are active.")
          }
          else {
            msg ("With main power at critical, the Scion is adrift.")
          }
        </look>
        <use type="script"><![CDATA[
          if (new_rods.parent = engine and player.parent <> captain_chair) {
            msg ("The Scion's propulsion systems are active.")
          }
          else if (player.parent = captain_chair) {
            msg ("You can't reach the propulsion control panel from the Captain's Chair.")
          }
          else {
            msg ("The panel displays only a warning about the main power levels being critical.")
          }
        ]]></use>
      </object>
    </object>
    <object name="mess_deck">
      <inherit name="editor_room" />
      <alias>Mess Deck</alias>
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <description>The large open area was designed to give the crew a break from the functional, confined spaces of the rest of the ship. Floor to ceiling windows line the deck, giving an incredible view of the stars. Recent exposure to vacuum has left the deck in a sorry state, with whatever objects that were unable to fit through the hull breach now strewn across the deck. Only the bar and the tables, which are bolted to the deck, remain where they belong.</description>
      <exit alias="west" to="fore_corridor">
        <inherit name="westdirection" />
      </exit>
      <object name="laser_opener">
        <inherit name="editor_object" />
        <alias>laser cutter</alias>
        <look>A low-power, handheld laser cutter. Looks like its batteries are included.</look>
        <volume type="int">1</volume>
        <take />
        <feature_usegive />
        <use type="script">
          if (laser_opener.parent=player and player.parent=cargo_bay) {
            msg ("The laser cut through the crate's seals with ease.")
            huge_crate.locked = false
            HelperOpenObject (huge_crate)
          }
          else {
            msg ("A laser cutter must be used with care, especially on a space ship. There is no useful target for it here.")
          }
        </use>
      </object>
      <object name="coffee">
        <inherit name="editor_object" />
        <alias>instant coffee canister</alias>
        <volume type="int">1</volume>
        <look>One of the modern wonders of the world: an apparatus containing instant coffee, water and a mechanism able to combine and heat them into a ready-to-serve beverage with a simple twist of the wrist and a few moments of patience. If only they could make it taste good... </look>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Drop</value>
          <value>Give</value>
        </inventoryverbs>
        <usestandardverblist />
        <take />
        <feature_usegive />
        <givesingle type="script">
          if (player.parent = bridge and captain.parent = captain_chair or player.parent = cryo_quarters and captain.parent = captain_pod) {
            RemoveObject (coffee)
            msg ("You twist the container's top, instantly mixing and heating its contents into passable coffee, and hand it to the Captain. He glances at you and grabs the container, favouring you with a half smile.")
            IncreaseScore (1)
          }
          else {
            msg ("There is no one to give this too. ")
          }
        </givesingle>
      </object>
      <object name="hypospray">
        <inherit name="editor_object" />
        <look>A glass and metal cylinder the size of your hand. You remember from your training that it can be used to administer any kind of medication.</look>
        <take />
        <volume type="int">1</volume>
        <feature_usegive />
        <use type="script"><![CDATA[
          if (hypospray.parent = player and player.parent = med_bay) {
            fillHypo
          }
          else if (hypospray.parent = player and player.parent = cryo_quarters and captain.state = "hurt" and hypospray.med <> "empty") {
            msg ("You kneel and administer the hypospray to the unconscious form of Captain Picker.")
            if (hypospray.med = "stimulant") {
              msg ("His eyes flutter and finally open. He props himself up, rubbing his head. <br/><br/>\"What happened?\" he asks, wincing as he touches his bruised head.")
              captain.state = "healed"
              IncreaseScore (1)
              talkToCaptain
            }
            else {
              msg ("The medication does not seem to have any effect.")
            }
            hypospray.med = "empty"
          }
          else if (hypospray.med = "empty") {
            msg ("The hypospray won't do anyone much good while it is empty.")
          }
          else {
            msg ("You consider injecting yourself, but then decide it wouldn't be advisable under the circumstances.")
          }
        ]]></use>
      </object>
    </object>
  </object>
  <function name="shipStatus">
    if (alien_ship.parent = space_mess_deck) {
      play sound ("alarm03.mp3", false, false)
      msg ("Warning: hostile vessel detected")
    }
    internalStatus
  </function>
  <function name="listComputerQueries" type="stringlist">
    queries = NewStringList()
    list add (queries, "State ship status")
    if (player.parent = cryo_pod) {
      list add (queries, "Open cryo pod")
    }
    if (eng_door.locked = true and player.parent = aft_corridor) {
      list add (queries, "Extinguish fire in Engine Room")
    }
    if (player.parent = fore_corridor) {
      list add (queries, "Override door to Mess Deck")
    }
    if (player.parent=engine_room) {
      list add (queries, "State engine status")
    }
    queries = ListCombine(queries, listRATQueries())
    return (queries)
  </function>
  <function name="walkthrough">
    msg ("Starting test...")
    UnlockExit (eng_door)
    HelperOpenObject (huge_crate)
    MoveObject (player, cryo_quarters)
    RemoveObject (old_rods)
    MoveObject (new_rods, engine)
    MoveObject (hypospray, player)
    hypospray.med = "stimulant"
    captain_pod.locked = false
    mess_door.locked = false
    msg ("Test completed")
  </function>
  <function name="computerFunction" parameters="queries"><![CDATA[
    if (ListCount(queries) = 0) {
      msg ("You hear an error chime sound from the ship's computer.")
      play sound ("computerbeep_1.mp3", false, false)
    }
    else {
      play sound ("computerbeep_10.mp3", false, false)
      ShowMenu ("\"Computer,\" you call loudly. <br> \"Specify query\", says a feminine robotic voice.", queries, true) {
        switch (result) {
          case ("State ship status") {
            shipStatus
          }
          case ("Open cryo pod") {
            if (cryo_pod.isopen = false) {
              msg ("\"Opening cryo pod 352,\" replies the computer.")
              HelperOpenObject (cryo_pod)
            }
            else {
              msg ("\"Crewmen Shepherd's cryo pod is already open,\" replies the computer with an error chime.")
              play sound ("computerbeep_1.mp3", false, false)
            }
          }
          case ("Extinguish fire in Engine Room") {
            msg ("\"Unable to comply,\" replies the computer with an error tone. \"Fire countermeasure systems are inoperative.\"")
            play sound ("computerbeep_1.mp3", false, false)
          }
          case ("Override door to Mess Deck") {
            msg ("\"Unable to comply,\" replies the computer with an error tone. \"No atmosphere present on Mess Deck. Warning: hull breach detected on Mess Deck.\"")
            play sound ("alarm03.mp3", false, false)
          }
          case ("State engine status") {
            engineStatus
          }
          case ("Command the RAT to remove degraded control rods from the engine") {
            ClearScreen
            msg ("\"Executing command,\" replies the computer.<br/><br/>The RAT's robotic arm begins to move, reaching out toward the engine. The depleted rods are removed smoothly and loaded on to the RAT's flat bed, ready for transport.<br/>")
            MoveObject (old_rods, RAT)
            ShowRoomDescription
          }
          case ("Move RAT") {
            destinations = NewStringList()
            list add (destinations, "Bridge")
            list add (destinations, "Medical Bay")
            list add (destinations, "Mess Deck")
            list add (destinations, "Cargo Bay")
            list add (destinations, "Crew Quarters")
            list add (destinations, "Engine Room")
            if (player.parent = RAT.parent or player.parent=engine_room and RAT.parent=containment_field) {
              ShowMenu ("\"Specify destination,\" replies the computer.", destinations, true) {
                switch (result) {
                  case ("Bridge") {
                    MoveObject (RAT, bridge)
                  }
                  case ("Medical Bay") {
                    MoveObject (RAT, med_bay)
                  }
                  case ("Mess Deck") {
                    MoveObject (RAT, mess_deck)
                  }
                  case ("Cargo Bay") {
                    MoveObject (RAT, cargo_bay)
                  }
                  case ("Crew Quarters") {
                    MoveObject (RAT, crew_quarters)
                  }
                  case ("Engine Room") {
                    MoveObject (RAT, engine_room)
                  }
                  default {
                    msg ("Unable to comply.")
                    play sound ("computerbeep_1.mp3", false, false)
                  }
                }
                msg ("\"Executing command,\" replies the computer.<br/><br/>Its motors whirring loudly, the RAT rolls out through the door.<br/>")
                ShowRoomDescription
              }
            }
            else {
              msg ("\"Unable to comply,\" replies the computer with an error chime. \"Safety protocols prohibit commanding a RAT unit without an operator present in the same room.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
          }
          case ("Command the RAT to load the new control rods") {
            if (new_rods.parent = huge_crate and old_rods.parent <> RAT and huge_crate.isopen = true) {
              ClearScreen
              msg ("\"Executing command,\" replies the computer.<br/><br/>The RAT's robotic arm begins to move, reaching into the crate. The new control rods are carefully extracted and loaded on to the RAT's flat bed, ready for transport.<br/>")
              MoveObject (new_rods, RAT)
              ShowRoomDescription
            }
            else if (huge_crate.isopen = false) {
              play sound ("computerbeep_1.mp3", false, false)
              msg ("\"Unable to comply,\" replies the computer. \"RAT unit is unable to access control rods inside sealed cargo container.\"")
            }
            else if (new_rods.parent = RAT or old_rods.parent = RAT) {
              play sound ("computerbeep_1.mp3", false, false)
              msg ("\"Unable to comply,\" replies the computer. \"Roboticized Automated Transport is at maximum capacity.\"")
            }
          }
          case ("Unload RAT") {
            if (RAT.parent = cargo_bay and player.parent = cargo_bay and old_rods.parent = RAT) {
              ClearScreen
              msg ("\"Executing command,\" replies the computer.<br/><br/>The airlock inner door slides open and the RAT moves inside. It unloads the degraded control rods and returns to the Cargo Bay. The airlock inner door slides closed behind it.<br/><br/>\"Jettisoning degraded control rods,\" explains the computer as the airlock's outer door opens and the rods are sucked into space, along with the atmosphere inside the airlock.<br/>")
              IncreaseScore (1)
              RemoveObject (old_rods)
              ShowRoomDescription
            }
            else if (RAT.parent = containment_field and player.parent = engine_room) {
              msg ("\"Unable to comply,\" replies the computer. \"Installing degraded control rods into plasma reactor violates safety protocols.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else if (old_rods.parent = RAT and player.parent = RAT.parent) {
              msg ("\"Unable to comply,\" replies the computer. \"Degraded control rods cannot be stored in " + RAT.parent.name + ". Exposure to degraded control rods is a severe hazard to crew health.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else if (new_rods.parent = RAT and player.parent = engine_room and RAT.parent = engine_room) {
              msg ("The RAT rolls through the containment field and over to the engine. Its robotic arm carefully loads each new control rod into place inside the reactor. Once the process is complete, the engine roars into life.<br/><br/>\"Power levels nominal,\" reports the ship's computer. ''Additional crew members may now be innervated.\"")
              MoveObject (RAT, containment_field)
              MoveObject (new_rods, engine)
              HelperCloseObject (engine)
              captain_pod.locked = false
              IncreaseScore (2)
              game.power = "normal"
              DisableTimer (lights)
              DisableTimer (powerWarning)
              DisableTimer (powerFailure)
            }
            else if (new_rods.parent = RAT) {
              msg ("\"Unable to comply,\" replies the computer. \"New control rods can be damaged if not stored in accordance with usage guidelines.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else if (player.parent <> RAT.parent) {
              msg ("\"Unable to comply,\" replies the computer with an error chime. \"Safety protocols prohibit commanding a RAT unit without an operator present in the same room.\"")
              play sound ("computerbeep_1.mp3", false, false)
            }
            else {
              msg ("\"Unable to comply,\" replies the computer unhelpfully.")
              play sound ("computerbeep_1.mp3", false, false)
            }
          }
          case ("Run test") {
            walkthrough
          }
          default {
            msg ("Unable to comply.")
            play sound ("computerbeep_1.mp3", false, false)
          }
        }
      }
    }
    JS.scrollToEnd ()
  ]]></function>
  <function name="listRATQueries" type="stringlist">
    RATqueries = NewStringList()
    if (engine.isopen=true and player.parent = engine_room and old_rods.parent=engine) {
      list add (RATqueries, "Command the RAT to remove degraded control rods from the engine")
    }
    if (old_rods.parent = RAT or new_rods.parent = RAT) {
      list add (RATqueries, "Move RAT")
      list add (RATqueries, "Unload RAT")
    }
    if (player.parent = cargo_bay and RAT.parent = cargo_bay and new_rods.parent = huge_crate) {
      list add (RATqueries, "Command the RAT to load the new control rods")
    }
    return (RATqueries)
  </function>
  <function name="listCaptainTopics" type="stringlist">
    dialogue = NewStringList()
    switch (captain.state) {
      case ("asleep") {
        msg ("Captain Picker is asleep.")
      }
      case ("awake") {
        msg ("\"Captain Picker,\" you begin. ")
        list add (dialogue, "\"How do you feel?\"")
        list add (dialogue, "\"Let me catch you up on what's been going on.\"")
      }
      case ("hurt") {
        msg ("The Captain is unconscious and unresponsive.")
      }
      case ("healed") {
        list add (dialogue, "The Scion is under attack!")
        list add (dialogue, "Sleeping on the job again")
      }
      case ("combat") {
        list add (dialogue, "What are your orders?")
        list add (dialogue, "We need to return fire!")
      }
    }
    return (dialogue)
  </function>
  <function name="fillHypo"><![CDATA[
    msg ("You plug the hypospray into the medication dispensary.")
    MoveObject (hypospray, dispensary)
    if (hypospray.med <> "empty") {
      msg ("An error chime sounds. The hypospray cannot be refilled until it is emptied.")
    }
    else {
      meds = NewStringList()
      list add (meds, "antibiotics")
      list add (meds, "sedative")
      list add (meds, "stimulant")
      list add (meds, "multi-vitamin")
      ShowMenu ("\"Select medication to dispense,\" says the ship's computer.", meds, false) {
        ClearScreen
        msg ("You hear the hum of machinery within the dispensary, followed by a faint hiss. A small indicator light on the hypospray changes from red to green.<br/>")
        hypospray.med = result
        ShowRoomDescription
      }
    }
  ]]></function>
  <function name="talkToCaptain"><![CDATA[
    dialogue = listCaptainTopics()
    ShowMenu ("", dialogue, false) {
      switch (result) {
        case ("\"How do you feel?\"") {
          msg ("Captain Picker sits up in his cryo pod and rubs his eyes.<br/><br/>\"I'm fine,\" he says. \"Just a bit groggy.\"")
        }
        case ("\"Let me catch you up on what's been going on.\"") {
          ClearScreen
          msg ("You relate everything that has happened since you awoke in your cryo pod. The Captain interjects with questions occasionally, but mostly furrows his brow in concentration as he absorbs the situation.<br/><br/>\"I see,\" he says simply as you finish. <br/>")
          play sound ("largeexplosion1.mp3", false, false)
          msg ("Just then, the Scion is rocked violently. You are thrown to the floor and hear a loud thud as the Captain is thrown into the bulkhead next to you. You scramble back to your feet.<br/>")
          captain.state = "hurt"
          MoveObject (captain, cryo_quarters)
          EnableTimer (attack)
          EnableTimer (shipDestroyed)
          ShowRoomDescription
        }
        case ("The Scion is under attack!") {
          msg ("\"What?\" exlaims the Captain. \"We need to get to the Bridge!\"<br/><br/>He struggles to his feet and without waiting for a response, he slides down the ladder to the Crew Quarters.")
          MoveObject (captain, captain_chair)
          captain.state = "combat"
        }
        case ("What are your orders?") {
          msg ("\"Take control of the weapon systems and destroy that ship!\" Captain Picker shouts.")
        }
        case ("We need to return fire!") {
          msg ("\"I know that! I already ordered you to fire on that ship! Get to it!\" Captain Picker shouts angrily.")
        }
        default {
          msg ("Captain Picker fixes you with a withering stare.")
        }
      }
    }
    JS.scrollToEnd ()
  ]]></function>
  <function name="internalStatus"><![CDATA[
    if (old_rods.parent <> engine and new_rods.parent <> engine) {
      msg ("Warning: plasma reactor is offline. Operating on auxiliary power.")
    }
    if (hull_breach.parent = space_mess_deck) {
      msg ("Warning: hull breach detected on Mess Deck.")
    }
    if (hull.isopen = false and eng_door.locked = true) {
      msg ("Warning: fire detected in Engine Room.")
    }
    else if (hull.isopen = true and eng_door.locked = true) {
      msg ("Warning: hull breach detected in Engine Room")
    }
    if (new_rods.parent <> engine) {
      msg ("Warning: power levels critical.<br/><br/>Immediate intervention is recommended to avoid loss of ship and all hands aboard.")
    }
    JS.scrollToEnd ()
  ]]></function>
  <function name="engineStatus">
    if (old_rods.parent = engine) {
      msg ("\"Plasma reactor is operational,\" replies the computer. \"Power output is limited due to degraded control rods.\"")
      HelperOpenObject (engine)
    }
    else if (new_rods.parent = engine) {
      msg ("\"Plasma reactor is operational,\" replies the computer. \"Power output within nominal operating parameters.\"")
    }
    else {
      msg ("\"Warning: plasma reactor is offline,\" replies the computer with a danger chime. \"Operating on auxiliary power.\"")
      play sound ("alarm03.mp3", false, false)
    }
    JS.scrollToEnd ()
  </function>
  <function name="SetupNautical"><![CDATA[
    game.compassdirections = ListExclude (game.compassdirections, "")
    list add (game.compassdirections, "fore")
    list add (game.compassdirections, "port")
    list add (game.compassdirections, "starboard")
    list add (game.compassdirections, "aft")
    list add (game.compassdirections, "f")
    list add (game.compassdirections, "p")
    list add (game.compassdirections, "sb")
    list add (game.compassdirections, "a")
    request (SetCompassDirections, Join(game.compassdirections, ";"))
    go.pattern = "^go to (?"+Chr(60)+"exit>.*)$|^go (?"+Chr(60)+"exit>.*)$|^(?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    lookdir.pattern = "^look (?"+Chr(60)+"exit>forward|fore|starboard|aft|port|north|south|east|west|northeast|northwest|southeast|southwest|in|out|up|down|f|s|sb|a|p|n|e|w|ne|nw|se|sw|o|u|d)$"
    foreach (exit, AllExits()) {
      if (StartsWith (exit.name, "fore")) {
        exit.alias = "fore"
        exit.alt = Split("f;forward")
      }
      if (StartsWith (exit.name, "aft")) {
        exit.alias = "aft"
        exit.alt = Split("a")
      }
      if (StartsWith (exit.name, "port")) {
        exit.alias = "port"
        exit.alt = Split("p")
      }
      if (StartsWith (exit.name, "starboard")) {
        exit.alias = "starboard"
        exit.alt = Split("sb")
      }
    }
    ChangeDirToNautical
  ]]></function>
  <function name="SendToJsEval" parameters="data"><![CDATA[
    regEx = "//"
    s = Chr(60) + "br/>"
    js = Split(data,s)
    notes = NewStringList()
    foreach (line, js) {
      if (StartsWith(line,"//")) {
        list add (notes, line)
      }
    }
    js = ListExclude(js,notes)
    finaljs = NewStringList()
    foreach (line, js) {
      code = line
      if (IsRegExMatch(regEx,line)) {
        list = Split(line,"//")
        code = list[0]
      }
      list add (finaljs, code)
    }
    js = Join(finaljs,"")
    js = Replace(js, "[br]", s)
    js = Replace(js, "[br/]", s)
    js = Replace(js, "[break]", s)
    js = Replace(js, "[linebreak]", s)
    js = Replace(js, "[line break]", s)
    JS.eval (js)
  ]]></function>
  <function name="ChangeDirToNautical"><![CDATA[
    foreach (exit, AllExits()) {
      if (ListCount(FilterByAttribute (ListParents(exit), "shiptype", true)) > 0) {
        if (exit.alias = "north") {
          exit.visible = false
          newname = "" + GetUniqueElementName("fore")
          create exit (newname, "fore", exit.parent, exit.to, "")
          newexit = GetObject(newname)
          newexit.to = exit.to
          newexit.alt = Split("f;forward")
        }
        else if (exit.alias = "south") {
          exit.visible = false
          newname = "" + GetUniqueElementName("aft")
          create exit (newname, "aft", exit.parent, exit.to, "")
          newexit = GetObject(newname)
          newexit.to = exit.to
          newexit.alt = Split("a")
        }
        else if (exit.alias = "west") {
          exit.visible = false
          newname = "" + GetUniqueElementName("port")
          create exit (newname, "port", exit.parent, exit.to, "")
          newexit = GetObject(newname)
          newexit.to = exit.to
          newexit.alt = Split("p")
        }
        else if (exit.alias = "east") {
          exit.visible = false
          newname = "" + GetUniqueElementName("starboard")
          create exit (newname, "starboard", exit.parent, exit.to, "")
          newexit = GetObject(newname)
          newexit.to = exit.to
          newexit.alt = Split("sb")
        }
      }
    }
  ]]></function>
  <timer name="lights">
    <interval>120</interval>
    <enabled />
    <script><![CDATA[
      if (player.parent <> space_cargo_bay and player.parent <> space_engine_room and player.parent <> space_mess_deck) {
        switch (game.power) {
          case ("low") {
            msg ("<br/>The lights in the room flicker for a few moments before turning on again.")
          }
          case ("critical") {
            msg ("<br/>The lights in the room switch off, leaving you in perfect blackness for a few moments before they turn on again. You shiver as you notice that the ambient temperature has dropped a few degrees.")
          }
          case ("normal") {
          }
        }
      }
      JS.scrollToEnd ()
    ]]></script>
  </timer>
  <timer name="powerFailure">
    <interval>900</interval>
    <enabled type="boolean">false</enabled>
    <script><![CDATA[
      ClearScreen
      if (new_rods.parent <> engine and space_suit.worn = false) {
        play sound ("alarm03.mp3", false, false)
        msg ("\"Plasma reactor failure,\" announces the computer. \"Unable to maintain minimal life support functions.\"<br/><br/>You feel the temperature dropping rapidly around you and you struggle to draw breath in the increasingly thin atmosphere. Within moments, you see bright spots appear before your eyes and then... darkness...<br/><br/>You failed to save the Scion!")
        DecreaseScore (-5)
        finish
      }
      else if (new_rods.parent <> engine and space_suit.worn = true) {
        play sound ("alarm03.mp3", false, false)
        msg ("\"Plasma reactor failure,\" announces the computer. \"Unable to maintain minimal life support functions.\"<br/><br/>From within the confines of your space suit, you watch the Scion's systems shut down around you. Your air supply keeps you alive a short time longer, but with nowhere to go and no way to resurrect the Scion, you drop to your knees in despair.<br/><br/>You failed to save the Scion!")
        DecreaseScore (-3)
        finish
      }
    ]]></script>
  </timer>
  <timer name="powerWarning">
    <interval>900</interval>
    <enabled />
    <script><![CDATA[
      if (new_rods.parent <> engine) {
        EnableTimer (powerFailure)
        game.power = "critical"
        play sound ("alarm03.mp3", false, false)
        msg ("\"Warning: plasma reactor power levels have dropped to critical levels,\" the computer states flatly. \"Life support failure in 15 minutes.\"")
      }
    ]]></script>
  </timer>
  <timer name="attack">
    <interval>60</interval>
    <script><![CDATA[
      play sound ("largeexplosion1.mp3", false, false)
      msg ("<br/>You stagger as the ship is rocked by another direct hit. You're not sure how much more the Scion can take...")
      JS.scrollToEnd ()
    ]]></script>
  </timer>
  <timer name="shipDestroyed">
    <interval>600</interval>
    <script><![CDATA[
      play sound ("largeexplosion1.mp3", false, false)
      msg ("You are thrown to the deck as the Scion is blasted yet again. Secondary explosions quickly follow the initial impact and you can hear explosive decompression occuring all around you. After another few moments of violence, you have just enough time to realize that the Scion is doomed before a bright flash fills your senses.<br/><br/>You have failed to save the Scion!")
      DecreaseScore (-3)
      finish
    ]]></script>
  </timer>
</asl>

That spoiler element is messed up.

Try adding a line break between the <details> element and the code. Like this:

<details>

```
CODE HERE
```

</details>

Fixed. Sorry about that.


It's cool. I only immediately knew what happened because I've done it before.


The exit script has a few inconsistencies.

The most important is the bit where you add JS.toggleNav(). This is turning the nautical directions OFF in the compass pane because this toggles. The nautical directions are already on when play begins, so this toggles them off (which switches back to the normal compass pane).

Only use JS.toggleNav() when entering or exiting a ship.

Every time JS.toggleNav() is called, the compass will switch from whatever it is displaying to whatever it is not displaying. It if is displaying nautical directions, it will toggle to the normal directions, and vice-versa.


Your (modified) exit script, which leads from the starting room out to the cryo-quarters:

if (not ListContains(ScopeVisible(), cryo_pod)) {
  if (not cryo_pod.isopen) {
    msg ("Your mind still fuzzy from the effects of prolonged cryo sleep, you push against the cryo pod's glass cover to no avail. As you slowly regain your faculties, you remember your training. Opening the cryo pod, as well as perfoming many other actions aboard the Scion, requires issuing verbal commands to the ship's computer.")
    SetTimeout (2) {
      JS.eval ("if (typeof (currentTab) !== 'string') {$('#divOutput').append(\"TUTORIAL: Click on the Computer link at the top right to issue verbal commands to the ship's computer.\");} else {$('#divOutput').append(\"TUTORIAL: Click on the Computer link at the bottom to issue verbal commands to the ship's computer.\");}")
      JS.scrollToEnd ()
    }
  }
  else {
    firsttime {
      msg ("You climb out of the pod carefully, making sure not to overexert your sluggish muscles. You still feel woozy from the effects of cryo sleep, but your senses are slowly returning to normal.")
      IncreaseScore (1)
    }
    otherwise {
      msg ("")
    }
    MakeObjectVisible (cryo_pod)
    MoveObject (player, cryo_quarters)
    // Commented out the next line because it messed up the compass!
    // JS.toggleNav ()
    MoveObject (player, this.to)
  }
}
else {
  MoveObject (player, cryo_quarters)
}

I commented out JS.toggleNav(), and it works.


Also remember, this needs to be on the starting room's "Before entering for the first time" script:

JS.toggleNav ()
do (nautical_buttons_turnscript, "script")

You have it on plain old "Before entering" script, and that will toggle the compass every single time the player goes back into the pod at any point during play.


To prevent errors, I have updated the turn script.

// Version 3
if (ListCount(FilterByAttribute (ListParents(game.pov), "shiptype", true)) > 0) {
  list = NewStringList()
  foreach (exit, ScopeUnlockedExitsForRoom(game.pov.parent)) {
    list add (list, exit.alias)
  }
  JS.eval ("if(!isElementVisible('#ship-nav')){toggleNav();}")
  JS.updateShipCompass (Join(list, "/"))
}

If the player is inside of a ship object*, this will toggle the compass if the nautical buttons aren't visible.

* "inside of a ship object" means the player object is contained by a ship object. This could mean the player is in an object in a room in a room inside of a ship, or any other amount of levels in between. If the top parent object is a ship, the compass should show the nautical directions when using this version of the turn script.


Thanks for the corrections. I've updated my code, but I'll only be able to test on a desktop tomorrow (it works on mobile, but without a compass).

A problem that remains is that two of my exits are unlocked at the start of the game when they shouldn't be. I think this is due to ChangeDirToNautical, which seems to replace my locked exits with new, unlocked exits. Couldn't this function check the locked attribute and set it on the new exit? The other part to this problem is that the doors are unlocked later through events, not with a key. So I refer to the exit by name in order to unlock it. Can the function also save the original exit name when transforming it into a nautical exit?


I'm curious why this library needs to replace exits with new ones rather than just changing their aliases. But if that's necessary, it would probably be beneficial to do:

foreach (attr, ListExclude (GetAttributeNames (exit, false), Split("name;alias;alt"))) {
  set (newexit, attr, GetAttribute (exit, attr))
}

That way exits that are locked or have scripts (or have a door attached, or other fancy stuff) will have those attributes preserved.

(News of the day: I'm a moron. I built my own nautical directions system, making it pretty flexible. So in the initialise script for any room or room-container, I can put changeCompassDirections (this, "north", "forward;fore") and similar, and it will affect all rooms within that one. Then I realised that I'm completely wasting my time, because I've got the compass pane disabled so I can do the same thing much easier by just changing the alias of each direction)


I'm curious why this library needs to replace exits with new ones rather than just changing their aliases.

As am I.

It seems like there was a reason, but I can't remember what it was...

Oh, it was due to exit types and the lack of types online.


I admit that this code could be better, but I am too distracted by current events to focus on it.


Will trying to change an object's name during play not throw an error? I can't test it right now, and I don't remember if I've tried, but it seems like I tried and it threw an error.


Will trying to change an object's name during play not throw an error?

Yes, you can't change an object's name. But there's no benefit in changing its name anyway. To change a 'west' exit into a 'port' exit, you only need to change its alias and alt. It can still inherit "westdirection", there's no reason to change that.

As far as I can tell, the default JS uses the types to determine which buttons to light up on the compass. So if you change an exit's "alt" and "alias" attributes while not changing the type it inherits, the compass will carry on working fine. You'd just want to override the JS compassClick function so that it issues the right commands; and loop over $(".compassbutton") changing their titles in case anyone hovers the mous over them.


Based on mrangel's advice, I changed ChangeDirToNautical to this:

  if (ListCount(FilterByAttribute (ListParents(exit), "shiptype", true)) > 0) {
    if (exit.alias = "north") {
      exit.alias = "fore"
      exit.alt = Split("f;forward")
    }
    else if (exit.alias = "south") {
      exit.alias = "aft"
      exit.alt = Split("a")
    }
    else if (exit.alias = "west") {
      exit.alias = "port"
      exit.alt = Split("p")
    }
    else if (exit.alias = "east") {
      exit.alias = "starboard"
      exit.alt = Split("sb")
    }
  }
} 

And it worked! My locked exits now remain locked, the compass and the text displays the nautical directions correctly!

One issue that remains is that the text output directions links allow the player to attempt to go through the locked exits, prompting my desired error message. However, the compass direction for the locked exits is disabled. Trying to figure out why...


The problem is that nautical_buttons_turnscript calls ScopeUnlockedExitsForRoom(room), which doesn't return the locked exits.

So I changed that call to ScopeExitsForRoom(room) and it solved the problem!

This now seems to be working perfectly! Thank you Richard Headkid and mrangel for all of your help!


Thank you, Gizmodeus!

You put in just as much work as everyone else, if not more.

Thanks to mrangel, too (as always)!


I'll update the code in a little while.


This was my thought for the javascript:

(function () {
  var directionOverrides = {};
  $(".compassbutton[title]").each(function (i) {
    if (! $(this).attr("data-base-title")) {
      $(this).attr("data-base-title", $(this).attr("title"))
    }
  });
  changeCompass = function (directions) {
    directionOverrides = directions;
    $(".compassbutton[data-base-title]").each (function (i) {
      ver dire = $(this).attr("data-base-title");
      if (directionOverrides.hasOwnProperty(dire)) {
        if (directionOverrides[dire] == "HIDE") {
          $(this).hide();
        } else {
          $(this).show();
          if (directionOverrides[dire]) {
            $(this).attr("title", directionOverrides[dire]);
          } else {
            $(this).attr("title", dire);
          }
        }
      }
    });
  };
  compassClick = function (direction) {
    if (directionOverrides[direction]) {
      sendCommand("go "+directionOverrides[direction]);
    } else {
      sendCommand(direction);
    }
  };
})();

So instead of creating a whole new set of buttons, showing them and hiding the old ones, it changes the mouseover text and command generated by the existing buttons, and continues relying on Quest's built-in functionality to update when they're visible.

(If you have an exit that inherits "westdirection" in the room, I think it will make the #cmdCompassW button enabled, even if that exit's alias has been changed to "port" and the button with the "←" on it has been changed to generate the command "go port" when clicked)

In this case, you could give any room an attribute containing a custom set of compass directions. (Not all ships have to use the same rules. Maybe the player can end up on a flat planet with "hubwards" and "rimwards" as compass points?)

You'd have a couple of scripts to handle this.
Added to the player object's changedparent script:

room = this.parent
while (not room = null) {
  if (HasAttribute (room, "compassdirections")) {
    this.compassdirections = room.compassdirections
    room = null
  }
  else {
    if (room.parent = null) {
      this.compassdirections = NewStringDictionary()
    }
    room = room.parent
  }
}

and in player.changedcompassdirections:

  JS.changeCompass (this.compassdirections)

so the ship could have an attribute like the one in the NauticalDirections library:

    <compassdirections type="stringdictionary">
      <item>
        <key>north</key>
        <value>fore</value>
      </item>
      <item>
        <key>east</key>
        <value>starboard</value>
      </item>
      <item>
        <key>west</key>
        <value>port</value>
      </item>
      <item>
        <key>south</key>
        <value>aft</value>
      </item>
    </compassdirections>

and our hypothetical flat world could have a similar attribute, and they both get swapped in as necessary.

(Yeah, I'm procrastinating now, messing around with this because I'm stressing about lack of book sales every time I turn to my actual work)


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

Support

Forums