Time-keeping methods

Start script

game.realMinutes = 0
game.minutes = 0
game.hours = 9
game.am_or_pm = "am"
game.timeDisplay = "9:00 am Day 1"
game.day = 1
game.statusattributes = NewStringDictionary()
dictionary add (game.statusattributes, "timeDisplay", "Time: !")
create turnscript ("myTurnScript")
myTurnScript.script => {
  game.realMinutes = game.realMinutes + 1
  if (game.realMinutes<60) {
    game.minutes = game.realMinutes
  }
  else {
    game.minutes = game.realMinutes%60
  }
  if (game.minutes = 0) {
    game.hours = game.hours + 1
    if (game.hours = 12) {
      if (game.am_or_pm = "am") {
        game.am_or_pm = "pm"
      }
      else {
        game.am_or_pm = "am"
      }
    }
  }
  if (game.hours = 13) {
    game.hours = 1
  }
  if (game.realMinutes/1440>0) {
    game.day = game.realMinutes/1440
  }
  game.timeDisplay = "" + game.hours + ":" + ProcessText("{if game.minutes<10:0}{game.minutes}") + " " + game.am_or_pm + " Day: " + game.day + ""
  //msg ("Time: {game.hours}:{if game.minutes<10:0}{game.minutes} {game.am_or_pm}")
}
EnableTurnScript (myTurnScript)

UPDATE: Added days (no months or years yet)

NOTE: If you have a wait command that allows any amount of time other than 1 minute to pass, you'll be better off skipping to this: http://textadventures.co.uk/forum/quest/topic/yg5skhiixk2h6ja2e01vxq/time-keeping-methods#609be57d-13d5-4cf5-9f60-92525d37f704


To calculate the actual amount of time since play began (not counting while, wait, get input, and such):

x = game.timeelapsed  // timeelapsed is a default attribute on the game object
game.hours = x / 3600
time = x%3600
game.minutes = x/60
x = time%60
game.seconds = x
if (game.minutes<10) {
  game.minutes = "0" + game.minutes
}
if (game.seconds<10) {
  game.seconds = "0" + game.seconds
}
game.realgametime = game.hours + "h" + game.minutes + "m" + game.seconds + "s"

This game uses Pixie's library:

http://textadventures.co.uk/games/view/rr9vezzxkeaovamsaqgxcw/they-call-ya-mister-quest-prototype-in-progress

https://github.com/ThePix/quest/wiki/Clock-Library

VIEW SCREENSHOT

image


Who else has some time-related code(s)?


The first one, I feel is a little wobbly. It might not be so easy to adapt if some command wants to take more than a minute. (For example, it would make sense if the "wait" command waited longer than a single minute).

I'd likely go for something more like...

// (assuming the same variables)

create turnscript ("myTurnScript")
myTurnScript.script => {
  game.realMinutes = game.realMinutes + 1
}
EnableTurnScript (myTurnScript)

game.changedrealMinutes => {
  game.minutes = game.realMinutes % 60
  realHours = game.realMinutes / 60

  game.military_hours = realHours % 24
  game.hours = 1 + ((realHours - 1) % 12)
  if (game.military_hours < 12) {
    game.am_or_pm = "am"
  }
  else {
    game.am_or_pm = "pm"
  }
  game.day = realHours / 24

  game.timeDisplay = "" + game.hours + ":" + ProcessText("{if game.minutes<10:0}{game.minutes}") + " " + game.am_or_pm + " Day: " + game.day + ""
}

OR ... less efficient, but possibly useful:

game.changedrealMinutes => {
  oldHour = oldvalue / 60
  newHour = game.realMinutes / 60

  if (newHour <> oldHour) {
    // In this case we iterate over the hours
    // This means that if you want something to happen every hour or every day, you can set a `game.changedhour` script
    // And if the sleep command says "You sleep for 6 hours" and adds 360 to realMinutes, those will be called the right
    // number of times
    // If none of those change scripts are set, we can do it in one step
    stepVar = newHour - oldHour
    if (HasScript(game, "changedhour")) {
      stepVar = 1
    }
    else if (HasScript(game, "changedam_or_pm")) {
      stepVar = 12
    }
    else if (HasScript(game, "changedday")) {
      stepVar = 24
    }

    for (realHours, oldHour, newHour, stepVar) {
      game.military_hours = realHours % 24
      game.hours = 1 + ((realHours - 1) % 12)
      if (game.military_hours < 12) {
        game.am_or_pm = "am"
      }
      else {
        game.am_or_pm = "pm"
      }
      game.day = realHours / 24
    }
  }
  game.minutes = game.realMinutes % 60
  game.timeDisplay = "" + game.hours + ":" + ProcessText("{if game.minutes<10:0}{game.minutes}") + " " + game.am_or_pm + " Day: " + game.day + ""
}

wow... half an hour to write that. I thought it would be shorter.


Thanks, mrangel!

(I added a note about the wait time thing to the first post, just so no one typed first and scrolled down later.)


Hmm... I like that library. Setting events to go off at a particular time is useful; but as it's something I don't actually have a need for, my brain immediately starts hunting for possible improvements. I'm going to step away now, and work on some of the things I have a deadline for.


From my Start script:

SetTime ("01:08:00")
game.clock = TimeAsString()
    game_clock.waittime = 1

Everything else:

<waitcount type="int">0</waitcount>
<object name="game_clock">
    <inherit name="editor_object" />
    <time type="int">0</time>
    <minutes type="int">0</minutes>
    <hours24 type="int">0</hours24>
    <days type="int">0</days>
    <countdown type="int">0</countdown>
    <increment type="int">1</increment>
    <waittime type="int">0</waittime>
    <testing type="boolean">false</testing>
    <clockmsg>You grab the spell reader and check the time. It's ###.</clockmsg>
    <startyear type="int">2017</startyear>
    <changedtime type="script">
      JS.eval ("$('#clock').html('" + TimeAsString() + "');")
    </changedtime>
  </object>
 <command name="wait">
    <pattern type="string">^wait$|^z$</pattern>
    <script><![CDATA[
      game.stop_waiting = false
      count = game_clock.waittime
      game_clock.event = false
      while (count > 0 and not game_clock.event) {
        // msg("count = " + count)
        // msg("game_clock.event = " + game_clock.event)
        count = count - 1
      }
      if (not game_clock.event) {
        if (not game_clock.waittime = 1) {
          P ("You wait " + game_clock.waittime + " minutes.")
        }
        else {
          P ("You wait " + game_clock.waittime + " minute.")
        }
      }
    ]]></script>
  </command>
<command name="wait minutes">
    <pattern type="string"><![CDATA[^(wait|z) (?<text>\w*)( minute| minutes| turn| turns|)$]]></pattern>
    <script><![CDATA[
      game_clock.event = true
      if (not IsInt(text)) {
        msg ("Wait how long (I did not understand \"" + text + "\")?")
      }
      else {
        game.waitcount = WaitN(ToInt(text))
        msg ("You wait for " + game.waitcount + " minute{if game.waitcount>1:s}.")
      }
    ]]></script>
  </command>
<turnscript name="turn_count">
    <enabled />
    <script>
      if (not game.notarealturn) {
        game.turns = game.turns + 1
      }
      else {
        msg ("I didn't quite catch that.")
      }
      game.notarealturn = false
    </script>
  </turnscript>
<turnscript name="high_noon">
    <enabled />
    <script>
      if (IsAfter("1:11:59")) {
        if (not IsAfter("1:12:00")) {
          MoveObject (Murphy, Mundane Corral)
          msg ("You hear the clock tower chiming. It is high noon.")
        }
      }
    </script>
  </turnscript>
<function name="IncTime"><![CDATA[
    on ready {
      game_clock.time = game_clock.time + 1
      // msg("game_clock.time = " + game_clock.time)
      // msg("game_clock.event = " + game_clock.event)
      game_clock.minutes = game_clock.time % 60
      game_clock.hours24 = (game_clock.time / 60) % 24
      game_clock.days = game_clock.time / (60 * 24)
      name = "event_" + DD(game_clock.days) + "_" + DD(game_clock.hours24) + "_" + DD(game_clock.minutes)
      game_clock.countdown = game_clock.countdown - 1
      // msg("Looking for: " + name)
      o = GetObject(name)
      if (not o = null and HasScript(o, "look")) {
        if (game_clock.testing) {
          msg ("Found: " + o + " (" + o.alias + ")")
        }
        // this is used by wait
        game_clock.event = true
        do (o, "look")
      }
      else if (game_clock.countdown < 0 and HasAttribute(game_clock, "nextstep")) {
        if (game_clock.testing) {
          msg ("Step found: " + game_clock.nextstep + " (" + game_clock.nextstep.alias + ")")
        }
        // this is used by wait
        game_clock.event = true
        step = game_clock.nextstep
        game_clock.nextstep = null
        do (step, "look")
      }
      game.clock = TimeAsString()
      IncUserTime
    }
  ]]></function>
  <function name="WaitN" parameters="n" type="int">
    game.stop_waiting = false
    for (i, 1, n-1) {
      IncTime
      if (game.stop_waiting) {
        return (i)
      }
    }
    return (n)
  </function>
<function name="IsAfter" parameters="time" type="boolean"><![CDATA[
    if (TypeOf(time) = "string") {
      l = Split(time, ":")
      if (not ListCount(l) = 3) {
        error ("SetTime failed to understand " + minutes)
      }
      days = ToInt(StringListItem(l, 0))
      hours24 = ToInt(StringListItem(l, 1))
      minutes = ToInt(StringListItem(l, 2))
      time = (days * 24 + hours24) * 60 + minutes
    }
    return (game_clock.time > time)
  ]]></function>

NOTE: This is all Pixie's code, unless I added something in from someone else on the forum and forgot about it.


Having read this, I have just updated my library to should "12 noon" rather than "12 pm" (as noon is not after the meridian). Similar for midnight.
http://www.rmg.co.uk/discover/explore/noon-12-am-or-12-pm

The first one, I feel is a little wobbly. It might not be so easy to adapt if some command wants to take more than a minute.

I had each increment as a single minute for my library so events can be triggered at a set time. If a command takes 5 minutes, then the time must be iterated 5 times to ensure events are not missed. There is a function to handle the iteration. Also, if the player does WAIT, it will iterate through 20 turns, but will stop when something happens that the player might want to react to.


I use the WAIT and the WAIT MINUTES commands extensively, and all of Pixie's stuff works flawlessly.

My first and second posts' codes are not Pixie's and not very good. The rest of my posts in this thread are Pixie's, and they're good.


@ ThePix

There are two instances of "12 am" every day, right?

...because the date doesn't change until 12:01 am.

...because "12 am" is really 24:00 hours.

...or "12 am" is really 0:00 hours...

That's right! It's both!


Technically, there is no 24:00hours. in a 24hour clock the time goes 23:59hrs then 00:00hrs. (or 0:00hrs)
The new day should begin when the clock reads 00:00hrs. (or 0:00hrs)
12 am is 12:00, 12:01hrs is 12:01pm


a

(test)


HK edit:

why is every post of mine getting blocked... argh.... HK bangs his head...

I can post 'a' as my content for a post, but I can't post my actual post...

HK is lost...


Doctor Agon: Depends. There's some argument about whether a leap second should be shown on clocks as 24:00:00 or 23:59:60. I doubt that'll ever matter in a game, though.

Pixie: Yep; didn't look at your library until after I'd responded to the first post. Looks pretty neat; though there's still things I wonder if they might be improved, like having multiple events at the same time. If I had a use for it, I'd probably end up using your library. And then hack it up so it can take events with a trigger time in crontab format.


this is what I personally like/use and understand for time:

00:00:00, night-time, mid-night, military-time == 12:00:00, pm-to-am, night-time, mid-night, civilian-time

00:00:01, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 12:00:01, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time
00:59:59, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 12:59:59, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time
01:00:00, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 01:00:00, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time
05:59:59, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 05:59:59, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time

06:00:00, night-time-to-day-time, sun-rise/dawn, military-time == 06:00:00, am, night-time-to-day-time, sun-rise/dawn, civilian-time

06:00:01, day-time, morning, military-time == 06:00:01, am, day-time, morning, civilian-time
11:59:59, day-time, morning, military-time == 11:59:59, am, day-time, morning, civilian-time

what the hell.... okay I can post half.... of my post... nothing wrong with any of those characters... used.... okay...


and let's try the other half now...

12:00:00, day-time, mid-day/noon, military-time == 12:00:00, am-to-pm, day-time, mid-day/noon, civilian-time

12:00:01, day-time, after-noon, military-time == 12:00:01, pm, day-time, after-noon, civilian-time
12:59:59, day-time, after-noon, military-time == 12:59:59, pm, day-time, after-noon, civilian-time
13:00:00, day-time, after-noon, military-time == 01:00:00, pm, day-time, after-noon, civilian-time
17:59:59, day-time, after-noon, military-time == 05:59:59, pm, day-time, after-noon, civilian-time

18:00:00, day-time-to-night-time, sun-set/dusk, military-time == 06:00:00, pm, day-time-to-night-time, sun-set/dusk, civilian-time

18:00:01, night-time, evening, military-time == 06:00:01, pm, night-time, evening, civilian-time
20:59:59, night-time, evening, military-time == 08:59:59, pm, night-time, evening,civilian-time
21:00:00, night-time, twilight, military-time == 09:00:00, pm, night-time, twilight, civilian-time
23:59:59, night-time, twilight, military-time == 11:59:59, pm, night-time, twilight, civilian-time

00:00:00, night-time, mid-night, military-time == 12:00:00, pm-to-am, night-time, mid-night, civilian-time

okay, no F'n problem with this half's characters....

so what the F', can't I post it as one post ??? ... WHY the F' does it allow half of everything I post only... WTF... is going on... ???!!!!

and it's not F' character length... so why can't I post that as one post, why'd it force me to break it into two posts??? FKN... what is going on... does my computer have a virus and its making extra/hidden scripts/text or is something fkn up with the server and/or the forum software it uses... ARGH.....


Poor HK!

I got banned for hours for making too many posts not too long ago, HK. So, it could be worse!


I always thought 24:00 hours and 0:00 were the same thing. (My uncle used to drone on about it, in fact.)

UPDATE:

http://militarytimechart.com/


"Time is an illusion. Lunchtime is doubly so."
- Douglas Adams


FKN POST IT FKN POST IT....

HK cries... it fkn blocks me from fkn posting anything... except one line spam posts... every FKN post, I half to split it into two posts, to get it to get fkn posted... HK cries... what the F' is going on... ??? !!!!

this is what I personally like/use and understand for time:

00:00:00, night-time, mid-night, military-time == 12:00:00, pm-to-am, night-time, mid-night, civilian-time

00:00:01, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 12:00:01, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time
00:59:59, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 12:59:59, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time
01:00:00, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 01:00:00, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time
05:59:59, night-time, twilight/pre-dawn/pre-sun-rise, military-time == 05:59:59, am, night-time, twilight/pre-dawn/pre-sun-rise, civilian-time

06:00:00, night-time-to-day-time, sun-rise/dawn, military-time == 06:00:00, am, night-time-to-day-time, sun-rise/dawn, civilian-time

06:00:01, day-time, morning, military-time == 06:00:01, am, day-time, morning, civilian-time
11:59:59, day-time, morning, military-time == 11:59:59, am, day-time, morning, civilian-time

12:00:00, day-time, mid-day/noon, military-time == 12:00:00, am-to-pm, day-time, mid-day/noon, civilian-time

12:00:01, day-time, after-noon, military-time == 12:00:01, pm, day-time, after-noon, civilian-time
12:59:59, day-time, after-noon, military-time == 12:59:59, pm, day-time, after-noon, civilian-time
13:00:00, day-time, after-noon, military-time == 01:00:00, pm, day-time, after-noon, civilian-time
17:59:59, day-time, after-noon, military-time == 05:59:59, pm, day-time, after-noon, civilian-time

18:00:00, day-time-to-night-time, sun-set/dusk, military-time == 06:00:00, pm, day-time-to-night-time, sun-set/dusk, civilian-time

18:00:01, night-time, evening, military-time == 06:00:01, pm, night-time, evening, civilian-time
20:59:59, night-time, evening, military-time == 08:59:59, pm, night-time, evening, civilian-time
21:00:00, night-time, twilight, military-time == 09:00:00, pm, night-time, twilight, civilian-time
23:59:59, night-time, twilight, military-time == 11:59:59, pm, night-time, twilight, civilian-time

00:00:00, night-time, mid-night, military-time == 12:00:00, pm-to-am, night-time, mid-night, civilian-time

okay.... WTF... that posted ... so it waits until I'm fkn crying... okay.... FK!


HK: twilight is defined by the position of the sun, not by the clock, so will be different times depending on your latitude and time of year.
A little confused that you include "twilight/pre-dawn" on your list; that seems a little contradictory. I'm used to "twilight" meaning the period before sunrise or after sunset where the sun's light is still visible on the horizon; so a term that describes either dawn or dusk.


When I posted the thing about making the time library support cron-style events, I thought that was a big project I'd never actually have the time for. But now I realise it's a lot less complex than I thought.

You can schedule an event for a time like "11:15" with Pixie's nice library. That's neat. I only skimmed over your code, but as it stands I don't think you can have an event with a time like "*:30", so that it happens at half past every hour. And I think I can see a surprisingly easy way to make that work (and possibly be more efficient, too).

The system in my head would give the you a CreateEvent function that takes a string of the form "(day) (hour):(minute):(second)". Each value can either be a number, a comma-separated list of numbers, an asterisk (every day/hour/whatever), a divisor ("/6" means every 6 minutes/hours/etc), a modulo ("%7" means "when the current minute is a multiple of 7"), or a dot ("10:." would mean "a random time between 10 and 11").

Obviously, doing it like this you can't iterate over all the minutes/seconds/whatever to check if something matches. Instead, I'd make an ObjectList of all the events. The CreateEvent function gives them a couple of extra attributes: "event_time", which contains the string as defined above, and "event_next" which is the time the event will next happen (as an epoch time).

Instead of iterating over all the minutes, checking if each has an event, until the time you've been told to wait until, you use ObjectListSort(game_clock.active_events, "event_next"), then grab the first event from the list. Repeat until you find one whose next-time is greater than the time you're waiting until.
(Remembering, of course, that after firing an event, you need to recalculate the next time it will go off, and then re-sort the list)

(Warning: Below this point I'm musing on the subject of over-engineering the clock library, doing things that might not be useful to most people)
I'm also thinking that a command setting the 'increment' attribute isn't quite perfect. For example, if you're trying to pick a lock, then you could fail if something distracts you.
Maybe something like...

msg ("You get out your tools and start working on the lock")
StartSlowAction(30, "picking the lock") {
  if (result) {
    msg ("You unlocked the lock!")
  }
  else if (time_elapsed > 25) {
    msg ("You almost got it finished, but then…")
  }
  else {
    msg ("There's always something to distract you when you're doing a tough job.")
  }
}

If you're doing something like that, then as well as your Quiet function, there would be an Interrupt one, which causes a task the player is currently doing to fail; triggering the callback.
Events which invoke neither Quiet nor Interrupt would display something on the screen while you're picking the lock; and possibly display a menu asking if you want to continue. Hence the string argument to StartSlowAction; so it can say "An alarm goes off somewhere else in the building. Continue picking the lock?"

Kind of tempted to try building this now ... but I really should be working.

Maybe later.


ya, twilight is indeed the partial light before sunrise (and a little after sunset too) from the curvature of light even though the sun is still below horizon, but I like using it to mean 'night hours' (from evening to dawn), as the only other word is night, and twilight just sounds cool for a 'night hour', hehe.

and I like using "am_to_pm" and "pm_to_am" for noon/midnight, and "day_time_to_night_time" and "night_time_to_day_time" for dawn/dusk, as those times are technically transitions-lines


Log in to post a reply.

Support

Forums