Import v6.12.4 of the Inform 6 standard library
[informlib.git] / parser.h
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