Suppressing Turn Scripts

Quest 5.8 will have a new attribute on the game object: suppressturnscripts, which is set to false by default.

The FinishTurn function has been modified to check this value before calling RunTurnScripts:

UPDATE: DO NOT USE THIS IN QUEST 5.8!

  <function name="FinishTurn">
    if (not GetBoolean(game, "suppressturnscripts")) {
      RunTurnScripts
    }
    game.suppressturnscripts = false
    UpdateStatusAttributes
    CheckDarkness
    UpdateObjectLinks
  </function>

If you are scripting something which will cause the turn scripts to fire an extra time (like a call to ASLEvent), you can add this to the script to suppress the turn scripts once:

game.suppressturnscripts = true

Note that this will not prevent the turn scripts from firing when using in conjunction with a call to ASLEvent. It will prevent the turn scripts from firing TWICE in one turn. This is because of the way ASLEvent calls are setup. Initially, they were only used for sending commands when clicking on the buttons or the hyperlinks, so they are hard-coded to call FinishTurn.

Also note that setting game.suppressturnscripts to true in a normal script (without a call to ASLEvent or Handle*Command, or something of that nature) will prevent the turn scripts from firing at all.


Confused yet?

Good! Now, let's add a turn count to the mix!


FOR DESKTOP USERS ONLY!!!

Sorry, online users! I will be overriding a Quest function in this code, and you can't do that. If you can't use the desktop version of Quest, reading any more of this will be a waste of your time. (This is only because of all of the crazy things I'm doing at once in this example game, mind you. I will make myself a note to post a different example for those of you using the web editor.)


Suppressing Turn Scripts and Turn Counts

An example game, piece by piece


The game object

Here is the game object in full code view:

  <game name="Suppressing the Turn Scripts">
    <gameid>65c36394-fcd4-4abf-89a5-4d0659cb4ef7</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <turns type="int">0</turns>
    <statusattributes type="stringdictionary">
      <item>
        <key>turns</key>
        <value>Turns: !</value>
      </item>
    </statusattributes>
  </game>

The turns attributes (on the game object)

I have an integer attribute named "turns", which is initially set to 0.

<turns type="int">0</turns>

I also have a statusattributes dictionary attribute set up on the game object:

    <statusattributes type="stringdictionary">
      <item>
        <key>turns</key>
        <value>Turns: !</value>
      </item>
    </statusattributes>

Turn Scripts, Commands, Quest Functions, Javascript Functions, and ASLEvents

The turn count

I have to set up a function which is called by a modified HandleSingleCommand to make all of this work together correctly:

  <function name="TurnCount">
    if (not GetBoolean(game, "notarealturn")) {
      IncreaseObjectCounter (game, "turns")
    }
    game.notarealturn = false
  </function>

Modifying HandleSingleCommand

I simply add the line TurnCount to the very end of the HandleSingleCommand function's script.

If you'd like to see the entire function in code view, click here:

  <function name="HandleSingleCommand" parameters="command"><![CDATA[
    if (LCase(command) = "again" or LCase(command) = "g") {
      // First handle AGAIN
      if (not game.pov.currentcommand = null) {
        HandleSingleCommand (game.pov.currentcommand)
      }
      else {
        msg ("There is nothing to repeat.")
      }
    }
    else {
      // Check through all commands for any that match
      candidates = NewObjectList()
      foreach (cmd, ScopeCommands()) {
        if (IsRegexMatch(cmd.pattern, command, cmd.name)) {
          list add (candidates, cmd)
        }
      }
      maxstrength = -1
      thiscommand = null
      // Pick the best match
      foreach (candidate, candidates) {
        strength = GetMatchStrength(candidate.pattern, command, candidate.name)
        // favour commands defined later, so an author can override a library command...
        if (strength >= maxstrength) {
          // ... except if the command defined later (candidate) has no parent, and the current best
          // match (thiscommand) does have a parent. We want to favour any commands defined in rooms
          // over global candidates.
          skip = false
          if (thiscommand <> null) {
            if (thiscommand.parent <> null and candidate.parent = null) {
              skip = true
            }
          }
          if (not skip) {
            thiscommand = candidate
            maxstrength = strength
          }
        }
      }
      if (thiscommand = null) {
        if (HasScript(game, "unresolvedcommandhandler")) {
          params = NewDictionary()
          dictionary add (params, "command", command)
          do (game, "unresolvedcommandhandler", params)
        }
        else {
          msg (Template("UnrecognisedCommand"))
        }
        HandleNextCommandQueueItem
      }
      else {
        varlist = Populate(thiscommand.pattern, command, thiscommand.name)
        HandleSingleCommandPattern (command, thiscommand, varlist)
      }
    }
    TurnCount
  ]]></function>

If I wish to suppress the turn count during out of world commands (such as HELP, HINT, etc.), I add this line to the command's script:

game.notarealturn = true

My TurnCount function will automatically set game.notarealturn back to false when called, so the turn count will be increased (as it normally would) on the next turn (unless I suppress the turn count again).


Suppressing turns scripts while suppressing the turn count

Now I can suppress the turn scripts and the turn count, even while calling an ASLEvent.

I have four test commands to play with:

  <command name="hint">
    <pattern>hint;hints</pattern>
    <script>
      game.suppressturnscripts = true
      game.notarealturn = true
      msg ("This story has no hints.")
    </script>
  </command>

  <command name="testone">
    <pattern>test one</pattern>
    <script>
      JS.testOne ()
    </script>
  </command>
  <command name="testtwo">
    <pattern>test two</pattern>
    <script>
      game.suppressturnscripts = true
      JS.testTwo ()
    </script>
  </command>
  <command name="testthree">
    <pattern>test three</pattern>
    <script>
      game.notarealturn = true
      game.suppressturnscripts = true
      JS.testThree ()
    </script>
  </command>

Note that the HINT command doesn't require anything extra, but each of the TEST commands are calling a JS function, each of which call an ASLEvent , which each call a Quest function:

  <function name="CallMeWithASL" parameters="data">
    msg (data)
  </function>

Javascript functions

I would normally show how to do this in JS.eval(), but, since we are already overriding functions to pull all of this off, we might as well just use the desktop player to our advantage and include a Javascript file.

<javascript src="javascript.js" />

javascript.js

// I am using a setTimeout so the text will actually print online.
// I am adding additional setTimout so the web player scrolls to the end after if finally decides to print the message.

function testOne(){
	setTimeout(function(){
		ASLEvent('CallMeWithASL','The turn scripts fired twice!');
		if (webPlayer){
		  setTimeout(function(){
		    scrollToEnd();
		  },500);
		}
	},1);
};

function testTwo(){
	setTimeout(function(){
		ASLEvent('CallMeWithASL','This did not cause the turn scripts to fire an extra time.  The turn scripts only fired once, as expected.');
		if (webPlayer){
		  setTimeout(function(){
		    scrollToEnd();
		  },500);
		}
	},1);
};

function testThree(){
	setTimeout(function(){
	    ASLEvent('CallMeWithASL','This did not cause the turn scripts to fire an extra time, and the turn count stayed the same.');
	    if (webPlayer){
		  setTimeout(function(){
		    scrollToEnd();
		  },500);
		}
	},1);
};

The Example Game

It's very boring and dumb, but it's working correctly.

http://textadventures.co.uk/games/view/wojva_z2wu2hh5r8kiernq/suppressing-the-turn-scripts

The Code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Suppressing the Turn Scripts">
    <gameid>65c36394-fcd4-4abf-89a5-4d0659cb4ef7</gameid>
    <version>0.5</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <turns type="int">0</turns>
    <statusattributes type="stringdictionary">
      <item>
        <key>turns</key>
        <value>Turns: !</value>
      </item>
    </statusattributes>
    <description><![CDATA[A test game.<br/><br/>Enter HINT:  no turn scripts, and no turn count<br/><br/>Enter TEST ONE: turn scripts fire twice in one turn, and the turn count increases by 2<br/><br/>Enter TEST TWO:  turns scripts fire once, and the turn count increases by 1<br/><br/>Enter TEST THREE: no turn scripts, and no turn count]]></description>
    <author>KV</author>
  </game>
  <turnscript name="test_turnscript">
    <enabled />
    <script><![CDATA[
      msg ("<b><center><br/>I AM THE TEST TURNSCRIPT!<br/></center></b>")
    ]]></script>
  </turnscript>
  <object name="room">
    <inherit name="editor_room" />
    <description><![CDATA[<br/>Enter (or click):<br/> {command:TEST ONE},  {command:TEST TWO}, or  {command:TEST THREE}]]></description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
  <command name="hint">
    <pattern>hint;hints</pattern>
    <script>
      game.suppressturnscripts = true
      game.notarealturn = true
      msg ("This story has no hints.")
    </script>
  </command>
  <command name="testone">
    <pattern>test one</pattern>
    <script>
      JS.testOne ()
    </script>
  </command>
  <command name="testtwo">
    <pattern>test two</pattern>
    <script>
      game.suppressturnscripts = true
      JS.testTwo ()
    </script>
  </command>
  <command name="testthree">
    <pattern>test three</pattern>
    <script>
      game.notarealturn = true
      game.suppressturnscripts = true
      JS.testThree ()
    </script>
  </command>
  <function name="HandleSingleCommand" parameters="command"><![CDATA[
    if (LCase(command) = "again" or LCase(command) = "g") {
      // First handle AGAIN
      if (not game.pov.currentcommand = null) {
        HandleSingleCommand (game.pov.currentcommand)
      }
      else {
        msg ("There is nothing to repeat.")
      }
    }
    else {
      // Check through all commands for any that match
      candidates = NewObjectList()
      foreach (cmd, ScopeCommands()) {
        if (IsRegexMatch(cmd.pattern, command, cmd.name)) {
          list add (candidates, cmd)
        }
      }
      maxstrength = -1
      thiscommand = null
      // Pick the best match
      foreach (candidate, candidates) {
        strength = GetMatchStrength(candidate.pattern, command, candidate.name)
        // favour commands defined later, so an author can override a library command...
        if (strength >= maxstrength) {
          // ... except if the command defined later (candidate) has no parent, and the current best
          // match (thiscommand) does have a parent. We want to favour any commands defined in rooms
          // over global candidates.
          skip = false
          if (thiscommand <> null) {
            if (thiscommand.parent <> null and candidate.parent = null) {
              skip = true
            }
          }
          if (not skip) {
            thiscommand = candidate
            maxstrength = strength
          }
        }
      }
      if (thiscommand = null) {
        if (HasScript(game, "unresolvedcommandhandler")) {
          params = NewDictionary()
          dictionary add (params, "command", command)
          do (game, "unresolvedcommandhandler", params)
        }
        else {
          msg (Template("UnrecognisedCommand"))
        }
        HandleNextCommandQueueItem
      }
      else {
        varlist = Populate(thiscommand.pattern, command, thiscommand.name)
        HandleSingleCommandPattern (command, thiscommand, varlist)
      }
    }
    TurnCount
  ]]></function>
  <function name="TurnCount">
    if (not GetBoolean(game, "notarealturn")) {
      IncreaseObjectCounter (game, "turns")
    }
    game.notarealturn = false
  </function>
  <function name="FinishTurn">
    if (not GetBoolean(game, "suppressturnscripts")) {
      RunTurnScripts
    }
    game.suppressturnscripts = false
    UpdateStatusAttributes
    CheckDarkness
    UpdateObjectLinks
  </function>
  <function name="CallMeWithASL" parameters="data">
    msg (data)
  </function>
  <javascript src="javascript.js" />
</asl>

NOTE: I didn't use a turn script for the turn count because the ASLEvent caused it to increase no matter what I did. In the end, I decided HandleSingleCommand was probably the best place to put it, anyway.


These commands should suppress turn scripts:

oops

help

save

version

log

all transcript commands


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

Support

Forums