[Solved] Can't figure why this script isn't working

Curt A. P.
15 Nov 2021, 10:10

I give two examples. One is working perfectly, the other one doesn't.

This works perfectly:

game.minute = 0
game.minute_string = "0" + ToString(game.minute)
game.changedminute => {
  if (game.minute > 59) {
    game.hour = game.hour + 1
    game.minute = 0
  }
  if (game.minute < 10) {
    game.minute_string = "0" + ToString(game.minute)
  }
  if (game.minute > 9) {
    game.minute_string = ToString(game.minute)
  }
}
game.changedminute_string => {
  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
}
game.minute_increase = 0
game.changedminute_increase => {
  if (game.minute_increase > 0) {
    game.minute = game.minute + 1
    game.minute_increase = game.minute_increase - 1
  }
  if (game.minute_increase < 1) {
    game.minute_increase = 0
  }
}

But this is not working:

game.second = 0
game.second_string = "0" + ToString(game.second)
game.changedsecond => {
  if (game.second > 59) {
    game.minute = game.minute + 1
    game.second = 0
  }
  if (game.second < 10) {
    game.second_string = "0" + ToString(game.second)
  }
  if (game.second > 9) {
    game.second_string = ToString(game.second)
  }
}
game.changedsecond_string => {
  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
}
game.second_increase = 0
game.changedsecond_increase => {
  if (game.second_increase > 0) {
    game.second = game.second + 1
    game.second_increase = game.second_increase - 1
  }
  if (game.second_increase < 1) {
    game.second_increase = 0
  }
}

So, even my debugging command shows that,
if I change the value of
game.second_increase
the value of
game.second
will not change despite having the changed-script,
game.changedsecond_increase


mrangel
15 Nov 2021, 14:01

Hmm… I can't see a problem in the code there.

Things to check:

  1. Has this code run before you increased second_increase? I assume this is running at the start of the game, but it's something to check just in case.
  2. Are you sure that game.second isn't changing? It might be worth temporarily making a command that displays the current values of all the variables; so for example you can check whether it's second, second_string, or clock_string that isn't updating as required.
  3. Have you checked that you didn't mistype second_increase in whichever script changes its value? We've all spent hours trying to debug a piece of code, only to find out that it's not even being run because of a typo. (Including second_increase in the debug function I mentioned above would help with this as well)

If this doesn't help, do you have a link to the game? People might spot something else if looking at the full code.


Curt A. P.
16 Nov 2021, 06:05

(the captcha to post a reply wasn't loading several hours yesterday. Different browsers. Would have replied earlier.)

Has this code run before you increased second_increase? I assume this is running at the start of the game, but it's something to check just in case.

Yes, the scripts run in the start script, called by a function. Both, minute and second second are in the same functions.

Are you sure that game.second isn't changing? It might be worth temporarily making a command that displays the current values of all the variables; so for example you can check whether it's second, second_string, or clock_string that isn't updating as required.

Yes, I already tested it debugging commands which prints ToString(game.second), and it does not change.

I look at this script since yesterday and I don't find any reason that the changed-script doesn't do anything? I don't get any errors.

Have you checked that you didn't mistype second_increase in whichever script changes its value? We've all spent hours trying to debug a piece of code, only to find out that it's not even being run because of a typo. (Including second_increase in the debug function I mentioned above would help with this as well)

I don't have access to Quest for Windows anymore, and there is no debug feature. (Or not?)

If this doesn't help, do you have a link to the game? People might spot something else if looking at the full code.

How can I do that?


Curt A. P.
16 Nov 2021, 07:43

I found the problem!

I replaced the changed-script, game.changedsecond_increase, a little bit further down in the code...

game.hour_increase = 0
game.changedsecond_increase => { 
  if (game.hour_increase > 0) {
    game.hour = game.hour + 1
    game.hour_increase = game.hour_increase - 1
  }

// Should be 

game.hour_increase = 0
game.changedhour_increase => {
  if (game.hour_increase > 0) {
    game.hour = game.hour + 1
    game.hour_increase = game.hour_increase - 1
  }

mrangel
16 Nov 2021, 10:22

Good that you caught it :)
Something to take away here is that if you can't see the problem in a piece of code, there's a good chance that something somewhere else is messing with it.


One other thing that puzzled me a little was this script:

game.changedsecond_increase => {
  if (game.second_increase > 0) {
    game.second = game.second + 1
    game.second_increase = game.second_increase - 1
  }
  if (game.second_increase < 1) {
    game.second_increase = 0
  }
}

Which seems to be a rather inefficient way of creating the same effect as:

game.changedsecond_increase => {
  if (game.second_increase > 0) {
    game.second = game.second + game.second_increase
  }
  game.second_increase = 0
}

Curt A. P.
16 Nov 2021, 12:07

One other thing that puzzled me a little was this script:

Which seems to be a rather inefficient way of creating the same effect as:

I think it less complicated on the long run... Because If I run scripts that determine higher values of second_increase I have to do the math for the higher units.
If the current time is (hh:mm:ss) 12:00:45
then an second_increase of 30 would affect the next higher unit, to 12:01:15.
In the most extreme case, if it's 23:59:59,
The increase of just 1 second would change every single time unit. If it's more than 1 second, there need to be additional math, which would make the code much longer.

To keep it easy, if I limit the maximum second_increase to maximum 60, it would start like this:

game.changedsecond_increase => {
  if (game.second_increase > 0) {
    if (game.second + game.second_increase > 60) {
      game.second = game.second + game.second_increase - 60
      game.minute = game.minute + 1
      game.second_increase = 0

...and more math for some other complicated cases and
Much more things to mess up with. My current attempt seems like save way to as long as I run the increased time in order: seconds > minutes > hours > days


mrangel
16 Nov 2021, 14:01

Oh yeah … increasing by more than 60 seconds at a time, you'd also have to change:

game.changedsecond => {
  if (game.second > 59) {
    game.minute = game.minute + 1
    game.second = 0
  }

to:

game.changedsecond => {
  game.minute = game.minute + game.second/60
  game.second = game.second % 60

Curt A. P.
16 Nov 2021, 16:14
game.second = game.second % 60

Please explain, what happens there?


This is the code at the moment. I plan to add to the changed-scripts a scope/filter function that reduces completion- or waiting times for different events.

// Function in the start script to initiate the clock

game.day = 1
game.hour = 10
game.minute = 0
game.second = 0
game.hour_string = ToString(game.hour)
game.minute_string = "0" + ToString(game.minute)
game.second_string = "0" + ToString(game.second)
game.day_string = "day " + ToString(game.day)
game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
game.changedsecond => {
  if (game.second > 59) {
    game.minute = game.minute + 1
    game.second = 0
  }
  if (game.second < 10) {
    game.second_string = "0" + ToString(game.second)
  }
  if (game.second > 9) {
    game.second_string = ToString(game.second)
  }
}
game.changedminute => {
  if (game.minute > 59) {
    game.hour = game.hour + 1
    game.minute = 0
  }
  if (game.minute < 10) {
    game.minute_string = "0" + ToString(game.minute)
  }
  if (game.minute > 9) {
    game.minute_string = ToString(game.minute)
  }
}
game.changedhour => {
  if (game.hour > 23) {
    game.day = game.day + 1
    game.hour = 0
  }
  if (game.second < 10) {
    game.hour_string = "0" + ToString(game.hour)
  }
  if (game.hour > 9) {
    game.hour_string = ToString(game.hour)
  }
}
game.changedday => {
  game.day_string = ToString(game.day)
}
game.changedsecond_string => {
  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
}
game.changedminute_string => {
  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
}
game.changedhour_string => {
  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
}

// Function to change the time in the start script 

game.second_increase = 0
game.changedsecond_increase => {
  if (game.second_increase > 0) {
    game.second = game.second + 1
    game.second_increase = game.second_increase - 1
  }
  if (game.second_increase < 1) {
    game.second_increase = 0
  }
}
game.minute_increase = 0
game.changedminute_increase => {
  if (game.minute_increase > 0) {
    game.minute = game.minute + 1
    game.minute_increase = game.minute_increase - 1
  }
  if (game.minute_increase < 1) {
    game.minute_increase = 0
  }
}
game.hour_increase = 0
game.changedhour_increase => {
  if (game.hour_increase > 0) {
    game.hour = game.hour + 1
    game.hour_increase = game.hour_increase - 1
  }
  if (game.hour_increase < 1) {
    game.hour_increase = 0
  }
}
game.day_increase = 0
game.changedday_increase => {
  if (game.day_increase > 0) {
    game.day = game.day + 1
    game.day_increase = game.day_increase - 1
  }
  if (game.day_increase < 1) {
    game.day_increase = 0
  }
}

mrangel
16 Nov 2021, 19:05
 game.second = game.second % 60

Please explain, what happens there?

The modulo operator % gives the remainder of a division. So for example 17 % 10 will give you 7, and 100 % 60 will give you 40. Makes the code a lot simpler, because you don't need any if/else logic.


A more common way to handle time is just using an 'epoch' time value, where you store the number of seconds after a given start point; then you only need to use % and / to extract the current time. The advantage of this method is that everything that deals with the passage of time involves changing the epoch time, so So your scripts would look like:

game.changedepoch => {
  game.second = game.epoch % 60
  game.minute = (game.epoch / 60) % 60
  game.hour = (game.epoch / 60 / 60) % 24
  game.day = game.epoch / 60 / 60 / 24

  game.second_string = Right("0" + game.second, 2)
  game.minute_string = Right("0" + game.minute, 2)
  game.hour_string = Right("0" + game.hour, 2)
  game.day_string = "day " + game.day

  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.hour_string
}
game.epoch= 0

// and if you find it easier to use these:

game.changedincrease_second => {
  game.epoch = game.epoch + game.increase_second
  game.increase_second = 0
}
game.changedincrease_minute => {
  game.epoch = game.epoch + game.increase_minute * 60
  game.increase_minute = 0
}
game.changedincrease_hour => {
  game.epoch = game.epoch + game.increase_hour * 60 * 60
  game.increase_hour = 0
}
game.changedincrease_day => {
  game.epoch = game.epoch + game.increase_day * 60 * 60 * 24
  game.increase_day = 0
}

(Technically, the 'epoch' is the time you use as 0. The game.epoch attribute in that example is the number of seconds since the epoch, but it's common to refer to it as an epoch time. For the clock on your computer, the real-world time is probably stored as the number of seconds since midnight (GMT) Jan 1st 1970 - currently 1637089325, and almost every app that uses it will be relying on the same set of % operations to turn that into a human-readable number as needed)

(You could replace the 60 * 60 with 3600, of course… I just figured it's easier to understand if you can see where the numbers come from)

An alternative way of doing the calculations without % would be:

  game.day = game.epoch / 60 / 60 / 24
  game.hour = game.epoch / 60 / 60 - 24 * game.day
  game.minute = game.epoch / 60 - 60 * (game.hour + 24 * game.day)
  game.second = game.epoch - 60 * (game.minute + 60 * (game.hour + 24 * game.day))

Curt A. P.
17 Nov 2021, 15:26

I tried to try this out today and I don't understand it fully, which makes it hard to implement. Some things in Quest I need explained slowly step-by-step until I can use it (like For Each last year).

First question. How would set a duration, for example, when the player moves to another area and it takes 30 minutes. How would I get from game.epoch = 30 to your suggested script?

game.changedepoch => {
  game.second = game.epoch % 60
  game.minute = (game.epoch / 60) % 60
  game.hour = (game.epoch / 60 / 60) % 24
  game.day = game.epoch / 60 / 60 / 24

  game.second_string = Right("0" + game.second, 2)
  game.minute_string = Right("0" + game.minute, 2)
  game.hour_string = Right("0" + game.hour, 2)
  game.day_string = "day " + game.day 

game.epoch = 0 

mrangel
17 Nov 2021, 17:06

If you want to advance the clock, you just add the number of seconds onto the epoch time. So for 30 minutes you'd do one of:

  • game.epoch = game.epoch + 30 * 60 (easier to read - work out how many seconds it is when you're writing it)
  • game.epoch = game.epoch + 1800 (simpler for the computer to run)
  • game.increase_minute = 30 (if you included the optional parts of that script)

Curt A. P.
18 Nov 2021, 06:34

Okay, if I go for 10 seconds it's
game.epoch = game.epoch + 10

10 minutes
game.epoch = game.epoch + 10 * 60

10 hours
game.epoch = game.epoch + 10 * 3600


game.increase_minute = 30 (if you included the optional parts of that script)

I can't see how the optional part would affect the the other units, for example if an increase of minutes would also increase the hour value. (To use it while coding certain events would be much easier, though.)

Edit: Sorry, got it! I have to use both parts.


Curt A. P.
18 Nov 2021, 10:50

Trying to get it to work. The clock is all over the place with times like 10:70:66.
So far, the actual values of seconds, minutes, and hours go up into infinity. With only the last two digits visible
The higher units only go up if, the increase is big enough:
12:00:00
adding 35 seconds results in
12:00:35
adding another 35 seconds is
12:00:70

But...
12:00:00
adding 70 seconds results in
12:01:70

I still need to insert somewhere the math for these cases.


game.second = 0
game.minute = 0
game.hour = 10
game.day = 1

The Right() function is a neat hack, didn't know to use it so efficient.
Also, it's new to me that ToString() isn't needed to print an integer. Surprised that it works.

game.second_string = Right("0" + game.second, 2)
game.minute_string = Right("0" + game.minute, 2)
game.hour_string = Right("0" + game.hour, 2)
game.day_string = "day " + game.day
game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
game.epoch = 0

I think this should have been
game.second = game.second + game.epoch % 60
and not
game.second = game.epoch % 60
because the time wasn't adding up:

game.changedepoch => {
  game.second = game.second + game.epoch % 60
  game.minute = game.minute + (game.epoch / 60) % 60
  game.hour = game.hour + (game.epoch / 60 / 60) % 24
  game.day = game.day + game.epoch / 60 / 60 / 24
  game.second_string = Right("0" + game.second, 2)
  game.minute_string = Right("0" + game.minute, 2)
  game.hour_string = Right("0" + game.hour, 2)
  game.day_string = "day " + game.day
  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
  game.epoch = 0
}
game.second_increase = 0
game.minute_increase = 0
game.hour_increase = 0
game.day_increase = 0
game.changedsecond_increase => {
  game.epoch = game.epoch + game.second_increase
  game.second_increase = 0
}
game.changedminute_increase => {
  game.epoch = game.epoch + game.minute_increase * 60
  game.minute_increase = 0
}
game.changedhour_increase => {
  game.epoch = game.epoch + game.hour_increase * 60 * 60
  game.hour_increase = 0
}
game.changedday_increase => {
  game.epoch = game.epoch + game.day_increase * 60 * 60 * 24
  game.day_increase = 0
}

mrangel
18 Nov 2021, 12:19

Trying to get it to work. The clock is all over the place with times like 10:70:66.

I can't see how that could happen. But just to check, I I pasted the code from my previous post into a new game and created a command that lets you add numbers onto the increase attributes, and then displays the value of the variables.

It seems to work fine for me (after fixing the typo where I had game_hour instead of game_second in the clock string):
Screenshot of a time command working as intended

Also, it's new to me that ToString() isn't needed to print an integer.

It's called implicit conversion. Some operators (like +) behave differently depending what type of data you give them. In the case of string + other value the other value is automatically converted to a string (although if it's an object, it gives a string like Object: bucket). Adding a string to a number is a quick way to convert it (and because of the way it's implemented, "" + somevariable is often faster than ToString (somevariable) to get the same result.)

I get into this habit more because of javascript, where ("" + a) and (0 + b) are the standard ways to force something to be a string or an int.

I think this should have been
game.second = game.second + game.epoch % 60
and not
game.second = game.epoch % 60
because the time wasn't adding up:

Why? Then you're adding the seconds of the new time onto the seconds of the old time, so you'll end up with the values continually going up towards infinity.

If game.epoch is the number of seconds since the start of the game, game.epoch / 60 is the number of minutes since the start of the game, and game.epoch % 60 is the number of seconds since the start of the last minute.

epoch % 60 gives the number of seconds since the last minute, not since the old value. If you wanted to use it as a relative time, you would have to do more calculations including oldvalue; but that's making the function much more complex again for no real reason.

The epoch date is not how much the date has changed by; that causes all kinds of confusion and values going outside the normal ranges. The epoch is just the number of seconds since midnight on day 0, so you don't want changedepoch to reset it to zero.

game.second = 0
game.minute = 0
game.hour = 10
game.day = 1

These won't do anything; the other values are calculated from the epoch every time it is used.
I put game.epoch = 0 after the changedepoch script so that it would immediately set day, hour, minute, and second to zero as well.

If you want to change it so that the day is numbered from 1 instead of 0, you would change:

  game.day = game.epoch / 60 / 60 / 24

to

  game.day = 1 + game.epoch / 60 / 60 / 24

and to make it start at 10:00, you just change the starting time:

game.epoch = 10 * 3600

So the full script would be:

game.changedepoch => {
  game.second = game.epoch % 60
  game.minute = (game.epoch / 60) % 60
  game.hour = (game.epoch / 60 / 60) % 24
  game.day = 1 + game.epoch / 60 / 60 / 24

  game.second_string = Right("0" + game.second, 2)
  game.minute_string = Right("0" + game.minute, 2)
  game.hour_string = Right("0" + game.hour, 2)
  game.day_string = "day " + game.day

  game.clock_string = game.hour_string + ":" + game.minute_string + ":" + game.second_string
}

// This line sets the initial time to 10 AM
game.epoch = 10 * 3600

game.changedincrease_second => {
  game.epoch = game.epoch + game.increase_second
  game.increase_second = 0
}
game.changedincrease_minute => {
  game.epoch = game.epoch + game.increase_minute * 60
  game.increase_minute = 0
}
game.changedincrease_hour => {
  game.epoch = game.epoch + game.increase_hour * 60 * 60
  game.increase_hour = 0
}
game.changedincrease_day => {
  game.epoch = game.epoch + game.increase_day * 60 * 60 * 24
  game.increase_day = 0
}

mrangel
18 Nov 2021, 12:41

One advantage of storing the time in a single attribute, and just creating others to display it, is that it's easier to change the format later if you want. For example, you could change to:

game.clock_string = ToString((game.hour - 1) % 12 + 1) + ":" + game.minute_string + ":" + game.second_string + StringListItem(Split(" AM; PM"), game.hour/12)

(Yeah, that's a bit unwieldy. But you get the idea. Storing one bit of information in one attribute makes it easier to change how you deal with it)


Curt A. P.
19 Nov 2021, 07:45

I did a mistake by thinking that the last line in game.changedepoch script was
game.epoch = 0

Makes much more sense now. Thanks.


Edit: It's up and running. Pretty slick this code. Thank you very much.