Inform - Support - Source

Back to List

Inventory
Complete

Backward
Forward

Plain
Coloured
Gaudy

This code
in plain text

Browsing parserm.h

NounDomain (lines 2002-2302)

2002  !  NounDomain does the most substantial part of parsing an object name.
2003  !
2004  !  It is given two "domains" - usually a location and then the actor who is
2005  !  looking - and a context (i.e. token type), and returns:
2006  !
2007  !   0    if no match at all could be made,
2008  !   1    if a multiple object was made,
2009  !   k    if object k was the one decided upon,
2010  !   REPARSE_CODE if it asked a question of the player and consequently rewrote
2011  !        the player's input, so that the whole parser should start again
2012  !        on the rewritten input.
2013  !
2014  !   In the case when it returns 1
2015  !   length_of_noun to the number of words in the input text matched to the
2016  !   noun.
2017  !   In the case k=1, the multiple objects are added to multiple_object by
2018  !   hand (not by MultiAdd, because we want to allow duplicates).
2019  ! ----------------------------------------------------------------------------
2020   
2021  [ NounDomain domain1 domain2 context    first_word i j k l
2022                                          answer_words marker;
2023   
2024  #ifdef DEBUG;
2025    if (parser_trace>=4)
2026    {   print "   [NounDomain called at word ", wn, "^";
2027        print "   ";
2028        if (indef_mode)
2029        {   print "seeking indefinite object: ";
2030            if (indef_type & OTHER_BIT)  print "other ";
2031            if (indef_type & MY_BIT)     print "my ";
2032            if (indef_type & THAT_BIT)   print "that ";
2033            if (indef_type & PLURAL_BIT) print "plural ";
2034            if (indef_type & LIT_BIT)    print "lit ";
2035            if (indef_type & UNLIT_BIT)  print "unlit ";
2036            if (indef_owner ~= 0) print "owner:", (name) indef_owner;
2037            new_line;
2038            print "   number wanted: ";
2039            if (indef_wanted == 100) print "all"; else print indef_wanted;
2040            new_line;
2041            print "   most likely GNAs of names: ", indef_cases, "^";
2042        }
2043        else print "seeking definite object^";
2044    }
2045  #endif;
2046   
2047    match_length=0; number_matched=0; match_from=wn; placed_in_flag=0;
2048   
2049    SearchScope(domain1, domain2, context);
2050   
2051  #ifdef DEBUG;
2052    if (parser_trace>=4) print "   [ND made ", number_matched, " matches]^";
2053  #endif;
2054   
2055    wn=match_from+match_length;
2056   
2057  !  If nothing worked at all, leave with the word marker skipped past the
2058  !  first unmatched word...
2059   
2060    if (number_matched==0) { wn++; rfalse; }
2061   
2062  !  Suppose that there really were some words being parsed (i.e., we did
2063  !  not just infer).  If so, and if there was only one match, it must be
2064  !  right and we return it...
2065   
2066    if (match_from <= num_words)
2067    {   if (number_matched==1) { i=match_list-->0; return i; }
2068   
2069  !  ...now suppose that there was more typing to come, i.e. suppose that
2070  !  the user entered something beyond this noun.  If nothing ought to follow,
2071  !  then there must be a mistake, (unless what does follow is just a full
2072  !  stop, and or comma)
2073   
2074        if (wn<=num_words)
2075        {   i=NextWord(); wn--;
2076            if (i ~=  AND1__WD or AND2__WD or AND3__WD or comma_word
2077                   or THEN1__WD or THEN2__WD or THEN3__WD
2078                   or BUT1__WD or BUT2__WD or BUT3__WD)
2079            {   if (lookahead==ENDIT_TOKEN) rfalse;
2080            }
2081        }
2082    }
2083   
2084  !  Now look for a good choice, if there's more than one choice...
2085   
2086    number_of_classes=0;
2087    
2088    if (number_matched==1) i=match_list-->0;
2089    if (number_matched>1)
2090    {   i=Adjudicate(context);
2091        if (i==-1) rfalse;
2092        if (i==1) rtrue;       !  Adjudicate has made a multiple
2093                               !  object, and we pass it on
2094    }
2095   
2096  !  If i is non-zero here, one of two things is happening: either
2097  !  (a) an inference has been successfully made that object i is
2098  !      the intended one from the user's specification, or
2099  !  (b) the user finished typing some time ago, but we've decided
2100  !      on i because it's the only possible choice.
2101  !  In either case we have to keep the pattern up to date,
2102  !  note that an inference has been made and return.
2103  !  (Except, we don't note which of a pile of identical objects.)
2104   
2105    if (i~=0)
2106    {   if (dont_infer) return i;
2107        if (inferfrom==0) inferfrom=pcount;
2108        pattern-->pcount = i;
2109        return i;
2110    }
2111   
2112  !  If we get here, there was no obvious choice of object to make.  If in
2113  !  fact we've already gone past the end of the player's typing (which
2114  !  means the match list must contain every object in scope, regardless
2115  !  of its name), then it's foolish to give an enormous list to choose
2116  !  from - instead we go and ask a more suitable question...
2117   
2118    if (match_from > num_words) jump Incomplete;
2119   
2120  !  Now we print up the question, using the equivalence classes as worked
2121  !  out by Adjudicate() so as not to repeat ourselves on plural objects...
2122   
2123    if (context==CREATURE_TOKEN)
2124        L__M(##Miscellany, 45); else L__M(##Miscellany, 46);
2125   
2126    j=number_of_classes; marker=0;
2127    for (i=1:i<=number_of_classes:i++)
2128    {   
2129        while (((match_classes-->marker) ~= i)
2130               && ((match_classes-->marker) ~= -i)) marker++;
2131        k=match_list-->marker;
2132   
2133        if (match_classes-->marker > 0) print (the) k; else print (a) k;
2134   
2135        if (i<j-1)  print ", ";
2136        if (i==j-1) print (string) OR__TX;
2137    }
2138    print "?^";
2139   
2140  !  ...and get an answer:
2141   
2142    .WhichOne;
2143    for (i=2:i<120:i++) buffer2->i=' ';
2144    answer_words=Keyboard(buffer2, parse2);
2145   
2146    first_word=(parse2-->1);
2147   
2148  !  Take care of "all", because that does something too clever here to do
2149  !  later on:
2150   
2151    if (first_word == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD)
2152    {   
2153        if (context == MULTI_TOKEN or MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN
2154                       or MULTIINSIDE_TOKEN)
2155        {   l=multiple_object-->0;
2156            for (i=0:i<number_matched && l+i<63:i++)
2157            {   k=match_list-->i;
2158                multiple_object-->(i+1+l) = k;
2159            }
2160            multiple_object-->0 = i+l;
2161            rtrue;
2162        }
2163        L__M(##Miscellany, 47);
2164        jump WhichOne;
2165    }
2166   
2167  !  If the first word of the reply can be interpreted as a verb, then
2168  !  assume that the player has ignored the question and given a new
2169  !  command altogether.
2170  !  (This is one time when it's convenient that the directions are
2171  !  not themselves verbs - thus, "north" as a reply to "Which, the north
2172  !  or south door" is not treated as a fresh command but as an answer.)
2173   
2174    #ifdef LanguageIsVerb;
2175    if (first_word==0)
2176    {   j = wn; first_word=LanguageIsVerb(buffer2, parse2, 1); wn = j;
2177    }
2178    #endif;
2179    if (first_word ~= 0)
2180    {   j=first_word->#dict_par1;
2181        if ((0~=j&1) && (first_word ~= 'long' or 'short' or 'normal'
2182                                       or 'brief' or 'full' or 'verbose'))
2183        {   CopyBuffer(buffer, buffer2);
2184            return REPARSE_CODE;
2185        }
2186    }
2187   
2188  !  Now we insert the answer into the original typed command, as
2189  !  words additionally describing the same object
2190  !  (eg, > take red button
2191  !       Which one, ...
2192  !       > music
2193  !  becomes "take music red button".  The parser will thus have three
2194  !  words to work from next time, not two.)
2195   
2196    k = WordAddress(match_from) - buffer; l=buffer2->1+1;
2197    for (j=buffer + buffer->0 - 1: j>= buffer+k+l: j--)
2198        j->0 = 0->(j-l);
2199    for (i=0:i<l:i++) buffer->(k+i) = buffer2->(2+i);
2200    buffer->(k+l-1) = ' ';
2201    buffer->1 = buffer->1 + l;
2202    if (buffer->1 >= (buffer->0 - 1)) buffer->1 = buffer->0;
2203   
2204  !  Having reconstructed the input, we warn the parser accordingly
2205  !  and get out.
2206   
2207    return REPARSE_CODE;
2208   
2209  !  Now we come to the question asked when the input has run out
2210  !  and can't easily be guessed (eg, the player typed "take" and there
2211  !  were plenty of things which might have been meant).
2212   
2213    .Incomplete;
2214   
2215    if (context==CREATURE_TOKEN)
2216        L__M(##Miscellany, 48); else L__M(##Miscellany, 49);
2217   
2218    for (i=2:i<120:i++) buffer2->i=' ';
2219    answer_words=Keyboard(buffer2, parse2);
2220   
2221    first_word=(parse2-->1);
2222    #ifdef LanguageIsVerb;
2223    if (first_word==0)
2224    {   j = wn; first_word=LanguageIsVerb(buffer2, parse2, 1); wn = j;
2225    }
2226    #endif;
2227   
2228  !  Once again, if the reply looks like a command, give it to the
2229  !  parser to get on with and forget about the question...
2230   
2231    if (first_word ~= 0)
2232    {   j=first_word->#dict_par1;
2233        if (0~=j&1)
2234        {   CopyBuffer(buffer, buffer2);
2235            return REPARSE_CODE;
2236        }
2237    }
2238   
2239  !  ...but if we have a genuine answer, then:
2240  !
2241  !  (1) we must glue in text suitable for anything that's been inferred.
2242   
2243    if (inferfrom ~= 0)
2244    {   for (j = inferfrom: j<pcount: j++)
2245        {   if (pattern-->j == PATTERN_NULL) continue;
2246            i=2+buffer->1; (buffer->1)++; buffer->(i++) = ' ';
2247      
2248            if (parser_trace >= 5)
2249            print "[Gluing in inference with pattern code ", pattern-->j, "]^";
2250   
2251            parse2-->1 = 0;
2252   
2253            ! An inferred object.  Best we can do is glue in a pronoun.
2254            ! (This is imperfect, but it's very seldom needed anyway.)
2255      
2256            if (pattern-->j >= 2 && pattern-->j < REPARSE_CODE)
2257            {   PronounNotice(pattern-->j);
2258                for (k=1: k<=LanguagePronouns-->0: k=k+3)
2259                    if (pattern-->j == LanguagePronouns-->(k+2))
2260                    {   parse2-->1 = LanguagePronouns-->k;
2261                        if (parser_trace >= 5)
2262                        print "[Using pronoun '", (address) parse2-->1, "']^";
2263                        break;
2264                    }
2265            }
2266            else
2267            {   ! An inferred preposition.
2268                parse2-->1 = No__Dword(pattern-->j - REPARSE_CODE);
2269                if (parser_trace >= 5)
2270                    print "[Using preposition '", (address) parse2-->1, "']^";
2271            }
2272      
2273            ! parse2-->1 now holds the dictionary address of the word to glue in.
2274      
2275            if (parse2-->1 ~= 0)
2276            {   k = buffer + i;
2277                @output_stream 3 k;
2278                print (address) parse2-->1;
2279                @output_stream -3;
2280                k = k-->0;
2281                for (l=i:l<i+k:l++) buffer->l = buffer->(l+2);
2282                i = i + k; buffer->1 = i-2;
2283            }
2284        }
2285    }
2286   
2287  !  (2) we must glue the newly-typed text onto the end.
2288   
2289    i=2+buffer->1; (buffer->1)++; buffer->(i++) = ' ';
2290    for (j=0: j<buffer2->1: i++, j++)
2291    {   buffer->i = buffer2->(j+2);
2292        (buffer->1)++;
2293        if (buffer->1 == 120) break;
2294    }    
2295   
2296  !  (3) we fill up the buffer with spaces, which is unnecessary, but may
2297  !      help incorrectly-written interpreters to cope.
2298   
2299    for (:i<120:i++) buffer->i = ' ';
2300   
2301    return REPARSE_CODE;
2302  ];


Last updated 27 February 2004. This site is no longer supported; information may be out of date.
Maintained as a historical archive by the Interactive Fiction Technology Foundation. Copyright 1993-2018 IFTF, CC-BY-SA unless otherwise noted.
This page was originally managed by Graham Nelson (graham@gnelson.demon.co.uk) assisted by C Knight.