! Positions.h ! Version 1.1 ! An Inform 6 extension by Nathan Schwartzman ! Feedback to naschwar@iupui.edu ! ! #Include between "Parser" and "Verblib". ! Before #Including "Parser", add the line ! "Replace TrygivenObject". ! ! This extension will allow input of the following type: ! ! TAKE THE BRASS KEY FROM THE POUCH IN THE TREASURE CHEST ! ! PUT EVERYTHING IN THE TOASTER ON THE TABLE ! ! This does not require you to alter existing ! code at all, unless you already have a replacement ! for TryGivenObject() for some reason. ! ! What doesn't work: ! PUT ALL IN CHEST ON CHAIR (may work by fiddling with ! grammar lines) ! Pronouns (e.g. X IT IN CHEST) ! ! Credit goes to Anson Turner and his Platypus library ! for the idea for this; I also took some of his code. ! I hope he doesn't mind. ! ! Version 1.1 fixes a bug and allows the use of articles ! and descriptors. Global indef_specific; [ TryGivenObject obj flag threshold k w j p; #Ifdef DEBUG; if (parser_trace >= 5) print " Trying ", (the) obj, " (", obj, ") at word ", wn, "^"; #Endif; ! DEBUG dict_flags_of_noun = 0; ! If input has run out then always match, with only quality 0 (this saves ! time). if (wn > num_words) { if (indef_mode ~= 0) dict_flags_of_noun = $$01110000; ! Reject "plural" bit MakeMatch(obj,0); #Ifdef DEBUG; if (parser_trace >= 5) print " Matched (0)^"; #Endif; ! DEBUG return 1; } ! Ask the object to parse itself if necessary, sitting up and taking notice ! if it says the plural was used: if (obj.parse_name~=0) { parser_action = NULL; j=wn; k = RunRoutines(obj,parse_name); if (k > 0) { wn=j+k; .MMbyPN; ! The next two lines take care of position parsing. p = AppendPreps(obj); if (p) { wn = wn + p; k = k + p; } if (parser_action == ##PluralFound) dict_flags_of_noun = dict_flags_of_noun | 4; if (dict_flags_of_noun & 4) { if (~~allow_plurals) k = 0; else { if (indef_mode == 0) { indef_mode = 1; indef_type = 0; indef_wanted = 0; } indef_type = indef_type | PLURAL_BIT; if (indef_wanted == 0) indef_wanted = 100; } } #Ifdef DEBUG; if (parser_trace >= 5) print " Matched (", k, ")^"; #Endif; ! DEBUG if (~~flag) MakeMatch(obj,k); return k; } if (k == 0) jump NoWordsMatch; } ! The default algorithm is simply to count up how many words pass the ! Refers test: parser_action = NULL; w = NounWord(); if (w == 1 && player == obj) { k=1; jump MMbyPN; } if (w >= 2 && w < 128 && (LanguagePronouns-->w == obj)) { k = 1; jump MMbyPN; } j=--wn; threshold = ParseNoun(obj); #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; } if (threshold < 0) { threshold = 1; dict_flags_of_noun = (w->#dict_par1) & $$01110100; w = NextWord(); while (Refers(obj, wn-1)) { threshold++; if (w) dict_flags_of_noun = dict_flags_of_noun | ((w->#dict_par1) & $$01110100); w = NextWord(); } } k = threshold; jump MMbyPN; ]; [ AppendPreps obj wd i m ap z x; ! Here we handle the case of PUT THE DAGGER IN THE SHEATH ON MY BELT. if (~~parent(obj)) rfalse; wn--; wd = NextWord(); if ((parent(obj) has container && wd == 'in' or 'inside' or 'within' or 'from') || (parent(obj) has supporter && wd == 'on' or 'upon' or 'off' or 'from')) { ! Are we sure we have PUT (DAGGER) IN (SHEATH) rather than PUT (DAGGER IN SHEATH)? for (x=1 : x<=LanguageDescriptors-->0 : x=x+4) if (NextWord() == LanguageDescriptors-->x) { m++; } else wn--; if (line_ttype-->pcount == PREPOSITION_TT) { z = pcount; if (WordLeft(line_tdata-->z)) jump Prepositions2; if ((line_token-->z)->0 & $20) { do { if (WordLeft(line_tdata-->z)) jump Prepositions2; z++; } until ((line_token-->z == ENDIT_TOKEN) || (((line_token-->z)->0 & $10) == 0)); } jump GiveResult; } ! Ok, now we're sure. .Prepositions2; ap = allow_plurals; i = TryGivenObject(parent(obj), 1); allow_plurals = ap; if (~~i) jump GiveResult; m = m + i + 1; obj = parent(obj); } .GiveResult; if (i == 0) rfalse; if (indef_wanted == 100) { if (parent(obj) has container) indef_specific = 1; if (parent(obj) has supporter) indef_specific = 2; } return m; ]; [ WordLeft w own cw flag; own = wn; while ((cw = NextWordStopped()) ~= -1) { if (flag) { if (cw && (cw->#dict_par1) & 1) break; flag = 0; } if (cw == w) { wn = own; rtrue; } if (IsALinkWord(w)) flag = 1; } wn = own; rfalse; ]; [ IsALinkWord wd; if (wd == COMMA_WORD or AND1__WD or AND2__WD or AND3__WD or THEN1__WD or THEN2__WD or THEN3__WD) rtrue; rfalse; ];