Import v6.12.6 of the Inform 6 standard library
[informlib.git] / parser.h
index d0b427ecd480f1f1951d63ddeec89b86af76765e..f72b571e42547f2620bcd86e33d3ae76f5b75c14 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.2 -- Serial number 180520
+!   Supplied for use with Inform 6 -- Release 6.12.6 -- Serial number 220219
 !
-!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2018
+!   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2022
 !
 !   This file is free software: you can redistribute it and/or modify
 !   it under the terms of the GNU Affero General Public License as
@@ -70,13 +70,10 @@ System_file;
 ! ------------------------------------------------------------------------------
 
 #Ifndef VN_1633;
-Message fatalerror "*** Library 6.12.2 needs Inform v6.33 or later to work ***";
+Message fatalerror "*** Library 6.12.x needs Inform v6.33 or later to work ***";
 #Endif; ! VN_
 
-Constant LibSerial       "180520";
-Constant LibRelease      "6.12.2";
-Constant LIBRARY_VERSION  612;
-Constant Grammar__Version 2;
+Include "version";
 
 Constant BEFORE_PARSER   10;
 Constant AFTER_PARSER    20;
@@ -118,8 +115,13 @@ Constant HDR_SCREENHLINES  $20;     ! byte
 Constant HDR_SCREENWCHARS  $21;     ! byte
 Constant HDR_SCREENWUNITS  $22;     ! word
 Constant HDR_SCREENHUNITS  $24;     ! word
+#Iftrue (#version_number == 6);
+Constant HDR_FONTHUNITS    $26;     ! byte
+Constant HDR_FONTWUNITS    $27;     ! byte
+#Ifnot;
 Constant HDR_FONTWUNITS    $26;     ! byte
 Constant HDR_FONTHUNITS    $27;     ! byte
+#Endif;
 Constant HDR_ROUTINEOFFSET $28;     ! word
 Constant HDR_STRINGOFFSET  $2A;     ! word
 Constant HDR_BGCOLOUR      $2C;     ! byte
@@ -164,6 +166,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 +329,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 +383,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 +825,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 +835,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 +1464,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 +1487,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;
 
@@ -1494,7 +1514,7 @@ Object  InformParser "(Inform Parser)"
     i = (~~i);
     #Endif; ! TARGET_
     if (i == 0) {    L__M(##Miscellany, 7); return 0; }
-    L__M(##Miscellany, 1);
+    L__M(##Miscellany, 6);
     return 1;
 ];
 
@@ -1692,6 +1712,9 @@ Object  InformParser "(Inform Parser)"
 
     if (usual_grammar_after == 0) {
         j = verb_wordnum;
+        #Ifdef TARGET_ZCODE;
+               parser_one = 0;
+        #Endif;
         i = RunRoutines(actor, grammar);
         #Ifdef DEBUG;
         if (parser_trace >= 2 && actor.grammar ~= 0 or NULL)
@@ -1700,9 +1723,10 @@ Object  InformParser "(Inform Parser)"
 
         #Ifdef TARGET_ZCODE;
         if ((i ~= 0 or 1) &&
+           (parser_one ~= 0 ||
             (UnsignedCompare(i, dict_start) < 0 ||
              UnsignedCompare(i, dict_end) >= 0 ||
-             (i - dict_start) % dict_entry_size ~= 0)) {
+             (i - dict_start) % dict_entry_size ~= 0))) {
             usual_grammar_after = j;
             i=-i;
         }
@@ -1743,14 +1767,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:
@@ -2226,7 +2250,7 @@ Object  InformParser "(Inform Parser)"
                 oops_from = 0;
 
                 ! ...explain any inferences made (using the pattern)...
-
+               ! This is where the parser replies (the sword) if things aren't clear.
                 if (inferfrom ~= 0 && no_infer_message == false) {
                     print "("; PrintCommand(inferfrom); print ")^";
                 }
@@ -2506,14 +2530,19 @@ Constant UNLIT_BIT  =  32;
     indef_nspec_at = 0;
 ];
 
-[ Descriptors  allows_multiple o x flag cto type m n;
+[ Descriptors  allows_multiple o x flag cto type m n;
     ResetDescriptors();
     if (wn > num_words) return 0;
     m = wn;
     for (flag=true : flag :) {
         o = NextWordStopped(); flag = false;
-       for (x=1 : x<=LanguageDescriptors-->0 : x=x+4)
+       for (x=1 : x<=LanguageDescriptors-->0 : x=x+4) {
             if (o == LanguageDescriptors-->x) {
+                ! Attempt to compensate for her-her confusion.
+                for (y = 1 : y<=LanguagePronouns-->0 : y=y+2) {
+                    if (o == LanguagePronouns-->y)
+                        jump PersonalPronoun;
+                }
                 flag = true;
                 type = LanguageDescriptors-->(x+2);
                 if (type ~= DEFART_PK) indef_mode = true;
@@ -2532,6 +2561,9 @@ Constant UNLIT_BIT  =  32;
                 if (type == light)  indef_type = indef_type | LIT_BIT;
                 if (type == -light) indef_type = indef_type | UNLIT_BIT;
             }
+        }
+        .PersonalPronoun;
+
         if (o == OTHER1__WD or OTHER2__WD or OTHER3__WD) {
             indef_mode = 1; flag = 1;
             indef_type = indef_type | OTHER_BIT;
@@ -2567,7 +2599,7 @@ Constant UNLIT_BIT  =  32;
     if (actor ~= player) rtrue;
     if (obj has animate) rtrue;
     if (obj hasnt talkable) rfalse;
-    if (action_to_be == ##Ask or ##Answer or ##Tell or ##AskFor) rtrue;
+    if (action_to_be == ##Ask or ##Answer or ##Tell or ##AskFor or ##AskTo) rtrue;
     rfalse;
 ];
 
@@ -2652,7 +2684,7 @@ Constant UNLIT_BIT  =  32;
             parsed_number = l; return GPR_NUMBER;
 
           CREATURE_TOKEN:
-            if (action_to_be == ##Answer or ##Ask or ##AskFor or ##Tell)
+            if (action_to_be == ##Answer or ##Ask or ##AskFor or ##AskTo or ##Tell)
                 scope_reason = TALKING_REASON;
 
           TOPIC_TOKEN:
@@ -2844,12 +2876,6 @@ 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 (ImplicitTake(l)) {
-               etype = NOTHELD_PE;
-               jump FailToken;
-           }
-       }
 
         if (indef_wanted == 100 && l == 0 && number_matched == 0)
             l = 1;  ! ReviseMulti if TAKE ALL FROM empty container
@@ -2865,7 +2891,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
@@ -3162,7 +3188,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) {
@@ -3652,6 +3678,18 @@ Constant SCORE__DIVISOR     = 20;
             }
 
         if (flag) {
+           if(match_length == 1) {
+               k = 0;
+               for (i=1 : i<=number_of_classes : i++) {
+                   while ((match_classes-->k) ~= i or -i) k++;
+                   j = match_list-->k;
+
+                   if(MatchWord(j, match_from)) {
+                       no_infer_message = true;
+                       return j;
+                   }
+               }
+           }
             #Ifdef DEBUG;
             if (parser_trace >= 4) print "   Unable to choose best group, so ask player.]^";
             #Endif; ! DEBUG
@@ -3775,9 +3813,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 +3909,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.
@@ -3921,6 +3959,50 @@ Constant SCORE__DIVISOR     = 20;
     rtrue;
 ];
 
+
+! ----------------------------------------------------------------------------
+!  MatchWord matches a word to the name of an object.  This is used to assume
+!  that an object simply named "key" is meant when the player types TAKE KEY
+!  rather than TAKE BRASS KEY.
+! ----------------------------------------------------------------------------
+
+[ MatchWord p_obj p_word_no       len_name len_input start_input i;
+
+    p_word_no--;
+
+    PrintToBuffer(StorageForShortName, SHORTNAMEBUF_LEN, p_obj);
+    len_name = StorageForShortName --> 0;
+
+    if(len_name > 9) {
+       for(i = 9 : i < len_name : i++)
+           if(StorageForShortName -> (WORDSIZE + i) == 32) rfalse;
+       len_name = 9;
+    }
+
+#Ifdef TARGET_ZCODE;
+    start_input = (parse + 2) -> (4 * p_word_no + 3);
+    len_input = (parse + 2) -> (4 * p_word_no + 2);
+    if(len_input > 9) len_input = 9;
+    if(len_name ~= len_input) rfalse;
+    for(i = 0 : i < len_name : i++) {
+       if(StorageForShortName -> (WORDSIZE + i) ~= buffer -> (start_input + i))
+           rfalse;
+    }
+#Ifnot;  ! TARGET_GLULX
+    start_input = parse --> (((p_word_no+1) * 3)) - 2;
+    len_input = parse --> ((p_word_no+1) * 3 - 1);
+    if(len_input > 9) len_input = 9;
+    if(len_name ~= len_input) rfalse;
+    for(i = 0 : i < len_name : i++) {
+       if(StorageForShortName -> (WORDSIZE + i) ~= buffer -> (start_input + i + 2))
+           rfalse;
+    }
+#Endif;  ! TARGET_
+
+    rtrue;
+];
+
+
 ! ----------------------------------------------------------------------------
 !  PrintCommand reconstructs the command as it presently reads, from
 !  the pattern which has been built up
@@ -3959,7 +4041,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 +4343,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.
@@ -4488,22 +4570,29 @@ Constant SCORE__DIVISOR     = 20;
     #Ifdef DEBUG;
     if (threshold >= 0 && parser_trace >= 5) print "    ParseNoun returned ", threshold, "^";
     #Endif; ! DEBUG
-    if (threshold < 0) wn++;
-    if (threshold > 0) { k = threshold; jump MMbyPN; }
-
-    if (threshold == 0 || Refers(obj,wn-1) == 0) {
-      .NoWordsMatch;
-        if (indef_mode ~= 0) {
-            k = 0; parser_action = NULL;
-            jump MMbyPN;
-        }
-        rfalse;
+    ! Don't arbitrarily increase wn when ParseNoun() returns -1
+    if (threshold > 0) {
+       k = threshold;
+       wn = j + k;
+       jump MMbyPN;
+    }
+    ! Check wn instead of wn - 1
+    if (threshold == 0 || Refers(obj,wn) == 0) {
+       .NoWordsMatch;
+       if (indef_mode ~= 0) {
+               ! Restore wn to pre-ParseNoun() state
+               k = 0; parser_action = NULL; wn = j;
+               jump MMbyPN;
+       }
+       rfalse;
     }
 
     if (threshold < 0) {
-        threshold = 1;
-        dict_flags_of_noun = (w->#dict_par1) & (DICT_X654+DICT_PLUR);!$$01110100;
-        w = NextWord();
+       ! Set threshold to reflect any words consumed by ParseNoun()
+       threshold = wn - j;
+       w = NextWord(); ! Ensure w contains actual first word of noun phrase
+                       ! if ParseNoun() moved wn.
+       dict_flags_of_noun = (w->#dict_par1) & (DICT_X654+DICT_PLUR);!$$01110100;
         while (Refers(obj, wn-1)) {
             threshold++;
             if (w)
@@ -4789,7 +4878,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;
@@ -4841,8 +4929,19 @@ Constant MAX_DECIMAL_BASE 214748364;
 
 #Ifdef TARGET_ZCODE;
 
-[ Dword__No w; return (w-(HDR_DICTIONARY-->0 + 7))/9; ];
-[ No__Dword n; return HDR_DICTIONARY-->0 + 7 + 9*n; ];
+[ Dword__No w dp dh;
+       dp = HDR_DICTIONARY-->0;
+       dh = dp->0 + 4;
+       dp = dp + dp->0 + 1;
+       return (w-(HDR_DICTIONARY-->0 + dh )) / (dp->0);
+];
+
+[ No__Dword n dp dh;
+       dp = HDR_DICTIONARY-->0;
+       dh = dp->0 + 4;
+       dp = dp + dp->0 + 1;
+       return HDR_DICTIONARY-->0 + dh + (dp->0 *n);
+];
 
 #Ifnot; ! TARGET_GLULX
 
@@ -5145,7 +5244,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 +5414,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 +6390,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_
@@ -6429,7 +6522,7 @@ Object  InformLibrary "(Inform Library)"
 #Endif; ! TARGET_ZCODE
 
 #Ifndef DrawStatusLine;
-[ DrawStatusLine width posa posb;
+[ DrawStatusLine width posa posb posc posd pose;
     #Ifdef TARGET_GLULX;
     ! If we have no status window, we must not try to redraw it.
     if (gg_statuswin == 0)
@@ -6444,7 +6537,13 @@ Object  InformLibrary "(Inform Library)"
     MoveCursor(1, 1);
 
     width = ScreenWidth();
-    posa = width-26; posb = width-13;
+    posa = width-26;   ! For standard move/score display.
+    posb = width-13;
+    posc = width-5;
+
+    posd = width-19;   ! For time display.
+    pose = width-14;
+
     spaces width;
 
     MoveCursor(1, 2);
@@ -6458,13 +6557,17 @@ Object  InformLibrary "(Inform Library)"
         else
             print (The) visibility_ceiling;
     }
-
-    if (sys_statusline_flag && width > 53) {
-        MoveCursor(1, posa);
-        print (string) TIME__TX;
-        LanguageTimeOfDay(sline1, sline2);
-    }
-    else {
+    if (sys_statusline_flag) {
+       if (width > 29) {
+           if (width > 39)
+               MoveCursor(1, posd);
+           else
+               MoveCursor(1, pose);
+           print (string) TIME__TX;
+           LanguageTimeOfDay(sline1, sline2);
+       } else
+           jump DSLContinue;
+    } else {
         if (width > 66) {
             #Ifndef NO_SCORE;
             MoveCursor(1, posa);
@@ -6473,14 +6576,24 @@ Object  InformLibrary "(Inform Library)"
             MoveCursor(1, posb);
             print (string) MOVES__TX, sline2;
         }
-        #Ifndef NO_SCORE;
-        if (width > 53 && width <= 66) {
-            MoveCursor(1, posb);
-            print sline1, "/", sline2;
-        }
-        #Endif;
+       if (width > 53 && width <= 66) {
+           MoveCursor(1, posb);
+           #Ifdef NO_SCORE;
+           print (string) MOVES__TX, sline2;
+           #Ifnot;
+           print sline1, "/", sline2;
+           #Endif;
+       }
+       if (width < 53) {
+          MoveCursor(1, posc);
+          #Ifdef NO_SCORE;
+          print (string) MOVES_S__TX, sline2;
+          #Ifnot;
+          print sline1, "/", sline2;
+          #Endif;
+       }
     }
-
+    .DSLContinue;
     MainWindow(); ! set_window
 ];
 #Endif;
@@ -6629,10 +6742,8 @@ Object  InformLibrary "(Inform Library)"
     gg_scriptstr = 0;
     gg_savestr = 0;
     gg_statuswin_cursize = 0;
-    #Ifdef DEBUG;
     gg_commandstr = 0;
     gg_command_reading = false;
-    #Endif; ! DEBUG
     ! Also tell the game to clear its object references.
     if (IdentifyGlkObject(0) == false) LibraryExtensions.RunWhile(ext_identifyglkobject, 0, 0);
 
@@ -6641,12 +6752,10 @@ Object  InformLibrary "(Inform Library)"
         switch (gg_arguments-->0) {
             GG_SAVESTR_ROCK: gg_savestr = id;
             GG_SCRIPTSTR_ROCK: gg_scriptstr = id;
-            #Ifdef DEBUG;
             GG_COMMANDWSTR_ROCK: gg_commandstr = id;
                                  gg_command_reading = false;
             GG_COMMANDRSTR_ROCK: gg_commandstr = id;
                                  gg_command_reading = true;
-            #Endif; ! DEBUG
             default: if (IdentifyGlkObject(1, 1, id, gg_arguments-->0) == false)
                          LibraryExtensions.RunWhile(ext_identifyglkobject, false, 1, 1, id, gg_arguments-->0);
         }
@@ -6910,7 +7019,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);
 ];
@@ -6919,7 +7028,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;
@@ -6969,7 +7078,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;
 ];
@@ -7244,6 +7353,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