! ==============================================================================
! 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.4 -- Serial number 200718
!
-! Copyright Graham Nelson 1993-2004 and David Griffith 2012-2018
+! 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";
!
! ------------------------------------------------------------------------------
! ------------------------------------------------------------------------------
#Ifndef VN_1633;
-Message fatalerror "*** Library 6.12.2 needs Inform v6.33 or later to work ***";
+Message fatalerror "*** Library 6.12.3 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;
Fake_Action PluralFound;
Fake_Action ListMiscellany;
Fake_Action Miscellany;
+Fake_Action RunTimeError;
Fake_Action Prompt;
Fake_Action NotUnderstood;
Fake_Action Going;
! "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
! ------------------------------------------------------------------------------
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;
! 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,
each_turn NULL,
time_out NULL,
describe NULL,
- article "the",
+ article THE__TX,
add_to_scope 0,
capacity 100,
parse_name 0,
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 "~ --> ~";
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;
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:
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);
#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;
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
! 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, "]^";
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) {
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 ||
[ 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.
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;
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.
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;
}
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)) {
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
];
#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_
#Endif; ! TARGET_ZCODE
#Ifndef DrawStatusLine;
-[ DrawStatusLine width posa posb;
+[ DrawStatusLine width posa posb posc;
#Ifdef TARGET_GLULX;
! If we have no status window, we must not try to redraw it.
if (gg_statuswin == 0)
MoveCursor(1, 1);
width = ScreenWidth();
- posa = width-26; posb = width-13;
+ posa = width-26;
+ posb = width-13;
+ posc = width-5;
spaces width;
MoveCursor(1, 2);
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;
+ }
}
MainWindow(); ! set_window
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);
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);
}
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);
];
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;
}
#Endif; ! TARGET_
- CapitRule (artform-->acode, ~~capitalise); ! print article
+ Cap (artform-->acode, ~~capitalise); ! print article
if (pluralise) return;
print (PSN__) o;
];
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