I’ve been sitting on this for a long time but never finished writing up the Parser so I never posted it. But what the heck, the rest of it is still useful. It’s for 10.1 (I had written it for the current dev version of Inform, but have, I hope, edited out the small number of differences).
The Turn Sequence
1. Parse command rule
Parser__parse (Parser.i6t)
if EarlyInTurnSequence is true, return immediately (doing nothing)
begin the reading a command activity
Before reading a command
For reading a command (if present, *or*...)
Keyboard (in Parser.i6t)
PrintPrompt (prints command prompt)
DrawStatusLine (you guessed it)
KeyboardPrimitive
TestKeyboardPrimitive (if we're running, e.g., TEST ME, or...)
VM_ReadKeyboard (Glulx.i6t *or* ZMachine.i6t)
VM_Tokenise (split command into tokens)
handle Oops
handle Undo
[ one of:
- generate a parser error and loop back to top of parser loop
- ask a disambiguation question
- accept command and identify action (stored in parser_results)
[...]
2. declare everything initially unmentioned (unmention *all* the things!)
3. generate action rule (GENERATE_ACTION_R in OrderOfPlay.i6t)
if EarlyInTurnSequence is true, return immediately (doing nothing)
set EarlyInTurnSequence to false
assign the basic action globals
if this is a multiple action
follow multiple action processing rules
GenerateMultipleActions (OrderOfPlay.i6t)
loop through multiple object list, calling BeginAction with each
otherwise, if singleton action
BeginAction (Actions.i6t)
ChronologyPoint (Chronology.i6t)
save existing action variables
ActionPrimitive (Actions.i6t)
Setting action variables rulebook
if out of world action,
descend to specific action rule (see below)
Follow action processing rulebook (see separate chart)
restore previous action variables
call TrackActions to update `if we have...`
if out of world action, rule succeeds [ skip rest of turn sequence and start again from the top ]
[ beyond this point, we should no longer count on previous values of current action, noun, etc ]
4. early scene changing stage rule
follow the scene changing rules
follow appropriate when <scene> begins, when <scene> ends rulebooks
5. every turn stage rule
follow the every turn rules
6. timed events rule (e.g., `at 9:15 am:`, `at the time when...`)
7. advance time rule (increment time, turn count)
8. update chronological records rule
loop through past tense conditions, testing them
ChronologyPoint
9. late scene changing rule
follow the scene changing rules
follow appropriate when <scene> begins, when <scene> ends rulebooks
10. adjust light rule
11. note object acquisitions rule (any undescribed things enclosed by player become described)
12. notify score changes rule
Action Processing
tl; dr: saying that it goes Before, Instead, Check, Carry Out, After, Report elides some things:
- before
- visibility, accessibility, carrying requirements
- instead
- persuasion
- check
- carry out
- after
- report
action processing rules
announce items from multiple object lists rule
set pronouns from items from multiple object lists rule
before stage rule
follow the before rules
basic visibility rule (Actions.i6t)
if action requires light and actor is the player (NPCs don't need light)
follow the visibility rules
can't act in the dark rule (standard rules) [only rule in rulebook]
if in darkness, rule succeeds
if rulebook succeeds (success/failure is backwards of what you might expect)
carry out the refusal to act in darkness activity
stop the action
basic accessibility rule (Actions.i6t)
if the action requires a touchable noun
if the noun is a direction, stop the action in failure
otherwise
test touchability (ObjectIsUntouchable in Light.i6t)
follow the accessibility rules (Standard Rules)
access through barriers rule (access_through_barriers_r in Light.i6t ) [only rule in rulebook]
find the common ancestor of the actor and noun
if there's a barrier between actor and common ancestor
follow the reaching outside rules
can't reach outside closed containers rule
if actor's in closed container, stop the action in failure
if there's a barrier between noun and common ancestor
follow the reaching inside rules
can't reach inside closed containers rule
if noun's in closed container, stop the action in failure
if the action requires a touchable second noun, proceed as above for the second noun
carrying requirements rule
if the action requires a carried noun and the actor isn't carrying it
carry out the implicitly taking activity with the noun
for implicitly taking
standard implicit taking rule
if player *still* isn't carrying it, stop the action in failure
if the action requires a carried second noun and the actor isn't carrying it
proceed as above for the second noun
instead stage rule
follow the instead rules
(if an instead rule applies, unless it explicitly *continues the action*, stop the action in failure)
requested actions require persuasion rule (Actions.i6t)
if player is asking someone to do something
follow the persuasion rules
unless a persuasion rule succeeds, stop the action in failure ("<npc> has better things to do.")
carry out requested actions rule (Actions.i6t)
if this as an asking someone to action and persuasion succeeded
store value of act requester (on stack)
set act requester to nothing (converts this to a regular, unrequested action with an NPC actor)
call BeginAction for this new action
if deadflag is false and the action failed (the rule as written says action failed or it's out of world, but actionPrimitive would already have failed it if the player had asked someone to do an out-of-world action)
follow the unsuccessful attempt by rules
unless an unsuccessful attempt by rule succeeds, output "<npc> is unable to do that"
restore previous value of act requester (from stack), i.e., we convert back to the original `ask someone to...` action with player as actor
follow the after rules *for the `ask someone to...` action*
(*don't* try to follow report rules, because `ask someone to...` can't have them)
stop the action *in success*, regardless of whether the NPC's action succeeded: `ask someone to...` succeeded
descend to specific action-processing rule (Glulx.i6t or Zmachine.i6t)
work out details of specific action rule (creates some data structures)
investigate player's awareness before action rule
follow the player's action awareness rules
check stage rule
specific action check rules
(typically, test conditions and stop the action in failure if condition isn't met, silently for NPCs or with a message for players. Sometimes, try
implicit actions and stop the action in failure if that action fails.)
carry out stage rule
specific action carry out rules
after stage rule
unless it's an out-of-world action
follow after rules
(if an after rule applies, unless the rule explicitly *continues* the action, stop the action in success)
investigate player's awareness after action rule (even for out-of-world)
follow the player's action awareness rules;
report stage rule
if awareness after action succeded,
follow the specific report rules
default action success rule
action succeeds (the end for out-of-world actions)
end action-processing in success
action succeeds
Startup
initialise memory rule
virtual machine startup rule
seed random number generator rule
update chronological records rule
declare everything initially unmentioned rule
position player in model world rule
start in the correct scenes rule
follow the scene changing rules
when play begins stage rule
follow the when play begins rulebook
fix baseline scoring rule
display banner rule
initial room description rule
try looking
Main
[ the Main function in OrderOfPlay.i6t ]
Follow the Startup rules
loop forever (until proven otherwise)
while deadflag is 0 [ we haven't encountered an `end the story` phrase ]
set EarlyInTurnSequence to true
initialize action variables
follow the Turn Sequence rules
[ we *did* encounter `end the story`... ]
follow the Shutdown rules
When Play Ends Stage rule
follow the When Play Ends rules
Resurrect Player If Asked rule
if `resurrect_please` is true [ a rule invoked `resume the story` ]
set deadflag to 0
set resurrect_please to false
stop the Shutdown rulebook (...returning to looping forever)
Print Player's Obituary rule
carry out the Printing the Player's Obituary activity
Ask the Final Question rule
carry out the Handling the Final Question Activity
if resurrect_please is true, return true
unless the Shutdown Rules returned true, break out of loop (ending game)
An I6 quit statement ends things immediately. This is what happens with the quit command (if you say yes to its confirmation question) or when the immediately quit rule is followed (which is what happens if you choose “quit” during the handling the final question activity).
end the story sets an I6 global called deadflag. resume the story sets an I6 global called resurrect_please but doesn’t alter deadflag So if an author adds a Final Question Option that invokes resume the story (and a player chooses it) we don’t dive right back into the loop that follows the turn sequence rules because deadflag is still non-zero: we end up following the Shutdown rules again and thus follow the When Play Ends rules again. When we get back to the Resurrect Player If Asked rule, deadflag is restored and, so, we end up following the turn sequence again.