! Positions.h
! Version 1.1
! An Inform 6 extension by Nathan Schwartzman
! Feedback to
[email protected]
!
! #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;
];