The TADS Alternate Library
Version 2.0
Reprocessing A Command
Copyright 2000 by Kevin Forchione.
This is part of the TADS Alternate Library Authors Manual.
Introduction and
Table of Contents
Infocom games suffered
from a design model “flaw” with regard to reprocessing a command. This design
“flaw” was later incorporated into the TADS 2 processing model. The “flaw” is
apparent in the reprocessing of the previous player command through the
<<again>> or <<g>> command. Both Infocom and TADS 2
repeat a player command by re-executing the disambiguated command objects.
In practical terms what
this means is that the same action is performed upon the same objects when the
<<again>> command is issued. Under most circumstances this doesn’t
cause a problem. But when the action changes the state of the object in such a
way that a repetitive action becomes illogical then the parser tends to display
messages that don’t mesh well with the reality of the game world.
For example:
Entryway
This large, formal entryway is slightly intimidating: the walls
are lined with somber portraits of gray-haired men from decades past; a
medieval suit of armor, posed with battle axe at the ready, towers over a
single straight-backed wooden chair. The front door leads back outside to the
south. A hallway leads north.
You see two apples here.
Little old Joe is here, looking hungry.
>eat
apple
That
was delicious!
>g
You
can't repeat that command.
Obviously we should be
able to eat the second apple, but modesty, and the TADS 2 parser prevent us from
doing so. The technical reason is because the <<g>> is actually
attempting to reprocess the eat command on the same apple selected in the
original player command, but that apple is no longer in the player’s scope.
The ideal solution to the
problem consists of resubmitting the player command “eat apple” to the parser
for object disambiguation and resolution prior to command execution. But
obtaining the player command and storing it is not as easy as it may at first
seem. An author first encounters the player command in the parser’s preparse()
hook. This function provides the author with the complete player command as it
was typed on the command line. But because the player can enter multiple
commands upon the command line it can be difficult to determine where
one command, if you will, ends and another begins.
The next place the player
encounters the player command is in the preparseCmd() hook. At this point the
player command line has been broken up into commands. But by this time
the command has undergone the following transformations:
This amounts to a
substantial transformation of the portion of the original player command line
under examination at that given time. Given the nature of the TADS 2 parser
recreating the exact original player command would require a great deal of
manual parsing by the author.
The solution Alt achieves
does not aim for an exact reproduction, but for one that is sufficiently
close to the player’s original command to enough to allow for object
disambiguation and resolution to occur with reasonable correctness while
providing minimal impact upon the library.
Entryway
This large, formal entryway is slightly intimidating: the
walls are lined with somber portraits of gray-haired men from decades past; a
medieval suit of armor, posed with battle axe at the ready, towers over a
single straight-backed wooden chair. The front door leads back outside to the
south. A hallway leads north.
You see two apples here.
Little old Joe is here, looking hungry.
>eat apple
That was delicious!
>g
That was delicious!
>g
I don't see any apple
here.
Alt accomplishes this by
using the againPCO preparse object in conjunction with the preCommand()
function and Stringizer class to capture the player command from preparseCmd(),
and convert it back into a player command string that approximates what the
player originally entered.
For instance, suppose we
tell Joe to sit down on the chair. This involves the following steps:
>Joe,
sit down on the chair
Obviously the string we’re
storing for repetition isn’t the same as what the player entered, but it is
close enough that the parser will reparse the command correctly, however if the
parser does have difficulty disambiguating or resolving the command objects
then it might display something other than what the player entered. For
example:
>joe,
sit down on the chair
Joe
looks at you bemusedly and leaves the room.
>g
I don’t
see any little old Joe here.
Although this problem
should be quite rare, there is a more serious possibility, that the input may
be substantially altered by preparse(). In this case the original player
command might be altered to a format that doesn’t produce the expected results
when it is reconstructed and passed back to the parser. This is the case with the
<<wait>> commands processed by the gameClockPPO. In this case
gameClockPPO strips off the time string portion of the command, converting it
to a waitTime value and storing it. This information is then concatenated with
the global.cmdString before it is reprocessed. Similar manipulations are
necessary where preparse() is used to remove portions of a command to be
converted to game state data.