Import v6.12.4 of the Inform 6 standard library v6.12.4
authorJason Self <j@jxself.org>
Thu, 23 Jul 2020 02:32:17 +0000 (19:32 -0700)
committerJason Self <j@jxself.org>
Thu, 23 Jul 2020 02:32:17 +0000 (19:32 -0700)
Modified to not print out the version of Inform and the version of
the standard library in use in the game's banner. Also relicensed to
AGPL per Section 4(c)(ii) of the Artistic License 2.0.

english.h
grammar.h
infix.h [new file with mode: 0644]
linklpa.h
parser.h
readme.txt
verblib.h
version.h [new file with mode: 0644]

index 647188b022fa85b8c76d84af16fbae6db2e0d700..2b2da8b4ba93de1aa994b413e2600ef72d6f8632 100644 (file)
--- a/english.h
+++ b/english.h
@@ -1,9 +1,9 @@
 ! ==============================================================================
 !   ENGLISH:  Language Definition File
 !
-!   Supplied for use with Inform 6 -- Release 6.12.3 -- Serial number 190320
+!   Supplied for use with Inform 6 -- Release 6.12.4 -- Serial number 200718
 !
-!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2019
+!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2020
 !
 !   This file is free software: you can redistribute it and/or modify
 !   it under the terms of the GNU Affero General Public License as
@@ -73,7 +73,7 @@ CompassDirection -> u_obj  with short_name "up above",  door_dir u_to,
                                 name 'u//' 'up' 'ceiling' 'above' 'sky';
 CompassDirection -> d_obj  with short_name "ground",    door_dir d_to,
                                 name 'd//' 'down' 'floor' 'below' 'ground';
-#endif; ! WITHOUT_DIRECTIONS
+#Endif; ! WITHOUT_DIRECTIONS
 
 CompassDirection -> in_obj  with short_name "inside",  door_dir in_to;
 CompassDirection -> out_obj with short_name "outside", door_dir out_to;
@@ -295,6 +295,15 @@ Array LanguageGNAsToArticles --> 0 0 0 1 1 1 0 0 0 1 1 1;
       'l//':   print "look";
       'x//':   print "examine";
       'z//':   print "wait";
+! CompassDirection
+      'n//':   print "north";
+      's//':   print "south";
+      'e//':   print "east";
+      'w//':   print "west";
+      'ne//':   print "northeast";
+      'nw//':   print "northwest";
+      'se//':   print "southeast";
+      'sw//':   print "southwest";
       default: rfalse;
     }
     rtrue;
@@ -373,6 +382,7 @@ Constant DARKNESS__TX   = "Darkness";
 
 Constant THOSET__TX     = "those things";
 Constant THAT__TX       = "that";
+Constant THE__TX        = "the";
 Constant OR__TX         = " or ";
 Constant NOTHING__TX    = "nothing";
 Constant IS__TX         = " is";
@@ -387,7 +397,24 @@ Constant AND__TX        = " and ";
 Constant WHOM__TX       = "whom ";
 Constant WHICH__TX      = "which ";
 Constant COMMA__TX      = ", ";
-Constant COLON__TX      = ": ";
+Constant COLON__TX      = ":";
+
+! For EnterSub()
+Constant STAND__TX     = 'stand';
+Constant SIT__TX       = 'sit';
+Constant LIE__TX       = 'lie';
+
+Constant LIBERROR__TX   = "Library error ";
+Constant TERP__TX       = "Interpreter ";
+Constant VER__TX        = "Version ";
+Constant STDTERP__TX    = "Standard interpreter ";
+Constant TERPVER__TX   = "Interpreter version ";
+Constant LIBSER__TX    = "Library Serial Number ";
+Constant VM__TX                = "VM ";
+Constant RELEASE__TX    = "Release ";
+Constant SERNUM__TX     = "Serial number ";
+Constant INFORMV__TX    = "Inform v";
+Constant LIBRARYV__TX   = " Library v";
 
 ! ----------------------------------------------------------------------------
 ! FYI on nominative pronouns versus accusative pronouns...
@@ -449,7 +476,7 @@ Constant COLON__TX      = ": ";
 ];
 
 ! Nominative
-[ CTheyreorThats obj;
+[ CTheyreOrThats obj;
     if (obj == player) {
        if (player provides narrative_voice) {
            if (player.narrative_voice == 1) { Tense("I'm", "I was"); return; }
@@ -477,7 +504,7 @@ Constant COLON__TX      = ": ";
 
 [ nop x; x = x; ];      ! print rule to absorb unwanted return value
 
-[ SubjectNotPlayer obj reportage v2 v3 past;
+[ SubjectNotPlayer obj reportage nocaps v2 v3 past;
     if (past && player provides narrative_tense && player.narrative_tense == PAST_TENSE) {
         v2 = past;
         v3 = past;
@@ -496,8 +523,21 @@ Constant COLON__TX      = ": ";
             else {print (the) obj, " ", (string) v3; return;}
     }
    else
-        if (obj has pluralname) { print (The) obj, " ", (string) v2; return;}
-        else                    { print (The) obj, " ", (string) v3; return;}
+        if (obj has pluralname) {
+           if (nocaps)
+               print (the) obj;
+           else
+               print (The) obj;
+           print " ", (string) v2;
+           return;
+       }
+        else {
+           if (nocaps)
+               print (the) obj;
+           else
+               print (The) obj;
+           print " ", (string) v3; return;
+       }
 ];
 
 [ CSubjectVoice obj v1 v2 v3 past;
@@ -541,7 +581,7 @@ Constant COLON__TX      = ": ";
         if (nocaps) { print "you ", (string) v2; return; }
        print "You ", (string) v2; return;
     }
-    SubjectNotPlayer(obj, reportage, v2, v3);
+    SubjectNotPlayer(obj, reportage, nocaps, v2, v3);
 ];
 
 [ CSubjectIs obj reportage nocaps;
@@ -557,7 +597,7 @@ Constant COLON__TX      = ": ";
         else Tense("You're", "You were");
         return;
     }
-    SubjectNotPlayer(obj, reportage, "are", "is", "was");
+    SubjectNotPlayer(obj, reportage, nocaps, "are", "is", "was");
 ];
 
 [ CSubjectIsnt obj reportage nocaps;
@@ -573,7 +613,7 @@ Constant COLON__TX      = ": ";
         else Tense("You aren't", "You weren't");
        return;
     }
-    SubjectNotPlayer(obj, reportage, "aren't", "isn't", "wasn't");
+    SubjectNotPlayer(obj, reportage, nocaps, "aren't", "isn't", "wasn't");
 ];
 
 [ CSubjectHas obj reportage nocaps;
@@ -589,7 +629,7 @@ Constant COLON__TX      = ": ";
         else Tense("You've", "You'd");
         return;
     }
-    SubjectNotPlayer(obj, reportage, "have", "has", "had");
+    SubjectNotPlayer(obj, reportage, nocaps, "have", "has", "had");
 ];
 
 [ CSubjectWill obj reportage nocaps;
@@ -605,7 +645,7 @@ Constant COLON__TX      = ": ";
         else Tense("You'll", "You'd");
         return;
     }
-    SubjectNotPlayer(obj, reportage, "will", "will", "would");
+    SubjectNotPlayer(obj, reportage, nocaps, "will", "will", "would");
 ];
 
 [ CSubjectCan obj reportage nocaps;
@@ -840,6 +880,9 @@ Constant COLON__TX      = ": ";
         1:  CSubjectIsnt(actor,true); " wearing ", (ThatOrThose) x1, ".";
         2:  CSubjectVerb(actor,false,false,"take off",0,"takes off", "took off");
             " ", (the) x1, ".";
+        3:  "(first taking ", (the) x1, " off)";
+        4: CSubjectVerb(actor,false,false, "will need to", 0, 0, "had to");
+           " remove ", (the) noun, " first.";
     }
   Drink:    print "There";
             Tense("'s", " was");
@@ -849,8 +892,7 @@ Constant COLON__TX      = ": ";
         2:  CSubjectVerb(actor, false, false, "haven't got", 0, "hasn't got",
                          "didn't have");
             " ", (the) x1, ".";
-        3:  "(first taking ", (the) x1, " off)";
-        4:  "Dropped.";
+        3:  "Dropped.";
     }
   Eat: switch (n) {
         1:  CSubjectIs(x1,true); " plainly inedible.";
@@ -1073,7 +1115,7 @@ Constant COLON__TX      = ": ";
   Mild:     "Quite.";
   Miscellany: switch (n) {
         1:  "(considering the first sixteen objects only)^";
-        2:  "Nothing to do!";
+        2:  "Nothing to do.";
         3:  print " "; CSubjectVerb(player, false, false, "died", "have died", "has died");
            print " ";
         4:  print " "; CSubjectVerb(player, false, false, "won", "have won", "has won");
@@ -1097,7 +1139,7 @@ Constant COLON__TX      = ": ";
             Tense("is now", "was");
             print " pitch dark in ";
             Tense("here", "there");
-            "!";
+            ".";
         10: "I beg your pardon?";
         11: "[You can't ~undo~ what hasn't been done!]";
         12: "[Can't ~undo~ twice in succession. Sorry!]";
@@ -1126,12 +1168,12 @@ Constant COLON__TX      = ": ";
         29: "I didn't understand that number.";
         30: CSubjectCant(actor,true); " see any such thing.";
         31: CSubjectVerb(actor, true, false, "seem", "seem", "seems", "seemed");
-            " to have said too little!";
-        32: CSubjectIsnt(actor); " holding that!";
+            " to have said too little.";
+        32: CSubjectIsnt(actor); " holding that.";
         33: "You can't use multiple objects with that verb.";
         34: "You can only use multiple objects once on a line.";
         35: "I'm not sure what ~", (address) x1, "~ refers to.";
-        36: "You excepted something not included anyway!";
+        36: "You excepted something not included anyway.";
         37: CSubjectCan(actor,true); " only do that to something animate.";
             #Ifdef DIALECT_US;
         38: "That's not a verb I recognize.";
@@ -1145,7 +1187,7 @@ Constant COLON__TX      = ": ";
             print " of those ";
             if (x1 == 1) print "is"; else print "are";
             " available.";
-        43: "Nothing to do!";
+        43: "Nothing to do.";
         44: print "There ";
             Tense("is", "was");
             " nothing to ", (address) x1, ".";
@@ -1184,16 +1226,16 @@ Constant COLON__TX      = ": ";
             "Score notification off.";
   NotifyOn: "Score notification on.";
   Objects: switch (n) {
-        1:  "Objects ", (nop) CSubjectVerb(actor, false, true, "have", "have", "has"), " handled:^";
-        2:  "None.";
-        3:  print "   (worn)";
-        4:  print "   (held)";
-        5:  print "   (given away)";
-        6:  print "   (in ", (name) x1, ")";
-        7:  print "   (in ", (the) x1, ")";
-        8:  print "   (inside ", (the) x1, ")";
-        9:  print "   (on ", (the) x1, ")";
-        10: print "   (lost)";
+        1:  print (nop) CSubjectVerb(actor, false, false, "have", "have", "has"), " handled";
+        2:  CSubjectVerb(actor, false, false, "have", "have", "has"); " handled nothing.";
+        3:  print " (worn)";
+        4:  print " (held)";
+        5:  print " (given away)";
+        6:  print " (in ", (name) x1, ")";
+        7:  print " (in ", (the) x1, ")";
+        8:  print " (inside ", (the) x1, ")";
+        9:  print " (on ", (the) x1, ")";
+        10: print " (lost)";
     }
   Open: switch (n) {
         1:  CSubjectIs  (x1,true);
@@ -1211,8 +1253,9 @@ Constant COLON__TX      = ": ";
     }
   Order:    CSubjectHas(x1,false); " better things to do.";
   Places: switch (n) {
-        1:  print "You have visited: ";
+        1:  print (nop) CSubjectVerb(actor, false, false, "have", "have", "has"), " visited";
         2:  ".";
+        3:  CSubjectVerb(actor, false, false, "have", "have", "has"); " visited nothing.";
     }
   Pray:     print "Nothing practical ";
             Tense("results", "resulted");
@@ -1280,7 +1323,7 @@ Constant COLON__TX      = ": ";
   Remove: switch (n) {
         1:  CSubjectIs  (x1,true); " unfortunately closed.";
         2:  print "But ";
-            CSubjectIsnt(x1,true); " there now.";
+            CSubjectIsnt(x1,true,true); " there now.";
         3:  "Removed.";
     }
   Restart: switch (n) {
@@ -1296,6 +1339,36 @@ Constant COLON__TX      = ": ";
             " nothing by this.";
         2:  DecideAgainst();
     }
+  RunTimeError: print "** ";
+       switch (n) {
+       1:  print "Preposition not found (this should not occur)";
+       2:  print "Property value not routine or string: ~", (property) x2,
+               "~ of ~", (name) x1, "~ (", x1, ")";
+       3:  print "Entry in property list not routine or string: ~",
+               (property) x2, "~ list of ~", (name) x1, "~ (", x1, ")";
+       4:  print "Too many timers/daemons are active simultaneously.
+               The limit is the library constant MAX_TIMERS
+               (currently ", MAX_TIMERS, ") and should be increased";
+       5:  print "Object ~", (name) x1, "~ has no ~", (property) x2,
+               "~ property";
+       7:  print "The object ~", (name) x1, "~ can only be used as a player
+               object if it has the ~number~ property";
+       8:  print "Attempt to take random entry from an empty table array";
+       9:  print x1, " is not a valid direction property number";
+       10: print "The player-object is outside the object tree";
+       11: print "The room ~", (name) x1, "~ has no ~", (property) x2,
+               "~ property";
+       12: print "Tried to set a non-existent pronoun using SetPronoun";
+       13: print "A 'topic' token can only be followed by a preposition";
+       14: print "Overflowed buffer limit of ", x1,
+               " using '@@64output_stream 3' ", (string) x2;
+       15: print "LoopWithinObject broken because the object ",
+               (name) x1, " was moved while the loop passed through it.";
+       16: print "Attempt to use illegal narrative_voice of ", x1, ".";
+       default:
+           print "(unexplained)";
+    }
+    print " **";
   Save: switch (n) {
         1:  "Save failed.";
         2:  "Ok.";
@@ -1404,6 +1477,8 @@ Constant COLON__TX      = ": ";
         11: CSubjectIs  (x1,true); " fixed in place.";
         12: CSubjectIs  (actor,true); " carrying too many things already.";
         13: "(putting ", (the) x1, " into ", (the) x2, " to make room)";
+       14: CSubjectVerb(actor, false, false, "should take", 0, 0, "should have taken");
+           " ", (the) x1, " first.";
     }
   Taste: switch (n) {
         1:  CSubjectVerb(actor,true,false,"taste",0,"tastes","tasted"); " nothing unexpected.";
@@ -1483,9 +1558,9 @@ Constant COLON__TX      = ": ";
         }
         ", feeling foolish.";
   Wear: switch (n) {
-        1:  CSubjectCant(actor,true); " wear ", (ThatOrThose) x1, "!";
-        2:  CSubjectIs  (actor,true); " not holding ", (ThatOrThose) x1, "!";
-        3:  CSubjectIs  (actor,true); " already wearing ", (ThatOrThose) x1, "!";
+        1:  CSubjectCant(actor,true); " wear ", (ThatOrThose) x1, ".";
+        2:  CSubjectIs  (actor,true); " not holding ", (ThatOrThose) x1, ".";
+        3:  CSubjectIs  (actor,true); " already wearing ", (ThatOrThose) x1, ".";
         4:  CSubjectVerb(actor,false,false,"put on",0,"puts on","put on"); " ", (the) x1, ".";
     }
 ! Yes:  see No.
index c7807c532f2d0a6a9013e33474d2d0380374c96c..4a47881a865f11c3eeccaea5c4d2fc445280ea05 100644 (file)
--- a/grammar.h
+++ b/grammar.h
@@ -1,7 +1,7 @@
 ! ==============================================================================
 !   GRAMMAR:  Grammar table entries for the standard verbs library.
 !
-!   Supplied for use with Inform 6 -- Release 6.12.3 -- Serial number 190320
+!   Supplied for use with Inform 6 -- Release 6.12.4 -- Serial number 200718
 !
 !   This file is free software: you can redistribute it and/or modify
 !   it under the terms of the GNU Affero General Public License as
@@ -96,9 +96,13 @@ Verb meta 'version'
 
 #Ifndef NO_PLACES;
 Verb meta 'objects'
-    *                                           -> Objects;
+    *                                           -> Objects
+    * 'tall'                                    -> ObjectsTall
+    * 'wide'                                    -> ObjectsWide;
 Verb meta 'places'
-    *                                           -> Places;
+    *                                           -> Places
+    * 'tall'                                    -> PlacesTall
+    * 'wide'                                    -> PlacesWide;
 #Endif; ! NO_PLACES
 
 ! ------------------------------------------------------------------------------
@@ -118,7 +122,7 @@ Verb meta 'changes'
 
 Verb meta 'gonear'
     * anynumber                                 -> GoNear
-    * noun                                      -> Gonear;
+    * noun                                      -> GoNear;
 
 
 Verb meta 'goto'
@@ -143,12 +147,12 @@ Verb meta 'showdict' 'dict'
     * topic                                     -> ShowDict;
 
 Verb meta 'showobj'
-    *                                           -> Showobj
-    * anynumber                                 -> Showobj
-    * multi                                     -> Showobj;
+    *                                           -> ShowObj
+    * anynumber                                 -> ShowObj
+    * multi                                     -> ShowObj;
 
 Verb meta 'showverb'
-    * special                                   -> Showverb;
+    * special                                   -> ShowVerb;
 
 Verb meta 'timers' 'daemons'
     *                                           -> TimersOn
@@ -185,7 +189,7 @@ Verb meta 'glklist'
 !  And now the game verbs.
 ! ------------------------------------------------------------------------------
 
-[ ADirection; if (noun in compass) rtrue; rfalse; ];
+[ ADirection; if (noun in Compass) rtrue; rfalse; ];
 
 Verb 'answer' 'say' 'shout' 'speak'
     * topic 'to' creature                       -> Answer;
@@ -442,11 +446,11 @@ Verb 'swing'
     * 'on' noun                                 -> Swing;
 
 Verb 'switch'
-    * noun                                      -> Switchon
-    * noun 'on'                                 -> Switchon
-    * noun 'off'                                -> Switchoff
-    * 'on' noun                                 -> Switchon
-    * 'off' noun                                -> Switchoff;
+    * noun                                      -> SwitchOn
+    * noun 'on'                                 -> SwitchOn
+    * noun 'off'                                -> SwitchOff
+    * 'on' noun                                 -> SwitchOn
+    * 'off' noun                                -> SwitchOff;
 
 Verb 'take' 'carry' 'hold'
     * multi                                     -> Take
@@ -476,10 +480,10 @@ Verb 'transfer'
 
 Verb 'turn' 'rotate' 'screw' 'twist' 'unscrew'
     * noun                                      -> Turn
-    * noun 'on'                                 -> Switchon
-    * noun 'off'                                -> Switchoff
-    * 'on' noun                                 -> Switchon
-    * 'off' noun                                -> Switchoff;
+    * noun 'on'                                 -> SwitchOn
+    * noun 'off'                                -> SwitchOff
+    * 'on' noun                                 -> SwitchOn
+    * 'off' noun                                -> SwitchOff;
 
 Verb 'unlock'
     * noun 'with' held                          -> Unlock;
@@ -555,6 +559,8 @@ Stub PrintTaskName     1;
 Stub PrintVerb         1;
 Stub TimePasses        0;
 Stub UnknownVerb       1;
+Stub AfterSave         1;
+Stub AfterRestore      1;
 
 #Ifdef TARGET_GLULX;
 Stub HandleGlkEvent    2;
diff --git a/infix.h b/infix.h
new file mode 100644 (file)
index 0000000..e9b0e60
--- /dev/null
+++ b/infix.h
@@ -0,0 +1,1211 @@
+! ==============================================================================
+!   INFIX:  Support for the optional library debugger extension "Infix".
+!
+!   Supplied for use with Inform 6 -- Release 6.12.4 -- Serial number 200718
+!
+!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2020
+!
+!   This file is free software: you can redistribute it and/or modify
+!   it under the terms of the GNU Affero General Public License as
+!   published by the Free Software Foundation, either version 3 of the
+!   License, or (at your option) any later version.
+!
+!   This file is distributed in the hope that it will be useful, but
+!   WITHOUT ANY WARRANTY; without even the implied warranty of
+!   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+!   Affero General Public License for more details.
+!
+!   You should have received a copy of the GNU Affero General Public
+!   License along with this program. If not, see
+!   https://gnu.org/licenses/
+!
+!   This file is automatically Included in your game file by "grammar" if you
+!   supply the -X compiler switch.
+! ==============================================================================
+
+System_file;
+
+! ------------------------------------------------------------------------------
+
+#Ifdef DEBUG;
+
+Constant INFIXTT_NUMBER          0;
+Constant INFIXTT_ARRAY           1;
+Constant INFIXTT_ROUTINE         2;
+Constant INFIXTT_CONSTANT        3;
+Constant INFIXTT_DWORD           4;
+Constant INFIXTT_ACTION          5;
+Constant INFIXTT_ATTRIBUTE       6;
+Constant INFIXTT_PROPERTY        7;
+Constant INFIXTT_GLOBAL          8;
+Constant INFIXTT_NAMEDOBJECT     9;
+Constant INFIXTT_SYSFUN         10;
+Constant INFIXTT_STATICSTRING   11;
+Constant INFIXTT_LOGICAL        12;
+
+Global infix_term_type;
+Global infix_data1;
+Global infix_data2;
+Global infix_lvalue;
+Global infix_parsed_lvalue;
+Array  infix_tolowercase -> 256;
+#Ifdef VN_1630;
+Array  infix_text buffer 126;
+#Ifnot;
+Array  infix_text -> 128;
+#Endif; ! VN_
+
+
+[ InfixPrintAttribute x; print (string) #attribute_names_array-->x; ];
+
+[ InfixPrintProperty x;  print (property) x; ];
+
+#Ifdef TARGET_GLULX;
+[ InfixPrintGIProperty x;  print (property) x; ];
+#Endif; ! TARGET_
+
+[ InfixPrintGlobal x;    print (string) #global_names_array-->x; ];
+
+[ InfixPrintAction x;    print (string) #action_names_array-->(x-#lowest_action_number); ];
+
+[ InfixPrintRoutine x;   print (string) #routine_names_array-->(x-#lowest_routine_number); ];
+
+[ InfixPrintConstant x;  print (string) #constant_names_array-->(x-#lowest_constant_number); ];
+
+[ InfixPrintArray x;     print (string) #array_names_array-->(x-#lowest_array_number); ];
+
+[ InfixPrintFakeAction x;
+                         print (string) #fake_action_names_array-->(x-#lowest_fake_action_number); ];
+
+[ InfixPrintPA x n;
+    for (n=#lowest_routine_number : n<=#highest_routine_number : n++) {
+        if (x == Symb__Tab(INFIXTT_ROUTINE, n)) {
+            print (InfixPrintRoutine) n; return;
+        }
+    }
+    print "Routine(", x, ")";
+];
+
+[ InfixMatchPrule PrintingRule range1 range2 wa wl t i i2 it2 itlc j k plus;
+    itlc = infix_tolowercase;
+    if (itlc->255 == 0) {
+        for (j=0 : j<256 : j++) itlc->j = j;
+        itlc->'A' = 'a';    itlc->'B' = 'b';
+        itlc->'C' = 'c';    itlc->'D' = 'd';
+        itlc->'E' = 'e';    itlc->'F' = 'f';
+        itlc->'G' = 'g';    itlc->'H' = 'h';
+        itlc->'I' = 'i';    itlc->'J' = 'j';
+        itlc->'K' = 'k';    itlc->'L' = 'l';
+        itlc->'M' = 'm';    itlc->'N' = 'n';
+        itlc->'O' = 'o';    itlc->'P' = 'p';
+        itlc->'Q' = 'q';    itlc->'R' = 'r';
+        itlc->'S' = 's';    itlc->'T' = 't';
+        itlc->'U' = 'u';    itlc->'V' = 'v';
+        itlc->'W' = 'w';    itlc->'X' = 'x';
+        itlc->'Y' = 'y';    itlc->'Z' = 'z';
+    }
+    switch (PrintingRule) {
+      InfixPrintAttribute:
+        if (wa->0 == '~') { wl--; wa++; plus = 100; } ! A tilde
+        t = #attribute_names_array;
+      InfixPrintProperty:   t = #property_names_array;
+      #Ifdef TARGET_GLULX;
+      InfixPrintGIProperty: t = #identifiers_table-->2;
+      #Endif; ! TARGET_
+      InfixPrintAction:     t = #action_names_array;
+      InfixPrintFakeAction: t = #fake_action_names_array;
+      InfixPrintGlobal:     t = #global_names_array;
+      InfixPrintRoutine:    t = #routine_names_array;
+      InfixPrintAction:     t = #constant_names_array;
+      InfixPrintArray:      t = #array_names_array;
+    }
+
+    i2 = range2-range1; it2 = infix_text+WORDSIZE;
+    for (i=0 : i<=i2 : i++) {
+        #Ifdef TARGET_ZCODE;
+        infix_text-->0 = 62; @output_stream 3 infix_text;
+        if (t) print (string) t-->i; else PrintingRule(i+range1);
+        @output_stream -3;
+        #Ifnot; ! TARGET_GLULX
+        if (t) PrintToBuffer(infix_text, 62, t-->i);
+        else PrintToBuffer(infix_text, 62, PrintingRule, i+range1);
+        #Endif; ! TARGET_
+        k = infix_text-->0;
+        if (k ~= wl) jump XL;
+        if (itlc->(it2->0) ~= itlc->(wa->0)) jump XL;
+        for (j=1 : j<k : j++)
+            if (itlc->(it2->j) ~= itlc->(wa->j)) jump XL;
+        parsed_number = i + range1 + plus;
+        rtrue;
+      .XL;
+    }
+    rfalse;
+];
+
+[ InfixActionToken;
+    if (InfixMatchPrule(InfixPrintAction, #lowest_action_number,
+        #highest_action_number, WordAddress(wn), WordLength(wn))) {
+        wn++; infix_lvalue = parsed_number; return 0;
+    }
+    if (InfixMatchPrule(InfixPrintFakeAction, #lowest_fake_action_number,
+        #highest_fake_action_number, WordAddress(wn), WordLength(wn))) {
+        wn++; infix_lvalue = parsed_number; return 0;
+    }
+    return -1;
+];
+
+[ InfixRvalueTerm n w i initial_wn wa wl sign base digit dcount;
+
+    initial_wn = wn;
+
+    infix_parsed_lvalue = -1;
+    infix_term_type = INFIXTT_NUMBER;
+
+    w = NextWordStopped();
+    if (w == -1) return -1;
+
+    wa = WordAddress(wn-1);
+    wl = WordLength(wn-1);
+    if (wa->0 == '-' or '$' or '0' or '1' or '2' or '3'
+              or '4' or '5' or '6' or '7' or '8' or '9') {
+        ! Parse decimal, hex or binary number
+
+        sign = 1; base = 10; dcount = 0;
+        if (wa->0 == '-') { sign = -1; wl--; wa++; }
+        else {
+            if (wa->0 == '$') { base = 16; wl--; wa++; }
+            if (wa->0 == '$') { base = 2; wl--; wa++; }
+        }
+        if (wl == 0) return -1;
+        n = 0;
+        while (wl > 0) {
+            if (wa->0 >= 'a') digit = wa->0 - 'a' + 10;
+            else digit = wa->0 - '0';
+            dcount++;
+            #Ifdef TARGET_ZCODE;
+            switch (base) {
+              2:
+                if (dcount == 17) return -1;
+              10:
+                if (dcount == 6) return -1;
+                if (dcount == 5) {
+                    if (n > 3276) return -1;
+                    if (n == 3276) {
+                        if (sign == 1 && digit > 7) return -1;
+                        if (sign == -1 && digit > 8) return -1;
+                    }
+                }
+              16:
+                if (dcount == 5) return -1;
+            }
+            #Ifnot; ! TARGET_GLULX
+            switch (base) {
+              2:
+                if (dcount == 33) return -1;
+              10:
+                if (dcount == 11) return -1;
+                if (dcount == 10) {
+                    if (n > 214748363) return -1;
+                }
+              16:
+                if (dcount == 9) return -1;
+            }
+            #Endif; ! TARGET_
+            if (digit >= 0 && digit < base) n = base*n + digit;
+            else return -1;
+            wl--; wa++;
+        }
+        parsed_number = n*sign; return 1;
+    }
+
+    ! Parse character constant 'a'
+
+    if (wl == 3 && wa->0 == ''' && wa->2 == ''') {
+        parsed_number = wa->1; return 1;
+    }
+
+    ! ##Action, 'dword'
+
+    switch (w) {
+      '##':
+        infix_term_type = INFIXTT_ACTION;
+        w = NextWordStopped(); if (w == -1) return -1;
+        wn--;
+        if (InfixActionToken() == 0) return 1;
+        return -1;
+      '^^':
+        infix_term_type = INFIXTT_DWORD;
+        w = NextWordStopped(); if (w == -1) return -1;
+        parsed_number = w; return 1;
+    }
+
+    ! Test for attribute, property, class name, variable name, array name, routine
+    ! name, constant name
+
+    wn--;
+    if ((wa->0 >= 'a' && wa->0 <= 'z') ||
+        (wa->0 >= 'A' && wa->0 <= 'Z') ||
+         wa->0 == '_') {
+
+
+        infix_term_type = INFIXTT_ATTRIBUTE;
+        if (InfixMatchPrule(InfixPrintAttribute, #lowest_attribute_number,
+            #highest_attribute_number, wa, wl)) {
+            wn++; return 1; }
+
+        infix_term_type = INFIXTT_PROPERTY;
+        #Ifdef TARGET_ZCODE;
+        if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
+            #highest_property_number, wa, wl)) {
+            wn++; return 1;
+        }
+        #Ifnot; ! TARGET_
+        if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
+            #identifiers_table-->1 - 1, wa, wl)) {
+            wn++; return 1;
+        }
+        if (InfixMatchPrule(InfixPrintGIProperty, INDIV_PROP_START,
+            #highest_property_number, wa, wl)) {
+            wn++; return 1;
+        }
+        #Endif; ! TARGET_
+
+
+        infix_term_type = INFIXTT_GLOBAL;
+        if (InfixMatchPrule(InfixPrintGlobal, #lowest_global_number,
+            #highest_global_number, wa, wl)) {
+            infix_parsed_lvalue = parsed_number-16;
+            parsed_number = #globals_array-->infix_parsed_lvalue;
+            wn++; return 1;
+        }
+
+        infix_term_type = INFIXTT_ARRAY;
+        if (InfixMatchPrule(InfixPrintArray, #lowest_array_number,
+            #highest_array_number, wa, wl)) {
+            infix_parsed_lvalue = parsed_number;
+            parsed_number = Symb__Tab(INFIXTT_ARRAY,parsed_number);
+            infix_data1 = temp__global3;
+            infix_data2 = temp__global2;
+            wn++; return 1;
+        }
+
+        infix_term_type = INFIXTT_ROUTINE;
+        if (InfixMatchPrule(InfixPrintRoutine, #lowest_routine_number,
+            #highest_routine_number, wa, wl)) {
+            infix_parsed_lvalue = parsed_number;
+            parsed_number = Symb__Tab(INFIXTT_ROUTINE,parsed_number);
+            infix_data1 = temp__global3;
+            infix_data2 = temp__global2;
+            wn++; return 1;
+        }
+
+        infix_term_type = INFIXTT_CONSTANT;
+        if (InfixMatchPrule(InfixPrintConstant, #lowest_constant_number,
+            #highest_constant_number, wa, wl)) {
+            infix_parsed_lvalue = parsed_number;
+            parsed_number = Symb__Tab(INFIXTT_CONSTANT,parsed_number);
+            infix_data1 = temp__global3;
+            infix_data2 = temp__global2;
+            wn++; return 1;
+        }
+
+        switch (w) {
+          'parent', 'child', 'children',
+          'random', 'metaclass', 'sibling':
+            parsed_number = w;
+            infix_parsed_lvalue = INFIXTT_SYSFUN;
+            wn++; return 1;
+        }
+    }
+
+    infix_term_type = INFIXTT_NAMEDOBJECT;
+
+    wn = initial_wn; i = ParseToken(SCOPE_TT, InfixBigScope);
+
+    if (i == GPR_REPARSE) return i;
+    if (i > GPR_MULTIPLE) {
+        print "(", (name) i, " (", i, "))^";
+        parsed_number = i; return 1;
+    }
+    return -1;
+]; ! end of InfixRvalueTerm
+
+[ InfixBigScope x;
+    if (scope_stage == 1) return false;  ! No multiples here
+    if (scope_stage == 2) {
+        objectloop (x ofclass Object) PlaceInScope(x);
+        return true; ! That's the whole scope
+    }
+    print "; I'm unable to make any sense of that term.^";
+];
+
+[ InfixCheckLineSpaced wa wl i force altered;
+    for (i=1 : i<=NumberWords() : i++) {
+        wa = WordAddress(i);
+        wl = WordLength(i);
+        if (wl > 3 && wa->0 == ''' && wa->(wl-1) == ''') {
+            wa->(wl-1) = ' ';
+            if (wa->(wl-2) == '/' && wa->(wl-3) == '/') {
+                wa->(wl-2) = ' ';
+                wa->(wl-3) = ' ';
+            }
+            LTI_Insert(wa-buffer, ''');
+            LTI_Insert(wa-buffer + 2, ' ');
+            altered = true; break;
+        }
+    }
+    for (i=WORDSIZE : i<GetKeyBufLength() + WORDSIZE : i++) {
+        #Ifdef TARGET_GLULX;
+        buffer->i = LowerCase(buffer->i);
+        #Endif; ! TARGET_
+        force = false;
+        if (buffer->i == '-' && buffer->(i+1) == '-' && buffer->(i+2) == '>')
+            force = true;
+        if (force) {
+            if (i>WORDSIZE && buffer->(i-1) ~= ' ') {
+                LTI_Insert(i++, ' '); altered = true;
+            }
+            if (buffer->(i+3) ~= ' ') {
+                LTI_Insert(i+3, ' '); i++; altered = true;
+            }
+            i = i + 2; continue;
+        }
+
+        if (buffer->i == ':' && buffer->(i+1) == ':') force = true;
+        if (buffer->i == '-' && buffer->(i+1) == '>') force = true;
+        if (buffer->i == '.' && buffer->(i+1) == '&') {
+            buffer->i = ']'; force = true;
+        }
+        if (buffer->i == '.' && buffer->(i+1) == '#') {
+            buffer->i = ']'; force = true;
+        }
+        if (buffer->i == ']' && buffer->(i+1) == '&') force = true;
+        if (buffer->i == ']' && buffer->(i+1) == '#') force = true;
+        if (buffer->i == '+' && buffer->(i+1) == '+') force = true;
+        if (buffer->i == '-' && buffer->(i+1) == '-') force = true;
+        if (buffer->i == '&' && buffer->(i+1) == '&') force = true;
+        if (buffer->i == '|' && buffer->(i+1) == '|') force = true;
+        if (buffer->i == '~' && buffer->(i+1) == '~') force = true;
+
+        if (buffer->i == '=' && buffer->(i+1) == '=') force = true;
+        if (buffer->i == '~' && buffer->(i+1) == '=') force = true;
+        if (buffer->i == '>' && buffer->(i+1) == '=') force = true;
+        if (buffer->i == '<' && buffer->(i+1) == '=') force = true;
+        if (buffer->i == '#' && buffer->(i+1) == '#') force = true;
+
+        if (force) {
+            if (i > WORDSIZE && buffer->(i-1) ~= ' ') {
+                LTI_Insert(i++, ' '); altered = true;
+            }
+            if (buffer->(i+2) ~= ' ') {
+                LTI_Insert(i+2, ' '); i++; altered = true;
+            }
+            i = i + 1; continue;
+        }
+
+        if (buffer->i == '+') force = true;
+        if (buffer->i == '-') force = true;
+        if (buffer->i == '*') force = true;
+        if (buffer->i == '/') force = true;
+        if (buffer->i == '%') force = true;
+        if (buffer->i == '(') force = true;
+        if (buffer->i == ')') force = true;
+        if (buffer->i == '<' && buffer->(i-1) ~= ';') force = true;
+        if (buffer->i == '>') force = true;
+        if (buffer->i == ',') force = true;
+        if (buffer->i == '.') force = true;
+        if (buffer->i == '&') force = true;
+        if (buffer->i == '|') force = true;
+        if (buffer->i == '~') force = true;
+        if (buffer->i == '=') force = true;
+        if (force) {
+            if (i > WORDSIZE && buffer->(i-1) ~= ' ') {
+                LTI_Insert(i++, ' '); altered = true;
+            }
+            if (buffer->(i+1) ~= ' ') {
+                LTI_Insert(i+1, ' '); i++; altered = true;
+            }
+        }
+    }
+    for (i=WORDSIZE : i<GetKeyBufLength() + WORDSIZE : i++)
+        if (buffer->i == '~') { buffer->i = '['; altered = true; }
+    return altered;
+]; ! end of InfixCheckLineSpaced
+
+Array InfixRV_rvals --> 32;
+Array InfixRV_lvals --> 32;
+Array InfixRV_op --> 32;
+Array InfixRV_lop --> 32;
+Array InfixRV_rop --> 32;
+Array InfixRV_types --> 32;
+Array InfixRV_commas --> 32;
+
+[ InfixInBounds addr index n;
+    if (addr < #array__start || addr > #array__end)
+        rtrue;
+    for (n=#lowest_array_number : n<=#highest_array_number : n++) {
+        if (addr == Symb__Tab(INFIXTT_ARRAY, n)) {
+            if (temp__global3 == 1 or 3)
+                temp__global2=temp__global2*WORDSIZE+WORDSIZE-1;
+            if (index > temp__global2) {
+                print "Array index out of range";
+                rfalse;
+            }
+        }
+    }
+    rtrue;
+];
+
+[ InfixRvalue acc w i n flag base expecting_term max maxi lop rop lvalside
+              a b sysfun_f;
+
+    if (InfixCheckLineSpaced()) return GPR_REPARSE;
+
+!   w = wn; for (i=0 : i<10 : i++) { wn = w; InfixRvalueTerm(); print i, "^"; }
+!   wn = w;
+
+    expecting_term = true; base = 0;
+    do {
+        w = NextWordStopped();
+        if (expecting_term) {
+            switch (w) {
+              '-//':
+                InfixRV_rvals-->n = 'unary-'; InfixRV_types-->n = base + 8;
+              '[//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
+              '[[':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
+              '++':
+                InfixRV_rvals-->n = 'pre++'; InfixRV_types-->n = base + 9;
+              '--':
+                InfixRV_rvals-->n = 'pre--'; InfixRV_types-->n = base + 9;
+              '(//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base+100;
+              ')//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base-100;
+                if (base < 0) { wn--; flag = true; }
+              -1:
+                flag = true;
+              default:
+                wn--;
+                if (InfixRValueTerm() == 1) {
+                    InfixRV_rvals-->n = parsed_number;
+                    InfixRV_lvals-->n = infix_parsed_lvalue;
+                    InfixRV_types-->n = -1;
+                    expecting_term = false;
+                }
+                else flag = true;
+            }
+        }
+        else {
+            expecting_term = true;
+            switch (w) {
+              comma_word:
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base;
+              '=//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 1;
+              '&&', '||':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
+              '==', '[=', '>//', '>=', '<//', '<=', 'has', 'hasnt',
+              'in', 'notin', 'ofclass', 'provides':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 3;
+              'or':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 4;
+              '+//', '-//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 5;
+              '*//', '@{2f}//', '%//', '&//', '|//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
+              '->', '-->':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 7;
+              ']&', ']#':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 10;
+              THEN1__WD:
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 12;
+              '::':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = base + 13;
+              '(//':
+                InfixRV_rvals-->n = '(rcall';
+                InfixRV_types-->n = base + 11; base = base + 100;
+              ')//':
+                InfixRV_rvals-->n = w; InfixRV_types-->n = -3;
+                base = base - 100;
+                if (base < 0) { wn--; flag = true; }
+                expecting_term = false;
+              '++':
+                InfixRV_rvals-->n = 'post++'; InfixRV_types-->n = base + 9;
+                expecting_term = false;
+              '--':
+                InfixRV_rvals-->n = 'post--'; InfixRV_types-->n = base + 9;
+                expecting_term = false;
+              default:
+                flag = true;
+            }
+        }
+        n++;
+    } until (flag || n == 32);
+    if (base > 0) return -1;
+    n--; if (n == 0) return -1;
+    wn--;
+
+    for (i=0 : i<n : i++) {
+        acc = 0; if (InfixRV_types-->i ~= -3) acc = InfixRV_rvals-->i;
+        InfixRV_op-->i = acc;
+    }
+
+    for (::) {
+
+!       for (i=0 : i<n : i++) {
+!           if (InfixRV_types-->i == -1) print InfixRV_rvals-->i, " ";
+!           else if (InfixRV_types-->i == -3) print " # ";
+!           else if (InfixRV_types-->i == -2) print " ## ";
+!           else print (address) InfixRV_rvals-->i, "_", InfixRV_types-->i, " ";
+!       }
+!       new_line;
+
+        max = -2;
+        for (i=0 : i<n : i++) if (InfixRV_types-->i > max) {
+                            max = InfixRV_types-->i; maxi = i; }
+        if (max == -1) { parsed_number = InfixRV_rvals-->maxi; return 1; }
+
+        lop = maxi-1; rop = maxi+1;
+        while (lop >= 0 && InfixRV_types-->lop < -1) lop--;
+        while (rop < n && InfixRV_types-->rop < -1) rop++;
+        if (lop >= 0) InfixRV_lop-->maxi = InfixRV_rvals-->lop;
+        if (rop < n) InfixRV_rop-->maxi = InfixRV_rvals-->rop;
+        flag = false;
+        infix_term_type = INFIXTT_NUMBER;
+        switch (InfixRV_rvals-->maxi) {
+          comma_word:
+            acc = (InfixRV_rvals-->rop);
+          '=//', 'pre++', 'post++', 'pre--', 'post--':
+            lvalside = lop;
+            switch (InfixRV_rvals-->maxi) {
+              '=//':        acc = (InfixRV_rvals-->rop);
+              'pre++':      acc = (InfixRV_rvals-->rop) + 1; lvalside = rop;
+              'pre--':      acc = (InfixRV_rvals-->rop) - 1; lvalside = rop;
+              'post++':     acc = (InfixRV_rvals-->lop) + 1;
+              'post--':     acc = (InfixRV_rvals-->lop) - 1;
+            }
+            switch (InfixRV_op-->lvalside) {
+              THEN1__WD:
+                (InfixRV_lop-->lvalside).(InfixRV_rop-->lvalside) = acc;
+              '->':
+                if (InfixInBounds(InfixRV_lop-->lvalside, InfixRV_rop-->lvalside))
+                    (InfixRV_lop-->lvalside)->(InfixRV_rop-->lvalside) = acc;
+              '-->':
+                if (InfixInBounds(InfixRV_lop-->lvalside, WORDSIZE * InfixRV_rop-->lvalside))
+                    (InfixRV_lop-->lvalside)-->(InfixRV_rop-->lvalside) = acc;
+              default:
+                w = InfixRV_lvals-->lvalside; if (w == -1) return -1;
+                #Ifdef TARGET_ZCODE;
+                @storew #globals_array w acc;
+                #Ifnot;
+                @astore #globals_array w acc;
+                #Endif;
+            }
+            switch(InfixRV_rvals-->maxi) {
+              'post++': acc--;
+              'post--': acc++;
+            }
+          '(rcall':
+            sysfun_f = false;
+            switch (InfixRV_op-->lop) {
+              THEN1__WD:
+                a = InfixRV_lop-->lop; b = InfixRV_rop-->lop;
+              default:
+                a = InfixRV_rvals-->lop; b = call;
+                if (InfixRV_lvals-->lop == INFIXTT_SYSFUN)
+                    sysfun_f = true;
+            }
+            w = 0;
+            i = maxi + 1; base = 100;
+            if (InfixRV_types-->i == -1 && InfixRV_rvals-->i == ')//') {
+                if (sysfun_f) return -1;
+                acc = a.b();
+            }
+            else {
+                while (base > 0) {
+                    if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == ')//') base = base - 100;
+                    if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == '(//') base = base + 100;
+                    if (InfixRV_op-->i == '(rcall') base = base + 100;
+                    if (base == 100 && InfixRV_op-->i == comma_word) {
+                        InfixRV_commas-->(w++) = i;
+!                       print "Comma found at ", i, "^";
+                    }
+                    i++;
+                }
+!               print "Num args = ", w + 1, "^";
+!               for (i=0 : i<w : i++)
+!                   print "arg: ", InfixRV_lop-->(InfixRV_commas-->i), "^";
+!               print "arg: ", InfixRV_rvals-->rop, "^";
+                switch (w+1) {
+                  1:
+                    if (sysfun_f) {
+                        b = InfixRV_rvals-->rop;
+                        infix_term_type = INFIXTT_NAMEDOBJECT;
+                        switch(a) {
+                          'metaclass':
+                            acc = metaclass(b);
+                          'parent':
+                            acc = parent(b);
+                          'child':
+                            acc = child(b);
+                          'children':
+                            acc = children(b);
+                            infix_term_type = INFIXTT_NUMBER;
+                          'random':
+                            acc = random(b);
+                            infix_term_type = INFIXTT_NUMBER;
+                          'sibling':
+                            acc = sibling(b);
+                        }
+                    }
+                    else
+                        acc = a.b(InfixRV_rvals-->rop);
+                  2:
+                    if (sysfun_f) return -1;
+                    acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
+                              InfixRV_rvals-->rop);
+                  3:
+                    if (sysfun_f) return -1;
+                    acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
+                              InfixRV_lop-->(InfixRV_commas-->1),
+                              InfixRV_rvals-->rop);
+                  4:
+                    if (sysfun_f) return -1;
+                    acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
+                              InfixRV_lop-->(InfixRV_commas-->1),
+                              InfixRV_lop-->(InfixRV_commas-->2),
+                              InfixRV_rvals-->rop);
+                  5:
+                    if (sysfun_f) return -1;
+                    acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
+                              InfixRV_lop-->(InfixRV_commas-->1),
+                              InfixRV_lop-->(InfixRV_commas-->2),
+                              InfixRV_lop-->(InfixRV_commas-->3),
+                              InfixRV_rvals-->rop);
+                  default:
+                    return -1;
+                }
+            }
+          '+//':        acc = (InfixRV_rvals-->lop) + (InfixRV_rvals-->rop);
+          '-//':        acc = (InfixRV_rvals-->lop) - (InfixRV_rvals-->rop);
+          '*//':        acc = (InfixRV_rvals-->lop) * (InfixRV_rvals-->rop);
+          '@{2f}//':    acc = (InfixRV_rvals-->lop) / (InfixRV_rvals-->rop);
+          '%//':        acc = (InfixRV_rvals-->lop) % (InfixRV_rvals-->rop);
+          THEN1__WD:    acc = (InfixRV_rvals-->lop) . (InfixRV_rvals-->rop);
+          '->':         acc = (InfixRV_rvals-->lop) -> (InfixRV_rvals-->rop);
+          '-->':        acc = (InfixRV_rvals-->lop) --> (InfixRV_rvals-->rop);
+          ']&':         acc = (InfixRV_rvals-->lop) .& (InfixRV_rvals-->rop);
+          ']#':         acc = (InfixRV_rvals-->lop) .# (InfixRV_rvals-->rop);
+          '::':         acc = (InfixRV_rvals-->lop) :: (InfixRV_rvals-->rop);
+          '&//':        acc = (InfixRV_rvals-->lop) & (InfixRV_rvals-->rop);
+          '|//':        acc = (InfixRV_rvals-->lop) | (InfixRV_rvals-->rop);
+          '&&':         acc = (InfixRV_rvals-->lop) && (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '||':         acc = (InfixRV_rvals-->lop) || (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '<//':        acc = (InfixRV_rvals-->lop) < (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '<=':         acc = (InfixRV_rvals-->lop) <= (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '>//':        acc = (InfixRV_rvals-->lop) > (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '>=':         acc = (InfixRV_rvals-->lop) >= (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '==':         acc = (InfixRV_rvals-->lop) == (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '[=':         acc = (InfixRV_rvals-->lop) ~= (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          'has':        acc = (InfixRV_rvals-->lop) has (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          'hasnt':      acc = (InfixRV_rvals-->lop) hasnt (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          'in':         acc = (InfixRV_rvals-->lop) in (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          'notin':      acc = (InfixRV_rvals-->lop) notin (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          'provides':   acc = (InfixRV_rvals-->lop) provides (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          'ofclass':    acc = (InfixRV_rvals-->lop) ofclass (InfixRV_rvals-->rop);
+                        infix_term_type = INFIXTT_LOGICAL;
+          '[[':         acc = ~~ (InfixRV_rvals-->rop); flag = true;
+          '[//':        acc = ~ (InfixRV_rvals-->rop); flag = true;
+          'unary-':     acc = - (InfixRV_rvals-->rop); flag = true;
+        } ! end of switch(InfixRV_rvals-->maxi)
+        InfixRV_rvals-->maxi = acc;
+        InfixRV_types-->maxi = -1;
+        if (rop < n) InfixRV_types-->rop = -2;
+        if (flag == false && lop >= 0) InfixRV_types-->lop = -2;
+    } ! end of for (::)
+]; ! end of InfixRvalue
+
+! ------------------------------------------------------------------------
+
+[ InfixWelcomeSub;
+    print "; Welcome to the ~Infix~ debugger (1/040828), which makes the
+        following verbs available:^^
+        ~; <expression>~: evaluates this Inform expression: e.g.
+        ~; location~ will print the value of the variable ~location~,
+        ~; 3*5+1~ will print 16, ~; children(old cloth bag)~ will tell you
+        how many items are in it. (You can name objects either by their
+        names inside the source code, such as ~d_obj~, or by typing the
+        names by which the game's parser would normally know them, such
+        as ~floor~: the effect is the same.)^
+        Any expression is allowed except that you can't use double-quoted
+        strings of text: but you can send messages, call routines or
+        assign values to variables, properties and array entries.
+        ^   ~; score++~ is one way to get on in the world.
+        ^   ~; deadflag = true~ is one way to get out of it.
+        ^   ~; StopDaemon(nasty little dwarf)~ will keep you from being pestered.^
+        Conditions like ~; score>20~ are also allowed and print
+        either 1 (if true) or 0 (if false).^^";
+    print "~;examine <something>~ or ~;x <something>~ gives full details
+        of whatever it is. For instance, ~;x ##Take~ describes the Take
+        action; ~;x Class~ the class Class; ~;x 'drop'~ the dictionary
+        word ~drop~ and so on for numbers, routines, arrays and of course
+        objects.  ~;xo~ examines something as an object, so for instance
+        ~;x location~ tells you about the variable ~location~, but ~;xo
+        location~ tells you what object it refers to.^^";
+    print "~;give~, ~;remove~ and ~;move~ work like the corresponding
+        Inform statements.^^";
+    print "~;<~ causes an action: for instance, ~;< Eat cheese~.^^";
+    print "~;watch~ or ~;w~ can set a watch on various activities:
+        type just ~;w~ for details.^^";
+    print "~;inventory~ or ~;i~ describes the contents of this story file.^";
+];
+
+[ InfixEvalSub; InfixExamineP(true); ];
+
+[ InfixActionSub;
+    print "; <", (InfixPrintAction) infix_lvalue;
+    if (noun) print " (", (the) noun, ")";
+    if (second) print " (", (the) second, ")";
+    print ">^";
+    if (second) <<(infix_lvalue) noun second>>;
+    if (noun) <<(infix_lvalue) noun>>;
+    <<(infix_lvalue)>>;
+];
+
+[ InfixGiveSub f t;
+    print "; give (", (the) noun, ") ";
+    if (second < 0) { second = ~second; f=true; }
+    #Ifdef VN_1630;
+    t = NUM_ATTR_BYTES * 8;
+    #Ifnot;
+    t = 48;
+    #Endif; ! VN_
+    if (second < 0 || second >= t) "<No such attribute>";
+    if (f) print "@@126";
+    print (DebugAttribute) second;
+    #Ifdef TARGET_ZCODE;
+    if (f) @clear_attr noun second;
+    else   @set_attr noun second;
+    #Ifnot; ! TARGET_GLULX
+    t = second + 8;
+    if (f) @astorebit noun t 0; ! give noun ~second;
+    else   @astorebit noun t 1; ! give noun second;
+    #Endif; ! TARGET_
+    if (t);  ! quell unused n variable warning
+    new_line;
+];
+
+[ InfixMoveSub;
+    print "; move (", (the) noun, ") to (", (the) second, ")^";
+    move noun to second;
+];
+
+[ InfixRemoveSub;
+    print "; remove (", (the) noun, ")^";
+    remove noun;
+];
+
+[ InfixHex x y;
+    #Ifdef TARGET_ZCODE;
+    y = (x & $7f00) / $100;
+    if (x < 0) y = y + $80;
+    #Ifnot; ! TARGET_GLULX
+    y = (x & $7f000000) / $1000000;
+    if (x < 0) y = y + $80;
+    print (Infixhexdigit) y/$10, (Infixhexdigit) y;
+    y = x & $ff0000 / $10000;
+    print (Infixhexdigit) y/$10, (Infixhexdigit) y;
+    y = (x & $ff00) / $100;
+    #Endif; ! TARGET_
+    x = x & $ff;
+    print (Infixhexdigit) y/$10, (Infixhexdigit) y, (Infixhexdigit) x/$10, (Infixhexdigit) x;
+];
+
+[ Infixhexdigit x; x = x % $10; if (x < 10) print x; else print (char) 'a'+x-10; ];
+
+[ InfixExamineOSub;
+    infix_data1 = metaclass(noun);
+    #Ifdef TARGET_GLULX; ! different coding for Glulx
+    if (infix_data1 == Object) infix_data1 = 2;
+    if (infix_data1 == Class) infix_data1 = 1;
+    #Endif; ! TARGET_
+    infix_term_type = INFIXTT_CONSTANT;
+    InfixExamineP(false);
+];
+
+[ InfixExamineSSub;
+    infix_term_type = INFIXTT_STATICSTRING;
+    InfixExamineP(false);
+];
+
+[ InfixExamineSub;     InfixExamineP(false); ];
+
+[ InfixExamineP brief x a b w flag lines;
+    switch (infix_term_type) {
+      INFIXTT_NUMBER:
+        if (brief) "; == ", noun;
+        print "; The number ", noun, " == $", (InfixHex) noun;
+        if (noun >= 32 && noun < 127) print " == '", (char) noun, "'";
+        new_line;
+      INFIXTT_NAMEDOBJECT:
+        print "~", (name) noun, "~ (", noun, ")^"; if (brief) return;
+        <<ShowObj noun>>;
+      INFIXTT_CONSTANT:
+        if (brief) "; == ", noun;
+        switch (infix_data1 & 15) {
+            nothing:
+                print "; Constant ", (InfixPrintConstant) infix_parsed_lvalue,
+                " == ", noun, "^";
+            2: <<ShowObj noun>>;
+            1:
+                print "Class ", (name) noun, "^";
+                objectloop (a ofclass noun) {
+                    if (flag) print ", "; else print "Contains: ";
+                    print (name) a, " (", a, ")"; flag=true;
+                }
+                if (flag == false) "No object is of this class";
+        }
+        new_line;
+      INFIXTT_ATTRIBUTE:
+        if (brief) "; == ", noun;
+        if (noun >= 48 || noun < 0) "; No such attribute";
+        print "; Attribute ", (InfixPrintAttribute) noun,
+            " (numbered ", noun, ")^";
+        objectloop (x has noun) {
+            if (flag) print ", ";
+            else print "Each of these ~has ", (InfixPrintAttribute) noun, "~: ";
+            print (name) x, " (", x, ")"; flag = true;
+        }
+        if (flag == false) "No object ~has ", (InfixPrintAttribute) noun, "~";
+        new_line;
+      INFIXTT_PROPERTY:
+        if (brief) "; == ", noun;
+        print "; Property ", (property) noun, " (numbered ", noun, ")^";
+        objectloop (x provides noun) {
+            if (flag) print ", "; else print "Provided by: ";
+            print (name) x, " (", x, ")"; flag = true;
+        }
+        if (flag == false) "Which is not provided by any object";
+        new_line;
+      INFIXTT_DWORD:
+        if (brief) "; == ", noun;
+        if (noun == 0) "; This word is not in the dictionary";
+        a = noun->#dict_par1;
+        print "; Dictionary word '", (address) noun;
+        if (a & 4) print "//p";
+        print "' (address ", noun, ")";
+        if (a) {
+            print ": ";
+            if (a & 2)   print "meta ";
+            if (a & 1)   print "verb   ";
+            if (a & 8)   print "preposition   ";
+            if (a & 4)   print "pluralising ";
+            if (a & 128) print "noun ";
+        }
+        new_line;
+        if (a & 1) <<ShowVerb noun>>;
+      INFIXTT_ROUTINE:
+        if (brief) "; == ", noun;
+        print "; Routine ", (InfixPrintRoutine) infix_parsed_lvalue, " (number ",
+          infix_parsed_lvalue, ", packed address ", noun, ")^";
+      INFIXTT_GLOBAL:
+        if (brief) "; == ", noun;
+        print "; Global ", (InfixPrintGlobal) infix_parsed_lvalue, " == ", noun, "^";
+      INFIXTT_ARRAY:
+        if (brief) "; == ", noun;
+        print "; Array ", (InfixPrintArray) infix_parsed_lvalue, " ";
+        infix_data1 = infix_data1 % 16;
+        switch (infix_data1) {
+          0:    print "->"; a=0;
+          1:    print "-->"; a=0;
+          2:    print "string"; a=1;
+          3:    print "table"; a=1;
+          4:    print "buffer"; a=WORDSIZE;
+        }
+        print " ", infix_data2 + 1 - a, "^; == "; b = infix_data2;
+        for (w=b : w>=a : w--)
+            if (infix_data1 == 0 or 2 or 4) { if (noun->w) break; }
+            else { if (noun-->w) break; }
+        if (b-w < 5) w=b;
+        for (: x<=w : x++) {
+            if (infix_data1 == 0 or 2 or 4) print noun->x, " ";
+            else print noun-->x, " ";
+            if (x+1 == a) print ": ";
+            }
+        if (w < b) print "(then ", b-w, " zero entries)";
+        new_line;
+      INFIXTT_ACTION:
+        if (brief) "; == ", noun;
+        if (noun >= #lowest_fake_action_number && noun <= #highest_fake_action_number)
+           "; Fake action ", (InfixPrintFakeAction) noun,
+            " (numbered ", noun, ")^Is not generated by any grammar";
+        print "; Action ", (InfixPrintAction) noun,
+            " (numbered ", noun, ")^";
+        #Ifdef TARGET_ZCODE;
+        w = HDR_DICTIONARY-->0;
+        for (b=0 : b<(HDR_DICTIONARY-->0 + 5)-->0 : b++) {
+            w = HDR_DICTIONARY-->0 + 7 + b*9;
+            if ((w->#dict_par1) & 1) {
+                a = (HDR_STATICMEMORY-->0)-->($ff-(w->#dict_par2));
+                lines = a->0; a++;
+                for (: lines>0 : lines--) {
+                    a = UnpackGrammarLine(a);
+                    if (action_to_be == noun) {
+                        print "'", (address) w, "' "; DebugGrammarLine();
+                        new_line;
+                        flag = true;
+                    }
+                }
+            }
+        }
+        #Ifnot; ! TARGET_GLULX
+        for (b=0 : b < #dictionary_table-->0 : b++) {
+            w = #dictionary_table + WORDSIZE + b*(DICT_WORD_SIZE + 7);
+            if ((w->#dict_par1) & 1) {
+                a = (#grammar_table)-->(DictionaryWordToVerbNum(w) + 1);
+                lines = a->0; a++;
+                for (: lines>0 : lines--) {
+                    a = UnpackGrammarLine(a);
+                    if (action_to_be == noun) {
+                        print "'", (address) w, "' "; DebugGrammarLine();
+                        new_line;
+                        flag = true;
+                    }
+                }
+            }
+        }
+        #Endif; ! TARGET_
+
+        if (flag == 0) "Is not generated by any grammar";
+      INFIXTT_SYSFUN:
+        if (brief) "; == ", noun;
+        "; System function ~", (address) infix_parsed_lvalue, "~ has
+        not been overridden by any routine and so has its standard definition.";
+      INFIXTT_STATICSTRING:
+        if (brief) "; == ", noun;
+        if (metaclass(noun) ~= String) "; ", noun, " is not a string.";
+        print "~", (string) noun, "~^";
+      INFIXTT_LOGICAL:
+        if (noun == true) "; true"; if (noun == false) "; false";
+        "; ", noun;
+    }
+    new_line;
+]; ! end of InfixExamineP
+
+[ InfixDescribeWatchSub x y z s flag aflag;
+    print "; The Infix ~;watch~ verb allows you to set a watch on any named
+        routine(s) or objects: for instance ~;watch ScoreSub~ or
+        ~;watch silver bars~. You can also:
+        ^    ~;watch objects~: changes to attribute or property settings";
+    if (debug_flag & 8) print " (on)"; else print " (off)";
+
+    print ";^    ~;watch timers~: the running of timers and daemons each turn";
+    if (debug_flag & 4) print " (on)"; else print " (off)";
+
+    print ";^    ~;watch messages~: all messages sent";
+    if (debug_flag & 1) print " (on)"; else print " (off)";
+
+    print ";^    ~;watch actions~: all actions generated";
+    if (debug_flag & 2) print " (on)"; else print " (off)";
+
+    print ".^~~;watch~ can be abbreviated to ~;w~ and use ~off~ to stop
+        watching: for instance ~;w location off~.^";
+    aflag = debug_flag;
+    objectloop (x has infix__watching) flag = true; aflag = aflag || flag;
+    if (flag) print "The following objects are currently being watched: ";
+    flag = false;
+    objectloop (x has infix__watching) {
+        if (flag) print ", "; flag = true;
+        print (name) x, " (", x, ")";
+    }
+    if (flag) new_line;
+    s = (#highest_routine_number - #lowest_routine_number);
+    if (s%8 == 0) s=s/8; else s=s/8+1;
+    for (flag=false,x=0 : x<s : x++) if (#routine_flags_array->x) flag = true;
+    aflag = aflag || flag;
+    if (flag) print "The following routines are currently being watched: ";
+    for (x=0,flag=false : x<s : x++) {
+        for (y=1,z=0 : y<256 : z++,y=y*2) {
+            if ((#routine_flags_array->x) & y) {
+                if (flag) print ", "; flag = true;
+                print (InfixPrintRoutine)
+                    #lowest_routine_number + x*8 + z;
+            }
+        }
+    }
+    if (flag) new_line;
+    if (aflag == false) "At present, nothing is being watched.";
+];
+
+[ InfixWatchOnSub i j k l;
+    if (noun == 0) return InfixDescribeWatchSub();
+    if (infix_term_type == INFIXTT_ROUTINE) {
+        i = infix_parsed_lvalue/8;
+        for (j=0,k=1 : j<infix_parsed_lvalue%8 : j++) k=k*2;
+        l = #routine_flags_array->i;
+        l = l | k;
+        #Ifdef TARGET_ZCODE;
+        @storeb #routine_flags_array i l;
+        #Ifnot; ! TARGET_GLULX
+        @astoreb #routine_flags_array i l;
+        #Endif; ! TARGET_
+       "; Watching routine ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
+    }
+    if (metaclass(noun) == Object) {
+        give noun infix__watching;
+       "; Watching object ~", (name) noun, "~ (", noun, ").";
+    }
+    InfixDescribeWatchSub();
+  ];
+
+[ InfixWatchOffSub i j k l;
+    if (noun == 0) return InfixDescribeWatchSub();
+    if (infix_term_type == INFIXTT_ROUTINE) {
+        i = infix_parsed_lvalue/8;
+        for (j=0,k=1 : j<infix_parsed_lvalue%8 : j++) k=k*2;
+        l = #routine_flags_array->i;
+        l = l & (~k);
+        #Ifdef TARGET_ZCODE;
+        @storeb #routine_flags_array i l;
+        #Ifnot; ! TARGET_GLULX
+        @astoreb #routine_flags_array i l;
+        #Endif; ! TARGET
+       "; Not watching ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
+    }
+    if (metaclass(noun) == Object) {
+        #Ifdef TARGET_ZCODE;
+        @clear_attr noun infix__watching;
+        #Ifnot; ! TARGET_GLULX
+        @astorebit noun (infix__watching+8) 0;
+        #Endif; ! TARGET_
+       "; Not watching object ~", (name) noun, "~ (", noun, ").";
+    }
+    InfixDescribeWatchSub();
+];
+
+[ InfixList from to tab filter i flag;
+    print "^    ";
+    for (i=from : i<=to : i++)
+        if (tab-->(i-from)) {
+            flag = true;
+            if (tab == #array_names_array) {
+                Symb__Tab(INFIXTT_ARRAY, i);
+                flag = ~~(temp__global3 & 16);
+            }
+            if (tab == #routine_names_array) {
+                Symb__Tab(INFIXTT_ROUTINE,i);
+                flag = ~~(temp__global3 & 16);
+            }
+            if (tab == #constant_names_array) {
+                Symb__Tab(INFIXTT_CONSTANT,i);
+                flag = (~~(temp__global3 & 16)) && (temp__global3 % 16 == filter);
+            }
+            if (flag) print (string) tab-->(i-from), " ";
+        }
+        new_line;
+];
+
+[ InfixInvSub i;
+
+    print (string) Story, (string) Headline;
+    print "  ", (number) #highest_object_number - #lowest_object_number + 1,
+        " objects;^";
+
+    print "  non-library object-name constants:";
+    InfixList(#lowest_constant_number, #highest_constant_number, #constant_names_array, 2);
+
+    print "  ", (number) #highest_class_number - #lowest_class_number + 1, "  classes:^    ";
+    for (i=#lowest_class_number : i<=#highest_class_number : i++)
+        print (name) #class_objects_array-->i, " ";
+    new_line;
+
+    print "  non-library arrays:";
+    InfixList(#lowest_array_number, #highest_array_number, #array_names_array);
+
+    print "  non-library routines:";
+    InfixList(#lowest_routine_number, #highest_routine_number, #routine_names_array);
+
+    print "  non-library constants:";
+    InfixList(#lowest_constant_number, #highest_constant_number, #constant_names_array, 0);
+
+    print "  (common) properties:";
+    #Ifdef TARGET_ZCODE;
+    InfixList(#lowest_property_number, INDIV_PROP_START-1, #property_names_array);
+    #Ifnot; ! TARGET_GLULX
+    InfixList(#lowest_property_number, #identifiers_table-->1 - 1, #property_names_array);
+    #Endif; ! TARGET_
+
+    print "  (individual) properties:";
+    #Ifdef TARGET_ZCODE;
+    InfixList(INDIV_PROP_START, #highest_property_number, #property_names_array + 126);
+    #Ifnot; ! TARGET_GLULX
+    InfixList(INDIV_PROP_START, #highest_property_number, #identifiers_table-->2);
+    #Endif; ! TARGET_
+
+    print "  attributes:";
+    InfixList(#lowest_attribute_number, #highest_attribute_number, #attribute_names_array);
+
+    if (true) return;
+
+    print "  variables:";
+    InfixList(#lowest_global_number, #highest_global_number, #global_names_array);
+
+    print "  actions:";
+    InfixList(#lowest_action_number, #highest_action_number, #action_names_array);
+
+    print "  fake actions:";
+    InfixList(#lowest_fake_action_number, #highest_fake_action_number, #fake_action_names_array);
+];
+
+Verb meta ';i' ';inv' ';inventory'
+    *                                           -> InfixInv;
+Verb meta ';x' ';examine'
+    * InfixRvalue                               -> InfixExamine;
+Verb meta ';xo' ';examineo'
+    * InfixRvalue                               -> InfixExamineO;
+Verb meta ';xs' ';examines'
+    * InfixRvalue                               -> InfixExamineS;
+Verb meta ';<'
+    * InfixActionToken                          -> InfixAction
+    * InfixActionToken InfixRvalue              -> InfixAction
+    * InfixActionToken InfixRvalue InfixRvalue  -> InfixAction;
+Verb meta ';//'
+    *                                           -> InfixWelcome
+    * InfixRvalue                               -> InfixEval;
+Verb meta ';give'
+    * InfixRvalue InfixRvalue                   -> InfixGive;
+Verb meta ';move'
+    * InfixRvalue "to" InfixRvalue              -> InfixMove;
+Verb meta ';remove'
+    * InfixRvalue                               -> InfixRemove;
+Verb meta ';watch' ';w'
+    *                                           -> InfixWatchOn
+    * "timers"/"daemons"                        -> TimersOn
+    * "timers"/"daemons" "off"                  -> TimersOff
+    * "actions"                                 -> ActionsOn
+    * "actions" "off"                           -> ActionsOff
+    * "messages"                                -> RoutinesOn
+    * "messages" "off"                          -> RoutinesOff
+    * "objects"                                 -> ChangesOn
+    * "objects" "off"                           -> ChangesOff
+    * InfixRvalueTerm                           -> InfixWatchOn
+    * InfixRvalueTerm "off"                     -> InfixWatchOff;
+
+#Endif; ! DEBUG
+
+! ==============================================================================
index 2525bc9c08ef5adc17066ea68ce668ac34a63570..34055eb174b08d04c01666724b76451c669bdb2e 100644 (file)
--- a/linklpa.h
+++ b/linklpa.h
@@ -1,9 +1,9 @@
 ! ==============================================================================
 !   LINKLPA:  Link declarations of common properties and attributes.
 !
-!   Supplied for use with Inform 6 -- Release 6.12.3 -- Serial number 190320
+!   Supplied for use with Inform 6 -- Release 6.12.4pre -- Serial number 200528
 !
-!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2019
+!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2020
 !
 !   This file is free software: you can redistribute it and/or modify
 !   it under the terms of the GNU Affero General Public License as
@@ -19,7 +19,7 @@
 !   License along with this program. If not, see
 !   https://gnu.org/licenses/
 !
-!   This file is automatically Included in your game file by "parser".
+!   This file is automatically Included in your game file by "Parser".
 ! ==============================================================================
 
 System_file;
@@ -42,13 +42,6 @@ Constant WORD_HIGHBIT = $80000000;
 ! ------------------------------------------------------------------------------
 
 Attribute animate;
-#Ifdef USE_MODULES;
-    #Iffalse (animate == 0);
-    Message error "Please move your Attribute declarations after the Include ~Parser~ line:
-                   otherwise it will be impossible to USE_MODULES";
-    #Endif;
-#Endif;
-
 Attribute absent;       Attribute non_floating alias absent;
 Attribute clothing;
 Attribute concealed;
@@ -100,13 +93,6 @@ Property d_to;
 Property in_to;
 Property out_to;
 
-#Ifdef USE_MODULES;
-    #Iffalse (7 >= n_to);
-    Message error "Please move your Property declarations after the Include ~Parser~ line:
-                   otherwise it will be impossible to USE_MODULES";
-    #Endif;
-#Endif;
-
 Property door_to;
 Property with_key;
 Property door_dir;
index e7165ec830bc8a1711ef86d42a3d53798a6bf7e9..c5b184a879a3de75e295ae521b4be04c138ccbe7 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -1,9 +1,9 @@
 ! ==============================================================================
 !   PARSER:  Front end to parser.
 !
-!   Supplied for use with Inform 6 -- Release 6.12.3 -- Serial number 190320
+!   Supplied for use with Inform 6 -- Release 6.12.4 -- Serial number 200718
 !
-!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2019
+!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2020
 !
 !   This file is free software: you can redistribute it and/or modify
 !   it under the terms of the GNU Affero General Public License as
 !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 !   Affero General Public License for more details.
 !
-!   You should have received a copy of the GNU Affero General Public
-!   License along with this program. If not, see
-!   https://gnu.org/licenses/
-!
 !   In your game file, Include three library files in this order:
 !       Include "parser";
-!       Include "verblib";
+!       Include "berblib";
 !       Include "grammar";
 !
 ! ------------------------------------------------------------------------------
@@ -73,10 +69,7 @@ System_file;
 Message fatalerror "*** Library 6.12.3 needs Inform v6.33 or later to work ***";
 #Endif; ! VN_
 
-Constant LibSerial       "190320";
-Constant LibRelease      "6.12.3pre";
-Constant LIBRARY_VERSION  612;
-Constant Grammar__Version 2;
+Include "version";
 
 Constant BEFORE_PARSER   10;
 Constant AFTER_PARSER    20;
@@ -164,6 +157,7 @@ Fake_Action TheSame;
 Fake_Action PluralFound;
 Fake_Action ListMiscellany;
 Fake_Action Miscellany;
+Fake_Action RunTimeError;
 Fake_Action Prompt;
 Fake_Action NotUnderstood;
 Fake_Action Going;
@@ -326,6 +320,10 @@ Global inventory_stage = 1;         ! 1 or 2 according to the context in which
                                     ! "invent" routines of objects are called
 Global inventory_style;             ! List-writer style currently used while
                                     ! printing inventories
+
+Global objects_style;               ! List-writer style currently used while
+Global places_style;                ! printing objects handled or places visited
+
 ! ------------------------------------------------------------------------------
 !   Menus and printing
 ! ------------------------------------------------------------------------------
@@ -376,6 +374,20 @@ Constant CLR_WHITE   9;
 Constant CLR_PURPLE  7;
 Constant CLR_AZURE   8;
 
+#Ifdef TARGET_GLULX;
+Array GlulxColourValues
+    --> (-2)
+        (-1)
+        $000000
+        $EF0000
+        $00D600
+        $EFEF00
+        $006BB5
+        $FF00FF
+        $00EFEF
+        $FFFFFF;
+#Endif; ! TARGET_GLULX
+
 Constant WIN_ALL     0;
 Constant WIN_STATUS  1;
 Constant WIN_MAIN    2;
@@ -804,7 +816,6 @@ Object  thedark "(darkness object)"
 
 ! If you want to use the third-person of the narrative voice, you will
 ! need to replace this selfobj with your own.
-
 Class  SelfClass
   with name ',a' ',b' ',c' ',d' ',e',
         short_name  YOURSELF__TX,
@@ -815,7 +826,7 @@ Class  SelfClass
         each_turn NULL,
         time_out NULL,
         describe NULL,
-        article "the",
+        article THE__TX,
         add_to_scope 0,
         capacity 100,
         parse_name 0,
@@ -1444,7 +1455,7 @@ Object  InformParser "(Inform Parser)"
     w2 = a_table-->(3*oops_from - 1); ! Length of word to go
     #Endif; ! TARGET_
 
-#IfDef OOPS_CHECK;
+#Ifdef OOPS_CHECK;
     print "[~";
     for (i=0 : i<w2 : i++) for (i=0 : i<w2 : i++) print (char)a_buffer->(i+w);
     print "~ --> ~";
@@ -1467,12 +1478,12 @@ Object  InformParser "(Inform Parser)"
 
     for (i=0 : i<x2 : i++) {
         a_buffer->(i+w) = buffer2->(i+x1);
-#IfDef OOPS_CHECK;
+#Ifdef OOPS_CHECK;
         print (char) buffer2->(i+x1);
 #Endif;
     }
 
-#IfDef OOPS_CHECK;
+#Ifdef OOPS_CHECK;
         print "~]^^";
 #Endif;
 
@@ -1743,14 +1754,14 @@ Object  InformParser "(Inform Parser)"
 
     if (verb_word == 0 || ((verb_word->#dict_par1) & DICT_VERB) == 0) {
 
-        ! So is the first word an object contained in the special object "compass"
+        ! So is the first word an object contained in the special object "Compass"
         ! (i.e., a direction)?  This needs use of NounDomain, a routine which
         ! does the object matching, returning the object number, or 0 if none found,
         ! or REPARSE_CODE if it has restructured the parse table so the whole parse
         ! must be begun again...
 
         wn = verb_wordnum; indef_mode = false; token_filter = 0;
-        l = NounDomain(compass, 0, NOUN_TOKEN);
+        l = NounDomain(Compass, 0, NOUN_TOKEN);
         if (l == REPARSE_CODE) jump ReParse;
 
         ! If it is a direction, send back the results:
@@ -2370,7 +2381,13 @@ Object  InformParser "(Inform Parser)"
     if (etype == NUMBER_PE)     L__M(##Miscellany, 29);
     if (etype == CANTSEE_PE) {  L__M(##Miscellany, 30); oops_from=saved_oops;}
     if (etype == TOOLIT_PE)     L__M(##Miscellany, 31);
-    if (etype == NOTHELD_PE) {  L__M(##Miscellany, 32, not_holding); oops_from=saved_oops; }
+    if (etype == NOTHELD_PE) {
+               if (parent(noun) has container)
+                       L__M(##Take, 14, noun);
+               else
+                       L__M(##Miscellany, 32, not_holding);
+               oops_from=saved_oops;
+    }
     if (etype == MULTI_PE)      L__M(##Miscellany, 33);
     if (etype == MMULTI_PE)     L__M(##Miscellany, 34);
     if (etype == VAGUE_PE)      L__M(##Miscellany, 35, pronoun_word);
@@ -2844,7 +2861,7 @@ Constant UNLIT_BIT  =  32;
         #Endif; ! DEBUG
         l = NounDomain(actors_location, actor, token);
         if (l == REPARSE_CODE) return l;                  ! Reparse after Q&A
-        if (l ~= nothing && l ~= 1 && l notin actor && token == MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN) {
+        if ((metaclass(l) == Class || metaclass(l) == Object) && l ~= 1 && l notin actor && token == MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN) {
            if (ImplicitTake(l)) {
                etype = NOTHELD_PE;
                jump FailToken;
@@ -2865,7 +2882,7 @@ Constant UNLIT_BIT  =  32;
                 wn = desc_wn;
                 jump TryAgain2;
             }
-            if (etype ~=TOOFEW_PE && (multiflag || etype ~= MULTI_PE))
+            if ((etype ~=TOOFEW_PE && etype ~= VAGUE_PE) && (multiflag || etype ~= MULTI_PE))
                 etype = CantSee();
             jump FailToken;
         } ! Choose best error
@@ -3054,6 +3071,7 @@ Constant UNLIT_BIT  =  32;
     ! allowing singulars (so that words like "six" are not swallowed up as
     ! Descriptors)
 
+    noun = l;  ! Allow the noun to be mentioned by the *_PE error messages.
     if (allow_plurals && indef_guess_p == 1) {
         #Ifdef DEBUG;
         if (parser_trace >= 4) print "   [Retrying singulars after failure ", etype, "]^";
@@ -3162,7 +3180,7 @@ Constant UNLIT_BIT  =  32;
 
     number_of_classes = 0;
 
-    if (match_length == 0 && indef_mode && indef_wanted ~= 100)
+    if (match_length == 0 && indef_mode && indef_wanted > 0 && indef_wanted < 100)
         number_matched = 0;  ! ask question for 'take three'
     if (number_matched == 1) i = match_list-->0;
     if (number_matched > 1) {
@@ -3775,9 +3793,9 @@ Constant SCORE__DIVISOR     = 20;
                 if (its_owner == actors_location) its_score = its_score + l_s;
                 else {
                     #Ifdef TRADITIONAL_TAKE_ALL;
-                    if (its_owner ~= compass) its_score = its_score + SCORE__NOTCOMPASS;
+                    if (its_owner ~= Compass) its_score = its_score + SCORE__NOTCOMPASS;
                     #Ifnot;
-                    if (its_owner ~= compass)
+                    if (its_owner ~= Compass)
                         if (take_all_rule && its_owner &&
                             its_owner has static or scenery &&
                               (its_owner has supporter ||
@@ -3871,7 +3889,7 @@ Constant SCORE__DIVISOR     = 20;
 [ Identical o1 o2 p1 p2 n1 n2 i j flag;
     if (o1 == o2) rtrue;  ! This should never happen, but to be on the safe side
     if (o1 == 0 || o2 == 0) rfalse;  ! Similarly
-    if (parent(o1) == compass || parent(o2) == compass) rfalse; ! Saves time
+    if (parent(o1) == Compass || parent(o2) == Compass) rfalse; ! Saves time
 
     !  What complicates things is that o1 or o2 might have a parsing routine,
     !  so the parser can't know from here whether they are or aren't the same.
@@ -3959,7 +3977,7 @@ Constant SCORE__DIVISOR     = 20;
         if (i >= REPARSE_CODE)
             print (address) No__Dword(i-REPARSE_CODE);
         else
-            if (i in compass && LanguageVerbLikesAdverb(verb_word))
+            if (i in Compass && LanguageVerbLikesAdverb(verb_word))
                 LanguageDirection (i.door_dir); ! the direction name as adverb
             else
                 print (the) i;
@@ -4261,7 +4279,7 @@ Constant SCORE__DIVISOR     = 20;
 
     if (indef_mode==0 && domain==actors_location
         && scope_reason==PARSING_REASON && context~=CREATURE_TOKEN)
-            ScopeWithin(compass);
+            ScopeWithin(Compass);
 
     ! Look through the objects in the domain, avoiding "objectloop" in case
     ! movements occur, e.g. when trying each_turn.
@@ -4789,7 +4807,6 @@ Constant MAX_DECIMAL_BASE 214748364;
           default:    return GPR_FAIL;
         }
         if (digit >= base) return GPR_FAIL;
-        digit_count++;
         switch (base) {
           16:     if (digit_count > 2*WORDSIZE)  return GPR_FAIL;
           2:      if (digit_count > 8*WORDSIZE)  return GPR_FAIL;
@@ -5145,7 +5162,7 @@ Object  InformLibrary "(Inform Library)"
                     }
                     l = multiple_object-->k;
                     PronounNotice(l);
-                    print (name) l, (string) COLON__TX;
+                    print (name) l, (string) COLON__TX, " ";
                     if (inp1 == 0) {
                         inp1 = l;
                         switch (self.actor_act(actor, action, l, second)) {
@@ -5315,13 +5332,17 @@ Object  InformLibrary "(Inform Library)"
     if (lightflag == 0) location = thedark;
 
     if (j ~= 2) Banner();
-#ifndef NOINITIAL_LOOK;
+#Ifndef NOINITIAL_LOOK;
     <Look>;
-#endif;
+#Endif;
     before_first_turn = false;
 ];
 
 [ GameEpilogue;
+    if (score ~= last_score) {
+       if (notify_mode == 1) NotifyTheScore();
+       last_score = score;
+    }
     print "^^    ";
     #Ifdef TARGET_ZCODE;
     #IfV5; style bold; #Endif; ! V5
@@ -6287,46 +6308,36 @@ Object  InformLibrary "(Inform Library)"
 ];
 
 #Ifdef COLOUR;
-[ SetColour f b window doclear  i fwd bwd swin;
-    if (window) swin = 5-window; ! 4 for TextGrid, 3 for TextBuffer
-
-    if (clr_on) {
-        fwd = MakeColourWord(f);
-        bwd = MakeColourWord(b);
-        for (i=0 : i<=10: i++) {
-            if (f == CLR_DEFAULT || b == CLR_DEFAULT) { ! remove style hints
-                glk_stylehint_clear(swin, i, 7);
-                glk_stylehint_clear(swin, i, 8);
-            }
-            else {
-                glk_stylehint_set(swin, i, 7, fwd);
-                glk_stylehint_set(swin, i, 8, bwd);
-            }
-        }
-        ! Now re-open the windows to apply the hints
-        if (gg_statuswin) glk_window_close(gg_statuswin, 0);
-
-        if (doclear || ( window ~= 1 && (clr_fg ~= f || clr_bg ~= b) ) ) {
-            glk_window_close(gg_mainwin, 0);
-            gg_mainwin = glk_window_open(0, 0, 0, 3, GG_MAINWIN_ROCK);
-            if (gg_scriptstr ~= 0)
-                glk_window_set_echo_stream(gg_mainwin, gg_scriptstr);
-        }
-
-        gg_statuswin = glk_window_open($12, gg_statuswin_cursize,
-           4, GG_STATUSWIN_ROCK);
-        if (statuswin_current && gg_statuswin)
-            MoveCursor(); else MainWindow();
+[ SetColour f b window;
+    if (window == 0) {  ! if setting both together, set reverse
+        clr_fgstatus = b;
+        clr_bgstatus = f;
     }
-
-    if (window ~= 2) {
+    if (window == 1) {
         clr_fgstatus = f;
         clr_bgstatus = b;
     }
-    if (window ~= 1) {
+    if (window == 0 or 2) {
         clr_fg = f;
         clr_bg = b;
     }
+    if (clr_on) {
+        if (glk_gestalt(gestalt_GarglkText, 0)) {
+            if (f >= 0 && f < 10) {
+                f = GlulxColourValues-->f;
+            }
+            else {
+                f = -2;
+            }
+            if (b >= 0 && b < 10) {
+                b = GlulxColourValues-->b;
+            }
+            else {
+                b = -2;
+            }
+            garglk_set_zcolors(f, b);
+        }
+    }
 ];
 #Endif; ! COLOUR
 #Endif; ! TARGET_
@@ -6918,7 +6929,7 @@ Array StorageForShortName -> WORDSIZE + SHORTNAMEBUF_LEN;
     PrintCapitalised(a, b, false, true, true);
 ];
 
-[ CapitRule str no_caps;
+[ Cap str no_caps;
     if (no_caps) print (string) str;
     else         PrintCapitalised(str,0,true);
 ];
@@ -6927,7 +6938,7 @@ Array StorageForShortName -> WORDSIZE + SHORTNAMEBUF_LEN;
     if (o provides articles) {
         artval=(o.&articles)-->(acode+short_name_case*LanguageCases);
         if (capitalise)
-            print (CapitRule) artval;
+            print (Cap) artval;
         else
             print (string) artval;
         if (pluralise) return;
@@ -6977,7 +6988,7 @@ Array StorageForShortName -> WORDSIZE + SHORTNAMEBUF_LEN;
     }
     #Endif; ! TARGET_
 
-    CapitRule (artform-->acode, ~~capitalise); ! print article
+    Cap (artform-->acode, ~~capitalise); ! print article
     if (pluralise) return;
     print (PSN__) o;
 ];
@@ -7252,6 +7263,8 @@ Object  LibraryExtensions "(Library Extensions)"
         ext_printverb           0,  ! [C2/R2]
         ext_timepasses          0,  ! [C2/R1]
         ext_unknownverb         0,  ! [C2/R2]
+        ext_aftersave           0,  ! [C2/R2]
+        ext_afterrestore        0,  ! [C2/R2]
         !                             [C1] = Called in all cases
         !                             [C2] = Called if EP is undefined, or returns false
         !                             [C3] = called if EP is undefined, or returns -1
index eb09529243927777b5de1deadd9b6223ce354f28..b6868b15df5bf31133d6c84e7a9fe6a21760f7a5 100644 (file)
@@ -1,4 +1,4 @@
-This directory contains version 6.12.3 of the Inform 6 standard
+This directory contains version 6.12.4 of the Inform 6 standard
 library. It has been modified slightly to not print out the version of 
 Inform and the version of the standard library in use in the game's 
 banner.
index e98bb22c1276f21878e1d68da362dd36eee7dd9e..c5e73a896628f778739d88604838a7c9ed0bdd9b 100644 (file)
--- a/verblib.h
+++ b/verblib.h
@@ -1,9 +1,9 @@
 ! ==============================================================================
 !   VERBLIB:  Front end to standard verbs library.
 !
-!   Supplied for use with Inform 6 -- Release 6.12.3 -- Serial number 190320
+!   Supplied for use with Inform 6 -- Release 6.12.4 -- Serial number 200718
 !
-!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2019
+!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2020
 !
 !   This file is free software: you can redistribute it and/or modify
 !   it under the terms of the GNU Affero General Public License as
@@ -54,7 +54,11 @@ Object LibraryMessages;
 
 #Ifndef NO_PLACES;
 [ ObjectsSub; Objects1Sub(); ];
+[ ObjectsTallSub; Objects1TallSub(); ];
+[ ObjectsWideSub; Objects1WideSub(); ];
 [ PlacesSub;  Places1Sub(); ];
+[ PlacesTallSub; Places1TallSub(); ];
+[ PlacesWideSub; Places1WideSub(); ];
 #Endif; ! NO_PLACES
 
 ! ------------------------------------------------------------------------------
@@ -79,16 +83,21 @@ Object LibraryMessages;
         print "^", (string) Story;
         glk_set_style(style_Normal);
         #Endif; ! TARGET_
-    }
+    } else
+        new_line;
+
     if (Headline) print (string) Headline;
+    else
+        new_line;
+
     #Ifdef TARGET_ZCODE;
-    print "Release ", (HDR_GAMERELEASE-->0) & $03ff, " / Serial number ";
+    print (string) RELEASE__TX, (HDR_GAMERELEASE-->0) & $03ff, " / ", (string) SERNUM__TX;
     for (i=0 : i<6 : i++) print (char) HDR_GAMESERIAL->i;
     #Ifnot; ! TARGET_GLULX;
-    print "Release ";
+    print (string) RELEASE__TX;
     @aloads ROM_GAMERELEASE 0 i;
     print i;
-    print " / Serial number ";
+    print " / ", (string) SERNUM__TX;
     for (i=0 : i<6 : i++) print (char) ROM_GAMESERIAL->i;
     #Endif; ! TARGET_
     new_line;
@@ -104,7 +113,7 @@ Object LibraryMessages;
     #Ifdef TARGET_ZCODE;
     ix = 0; ! shut up compiler warning
     if (standard_interpreter > 0) {
-        print "Standard interpreter ", standard_interpreter/256, ".", standard_interpreter%256,
+        print (string) STDTERP__TX, standard_interpreter/256, ".", standard_interpreter%256,
             " (", HDR_TERPNUMBER->0;
         #Iftrue (#version_number == 6);
         print (char) '.', HDR_TERPVERSION->0;
@@ -114,7 +123,7 @@ Object LibraryMessages;
         print ") / ";
         }
     else {
-        print "Interpreter ", HDR_TERPNUMBER->0, " Version ";
+        print (string) TERP__TX, HDR_TERPNUMBER->0, (string) VER__TX;
         #Iftrue (#version_number == 6);
         print HDR_TERPVERSION->0;
         #Ifnot;
@@ -125,12 +134,12 @@ Object LibraryMessages;
 
     #Ifnot; ! TARGET_GLULX;
     @gestalt 1 0 ix;
-    print "Interpreter version ", ix / $10000, ".", (ix & $FF00) / $100,
+    print (string) TERPVER__TX, ix / $10000, ".", (ix & $FF00) / $100,
       ".", ix & $FF, " / ";
     @gestalt 0 0 ix;
-    print "VM ", ix / $10000, ".", (ix & $FF00) / $100, ".", ix & $FF, " / ";
+    print (string) VM__TX, ix / $10000, ".", (ix & $FF00) / $100, ".", ix & $FF, " / ";
     #Endif; ! TARGET_;
-    print "Library serial number ", (string) LibSerial, "^";
+    print (string) LIBSER__TX, (string) LibSerial, "^";
     #Ifdef LanguageVersion;
     print (string) LanguageVersion, "^";
     #Endif; ! LanguageVersion
@@ -141,36 +150,13 @@ Object LibraryMessages;
     #Ifdef LanguageError;
     LanguageError(n, p1, p2);
     #Ifnot;
+
+    print "** ", (string) LIBERROR__TX, n, " (", p1, ", ", p2, ") **";
     #Ifdef DEBUG;
-    print "** Library error ", n, " (", p1, ", ", p2, ") **^** ";
-    switch (n) {
-      1:    print "preposition not found (this should not occur)";
-      2:    print "Property value not routine or string: ~", (property) p2, "~ of ~", (name) p1,
-                  "~ (", p1, ")";
-      3:    print "Entry in property list not routine or string: ~", (property) p2, "~ list of ~",
-                  (name) p1, "~ (", p1, ")";
-      4:    print "Too many timers/daemons are active simultaneously.
-                  The limit is the library constant MAX_TIMERS
-                  (currently ", MAX_TIMERS, ") and should be increased";
-      5:    print "Object ~", (name) p1, "~ has no ~", (property) p2, "~ property";
-      7:    print "The object ~", (name) p1, "~ can only be used as a player object if it has
-                  the ~number~ property";
-      8:    print "Attempt to take random entry from an empty table array";
-      9:    print p1, " is not a valid direction property number";
-      10:   print "The player-object is outside the object tree";
-      11:   print "The room ~", (name) p1, "~ has no ~", (property) p2, "~ property";
-      12:   print "Tried to set a non-existent pronoun using SetPronoun";
-      13:   print "A 'topic' token can only be followed by a preposition";
-      14:   print "Overflowed buffer limit of ", p1, " using '@@64output_stream 3' ", (string) p2;
-      15:   print "LoopWithinObject broken because the object ", (name) p1, " was moved while the loop passed through it.";
-      16:   print "Attempt to use illegal narrative_voice of ", p1, ".";
-      default:
-            print "(unexplained)";
-    }
-    " **";
-    #Ifnot;
-    "** Library error ", n, " (", p1, ", ", p2, ") **";
-    #Endif; ! DEBUG
+    L__M(##RunTimeError, n, p1, p2);
+    #Endif;
+    print "^";
+
     #Endif; ! LanguageError
 ];
 
@@ -347,8 +333,8 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     if (c_style & ISARE_BIT) {
         if (j == 1 && o hasnt pluralname) Tense(IS__TX, WAS__TX);
         else                              Tense(ARE__TX, WERE__TX);
-        if (c_style & NEWLINE_BIT)   print ":^";
-        else                              print (char) ' ';
+        if (c_style & NEWLINE_BIT)   print (string) COLON__TX, "^";
+        else                         print (char) ' ';
         c_style = c_style - ISARE_BIT;
     }
 
@@ -414,7 +400,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
                     EnglishNumber(q); print " ";
                     print (string) j.list_together;
                     if (c_style & ENGLISH_BIT) print " (";
-                    if (c_style & INDENT_BIT)  print ":^";
+                    if (c_style & INDENT_BIT)  print (string) COLON__TX, "^";
                 }
                 q = c_style;
                 if (k2 ~= String) {
@@ -520,7 +506,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
                     EnglishNumber(l); print " ";
                     print (string) j.list_together;
                     if (c_style & ENGLISH_BIT) print " (";
-                    if (c_style & INDENT_BIT) print ":^";
+                    if (c_style & INDENT_BIT) print (string) COLON__TX, "^";
                 }
                 q = c_style;
                 if (k ~= String) {
@@ -1140,7 +1126,10 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     restore Rmaybe;
     return L__M(##Restore, 1);
   .RMaybe;
-    L__M(##Restore, 2);
+    if (AfterRestore() == 1)
+        LibraryExtensions.RunAll(ext_afterrestore);
+    else
+        L__M(##Restore, 2);
 ];
 
 [ SaveSub flag;
@@ -1148,16 +1137,26 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     @save -> flag;
     switch (flag) {
       0: L__M(##Save, 1);
-      1: L__M(##Save, 2);
+      1:
+         if (AfterSave() == 1)
+             LibraryExtensions.RunAll(ext_aftersave);
+         else
+             L__M(##Save, 2);
       2:
         RestoreColours();
-        L__M(##Restore, 2);
+        if (AfterRestore() == 1)
+            LibraryExtensions.RunAll(ext_afterrestore);
+        else
+            L__M(##Restore, 2);
     }
     #Ifnot;
     save Smaybe;
     return L__M(##Save, 1);
   .SMaybe;
-    L__M(##Save, 2);
+    if (AfterSave() == 1)
+        LibraryExtensions.RunAll(ext_aftersave);
+    else
+        L__M(##Save, 2);
     #Endif; ! V5
 ];
 
@@ -1231,7 +1230,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     L__M(##Restore, 1);
 ];
 
-[ SaveSub res fref;
+[ SaveSub res fref retval;
     fref = glk_fileref_create_by_prompt($01, $01, 0);
     if (fref == 0) jump SFailed;
     gg_savestr = glk_stream_open_file(fref, $01, GG_SAVESTR_ROCK);
@@ -1246,11 +1245,20 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
         GGRecoverObjects();
         glk_stream_close(gg_savestr, 0);
         gg_savestr = 0;
-        return L__M(##Restore, 2);
+        if (AfterRestore() == 1)
+            return LibraryExtensions.RunAll(ext_afterrestore);
+        else
+            return L__M(##Restore, 2);
+        return retval;
     }
     glk_stream_close(gg_savestr, 0);
     gg_savestr = 0;
-    if (res == 0) return L__M(##Save, 2);
+    if (res == 0) {
+        if (AfterSave() == 1)
+            return LibraryExtensions.RunAll(ext_aftersave);
+        else
+            return L__M(##Save, 2);
+    }
   .SFailed;
     L__M(##Save, 1);
 ];
@@ -1271,7 +1279,6 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     if (gg_scriptstr == 0) jump S1Failed;
     glk_window_set_echo_stream(gg_mainwin, gg_scriptstr);
     L__M(##ScriptOn, 2);
-    VersionSub();
     return;
   .S1Failed;
     L__M(##ScriptOn, 3);
@@ -1326,21 +1333,69 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
 [ NotifyOnSub;  notify_mode = true; L__M(##NotifyOn);  ];
 [ NotifyOffSub; notify_mode = false; L__M(##NotifyOff); ];
 
+[ Places1TallSub;
+       places_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT;
+       <Places>;
+];
+
+[ Places1WideSub;
+       places_style = ENGLISH_BIT+FULLINV_BIT;
+       <Places>;
+];
+
 [ Places1Sub i j k;
-    L__M(##Places, 1);
     objectloop (i has visited) j++;
+    if (j == 0)
+        return L__M(##Places, 3);
+
+    L__M(##Places, 1);
+    if (places_style & INDENT_BIT) print (string) COLON__TX, "^";
+    else print " ";
+
     objectloop (i has visited) {
+        if (places_style & INDENT_BIT) Print__Spaces(2);
         print (name) i; k++;
-        if (k == j) return L__M(##Places, 2);
-        if (k == j-1) print (SerialComma) j, (string) AND__TX;
-        else          print (string) COMMA__TX;
+
+        if (places_style & INDENT_BIT)
+            new_line;
+        else {
+            if (k == j)
+                return L__M(##Places, 2);
+            if (k == j-1)
+                print (SerialComma) j, (string) AND__TX;
+            else
+                print (string) COMMA__TX;
+        }
     }
 ];
 
-[ Objects1Sub i j f;
+[ Objects1TallSub;
+       objects_style = NEWLINE_BIT+INDENT_BIT+FULLINV_BIT;
+       <Objects>;
+];
+
+[ Objects1WideSub;
+       objects_style = ENGLISH_BIT+FULLINV_BIT;
+       <Objects>;
+];
+
+[ Objects1Sub i j f object_count;
+    object_count = 0;
+    objectloop (i has moved) {
+        object_count++;
+    }
+    if (object_count == 0)
+        return L__M(##Objects, 2);
+
     L__M(##Objects, 1);
+    if (objects_style & INDENT_BIT) print (string) COLON__TX, "^";
+    else print " ";
+
     objectloop (i has moved) {
-       f = 1; print (the) i; j = parent(i);
+      f++;
+      if (objects_style & INDENT_BIT) Print__Spaces(2);
+      print (the) i;
+       j = parent(i);
         if (j) {
            if (j == player) {
                if (i has worn) L__M(##Objects, 3, j, i);
@@ -1357,9 +1412,24 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
 
       .Obj__Ptd;
 
-        new_line;
+        if ((object_count - f) >= 1) {
+            if (objects_style & INDENT_BIT) {
+                Print__Spaces(2);
+                new_line;
+             } else {
+                 if ((object_count - f) == 1) {
+                     SerialComma(object_count);
+                     print " ", (address) AND1__WD, " ";
+                 } else if (object_count > 2)
+                     print (string) COMMA__TX;
+             }
+        }
     }
-    if (f == 0) L__M(##Objects, 2);
+
+    if ((objects_style & INDENT_BIT) == 0)
+        print ".^";
+    else
+        print "^";
 ];
 
 ! ----------------------------------------------------------------------------
@@ -1434,7 +1504,6 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     else
         inventory_style = ENGLISH_BIT+PARTINV_BIT;
     <Inv, actor>;
-    inventory_style = 0;
 ];
 
 [ InvTallSub;
@@ -1443,7 +1512,6 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     else
         inventory_style = NEWLINE_BIT+INDENT_BIT+PARTINV_BIT;
     <Inv, actor>;
-    inventory_style = 0;
 ];
 
 [ InvSub x;
@@ -1773,7 +1841,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     if (res >= 2) rtrue;
     ks = keep_silent; keep_silent = 1; <Disrobe obj, actor>; keep_silent = ks;
     if (obj has worn && obj in actor) rtrue;
-    if (res == 0 && ~~keep_silent) L__M(##Drop, 3, obj);
+    if (res == 0 && ~~keep_silent) L__M(##Disrobe, 3, obj);
     rfalse;
 ];
 
@@ -1809,10 +1877,11 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     if (noun == actor)         return L__M(##PutOn, 4, noun);
     if (noun in parent(actor)) return L__M(##Drop, 1, noun);
     if (noun notin actor && ~~ImplicitTake(noun)) return L__M(##Drop, 2, noun);
+    if (noun has worn && no_implicit_actions) return L__M(##Disrobe, 4, noun);
     if (noun has worn && ImplicitDisrobe(noun)) return;
     move noun to parent(actor);
     if (AfterRoutines() || keep_silent) return;
-    L__M(##Drop, 4, noun);
+    L__M(##Drop, 3, noun);
 ];
 
 [ PutOnSub ancestor;
@@ -1929,7 +1998,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
         }
         if (k-- == 0) flag = 1;
         if (flag) break;
-        if (keep_silent == 0) print (name) i, (string) COLON__TX;
+        if (keep_silent == 0) print (name) i, (string) COLON__TX, " ";
         <Transfer i second, actor>;
         i = j;
     }
@@ -1968,7 +2037,12 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
 ! ----------------------------------------------------------------------------
 
 [ EnterSub ancestor j ks;
-    if (noun has door || noun in compass) <<Go noun, actor>>;
+    if (noun has door || noun in Compass) {
+       if (verb_word == STAND__TX or SIT__TX or LIE__TX)
+           return L__M(##Enter, 2, noun, verb_word);
+       <<Go noun, actor>>;
+    }
+
     if (actor in noun) return L__M(##Enter, 1, noun);
     if (noun hasnt enterable) return L__M(##Enter, 2, noun, verb_word);
 
@@ -2065,11 +2139,21 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
         }
     }
 
-    thedir = noun.door_dir;
-    if (metaclass(thedir) == Routine) thedir = RunRoutines(noun, door_dir);
+    if (noun.door_dir ~= nothing) {
+       thedir = noun.door_dir;
+       if (metaclass(thedir) == Routine)
+           thedir = RunRoutines(noun, door_dir);
+       next_loc = i.thedir;
+    } else
+       next_loc = noun;
+
+    k = metaclass(next_loc);
+
+    if (k == String) {
+       print (string) next_loc;
+       new_line; rfalse;
+    }
 
-    next_loc = i.thedir; k = metaclass(next_loc);
-    if (k == String) { print (string) next_loc; new_line; rfalse; }
     if (k == Routine) {
         next_loc = RunRoutines(i, thedir);
         if (next_loc == 1) rtrue;
@@ -2080,6 +2164,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
         else                              L__M(##Go, 2);
         rfalse;
     }
+
     if (next_loc has door) {
         if (next_loc has concealed) return L__M(##Go, 2);
         if (next_loc hasnt open && ImplicitOpen(next_loc)) {
@@ -2121,6 +2206,8 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     LookSub(1);
 ];
 
+
+
 ! ----------------------------------------------------------------------------
 !   Describing the world.  SayWhatsOn(object) does just that (producing
 !   no text if nothing except possibly "scenery" and "concealed" items are).
@@ -2129,6 +2216,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
 !   descriptions as it goes.
 ! ----------------------------------------------------------------------------
 
+
 [ SayWhatsOn descon j f;
     if (descon == parent(player)) rfalse;
     objectloop (j in descon)
@@ -2137,6 +2225,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     L__M(##Look, 4, descon);
 ];
 
+
 [ NotSupportingThePlayer o i;
     i = parent(player);
     while (i && i ~= visibility_ceiling) {
@@ -2146,70 +2235,113 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     }
     rtrue;
 ];
-! modified with the fix for L61122
-[ Locale descin text_without_ALSO text_with_ALSO
-    o p num_objs must_print_ALSO;
-    objectloop (o in descin) give o ~workflag;
-    num_objs = 0;
-    objectloop (o in descin)
-        if (o hasnt concealed && NotSupportingThePlayer(o)) {
-            #Ifndef MANUAL_PRONOUNS;
-            PronounNotice(o);
-            #Endif;
-            if (o has scenery) {
-                if (o has supporter && child(o)) SayWhatsOn(o);
-            }
-            else {
-                give o workflag; num_objs++;
-                p = initial;
-                if ((o has door or container) && o has open && o provides when_open) {
-                    p = when_open; jump Prop_Chosen;
-                }
-                if ((o has door or container) && o hasnt open && o provides when_closed) {
-                    p = when_closed; jump Prop_Chosen;
-                }
-                if (o has switchable && o has on && o provides when_on) {
-                    p = when_on; jump Prop_Chosen;
-                }
-                if (o has switchable && o hasnt on && o provides when_off) {
-                    p = when_off;
-                }
 
-              .Prop_Chosen;
-
-                if (o.&describe && RunRoutines(o, describe)) {
-                    must_print_ALSO = true;
-                    give o ~workflag; num_objs--;
-                    continue;
-                }
-                if (o.p && (o hasnt moved || p ~= initial)) {
-                    new_line;
-                    PrintOrRun(o, p);
-                    must_print_ALSO = true;
-                    give o ~workflag; num_objs--;
-                    if (o has supporter && child(o)) SayWhatsOn(o);
-                }
-            }
-        }
 
-    if (num_objs == 0) return 0;
+! Determine if something is casually visible.  Includes things on
+! supporters or in open/transparent containers that are scenery.  Static
+! objects are not included.
+[ Locale descin text_without_ALSO text_with_ALSO
+    o p num_objs must_print_ALSO x flag;
+
+    objectloop (o in descin) {
+        if (o has scenery && (o has supporter || (o has container && o has open or transparent)) && children(o) > 0) {
+           flag = 0;
+           objectloop (x in o) {
+               if (x hasnt scenery && x hasnt concealed)
+                   flag++;
+           }
+           if (flag > 0) {
+               if (num_objs == 0)
+                   print "^";
+               else
+                   print " ";
+
+               if (o has supporter)
+                   print "On ", (the) o;
+               else
+                   print "In ", (the) o;
+
+               WriteListFrom(child(o), ENGLISH_BIT+TERSE_BIT+CONCEAL_BIT+ISARE_BIT);
+               print ".";
+               num_objs++;
+           }
+       }
+    }
+
+    if (num_objs > 0)
+       print "^";
 
-    if (actor ~= player) give actor concealed;
+    objectloop (o in descin)
+       give o ~workflag;
+    num_objs = 0;
+    objectloop (o in descin) {
+       if (o hasnt concealed && NotSupportingThePlayer(o)) {
+#Ifndef MANUAL_PRONOUNS;
+           PronounNotice(o);
+#Endif;
+           if (o hasnt scenery) {
+               give o workflag;
+               num_objs++;
+               p = initial;
+               if ((o has door or container) && o has open && o provides when_open) {
+                   p = when_open;
+                   jump Prop_Chosen;
+               }
+               if ((o has door or container) && o hasnt open && o provides when_closed) {
+                   p = when_closed;
+                   jump Prop_Chosen;
+               }
+               if (o has switchable && o has on && o provides when_on) {
+                   p = when_on;
+                   jump Prop_Chosen;
+               }
+               if (o has switchable && o hasnt on && o provides when_off)
+                   p = when_off;
+.Prop_Chosen;
+               if (o.&describe && RunRoutines(o, describe)) {
+                   must_print_ALSO = true;
+                   give o ~workflag;
+                   num_objs--;
+                   continue;
+               }
+               if (o.p && (o hasnt moved || p ~= initial)) {
+                   new_line;
+                   PrintOrRun(o, p);
+                   must_print_ALSO = true;
+                   give o ~workflag;
+                   num_objs--;
+                   if (o has supporter && child(o))
+                       SayWhatsOn(o);
+               }
+           }
+       }
+    }
+
+    if (num_objs == 0)
+       return 0;
+    if (actor ~= player)
+       give actor concealed;
     if (text_without_ALSO) {
-        new_line;
-        if (must_print_ALSO) print (string) text_with_ALSO, " ";
-        else print (string) text_without_ALSO, " ";
-        WriteListFrom(child(descin),
-          ENGLISH_BIT+RECURSE_BIT+PARTINV_BIT+TERSE_BIT+CONCEAL_BIT+WORKFLAG_BIT);
-    }
-    else {
-        if (must_print_ALSO) L__M(##Look, 5, descin);
-        else L__M(##Look, 6, descin);
-    }
-    if (actor ~= player) give actor ~concealed;
+       new_line;
+       if (must_print_ALSO)
+           print (string) text_with_ALSO, " ";
+       else
+           print (string) text_without_ALSO, " ";
+
+       WriteListFrom(child(descin), ENGLISH_BIT+RECURSE_BIT+PARTINV_BIT+TERSE_BIT+CONCEAL_BIT+WORKFLAG_BIT);
+    } else {
+       if (must_print_ALSO)
+           L__M(##Look, 5, descin);
+       else
+           L__M(##Look, 6, descin);
+    }
+    if (actor ~= player)
+       give actor ~concealed;
     return num_objs;
 ];
 
+
+
 ! ----------------------------------------------------------------------------
 !   Looking.  LookSub(1) is allowed to abbreviate long descriptions, but
 !     LookSub(0) (which is what happens when the Look action is generated)
@@ -2349,7 +2481,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
         return L__M(##Examine, 2, noun);
     }
     i = PrintOrRun(noun, description);
-    if (i < 2 && noun has switchable) L__M(##Examine, 3, noun);
+    if (i == 0 && noun has switchable) L__M(##Examine, 3, noun);
     AfterRoutines();
 ];
 
@@ -2407,7 +2539,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     L__M(##Lock, 5, noun);
 ];
 
-[ SwitchonSub;
+[ SwitchOnSub;
     if (ObjectIsUntouchable(noun)) return;
     if (noun hasnt switchable) return L__M(##SwitchOn, 1, noun);
     if (noun has on)           return L__M(##SwitchOn, 2, noun);
@@ -2417,7 +2549,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
     L__M(##SwitchOn, 3, noun);
 ];
 
-[ SwitchoffSub;
+[ SwitchOffSub;
     if (ObjectIsUntouchable(noun)) return;
     if (noun hasnt switchable) return L__M(##SwitchOff, 1, noun);
     if (noun hasnt on)         return L__M(##SwitchOff, 2, noun);
@@ -2492,7 +2624,7 @@ Constant ID_BIT        $2000;       ! Print object id after each entry
 ! ----------------------------------------------------------------------------
 
 [ AllowPushDir i;
-    if (parent(second) ~= compass) return L__M(##PushDir, 2, noun);
+    if (parent(second) ~= Compass) return L__M(##PushDir, 2, noun);
     if (second == u_obj or d_obj)  return L__M(##PushDir, 3, noun);
     AfterRoutines(); i = noun; move i to actor;
     <Go second, actor>;
diff --git a/version.h b/version.h
new file mode 100644 (file)
index 0000000..7eb11f3
--- /dev/null
+++ b/version.h
@@ -0,0 +1,6 @@
+System_file;
+
+Constant LibSerial       "200718";
+Constant LibRelease      "6.12.4";
+Constant LIBRARY_VERSION  612;
+Constant Grammar__Version 2;