Original Parser

version 1 by Ron Newcomb

  • Home page
  • Beginning
  • Previous
  • Next



  • Chapter - Adjudicate

    [The |Adjudicate| routine tries to see if there is an obvious choice, when
    faced with a list of objects (the |match_list|) each of which matches the
    player's specification equally well. To do this it makes use of the |context|
    (the token type being worked on).

    It counts up the number of obvious choices for the given context -- all to
    do with where a candidate is, except for 6 (|animate|) which is to
    do with whether it is animate or not -- and then:

    (a) if only one obvious choice is found, that is returned;
    (b) if we are in indefinite mode (don't care which) one of the obvious choices
    is returned, or if there is no obvious choice then an non-obvious one is made;
    (c) at this stage, we work out whether the objects are distinguishable from
    each other or not: if they are all indistinguishable from each other, then
    choose one, it doesn't matter which;
    (d) otherwise, 0 (meaning, unable to decide) is returned (but remember
    that the equivalence classes we've just worked out will be needed by other
    routines to clear up this mess, so we can't economise on working them out).

    |Adjudicate| returns $-1$ if an error occurred.

    returns 1 on multiple-object list?
    ]

    To decide what pattern union is the result of adjudicating under (context - a grammar token) (this is Adjudicate):
        if trace 4, say " [bracket]Adjudicating match list of size [the number of objects in the match list] in context [the context][line break] [the descriptor status]";
        [ First, let's see which ones agree with the specified Understand Token. ]
        let the count of hopefuls be 0;
        let the recent hopeful be nothing;
        repeat through the match list of size the number of objects in the match list:
            change the match score list element to 0;
            if the context is:
                -- 'something preferably held':
                    if the chosen element is directly in the person asked:
                        change the match score list element to how much token agreement's worth;
                -- 'things':
                    if the chosen element is not the person asked and the chosen element does not provide the property undescribed directly and the chosen element does not provide the property scenery directly and the scope ceiling of the chosen element is the scope ceiling of the person asked:
                        change the match score list element to how much token agreement's worth;
                -- 'things preferably held':
                    if the chosen element is directly in the person asked:
                        change the match score list element to how much token agreement's worth;
                -- 'other things':
                    if we do not suspect what the second noun will be or the chosen element is not the likely second noun:
                        change the match score list element to how much token agreement's worth;
                -- 'things inside':
                    if we do not suspect what the second noun will be:
                        if the person asked doesn't have the chosen element:
                            change the match score list element to how much token agreement's worth;
                    otherwise if the chosen element is directly in the likely second noun:
                        change the match score list element to how much token agreement's worth;
                -- 'someone':
                    if the chosen element is a creature:
                        change the match score list element to how much token agreement's worth;
            if the match score list element is at least 1:
                increment the count of hopefuls;
                now the recent hopeful is the chosen element;
        if the count of hopefuls is 1:
            decide on the recent hopeful as a successful match;
        [ If there is ambiguity about what was typed, but it definitely wasn't animate as required, then return anything; higher up in the parser a suitable error will be given. (This prevents a question being asked.) ]
        if the count of hopefuls is 0 and the context is 'someone':
            decide on the 0th element of the match list as a [non-]successful match;
        if the indefinite article mode is false:
            exclude all possibilities from the type of descriptor word used;
        RANK the remaining according to their properties and descriptor words used and their location regarding the context;
        if the number of objects [hopefuls] in the match list is 0:
            decide on the null pattern;
        if the indefinite article mode is false: [ if 'THE', ]
            let the hopeful be the single best guess;
            unless the hopeful is the used-up object:
                if trace 4, say " Single best-scoring object returned.[close bracket][line break]";
                decide on the hopeful as a successful match;
        if the indefinite article mode is true and the type of descriptor word used includes a plural descriptor:
            if the context is neither 'things' nor 'things preferably held' nor 'other things' nor 'things inside':
                issue "You can’t use multiple objects with that verb." as can’t use multiple objects error;
                decide on the null pattern; [get here with EXAMINE ALL HAT ]
            now the count of hopefuls is 0;
            now the recent hopeful is the best guess;
            let include it be false;
            while the recent hopeful is not the used-up object and the count of hopefuls < the number of items wanted: [ get here with TAKE ALL HAT ]
                begin THE DECIDING WHETHER ALL INCLUDES ACTIVITY with the recent hopeful;
                unless handling THE DECIDING WHETHER ALL INCLUDES ACTIVITY with the recent hopeful:
                    we should include it if the rule succeeded;
                otherwise:
                    we should include it if the recent hopeful is described not worn;
                    if the person asked doesn't have the recent hopeful and the context is either 'things preferably held' or 'other things':
                        we shouldn't include it;
                    if the recent hopeful is directly in the person asked and the action to be is either the taking action or the removing it from action:
                        we shouldn't include it;
                end THE DECIDING WHETHER ALL INCLUDES ACTIVITY with the recent hopeful;
                if trace 4, say " [if we should include it]Accept[else]Reject[end if]ing it[line break]";
                if we should include it:
                    add the recent hopeful to the multiple-object list, allowing duplicates;
                    increment the count of hopefuls;
                now the recent hopeful is the best guess;
            if the count of hopefuls < the number of items wanted and the number of items wanted < all items are wanted: [ get here with TAKE 9 HAT though the error message may be changed. ]
                issue "Only X of those are available." as the not enough of those available error;
                now the number of items wanted previously wanted is the number of items wanted;
                now the number of items actually received is the count of hopefuls;
                decide on the null pattern;
            now the kind of multi is the context;
            if trace 4, say " Made multiple object of size [the count of hopefuls][close bracket][line break]";
            decide on the noun domain's bunch of objects;
        [ Now that we have the list of "all" of the objects, let's group indistinguishable objects together. ]
        now the number of match groups is 0; [ get here with TAKE HAT that provokes a which-did-you-mean. ]
        repeat through the match list's groups of size the number of objects in the match list:
            change the chosen element of the match list's groups to the 0th [group];
            if an earlier indistinguishable element is listed in the match list:
                we should say the earlier element of the match list's groups as A\AN\SOME;
                change the chosen element of the match list's groups to the earlier element of the match list's groups;
            if the match list's groups element is [still] 0:
                increment the number of match groups;
                change the chosen element of the match list's groups to the number of match groups;
        if trace 4, say " Grouped into [the number of match groups] possibilities by name:[line break][the match list]";
        if the indefinite article mode is false and the number of match groups is at least 2:
            let found a clear winner be false;
            let the best score so far be -1;
            repeat through the match score list of size the number of objects in the match list:
                if the match score list element is greater than the best score so far:
                    now the best score so far is the match score list element;
                    we just found a clear winner;
                otherwise if the match score list element is the best score so far:
                    we no longer have found a clear winner;
            if we haven't found a clear winner:
                if trace 4, say " Unable to choose best group, so ask player.[close bracket][line break]";
                decide on a bunch of objects;
            if trace 4, say " Best choices are all from the same group.";
        [ When the player is really vague, or there's a single collection of indistinguishable objects to choose from, choose the one the player most recently acquired, or if the player has none of them, then the one most recently put where it is. ]
        if the number of match groups is 1, we needn't make inferences;
        decide on the best guess as a successful match.

    [ Adjudicate context i j k good_ones last n ultimate flag offset;
    #Ifdef DEBUG;
    if (parser_trace >= 4) {
    print " [Adjudicating match list of size ", number_matched,
    " in context ", context, "^";
    print " ";
    if (indef_mode) {
    print "indefinite type: ";
    if (indef_type & OTHER_BIT) print "other ";
    if (indef_type & MY_BIT) print "my ";
    if (indef_type & THAT_BIT) print "that ";
    if (indef_type & PLURAL_BIT) print "plural ";
    if (indef_type & LIT_BIT) print "lit ";
    if (indef_type & UNLIT_BIT) print "unlit ";
    if (indef_owner ~= 0) print "owner:", (name) indef_owner;
    new_line;
    print " number wanted: ";
    if (indef_wanted == INDEF_ALL_WANTED) print "all"; else print indef_wanted;
    new_line;
    print " most likely GNAs of names: ", indef_cases, "^";
    }
    else print "definite object^";
    }
    #Endif; ! DEBUG

    j = number_matched-1; good_ones = 0; last = match_list-->0;
    for (i=0 : i<=j : i++) {
    n = match_list-->i;
    match_scores-->i = good_ones;
    ultimate = ScopeCeiling(n);

    if (context==HELD_TOKEN && parent(n)==actor)
    { good_ones++; last=n; }
    if (context==MULTI_TOKEN && ultimate==ScopeCeiling(actor)
    && n~=actor && n hasnt concealed && n hasnt scenery)
    { good_ones++; last=n; }
    if (context==MULTIHELD_TOKEN && parent(n)==actor)
    { good_ones++; last=n; }

    if (context==MULTIEXCEPT_TOKEN or MULTIINSIDE_TOKEN)
    { if (advance_warning==-1)
    { if (context==MULTIEXCEPT_TOKEN)
    { good_ones++; last=n;
    }
    if (context==MULTIINSIDE_TOKEN)
    { if (parent(n)~=actor) { good_ones++; last=n; }
    }
    }
    else
    { if (context==MULTIEXCEPT_TOKEN && n~=advance_warning)
    { good_ones++; last=n; }
    if (context==MULTIINSIDE_TOKEN && n in advance_warning)
    { good_ones++; last=n; }
    }
    }
    if (context==CREATURE_TOKEN && CreatureTest(n)==1)
    { good_ones++; last=n; }

    match_scores-->i = SCORE__IFGOOD*(good_ones - match_scores-->i);
    }
    if (good_ones == 1) return last;

    ! If there is ambiguity about what was typed, but it definitely wasn't
    ! animate as required, then return anything; higher up in the parser
    ! a suitable error will be given. (This prevents a question being asked.)

    if (context == CREATURE_TOKEN && good_ones == 0) return match_list-->0;

    if (indef_mode == 0) indef_type=0;

    ScoreMatchL(context);
    if (number_matched == 0) return -1;

    if (indef_mode == 0) {
    ! Is there now a single highest-scoring object?
    i = SingleBestGuess();
    if (i >= 0) {

    #Ifdef DEBUG;
    if (parser_trace >= 4) print " Single best-scoring object returned.]^";
    #Endif; ! DEBUG
    return i;
    }
    }

    if (indef_mode == 1 && indef_type & PLURAL_BIT ~= 0) {
    if (context ~= MULTI_TOKEN or MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN
    or MULTIINSIDE_TOKEN) {
    etype = MULTI_PE;
    return -1;
    }
    i = 0; offset = multiple_object-->0;
    for (j=BestGuess(): j~=-1 && i<indef_wanted && i+offset<MATCH_LIST_WORDS-1:
    j=BestGuess()) {
    flag = 0; ! flag is a rulebook outcome for . the it does not outcome.
    BeginActivity(DECIDING_WHETHER_ALL_INC_ACT, j);
    if ((ForActivity(DECIDING_WHETHER_ALL_INC_ACT, j)) == 0) {

    if (j hasnt concealed && j hasnt worn) flag = 1;

    if (context == MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN && parent(j) ~= actor)
    flag = 0;

    if (action_to_be == ##Take or ##Remove && parent(j) == actor)
    flag = 0;

    k = ChooseObjects(j, flag);

    if (k == 1) ! "it does"
    flag = 1;
    else {
    if (k == 2) flag = 0; ! "it does not"
    }
    } else {
    flag = 0; if (RulebookSucceeded()) flag = 1;
    }
    EndActivity(DECIDING_WHETHER_ALL_INC_ACT, j);
    if (flag == 1) { ! if the rule succeeded,
    i++; multiple_object-->(i+offset) = j;
    #Ifdef DEBUG;
    if (parser_trace >= 4) print " Accepting it^";
    #Endif; ! DEBUG
    }
    else {
    i = i;
    #Ifdef DEBUG;
    if (parser_trace >= 4) print " Rejecting it^";
    #Endif; ! DEBUG
    }
    }
    if (i < indef_wanted && indef_wanted < INDEF_ALL_WANTED) {
    etype = TOOFEW_PE; multi_wanted = indef_wanted;
    multi_had=i;
    return -1;
    }
    multiple_object-->0 = i+offset;
    multi_context = context;
    #Ifdef DEBUG;
    if (parser_trace >= 4)
    print " Made multiple object of size ", i, "^";
    #Endif; ! DEBUG
    return 1;
    }

    for (i=0 : i<number_matched : i++) match_classes-->i = 0;

    n = 1;
    for (i=0 : i<number_matched : i++)
    if (match_classes-->i == 0) {
    match_classes-->i = n++; flag = 0;
    for (j=i+1 : j<number_matched : j++)
    if (match_classes-->j == 0 && Identical(match_list-->i, match_list-->j) == 1) {
    flag=1;
    match_classes-->j = match_classes-->i;
    }
    if (flag == 1) match_classes-->i = 1-n;
    }
    n--; number_of_classes = n;

    #Ifdef DEBUG;
    if (parser_trace >= 4) {
    print " Grouped into ", n, " possibilities by name:^";
    for (i=0 : i<number_matched : i++)
    if (match_classes-->i > 0)
    print " ", (The) match_list-->i, " (", match_list-->i, ") --- group ",
    match_classes-->i, "^";
    }
    #Endif; ! DEBUG

    if (indef_mode == 0)
    {
    if (n > 1)
    {
    k = -1;
    for (i=0 : i<number_matched : i++)
    {
    if (match_scores-->i > k)
    {
    k = match_scores-->i;
    j = match_classes-->i; j = j*j;
    flag = 0;
    }
    else if (match_scores-->i == k)
    {
    if ((match_classes-->i) * (match_classes-->i) ~= j)
    flag = 1;
    }
    }

    if (flag)
         {
    #Ifdef DEBUG;
    if (parser_trace >= 4) print " Unable to choose best group, so ask player.^";
    #Endif; ! DEBUG
    return 0;
    }
    #Ifdef DEBUG;
    if (parser_trace >= 4) print " Best choices are all from the same group.^";
    #Endif; ! DEBUG
    }
    }

    ! When the player is really vague, or there's a single collection of
    ! indistinguishable objects to choose from, choose the one the player
    ! most recently acquired, or if the player has none of them, then
    ! the one most recently put where it is.

    if (n == 1) dont_infer = false; !true;
    return BestGuess();
    ]