The CONTEXT mechanism or how to avoid use of QUERY
The way A-code is currently implemented, has one substantial disadvantage.
The two input directives (INPUT and QUERY) expect execution to proceed from
the the point where they have been called, which is fine if the game
executable takes care of its own main loop. However, in the single turn
(CGI) and library modes, this is not the case. Input is obtained by other
controlling software (e.g. by a PHP script, in the single turn mode) and
there is no mechanism to return the game to the point at which an input
directive is used. The problem is aggravated by the fact that it may make
perfect sense to have multiple calls for input in a single pass through the
main loop (e.g. get general command, if this command is SAVE without a name
to save the game under, get the name; if there is already such a saved game,
query whether it should be overwritten).
In Platt's original A-code implementation as a virtual machine this would
not have been a problem. One simply saved the state of the VM before
returning control to the external software. Once the game code is re-invoked
and supplied with the next command, the VM state is restored and execution
proceeds as normal. Things are nowhere near as simple when a game is simply
an executable (or a library) built from C sources.
There are possible solutions, of course. The game could be split into two
processes: one in charge of player communication and the other running the
game's world. Indeed, that's how the browser mode build works, but this
arrangement is not suitable for running in a third-party cloud.
The CONTEXT mechanism was my solution to this problem when implementing the
original CGI-based implementation of Adv770 to be used by game's
beta-testers. The idea is a simple one. The game can acquire query responses
as a part of the main loop – it just needs to know that a question has
been asked and specifically what question has been asked. Then having
acquired player's input it can deal with it appropriately.
At first glance, no kernel involvement is required for this to work, but
there are reasons why it does have to be aware of this mechanism. Otherwise
anomalies would arise in e.g. orphan command word handling and the game
persistence mechanism. Thus variable named CONTEXT is deemed to be special
by the kernel. If it is set to zero, the next expected input is just a
general game command. If set to non-zero, however, an answer to a particular
query is expected by the game.
Here is a very simple example. First a trivial A-code program using
QUERY:
style 12
verb quit
init
repeat
# (Some house-keeping code)
repeat
input # No initialisation
query "Really?_" # The underscore is a forced space
ifkey quit
say "Bye..."
stop
else
say "OK."
fin
else
say "If not, not."
fin
say "_" # Add a blank line
And here is one possible equivalent using the CONTEXT variable instead of
the QUERY directive:
style 12
var context
verb quit
verb yes # Any other query answer is deemed to be no
init # CONTEXT automatically initialised to zero
repeat
ifturn
and
ifflag context, prompted
proceed
fin
# (Some house-keeping code here)
repeat
ifeq context, 0 # A general command is required
proceed
fin
save command # Preserve player's original command
input # Get query response
ifkey yes
restore command # Restore the original command
ifkey quit # And act on it if appropriate
say "Bye..."
stop
fin
say "OK."
else
say "If not, not."
fin
set context, 0 # Ensure next loop is just a general command one
quip "_" # Add a blank line
repeat
input
set context, 1 # Signal query processing is needed
quip "f:Really?_"
Note the addition to the first, house-keeping REPEAT section. In single turn
builds it ensures that the housekeeping code is not executed twice, whenever
the player is prompted for input.
Probably the best way of getting to grips with the context mechanism is to
examine differences between A-code sources of Dave
Platt's non-CGI and my CGI versions of Platt's Adv550.
|