Table of Contents |
Actions > Implicit Actions
Implicit Actions
An implicit action is an action that the game carries out for the player to allow the explicitly commanded action to proceed. For example, if the player types THROW BALL AT STONE when the player character is not holding the ball, but the ball is within reach, rather than having the parser respond with “You need to be holding the ball before you can throw it”, the game simply has the player character take the ball as an implicit action (i.e. an action not explicitly requested by the player but necessary to carry out the command the player did type), and reports the result with a message like ‘(first taking the ball)’. Similarly, LOOK IN BOX when the box is closed would result in an implicit open action and the report ‘(first opening the box)’. If, however, the box can’t be opened, because it’s locked, say, the parser will instead report the failed attempt to perform the requisite implicit action (opening the box) with a message like ‘(first trying to open the box)’. Here the word ‘trying’ is intended to convey to the player that it is necessary to open the box before looking inside it, but that in this instance the attempt to open it did not succeed.
Triggering Implicit Actions
The commonest way for an implicit action to be triggered is via a
PreCondition, that is an object used to define
what conditions must hold in order for a particular action to go ahead
(as discussed in the section on Action Results).
You can, however, trigger an implicit action explicitly in your own code
using the tryImplicitAction() macro. This takes the form
tryImplicitAction(*action-name*, *objs...*)
,
where action-name is the name of the action you wish to be explicitly
performed, such as Take
, and objs… is the
object or objects you want the implicit action to apply to. So, for
example, to trigger an implicit TAKE RED BALL action in your own code
you might write:
tryImplicitAction(Take, redBall);
The place where you might typically write such code is in the action section of a dobjFor() or iobjFor() block in your own code. For example, suppose that you are implementing the response to the WriteOn action for a sheet of paper, but in order to write on the piece of paper the player character has to be holding a pen. Rather than just preventing the action if the pen isn’t held, you could make the player character take the pen automatically via an implicit action provided the pen is within reach, something like:
pieceOfPaper: Thing 'piece of paper'
...
dobjFor(WriteOn)
{
check()
{
if(!gActor.canReach(pen))
"You need a pen to do that. ";
}
action()
{
if(!pen.isDirectlyHeldBy(gActor))
tryImplicitAction(Take, pen);
...
}
}
Reporting Implicit Actions
As stated above, the library normally reports implicit actions with text
such as ‘(first taking the pen)’ (when the implicit action succeeds) or
‘(first trying to take the pen)’ (when the implicit action fails. The
library also attempts to group implicit action reports as far as
possible, to give reports like ‘(first taking the gold key, then
unlocking the small box with the gold key, then opening the small box)’
rather than giving three separate implicit action reports relating to
the same command. To do this it stores the implicit action reports it
needs to produce in the implicitActionReports of the current Command
object (gCommand
) until they are ready (or
need) to be displayed. This mechanism make the handling of implicit
action reports by the library a fairly complex matter, the details of
which most game authors probably won’t want to concern themselves with.
On the other hand, game authors may wish to customize these reports or
control whether and when they appear. Whether an implicit action report
is produced at all is controlled by the reportImplicitActions
property of the Action
class. Usually, it’s a
good idea to display implicit action reports so that players can see
what actions have been performed on their behalf, otherwise they may not
be aware that the pen has been taken or the box opened as a side-effect
of the command they actually entered, but some game authors dislike
implicit action reports, and since it’s your game you’re writing you
can, if you like, banish all implicit action reports with the following
few lines of code:
modify Take
reportImplicitActions = nil
;
You can also do this on a per action basis. For example, the following code would suppress implicit take reports but allow all other implicit actions to be reported:
modify Take
reportImplicitActions = nil
;
To suppress the implicit action reports that would stem from a particular action applied to particular objects, we can use a Doer, like so:
Doer 'look in octopusTank'
execAction(c)
{
try
{
Action.reportImplicitActions = nil;
inherited(c);
}
finally
{
Action.reportImplicitActions = true;
}
}
;
This would prevent any implicit action reports appearing in response to
the command LOOK IN OCTOPUS TANK. We could also, of course, use a Doer
in a similar way with a class (such as Thing
)
in place of a particular object (such as
octopusTank
) to suppress the implicit actions
reports for an action applied to a whole class of objects. Note the use
of the try…finally blocks here to ensure that
Action.reportImplicitActions
is restored to
true at the end of the action even if it throws an exception.
Finally, we can customize some of the fragments of text that go to build up implicit action reports by using a CustomMessages object like so:
CustomMessages
messages = [
Msg(implicit action report start, '[after '),
Msg(implicit action report failure, 'failing to '),
Msg(implicit action report separator, ' and next '),
Msg(implicit action report terminator, ']\n')
]
;
This example would turn a report like ‘(first taking the ball)’ into ‘[after taking the ball]’, ‘(first trying to open the box)’ into ‘[after failing to open the box]’ and ‘(first opening the box then taking the ball)’ into ‘[after opening the box and next taking the ball]’. Note where the spaces need to occur in these textual fragments.
adv3Lite Library Manual
Table of Contents |
Actions > Implicit Actions