Random 'canAdd' error.

Sometimes when I'm testing my game I get this seemingly random error:
Error running script: Error evaluating expression 'canAdd': Unknown object or variable 'canAdd'
Error running script: Unknown object or variable 'canAdd'

Problem is, I have NO idea where this error could be coming from. My scripts don't seem to have anything wrong with them and I never got this before the Quest desktop update. Is it just a Quest bug, or am I overlooking something?


Check the scripts around where this error occurs. Without seeing the script, it could be a missing space, or " in the wrong place. if you can post your script i'm sure the 'Quest' community can help you out.


Considering it seems to happen randomly, anywhere I'm at in the game, I taking a wild guess that there's something wrong with my "timer script." A mechanic is that the game flows in real time and I use the following timer to do this. The script runs when 1 second passes. Considering the "canAdd" bug happens anywhere in the game so far, I'm willing to be something is wrong here. It's the only thing I can think of.

game.second = game.second + 1
if (game.second = 60) {
game.second = 0
if (game.minuteSECOND = 9) {
if (game.minuteFIRST = 5) {
if (game.hour = 12) {
game.hour = 1
}
else {
game.hour = game.hour + 1
}
game.minuteFIRST = 0
game.minuteSECOND = 0
}
else {
game.minuteSECOND = 0
game.minuteFIRST = game.minuteFIRST + 1
}
}
else {
game.minuteSECOND = game.minuteSECOND + 1
}
}


Hello.

To make it easier to read your code, you can wrap it in ```, like so:


```
if (this was a real code){
  msg("This would keep the formatting intact.")
}
```

This would display:

if (this was a real code){
  msg("This would keep the formatting intact.")
}

I've taken the liberty of formatting your code..

game.second = game.second + 1
if (game.second = 60) {
  game.second = 0
  if (game.minuteSECOND = 9) {
    if (game.minuteFIRST = 5) {
      if (game.hour = 12) {
        game.hour = 1
      }
      else {
        game.hour = game.hour + 1
      }
      game.minuteFIRST = 0
      game.minuteSECOND = 0
    }
    else {
      game.minuteSECOND = 0
      game.minuteFIRST = game.minuteFIRST + 1
    }
  }
  else {
    game.minuteSECOND = game.minuteSECOND + 1
  }
}

Are you using JS or a SetTimeout to call this script every second?

Can you paste that code here, too?

Never mind me. If I had slowed down a little while reading your post, I'd have known this is the SetTimeout script.

I'll go mess with this and be right back.


This tester works fine for me:

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Place Your Bets">
    <gameid>eb3aa6cf-5961-4ed1-aa58-06f517ff9827</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <showmoney type="boolean">false</showmoney>
    <start type="script">
      game.second = 0
      game.hour = 0
      game.minuteFIRST = 0
      game.minuteSECOND = 0
      doTime
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
  <function name="doTime"><![CDATA[
    game.second = game.second + 1
    if (game.second = 60) {
      game.second = 0
      if (game.minuteSECOND = 9) {
        if (game.minuteFIRST = 5) {
          if (game.hour = 12) {
            game.hour = 1
          }
          else {
            game.hour = game.hour + 1
          }
          game.minuteFIRST = 0
          game.minuteSECOND = 0
        }
        else {
          game.minuteSECOND = 0
          game.minuteFIRST = game.minuteFIRST + 1
        }
      }
      else {
        game.minuteSECOND = game.minuteSECOND + 1
      }
    }
    msg ("<br/>"+game.hour+" HOURS, "+game.minuteFIRST+""+game.minuteSECOND+" MINUTES, "+game.second+" SECONDS")
    JS.addTextAndScroll("")
    SetTimeout (1) {
      doTime
    }
  ]]></function>
</asl>

It may be due to another script that's using a timer...

(You can't cross the streams sometimes.)


Also, I can't remember who taught me this trick (I think it was mrangel), but you can use PadString() instead of making 2 minute attributes (minuteFIRST and minuteSECOND).

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Place Your Bets">
    <gameid>eb3aa6cf-5961-4ed1-aa58-06f517ff9827</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <showmoney type="boolean">false</showmoney>
    <start type="script">
      game.second = 0
      game.hour = 0
      game.minute = 0
      doTime
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
  <function name="doTime"><![CDATA[
    game.second = game.second + 1
    if (game.second = 60) {
      game.second = 0
      if (game.minute = 59) {
        if (game.hour = 12) {
          game.hour = 1
        }
        else {
          game.hour = game.hour + 1
        }
        game.minute = 0
      }
      else {
        game.minute = game.minute + 1
      }
    }
    // PadString is adding the 0 in front when not 2 digits
    hrs = PadString(game.hour, 2, 0)
    mins = PadString(game.minute, 2, 0)
    secs = PadString(game.second, 2, 0)
    msg ("<br/>"+hrs+" HOURS, "+mins+" MINUTES, "+secs+" SECONDS")
    //This next line of code just makes it scroll down, so I don't \
    //  have to do the scrolling while watching the time go by.
    JS.addTextAndScroll ("")  
    SetTimeout (1) {
      doTime
    }
  ]]></function>
</asl>

canAdd is local variable in the ContainsAccessible function in Quest (in CoreScopes.aslx), which is used by ScopeInventoryand others. It is not something that got changed in the last update. The block of code is used when there is an object in a container, and Quest is tryng to decide if the object is visible or reachable; if it cam then canAdd is set to true.

I cannot see anything wrong with the code, and I cannot imagine this would not have been spotted earlier if it was a bug. That said, I cannot imagine how anything in your code would be doing this either.


That error appears to concern scope.

[email protected]:~$ cd /mnt/c/Program\ Files\ \(x86\)/Quest\ 5/
[email protected]:/mnt/c/Program Files (x86)/Quest 5$ grep -r canAdd *
Core/CoreScopes.aslx:          canAdd = CanReachThrough(searchObj.parent)
Core/CoreScopes.aslx:          canAdd = CanSeeThrough(searchObj.parent)
Core/CoreScopes.aslx:        if (canAdd) {
Binary file devtools_resources.pak matches

And this script contains the only three instances of canAdd:

<function name="ContainsAccessible" type="boolean" parameters="parentObj, searchObj, onlyReachable">
    if (not HasObject(searchObj, "parent")) {
      return (false)
    }
    else if (not searchObj.visible) {
      return (false)
    }
    else if (GetBoolean(parentObj, "darklevel") and not GetBoolean(searchObj, "lightsource")) {
      return (false)
    }
    else {
      if (searchObj.parent = null) {
        return (false)
      }
      else if (searchObj.parent = parentObj) {
        return (true)
      } else {
        if (onlyReachable) {
          canAdd = CanReachThrough(searchObj.parent)
        }
        else {
          canAdd = CanSeeThrough(searchObj.parent)
        }
        
        if (canAdd) {
          return (ContainsAccessible(parentObj, searchObj.parent, onlyReachable))
        } else {
          return (false)
        }
      }
    }
  </function>

That script is called by these two (which, I believe are invoked after each turn):

  <function name="ContainsVisible" type="boolean" parameters="parentObj, searchObj">
    return (ContainsAccessible(parentObj, searchObj, false))
  </function>

  <function name="ContainsReachable" type="boolean" parameters="parentObj, searchObj">
    return (ContainsAccessible(parentObj, searchObj, true))
  </function>

Yep. That's definitely called each turn.

  <function name="ScopeInventory" type="objectlist">
    result = NewObjectList()
    foreach (obj, GetAllChildObjects(game.pov)) {
      if (ContainsVisible(game.pov, obj)) {
        list add(result, obj)
      }
    }
    return (result)
  </function>

Also, I added other SetTimeout scripts, along with get input, Ask, and ShowMenu, and I never saw that error.

I'm guessing your error is being caused by something besides your clock.


EDIT

I was playing around with this while typing it up for about ten minutes, and I didn't see that The Pixie had posted the answer until just now... (Hehehe.)


So basically, I'm not gonna be able to figure out what specifically caused this error?
Because I honestly cannot think of what else could have caused it. I don't think I can just post ALL of the game's scripts here, to figure it out.


I don't think I can just post ALL of the game's scripts here

You can email me the .aslx file or post the code as a secret GitHub Gist (which can be easily deleted or altered) and link to it here.

(Message me if you'd like to go the email route.)


If it's not terribly long, you could just copy the entire game's text and paste it here. (We probably need to get at the entire game, though. If the game is published online and just not available for everyone to see, we could test it out that way, too.)


I also experience something similar and possibly related, wherein I get bizarre, seemingly random, and inconsistent error messages (including "CanAdd" messages). Many of these had to do with conflicts using "wait" scripts. What happens is that Quest will continue executing other scripts that are in subsequent blocks while waiting for the scripts in the current "wait" block to finish. So you get an issue with two streams of scripts simultaneously executing. This potentially applies to scripts with blocks that wait, and functions with scripts that wait (timers), as Pixie has outlined here:

http://docs.textadventures.co.uk/quest/blocks_and_scripts.html

My solution was to use "on ready" and quarter-second silent sound files (that play nothing; found these on GitHub) to force Quest to resolve the wait blocks before continuing on with the main stream of remaining scripts.

The other thing I've found that causes this type of issue is when, as a player, you input commands too fast before Quest has resolved the last turn. If you input commands too soon, Quest will ignore them (with no error messages); if you input them after Quest has fully resolved the last turn, things work fine. But there is a slim window between the two where if you input commands JUST AS Quest is finishing the previous turn, Quest will spit out strange error messages but still manage to process the new turn OK.


Log in to post a reply.

Support

Forums