§20   Daemons and the passing of time

Some, such as Sleep and Love, were never human. From this class an individual daemon is allotted to each human being as his ‘witness and guardian’ through life.
— C. S. Lewis (1898–1963), The Discarded Image
A great Daemon… Through him subsist all divination, and the science of sacred things as it relates to sacrifices, and expiations, and disenchantments, and prophecy, and magic… he who is wise in the science of this intercourse is supremely happy…
— Plato (c.427–347 B.C.), The Symposium, in the translation by Percy Bysshe Shelley (1792–1822)

To medieval philosophers, daemons were the intermediaries of God, hovering invisibly over the world and interfering with it. They may be guardian spirits of places or people. So also with Inform: a daemon is a meddling spirit, associated with a particular game object, which gets a chance to interfere once per turn while it is ‘active’. ‘Advent’ has five: one to deplete the lamp's batteries, three to move the bear, the pirate and the threatening little dwarves and one to close the cave when all the treasures have been collected. Though there isn't much to say about daemons, they are immensely useful, and there are some rule-based design systems for interactive fiction in which the daemon is a more fundamental concept than the object. (The early 1980s system by Scott Adams, for instance.)

The daemon attached to an object is its daemon routine, if one is given. However, a daemon is normally inactive, and must be explicitly activated and deactivated using the library routines

StartDaemon(object);
StopDaemon(object);

Daemons are often started by a game's Initialise routine and sometimes remain active throughout. When active, the daemon property of the object is called at the end of each turn, regardless of where that object is or what the circumstances, provided only that the player is still alive. This makes daemons useful for ‘tidying-up operations’, putting rooms back in order after the player has moved on, or for the consequences of actions to catch up with the player.

EXERCISE 42
Many games contain “wandering monsters”, characters who walk around the map. Use a daemon to implement one who wanders as freely as the player, like the gentleman thief in ‘Zork’.

EXERCISE 43
Use a background daemon to implement a system of weights, so that the player can only carry a certain weight before strength gives out and something must be dropped. It should allow for feathers to be lighter than lawn-mowers.

· · · · ·

It's also possible to attach a timer to an object. (In other design languages, timers are called “fuses”.) To set up a timer, you need to give an object two properties: time_left and time_out. Like daemons, timers are inactive until explicitly started:

StartTimer(object, time);

will set object.time_left to time. This value will be reduced by 1 each turn, except that if this would make it negative, the Inform library instead sends the message

object.time_out()

once and once only, after which the timer is deactivated again. You're free to alter time_left yourself: a value of 0 means “will go off at the end of the present turn”, so setting time_left to 0 triggers immediate activation. You can also deactivate the timer, so that it never goes off, by calling

StopTimer(object);

EXERCISE 44
Construct an egg-timer which runs for three turns.

At most 32 timers or daemons can be active at the same time, together with any number of inactive ones. This limit of 32 is easily raised, though: just define the constant MAX_TIMERS to some larger value, putting the definition in your code before "Parser.h" is included.

· · · · ·

There is yet a third form of timed event. If a room provides an each_turn routine, then the library will send the message

location.each_turn()

at the end of every turn when the player is present. Similarly, for every object O which is near the player and provides each_turn:

O.each_turn()

will be sent every turn. This would be one way to code the sword of ‘Zork’, for instance, which begins to glow when monsters are nearby. each_turn is also convenient to run creatures which stay in one place and are only active when the player is nearby. An ogre with limited patience can therefore have an each_turn routine which worries the player (“The ogre stamps his feet angrily!” and so forth) while also having a timer set to go off when patience runs out.

“Near the player” actually means “in scope”, a term which will be properly defined in §32 but which roughly translates as “in the same place and visible”. You can change the scope rules using an InScope routine, say to make the ‘Zork I’ thief audible throughout the maze he is wandering around in. In case you want to tell whether scope is being worked out for ordinary parsing reasons or instead for each_turn processing, look to see whether the scope_reason variable has the value EACHTURN_REASON. (Again, see §32 for more.)

It is safe to move an object when its own each_turn rule is running, but not to move any other objects which are likely to be in scope.

EXERCISE 45
(‘Ruins’.) Make “the sound of scuttling claws” approach in darkness and, after 4 consecutive turns in darkness, kill the player.

EXERCISE 46
Now try implementing the scuttling claws in a single object definition, with no associated code anywhere else in the program, not even a line in Initialise, and without running its daemon all the time.

· · · · ·

The library also has a limited ability to keep track of time of day as the game goes on. The current time is held in the variable the_time and runs on a 24-hour clock: this variable holds the number of minutes since midnight, so it takes values between 0 and 1439. The time can be set by

SetTime(60 × ‹hours› + ‹minutes›, ‹rate);

The rate controls how rapidly time is moving: a rate of 0 means it is standing still, that is, that the library doesn't change it: your routines still can. A positive rate means that that many minutes pass between each turn, while a negative rate means that many turns pass between each minute. It's usual for a timed game to start off the clock by calling SetTime in its Initialise routine. The time will appear on the game's status line, replacing the usual listing of score and turns, if you set

Statusline time;

as a directive at the start of your source code.

EXERCISE 47
How could you make your game take notice of the time passing midnight, so that the day of the week could be nudged on?

EXERCISE 48
Make the lighting throughtout the game change at sunrise and sunset.

· · · · ·

Here is exactly what happens at the end of each turn. The sequence is abandoned if at any stage the player dies or wins.

EXERCISE 49
Suppose the player is magically suspended in mid-air, but that anything let go of will fall out of sight. The natural way to code this is to use a daemon which gets rid of anything it finds on the floor: this is better than trapping Drop actions because objects might end up on the floor in many different ways. Why is each_turn better still?

EXERCISE 50
How would a game work if it involved a month-long archaeological dig, where anything from days to minutes pass between successive game turns?

REFERENCES
Daemons abound in most games. Apart from ‘Advent’, see the flying tortoise from ‘Balances’ and the chiggers from ‘Adventureland’. For more ingenious uses of daemon, see the helium balloon and the matchbook from ‘Toyshop’.   Typical timers include the burning match and the hand grenade from ‘Toyshop’, the endgame timer from ‘Advent’ and the ‘Balances’ cyclops (also employing each_turn).   ‘Adventureland’ makes much use of each_turn: see the golden fish, the mud, the dragon and the bees.   The chapter of ‘Jigsaw’ set on the Moon runs the clock at rate −28, to allow for the length of the lunar day.   The library extension "timewait.h" by Andrew Clover thoroughly implements time of day, allowing the player to “wait until quarter past three”.   Whereas Erik Hetzner's "printtime.h" does just the reverse: it prints out Inform's numerical values of time in the form of text like “half past seven”. Erik is also author of "timepiece.h", which models watches and clocks, allowing them to run slow or fast compared to the library's absolute notion of time. (As yet nobody has needed a relativistic world model.)