Additions to the Basic Inform template which are needed only if the Standard Rules are not to be used.


§1. Identification.

Constant BASICINFORMEXTRASKIT = 1;

§2. Justification. Q. Why isn't all of this done with conditional compilation in the Basic Inform template files? A. That wouldn't work, since template files are assimilated before it is known how they will be used.

§3. Miscellany.

[ DefaultTopic; return 0; ];
[ PrintSnippet x; ];
[ LIST_WRITER_INTERNAL_RM x;
    print " and ";
];
[ RunTimeProblemShowWM n x y z; ];
[ OwnerOf o; return nothing; ];
[ MoveObject from to; ];
[ WriteListOfMarkedObjects in_style
    obj c;
    objectloop (obj ofclass Object && obj has workflag2) {
        c++;
    }
    objectloop (obj ofclass Object && obj has workflag2) {
        PrintShortName(obj);
        c--;
        if (c > 0) print ", ";
    }
];

[ Main;
    self = COL_HSIZE; To ensure this definition is not optimised out
    VM_Initialise();
    INITIALISE_MEMORY_R();
    SEED_RANDOM_NUMBER_GENERATOR_R();
    Submain();
];

[ INITIALISE_MEMORY_R;
    #ifdef TARGET_GLULX; VM_PreInitialise(); #Endif;
    #Ifdef LanguageInitialise; LanguageInitialise(); #Endif;

    HeapInitialise(); Create a completely unused memory allocation heap
    StackFramingInitialise(); Create an empty stack
    CreateDynamicRelations(); Create relation structures on the heap

    rfalse;
];

[ DrawStatusLine width posb;
];

§4. Veneer.

#Ifdef TARGET_ZCODE;
[ VM_Initialise i;
    standard_interpreter = HDR_TERPSTANDARD-->0;

    if (KIT_CONFIGURATION_BITMAP & FIX_RNG_TCBIT) {
        @random 10000 -> i;
        i = -i-2000;
        print "[Random number generator seed is ", i, "]^";
        @random i -> i;
    }
];
#Endif;

§5. Short Name Storage. None of the following functions should be called for the Z-machine if the short name exceeds the size of the following buffer: whereas the Glulx implementation of VM_PrintToBuffer will safely truncate overlong text, that's impossible for the Z-machine, and horrible results will follow.

CPrintOrRun is a variation on PrintOrRun, simplified by not needing to handle entire paragraphs (so, no fuss about dividing) but complicated by having to capitalise the first letter. We do this by writing to the buffer and then altering the first character.

Array StorageForShortName buffer 250;

[ CPrintOrRun obj prop  v length i;
    if ((obj ofclass String or Routine) || (prop == 0))
        VM_PrintToBuffer (StorageForShortName, 160, obj);
    else {
        if (obj.prop == NULL) rfalse;
        if (metaclass(obj.prop) == Routine or String)
            VM_PrintToBuffer(StorageForShortName, 160, obj, prop);
        else return RunTimeError(2, obj, prop);
    }

    length = StorageForShortName-->0;

    StorageForShortName->WORDSIZE = VM_LowerToUpperCase(StorageForShortName->WORDSIZE);
    for (i=WORDSIZE: i<length+WORDSIZE: i++) print (char) StorageForShortName->i;
    if (i>WORDSIZE) say__p = 1;

    return;
];

[ Cap str nocaps;
    if (nocaps) print (string) str;
    else CPrintOrRun(str, 0);
];

§6. Object Names I. We now begin the work of printing object names. In the lowest level of this process we print just the name itself (without articles attached), and we do it by carrying out an activity.

[ PSN__ o;
    if (o == 0) { LIST_WRITER_INTERNAL_RM('Y'); rtrue; }
    switch (metaclass(o)) {
        Routine:  print "<routine ", o, ">"; rtrue;
        String:   print "<string ~", (string) o, "~>"; rtrue;
        nothing:  print "<illegal object number ", o, ">"; rtrue;
    }
    RegardingSingleObject(o);
    CarryOutActivity(PRINTING_THE_NAME_ACT, o);
];

[ PrintShortName obj i;
    i = indef_mode; indef_mode = NULL;
    PSN__(obj); indef_mode = i;
];

§7. Standard Name Printing Rule. In its initial state, the "printing the name of" activity has just one rule: the following "for" rule.

Global caps_mode = false;

[ STANDARD_NAME_PRINTING_R obj;
    obj = parameter_value;
    if (obj == 0) {
        LIST_WRITER_INTERNAL_RM('Y'); return;
    }
    switch (metaclass(obj)) {
        Routine:  print "<routine ", obj, ">"; return;
        String:   print "<string ~", (string) obj, "~>"; return;
        nothing:  print "<illegal object number ", obj, ">"; return;
    }
    #Ifdef LanguagePrintShortName;
    if (LanguagePrintShortName(obj)) return;
    #Endif; LanguagePrintShortName
    if (indef_mode && obj provides short_name_indef &&
        PrintOrRun(obj, short_name_indef, true) ~= 0) return;
    if (caps_mode &&
        obj provides cap_short_name && PrintOrRun(obj, cap_short_name, true) ~= 0) {
        caps_mode = false;
        return;
    }
    if (obj provides short_name && PrintOrRun(obj, short_name, true) ~= 0) return;
    print (object) obj;
];

[ STANDARD_PLURAL_NAME_PRINTING_R obj;
    obj = parameter_value;
    PrintOrRun(obj, plural, true);
];

§8. Object Names II. The second level of the system for printing object names handles the placing of articles in front of them: {\it the} red herring, {\it an} elephant, {\it Some} bread. The following routine allows us to choose:

The routine then looks after issues such as which contraction form to use: for instance, in English, whether to use "a" or "an" for the indefinite singular depends on the text of the object's name.

Global short_name_case;

[ PrefaceByArticle obj acode pluralise capitalise  i artform findout artval;
    if (obj provides articles) {
        artval=(obj.&articles)-->(acode+short_name_case*LanguageCases);
        if (capitalise)
            print (Cap) artval;
        else
            print (string) artval;
        if (pluralise) return;
        print (PSN__) obj; return;
    }

    i = GetGNAOfObject(obj);
    if (pluralise) {
        if (i < 3 || (i >= 6 && i < 9)) i = i + 3;
    }
    i = LanguageGNAsToArticles-->i;
    artform = LanguageArticles
        + 3*WORDSIZE*LanguageContractionForms*(short_name_case + i*LanguageCases);

    switch (LanguageContractionForms) {
        2: if (artform-->acode ~= artform-->(acode+3)) findout = true;
        3: if (artform-->acode ~= artform-->(acode+3)) findout = true;
           if (artform-->(acode+3) ~= artform-->(acode+6)) findout = true;
        4: if (artform-->acode ~= artform-->(acode+3)) findout = true;
           if (artform-->(acode+3) ~= artform-->(acode+6)) findout = true;
           if (artform-->(acode+6) ~= artform-->(acode+9)) findout = true;
        default: findout = true;
    }
    #Ifdef TARGET_ZCODE;
    if (standard_interpreter ~= 0 && findout) {
        StorageForShortName-->0 = 160;
        @output_stream 3 StorageForShortName;
        if (pluralise) print (number) pluralise; else print (PSN__) obj;
        @output_stream -3;
        acode = acode + 3*LanguageContraction(StorageForShortName + 2);
    }
    #Ifnot; TARGET_GLULX
    if (findout) {
        if (pluralise)
            Glulx_PrintAnyToArray(StorageForShortName, 160, EnglishNumber, pluralise);
        else
            Glulx_PrintAnyToArray(StorageForShortName, 160, PSN__, obj);
        acode = acode + 3*LanguageContraction(StorageForShortName);
    }
    #Endif; TARGET_

    Cap (artform-->acode, ~~capitalise); print article
    if (pluralise) return;
    print (PSN__) obj;
];

§9. Object Names III. The routines accessible from outside this segment.

[ IndefArt obj i s;
    if (obj == 0) { LIST_WRITER_INTERNAL_RM('Y'); rtrue; }
    i = indef_mode; indef_mode = true; s = self; self = obj;
    if (obj has proper) { indef_mode = NULL; print (PSN__) obj; indef_mode = i; self = s; return; }
    if ((obj provides article) && (TEXT_TY_Compare(obj.article, EMPTY_TEXT_VALUE) ~= 0)) {
        PrintOrRun(obj, article, true); print " ", (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 2); indef_mode = i; self = s;
];

[ CIndefArt obj i s;
    if (obj == 0) { LIST_WRITER_INTERNAL_RM('X'); rtrue; }
    i = indef_mode; indef_mode = true; s = self; self = obj;
    if (obj has proper) {
        indef_mode = NULL;
        caps_mode = true;
        print (PSN__) obj;
        indef_mode = i;
        caps_mode = false;
        self = s;
        return;
    }
    if ((obj provides article) && (TEXT_TY_Compare(obj.article, EMPTY_TEXT_VALUE) ~= 0)) {
        TEXT_TY_Say_Capitalised(obj.article); print " ", (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 2, 0, 1); indef_mode = i; self = s;
];

[ DefArt obj i s;
    i = indef_mode; indef_mode = false; s = self; self = obj;
    if ((~~obj ofclass Object) || obj has proper) {
        indef_mode = NULL; print (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 1); indef_mode = i; self = s;
];

[ CDefArt obj i s;
    i = indef_mode; indef_mode = false; s = self; self = obj;
    if ((obj ofclass Object) && (obj has proper)) {
        indef_mode = NULL;
        caps_mode = true;
        print (PSN__) obj;
        indef_mode = i;
        caps_mode = false;
        self = s;
        return;
    }
    if ((~~obj ofclass Object) || obj has proper) {
        indef_mode = NULL; print (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 0); indef_mode = i; self = s;
];

[ GetGNAOfObject obj case gender;
    if (gender == 0) {
        if (case == 0) gender = LanguageAnimateGender;
        else gender = LanguageInanimateGender;
    }
    if (obj has pluralname) case = case + 3;
    return case;
];

[ PNToVP gna;
if (prior_named_noun == player) return story_viewpoint;
    if (prior_named_noun) gna = GetGNAOfObject(prior_named_noun);
    if (((gna%6)/3 == 1) || (prior_named_list >= 2)) return 6;
    return 3;
];