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 web site has not been fully supported since April 2008. Information may be out of date. This page was originally managed by Graham Nelson (graham@gnelson.demon.co.uk) assisted by C Knight.