How to make Inform 7 not skip events that are 30 minutes (or more) late?

Hello, I have an I7 story where the player can take actions that take a long time (more than 30m) and there are events that should fire off at certain times.

The thing is that as said in the documentation 9.11:

A small warning: timed events like these only have a chance to occur during the turn sequence, that is, once every turn. In most stories, one turn takes one minute, so there will in due course be a turn happening at exactly (say) 11:35 AM. But if the clock is being advanced faster than this, it’s possible that there are turns at (say) 11:32 AM and then not until 11:37 AM. But an event set for 11:35 AM will nevertheless happen – it will run at the first available turn after that time, which will be 11:37 AM. Events can thus happen up to half an hour late, though Inform cancels them if the elapsed time is greater than that.

if it’s 10:00AM and the player takes an action that advances time by 3 hours (with “increase the time of day by 180 minutes;” ), if there is an event “At 11:00AM:” that event never fires as it is more than half an hour late.

I tried something like this to have the events fire even when the time that needs to pass is more than 30 minutes:

Wait is a number that varies. Wait is 275.

Every turn when Wait is greater than 0:
	decrease Wait by 1;
	follow the turn sequence rules.

It kinda works, but it seems that 275 is the highest number I can set Wait to without getting an overflow error.

How can I instead change the “small warning” rule described in 9.11?

You could hack the template with an i6-y solution to changing the default behavior of timed events, but it’s probably easier/safer to just create your own way of keeping track of events. Something like:

The Lab is a room.

When play begins:
	 now the command prompt is "[time of day] >".

At 9:05 AM:
	say "9:05 alarm, standard.".
	
Instead of saying yes:
	say "That took a total of eleven minutes.";
	increase the time of day by ten minutes.
	
Instead of jumping:
	say "Wow, time flies when you're jumping!";
	increase the time of day by 11 hours 50 minutes.
		
An event is a kind of thing. An event can be triggered or untriggered.
An event has a time called the alarm.

To update events:
	repeat with pending running through untriggered events:
		if the alarm of pending is at most the time of day:
			now pending is triggered;
			fire off pending.
			
Every turn (this is the update events rule): [comment this out to see the difference]
	update events.

[we need to define these in chronological order in our source for things to go in order]

New nine-o-five is an event. The alarm is 9:05 AM.	
Boo is an event. The alarm is 9:10 AM.

[these don't have to be in order:]

To fire off (E - an event):
	say "This is the default and shouldn't fire.".

To fire off (E - Boo):
	say "BOO! - 9:10 alarm, custom (using events).".
		
To fire off (E - New nine-o-five):
	say "9:05 alarm, custom (using events).".
	
test me1 with "z/z/z/z/z/z/jump".
test me2 with "jump".
3 Likes

Thanks a lot man, I was hoping there could be a way to simply edit the 30 minutes thing, but this is even better. Thanks again for taking the time to type this out!

Your most welcome. Just a heads up though: if you’ve got a story which takes place over multiple days – for example, if your story begins at 9:00 AM and you want something to happen at 9:05 AM the following day – you’ll need additional code to deal with that. (But you would have needed that with the existing system as well.)

Yes thanks, but that seems easy enough that I can do it myself. Just adding a “day” variable to the events to compare to a global “currentDay” variable in the “to update events:” function I think.

Thanks again!

It wasn’t as easy as I thought it would be… but this seems to work:

The Lab is a room.

Current day is a number that varies. Current day is 1.

When play begins:
	now the command prompt is "Day: [current day], [time of day] >";
	now the time of day is 9:04 AM.

At 9:05 AM:
	say "9:05 alarm, standard.".
	
Instead of saying yes:
	say "That took a total of eleven minutes.";
	[increase the time of day by ten minutes.]
	advance time 10.
	
Instead of jumping:
	say "Wow, time flies when you're jumping!";
	[increase the time of day by 11 hours 50 minutes.]
	[advance time 720.]
	advance time 2880.

An event is a kind of thing. An event can be triggered or untriggered.
An event has a time called the alarm. An event has a number called the day.

To update events:
	repeat with pending running through untriggered events:
		if the day of pending is current day:
			if the alarm of pending is at most the time of day:
				now pending is triggered;
				fire off pending.
			
Every turn (this is the update events rule): [comment this out to see the difference]
	update events.

[we need to define these in chronological order in our source for things to go in order]

New nine-o-five is an event. The alarm is 9:05 AM. The day is 1.
Boo is an event. The alarm is 9:10 AM. The day is 1.
BooBoo is an event. The alarm is 9:10 PM. The day is 1.
FooFoo is an event. The alarm is 9:02 AM. The day is 2.
Foo is an event. The alarm is 9:10 AM. The day is 2.
Doo is an event. The alarm is 9:10 AM. The day is 3.

[day changing events need to be in reverse order]

Day4 is an event. The alarm is 11:59 PM. The day is 3.
Day3 is an event. The alarm is 11:59 PM. The day is 2.
Day2 is an event. The alarm is 11:59 PM. The day is 1.

[advance time: to be used instead of "increase the time of day"]
		
To advance time (T - a number):
	let X be (60 * the hours part of time of day) + (0 + the minutes part of time of day);
	while ((X + T) > 1440):
		increase the time of day by (1439 - X) minutes;
		update events;
		increase the time of day by (X + 1) minutes;
		now T is (T - 1440);
	if (T > -1):
		increase the time of day by (T - 1)  minutes.

[these don't have to be in order:]

To fire off (E - an event):
	say "This is the default and shouldn't fire.".

To fire off (E - Boo):
	say "BOO! - 9:10 alarm, custom (using events).".
	
To fire off (E - BooBoo):
	say "BOOBOO! - 9:10 PM alarm, custom (using events).".
		
To fire off (E - New nine-o-five):
	say "9:05 alarm, custom (using events).".

To fire off (E - Day2):
	increase current day by 1;
	say "The first day turns into the second day.".

To fire off (E - FooFoo):
	say "FOOFOO! - 9:02 alarm, custom (using events).".

To fire off (E - Foo):
	say "FOO! - 9:10 alarm, custom (using events).".

To fire off (E - Day3):
	increase current day by 1;
	say "The second day turns into the third day.".
	
To fire off (E - Doo):
	say "DOO! - 9:10 alarm, custom (using events).".
	
To fire off (E - Day4):
	increase current day by 1;
	say "The third day turns into the fourth day.";
	say "Game Over.";
	end the story finally.
	
test me1 with "z/z/z/z/z/z/jump".
test me2 with "jump".
test me3 with "jump/jump".

Inelegant, I know, but I’m open to feedback.

Thanks again!

1 Like

You got farther than I did! I started messing around with adding days and then trying to set it up so one daily alarm could advance the day counter, but finally gave up in frustration. I was about to add individual alarms for each day (as you have) but then ran into issues w/ the whole cyclical clock thing, which you seemed to have solved with your advance time phrase and reverse ordering of declarations of day-changing events. Nice work!

P.S. - while I agree there’s almost certainly a more elegant way of doing this without individual alarms for advancing the day count, I’m all for the “problem solved for this use-case – moving on to the rest of the story” approach.

1 Like

It was actually a pretty easy fix!

The Lab is a room.

Current day is a number that varies. Current day is 1.

When play begins:
	now the command prompt is "Day: [current day], [time of day] >";
	now the time of day is 9:04 AM.

At 9:05 AM:
	say "9:05 alarm, standard.".
	
Instead of saying yes:
	say "That took a total of eleven minutes.";
	[increase the time of day by ten minutes.]
	advance time 10.
	
Instead of jumping:
	say "Wow, time flies when you're jumping!";
	[increase the time of day by 11 hours 50 minutes.]
	[advance time 720.]
	advance time 2880.

An event is a kind of thing. An event can be triggered or untriggered.
An event has a time called the alarm. An event has a number called the day.

To update events:
	repeat with pending running through untriggered events:
		if the day of pending is current day:
			if the alarm of pending is at most the time of day:
				now pending is triggered;
				fire off pending.
			
Every turn (this is the update events rule): [comment this out to see the difference]
	update events.

[we need to define these in chronological order in our source for things to go in order]

New nine-o-five is an event. The alarm is 9:05 AM. The day is 1.
Boo is an event. The alarm is 9:10 AM. The day is 1.
BooBoo is an event. The alarm is 9:10 PM. The day is 1.
FooFoo is an event. The alarm is 9:02 AM. The day is 2.
Foo is an event. The alarm is 9:10 AM. The day is 2.
Doo is an event. The alarm is 9:10 AM. The day is 3.

[advance time: to be used instead of "increase the time of day"]
		
To advance time (T - a number):
	let X be (60 * the hours part of time of day) + (0 + the minutes part of time of day);
	while ((X + T) > 1440):
		increase the time of day by (1439 - X) minutes;
		update events;
		increase current day by 1;
		say "The day turns.";
		increase the time of day by (X + 1) minutes;
		now T is (T - 1440);
	if (T > -1):
		increase the time of day by (T - 1)  minutes.

[we need to increase the day if we arrive at the end of the day without using the "advance time" function:]

At 11:59 PM:
	increase current day by 1;
	say "The day turns.".

[these don't have to be in order:]

To fire off (E - an event):
	say "This is the default and shouldn't fire.".

To fire off (E - Boo):
	say "BOO! - 9:10 alarm, custom (using events).".
	
To fire off (E - BooBoo):
	say "BOOBOO! - 9:10 PM alarm, custom (using events).".
		
To fire off (E - New nine-o-five):
	say "9:05 alarm, custom (using events).".

To fire off (E - FooFoo):
	say "FOOFOO! - 9:02 alarm, custom (using events).".

To fire off (E - Foo):
	say "FOO! - 9:10 alarm, custom (using events).".
	
To fire off (E - Doo):
	say "DOO! - 9:10 alarm, custom (using events).".
	
test me1 with "z/z/z/z/z/z/jump".
test me2 with "jump".
test me3 with "jump/jump".

(And thanks a bunch for taking the time to try!)

I ended up remaking the whole thing from scratch. If anyone is interested, the enhancements mostly are:

  • Less and simpler code
  • No need to define the events in any order
  • You can add and remove events during runtime with the power of tables

Enjoy:

The Dungeon is a room.

[We hold in mTime the number of minutes passed since the start of the story, we hold in lastUpdate the number of minutes since the start of the story that last the events were updated]

mTime is a number that varies. mTime is 0.
lastUpdate is a number that varies. lastUpdate is 0.

When play begins:
	now the command prompt is "Day: [(mTime / 1440) + 1], I7 Clock: [time of day], mTime:  [mTime]>";
	now time of day is 12:00 AM.

[We use a table to hold our events: event is the event fire label, mFire is the number of minutes since the start of the story when we want the event to fire]

Table of Events
Event	mFire
"Cockerel"	10
"Alarm"	5
"Sirens"	1440
"Sirens"	2880
"Game Over"	4319
with 9 blank rows

Instead of sleeping:
	say "You sleep profoundly for quite some time.";
	advance time 1440.
	
Instead of jumping:
	say "While in the air you realise that you will hear a trumpet 3 minutes from now.";
	choose a blank row in Table of Events; 
	now event entry is "Trumpet"; 
	now mFire entry is (mTime + 3).

Every turn (this is the update events rule):
	update events.

To update events:
	repeat through the Table of Events in mFire order:
		if mFire entry >= lastUpdate and mFire entry <= mTime:
			fire off event entry;
			blank out the whole row;
	Increase mTime by 1;
	now lastUpdate is mTime.

[Advance time: to be used instead of "increase the time of day"]
		
To advance time (T - a number):
	increase mTime by T - 1;
	increase time of day by T - 1 minutes.

[The events]

To fire off (E - some text):
	say "Error! An unscripted event has fired!".

To fire off (E - "Alarm"):
	say "The Alarm rings 5 minutes into the game.".
	
To fire off (E - "Cockerel"):
	say "The Cockerel sings 10 minutes into the game.".
	
To fire off (E - "Sirens"):
	say "Sirens blast in the distance and mark the start of a new day.".
	
To fire off (E - "Trumpet"):
	say "You hear a loud trumpet!".

To fire off (E - "Game Over"):
	say "Time has run out!";
	end the story finally.
	
test me with "jump/z/z/z/z/z/sleep/sleep/sleep".

(RIP “moving on with the story approach” ;_; )

2 Likes