X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=parser.h;h=f72b571e42547f2620bcd86e33d3ae76f5b75c14;hb=b008d894933fd9671e194eb00fedbd66f7964bf4;hp=c5b184a879a3de75e295ae521b4be04c138ccbe7;hpb=5bfb408b991028b28b411c28971831f59ece4684;p=informlib.git diff --git a/parser.h b/parser.h index c5b184a..f72b571 100644 --- a/parser.h +++ b/parser.h @@ -1,9 +1,9 @@ ! ============================================================================== ! PARSER: Front end to parser. ! -! Supplied for use with Inform 6 -- Release 6.12.4 -- Serial number 200718 +! Supplied for use with Inform 6 -- Release 6.12.6 -- Serial number 220219 ! -! Copyright Graham Nelson 1993-2004 and David Griffith 2012-2020 +! 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 @@ -15,9 +15,13 @@ ! 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 "berblib"; +! Include "verblib"; ! Include "grammar"; ! ! ------------------------------------------------------------------------------ @@ -66,7 +70,7 @@ System_file; ! ------------------------------------------------------------------------------ #Ifndef VN_1633; -Message fatalerror "*** Library 6.12.3 needs Inform v6.33 or later to work ***"; +Message fatalerror "*** Library 6.12.x needs Inform v6.33 or later to work ***"; #Endif; ! VN_ Include "version"; @@ -111,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 @@ -1505,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; ]; @@ -1703,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) @@ -1711,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; } @@ -2237,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 ")^"; } @@ -2381,13 +2394,7 @@ 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) { - if (parent(noun) has container) - L__M(##Take, 14, noun); - else - L__M(##Miscellany, 32, not_holding); - oops_from=saved_oops; - } + if (etype == NOTHELD_PE) { 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); @@ -2523,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 y 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; @@ -2549,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; @@ -2584,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; ]; @@ -2669,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: @@ -2861,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 ((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; - } - } if (indef_wanted == 100 && l == 0 && number_matched == 0) l = 1; ! ReviseMulti if TAKE ALL FROM empty container @@ -3071,7 +3080,6 @@ 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, "]^"; @@ -3670,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 @@ -3939,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 @@ -4506,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) @@ -4858,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 @@ -6440,7 +6522,7 @@ Object InformLibrary "(Inform Library)" #Endif; ! TARGET_ZCODE #Ifndef DrawStatusLine; -[ DrawStatusLine width posa posb posc; +[ 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) @@ -6455,9 +6537,13 @@ Object InformLibrary "(Inform Library)" MoveCursor(1, 1); width = ScreenWidth(); - posa = width-26; + 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); @@ -6471,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); @@ -6503,7 +6593,7 @@ Object InformLibrary "(Inform Library)" #Endif; } } - + .DSLContinue; MainWindow(); ! set_window ]; #Endif;