Monday, February 18, 2019

Chapter 6. MAIN-LOOP - Heart of the Game

  • Arguments: None
  • Return: None

6.1. Introduction

MAIN-LOOP is the heart of all Infocom games and keeps the game structure orderly. It repeatedly requests for parsed commands and loops indefinitely. MAIN-LOOP does not get modified too much with newer games. Many of the changes were to make programming game-specific details and restrictions easier to do. These game changes essentially provided more checks on the player input and provided better responses. Only significant changes to MAIN-LOOP will be later described.

6.2. The Details

MAIN-LOOP will call PARSER to ask and process a user’s command. If PARSER cannot properly parse the command, MAIN-LOOP will continue to call PARSER to process new commands. If it has successfully processed a command, PARSER will set PRSA (parser action) with the requested action number (the 8th byte in a syntax entry) and fill the PRSO (parser direct object) and PRSI (parser indirect object) tables (P-PRSO and P-PRSI) with all the direct and indirect objects requested. This is different to what is described in “Learning ZIL”. MAIN-LOOP then loops and acts upon all the objects:
  1. Check the number of objects in the direct and indirect clauses
  2. If the direct objects clause has no objects, then see it the action is GO.
    1. If so, then call PERFORM with GO and the direction in PRSO.
    2. If no objects are needed for the requested action, then call PERFORM on PRSA with no objects
    3. If at least 1 object clause is needed for the requested action, then print an error message. Display a specific error message if the command is an invalid response to an orphaned command.
  3. One clause will be designated the multiple one and one clause has a constant object, first one in the clause.
  4. Call the requested action with PERFORM multiple times for each object in the multiple object clause as while the other clause just has its first object used.
    1. If M-END is returned, then halt the processing of multiple objects. Erase any remaining commands.
    2. If M-END is not returned, then continue looping through the multiple objects
  5. Increase number of turns by 1 (even if multiple object are processed).
  6. Call CLOCKER to check interrupts even if the given command was not valid. This was later changed in Deadline and other future games to only calling CLOCKER if PARSER was successful.

6.3. Details of Multiples of Multiples

The MAIN-LOOP handles commands with multiple objects for a given action. It will loop through these objects and execute the same action for each object. However, there is some confusion as to how it determines preference if two sets of objects are given. The examples below show how MAIN-LOOP iterates through multiple objects.

Multiple Direct Objects
Multiple Indirect Objects
Multiple Direct and Indirect Objects
IGNITE CANDLE AND, PAPER WITH TORCH
  • IGNITE CANDLE WITH TORCH
  • IGNITE PAPER WITH TORCH
CUT TREE WITH AXE AND SWORD
  • CUT TREE WITH AXE
  • CUT TREE WITH SWORD
IGNITE CANDLE AND PAPER WITH TORCH AND FIRE
  • IGNITE CANDLE WITH TORCH
  • IGNITE PAPER WITH TORCH
So any additional indirect objects are ignored when there are both multiple direct and indirect objects. MAIN-LOOP will always iterate through the direct object clause if it has the same or more objects than the indirect clause. The indirect object remains constant (the first one in the clause) for all iterations. The only exception is for only 1 direct object and multiple indirect objects. MAIN-LOOP will then iterate through the indirect objects while keeping the direct object constant.

6.4 Update: Managing Global Variables

Only minor improvements were made with handling the PRSA, PRSO, and PRSI variables. Updating the L- versions of these variables which are used by the AGAIN command was moved into the MAIN-LOOP section starting with Zork 2. Later games would excluding updating these variables if certain commands were used. Zork 3 added the option of checking the the LIT variable with commands that require no objects. If it was clear, then a “It’s too dark to see” error would be given. Zork 2 (R28) also moved the updating of the IT-OBJECT and its location variable into the MAIN-LOOP instead of PERFORM. LGOP and Plundered Hearts also added a specific check on the visibility of the IT-OBJECT in the MAIN-LOOP.

6.5 Update: How many NOT-HERE-OBJECTs?

To generate a better user responses when some objects are missing in a command, MAIN-LOOP (since Infidel) started to count how many requested objects in a multiple object command were not present. This number was kept in the global P-NOT-HERE variable and used to provide a more specific error message for missing objects. For example, if more than P-NOT-HERE was greater than 1, the error message would use “objects” instead of “object”. One final coding relic is the P-MULT flag. It is cleared and set in the MAIN-LOOP, but has been used only in Infidel’s NOT-HERE-OBJECT ACTION routine.  All subsequent ZIP 3 games since Infidel still set this flag, but it is never used. It is also present in various developmental versions but not used. Its true function remains unclear.

6.6 Update: Checking For Invalid Exceptions

Starting with Deadline, MAIN-LOOP would check for specific invalid situation where an action should not be done on a specific object. Deadline ensured that none of the referred objects in a command was the WINNER. Planetfall had its own special check on objects used with “PICK UP” by making sure the PRSO was on/in PRSI. If not, it would skip over that PRSO.
Wishbringer (R69) would be the first game to check for these exceptions in a separate routine instead of in MAIN-LOOP.  It would be called whenever the GETFLAG mode in the game is set to ALL. MAIN-LOOP will iterate through each object in a multiple object clause and check it for any invalid exceptions exits before sending it off to PERFORM. If an invalid exception exists, PERFORM will be skipped. This CheckException routine usually looks for the actions that require the object be held or local such as DROP or INSERT. If that command is being used, the routine will see if the proper attributes are set (TAKEN, for example), held by the WINNER, or not already inserted for example. Every game since Wishbringer has such a routine.

No comments:

Post a Comment