Inform.t
Version
3.2
This
file is part of the Inform.t Author’s Manual
Copyright
© 1999 by Kevin Forchione. All rights reserved.
Object Reactions
Third-party reactions occur when the action between the
actor, and possibly direct and indirect objects indirectly effect another
object. A good example is the garage opener in Mike Robert's The Plant. Taking
the garage opener out of the glovebox when Mr. Teeterwaller is present elicits
a response. This kind of interaction goes a long way toward making your game
feel realistic and three-dimensional.
With the advent of TADS version 2.5 there are many different
ways to code third-party reactions. Inform 3.0 simplified the coding of the
reactions and moved the after reaction logic to postAction, while moving
the eachTurn logic to endCommand.
Inform.t version 3.1 has made some further enhancements and
changed the naming of the reaction methods to be more "intuitively
obvious" and
(A)
preCommand()
(B)
verbAction()
(1)
actor.actorPreAction()
(2)
actor.location.roomPreAction() // location is
scopeCeiling
(3)
obj.scopePreAction() // obj is within
actor's scope for the verb
(4)
iobj.ioPreAction()
(5)
dobj.doPreAction()
(C)
actor.actorAction
(D)
actor.location.roomAction()
(E)
iobjCheck - ioAction / dobjCheck - doAction
(F)
postAction()
(1)
obj.scopePostAction() // obj is within
actor's scope for the verb
(2)
actor.location.roomPostAction() //
location is scopeCeiling
(3)
iobj.ioPostAction()
(4)
dobj.doPostAction()
(G)
Run daemons / fuses
(H)
endCommand()
(1)
turncount()
// turn count advance
(2)
timesys.advance() // time-clock advance
(3)
actor.location.roomEndCommand() //
location is scopeCeiling
(4)
obj.scopeEndCommand() // obj is within
actor's scope for the verb
(5)
timesys.events // time-driven events
(6)
scoreStatus()
Because inform.t is TADS version of reaction behaviour
the above execution sequence parallels that of the inform language to a high
degree, while also capitalising on several of the advantages provided by TADS.
This execution sequence maximizes object-interactions by providing
opportunities for object behaviour both before and after the action methods
have executed. Of course, it also retains the core TADS execution sequence,
which means that if you don't code for reactions then your game will behave
like any other TADS game.
These reaction methods can execute the TADS built-in
functions exitobj, exit, and abort which will terminate the reaction process,
as well as having the same behaviour as they would when executed from the
corresponding action method (preAction processing, because it has no
corresponding preAction function in TADS, is called from verbAction and so
passes control to postAction, unlike preCommand, which passes control to
endCommand).
Additionally, reaction methods can choose to return values
equivalent to the above mentioned built-in functions. Passing back EC_SUCCESS,
EC_EXITOBJ, EC_EXIT, or EC_ABORT will perform exactly as though you had issued
return, exitobj, exit, or abort.
actorPreAction
This method performs a similar function to actorAction(),
but allows the author to terminate processing before roomPreAction has been
executed, or to tailor the ordering of display messages.
roomPreAction / roomPostAction
Because inform.t uses an alternative scoping mechanism, it
doesn't generally work with top-level locations, but determines a scopeCeiling
for the actor based on accessibility rules. While the TADS built-in parser will
call actor.location.roomAction() this might not be accurate for an actor inside
an enterable class or similar object.
The actor.location.roomPreAction() and
actor.location.roomAction() methods may at first appear to be redundant, but
allows for a more accurate and tighter check on the actor's location.
scopePreAction and scopePostAction
These methods are called for each object within the actor's
scope for the given verb and scopeCeiling, excluding the actor,
scopeCeiling_location, direct object, and indirect object. These methods allow
for a bearded psychiatrist to make observations on the actor's efforts at
object manipulation or allow teeterwaller to comment on our garage opener or
map.
postAction Status
Because postAction() receive the status of the execution
sequence it's possible to code for both successful and unsuccessful execution
of the action method (You may still have to check game-state). This allows for
the following style of interactions:
Wonderful World of Containers
This is Room 11, east of the foyer. You notice a
typical piece of scenery which
turns out to be a surface: a mantelpiece.
You see a green ball, a red cone, a blue pyramid, a
plain shopping bag (which
can only hold 2 things) , a glass box with a lid, a steel
box with a lid, a toothed bag,
a bolted cupboard, a bolted key, and a television here. The
macrame bag seems
to contain a music box.
A beardded psychiatrist has you under observation.
>take ball
“Subject feels lack of the green ball. Suppressed Oedipal complex? Mmm.”
Taken.
>put ball in steel box
Done.
“Subject puts a green ball in the steel box with a lid.
Interesting.”
>close steel box
Closed.
>put cone in steel box
The steel box with a lid is closed.
“Subject fails to put a red cone in the steel box with a
lid. Most distressing.”
ioPreAction / doPreAction / ioPostAction doPostAction
These methods resemble xobjCheck() methods in functionality
and are included into the inform.t schema for completeness. They allow an
object to have a say before the execution of the command, and after the
execution. Of particular usefulness are the postAction methods, which carry the
status of the commands action method with them. Using these methods the
following scenario is possible.
>GIVE THE DOG A BONE
You reach into your pocket, groping about
frantically. // actorPreAction generated message
You don't have a bone! // default
verification message
The dog, perceiving your movements
// doPostAction generated message
as a threatening gesture, lunges at you
menacingly.
endCommand Processing
You will notice that endCommand handles the increment of
turncount and the advancement of time. This is a reversal in the normal TADS /
Inform processing, which update the turn counters and advance the time before
running daemons and fuses.
Differences between the two processes will only be apparent
in games which reference the global.turnsofar or timesys object directly. In
this case the will be one unit behind normal TADS processing. However, if
the daemon or fuse does not address the global.turnsofar or timesys object
directly then this change has no affect on the execution of the daemon or fuse.
From a philosophical perspective this makes the
daemon or fuse the last part of the current "turn" and not the
beginning of the following "turn", but again, this will not be
noticeable unless the daemon addresses the global.turnsofar or timesys object
from within its code. In this case it the counter values would need to be
incremented by one in order to keep the behaviour in line with the normal TADS
library.
This change in processing order has some advantages. It
frees the time-oriented waiting process (>Wait for 5 minutes) from the
daemons/fuses processing and allows for the advancement of daemons / fuses to
be independent of turns / time. While under normal processing a daemon / fuse
is advanced once per "turn", inform.t allows these processes to be
decoupled so that daemon / fuse execution can occur either once per timerate or
once per turn. This allows the author to keep daemon / fuse execution consistent
during waiting and non-waiting intervals.
roomEndCommand and scopeEndCommand
After the increment of turns and time, as well as the
processing of any timesys.events (such as room lighting) have occurred the
actor.location.roomEndCommand process is called, which becomes the first
reaction of the new "turn". The location is based upon the
determination of the scopeCeiling for the actor.
Next, the scopeEndCommand process executes for each object
within the actor's scope. This includes the direct and indirect objects of a
command, but excludes the actor and scopeCeiling
timesys.events
Lastly, endCommand() executes a user-defined method,
timesys.events. This allows the author to affect time-related events such as
room lighting, anouncement of the hour by clocks, changing weather patterns,
etc.