Original Parser

version 1 by Ron Newcomb

  • Home page
  • Beginning
  • Previous
  • Next



  • Book - Does The Player Mean

    Chapter - Choose Objects

    [This material, the final body of code in the parser, is an I7 addition.
    The I6 parser leaves it to the user to provide a |ChooseObjects| routine
    to decide between possibilities when the situation is ambiguous. For I7
    use, we provide a |ChooseObjects| which essentially runs the ``does the
    player mean'' rulebook to decide, though this is not obvious from the
    code below because it is hidden in the |CheckDPMR| routine -- which
    is defined in the Standard Rules, not here.]

    To decide which number is the maximum possible does-the-player-mean score: (- HIGHEST_DPMR_SCORE -).
    To decide which 0-based index based rulebook producing objects is the alternate match list: (-alt_match_list-).
    The number of objects in the alternate match list is a number that varies.
    [ The alternate match list was originally 1-based even though the original match list is 0-based. I've made it 0-based because the code is much neater that way. ]

    Include (-
    !Constant COBJ_DEBUG;

    ! the highest value returned by CheckDPMR (see the Standard Rules)
    Constant HIGHEST_DPMR_SCORE = 4;

    Array alt_match_list --> (MATCH_LIST_WORDS+1);
    -).

    [ swap alt_match_list with match_list/number_matched ]
    To swap the match list with the alternate match list (this is COBJ__SwapMatches):
        let x be the number of objects in the match list;
        now the number of objects in the match list is the number of objects in the alternate match list;
        now the number of objects in the alternate match list is x;
        let obj be an object;
        repeat through the match list of size the number of objects in the match list:
            now obj is the match list element;
            change the chosen element of the match list to the alternate match list element;
            change the chosen element of the alternate match list to obj.

    [ COBJ__SwapMatches i x;
        ! swap the counts
        x = number_matched;
        number_matched = alt_match_list-->0;
        alt_match_list-->0 = x;
        ! swap the values
        if (x < number_matched) x = number_matched;
        for (i=x: i>0: i-- ) {
            x = match_list-->(i-1);
            match_list-->(i-1) = alt_match_list-->i;
            alt_match_list-->i = x;
        }
    ]

    [ To remove the Jumps from this, the bottom third of the function was moved to be the first third. To ease the creation of its surrounding utility functions, the alternate match list was changed from being 1-based to 0-based just like the match list that it mirrors. ]
    To decide what number is how much does the player mean (obj - an object) (this is ChooseObjects):
        [if the deciding whether all includes activity is going on, decide on 0; ]
        if the ranking strategy is 0:
            if the choose objects debugging option is active, say "[bracket]choosing a cobj strategy: ";
            [ save these ]
            let saved position be the parser's current word position;
            let saved understood command's current position be the understood command's current position;
            [ advance past the "prepositions" ]
            while '<understood word>' is the (understood command's current position) element of the grammar line types:
                increment the understood command's current position;
            if the (understood command's current position) element of the grammar line types is '<grammar token>':
                while the parser's current word position <= the number of words in the command:
                    let the current word be the next word if any;
                    if (the current word is either a word unknown by the game or no more words left to parse) and the usage of the current word includes being a preposition, next;
                    if the current word is 'ALL', next;
                    decrement the parser's current word position; [back up again to point at the non-ALL word]
                    [ get here with TAKE ALL HATS ]
                    skip over any descriptor words;
                    [ save some state, including the whole match list ]
                    save the number of words matched per object;
                    save the noun filter;
                    save the next word to parse's position;
                    now the number of objects in the alternate match list is the number of objects in the match list;
                    copy (number of objects in the match list) chosen objects from the match list to the alternate match list;
                    [ Change what's in scope?? ]
                    now the number of words matched per object is 0;
                    now the noun filter is the nothing rule;
                    now the number of objects in the match list is 0;
                    now the next word to parse's position is the parser's current word position;
                    search the scope of the person asked and the actor's scopewise location under the (understood command's current position) element of the grammar line data;
                    if the choose objects debugging option is active, say "[number of objects in the match list] possible second nouns[close bracket][line break]";
                    now the ranking strategy is 1;
                    [ restore ]
                    swap the match list with the alternate match list;
                    restore the next word to parse's position;
                    restore the noun filter;
                    restore the the number of words matched per object;
            [ now restore these ]
            now the understood command's current position is the saved understood command's current position;
            now the parser's current word position is the saved position;
            unless the ranking strategy is 1:
                now the ranking strategy is 2;
                if the choose objects debugging option is active, say "nothing interesting[close bracket][line break]";
        let this object's score be 0;
        if the ranking strategy is 1:
            if the number of parameters in the command is at least one:
                if the choose objects debugging option is active, say "[bracket]scoring [the obj] (second)[close bracket][line break]";
                decide on the disambiguating score for the parser's returned noun combined with the obj;
            otherwise:
                if the choose objects debugging option is active, say "[bracket]scoring [the obj] (first) in [the number of objects in the alternate match list] combinations[close bracket][line break]";
                let their maximum score be 0;
                repeat through the alternate match list of size the number of objects in the alternate match list:
                    now this object's score is the disambiguating score for the obj combined with the object element;
                    if this object's score is the maximum possible does-the-player-mean score:
                        if the choose objects debugging option is active, say "[bracket]scored [this object's score] - best possible[close bracket][line break]";
                        decide on this object's score;
                    if this object's score > their maximum score, now their maximum score is this object's score;
                decide on their maximum score;
        otherwise [ the ranking strategy is 2 ]:
            if the choose objects debugging option is active, say "[bracket]scoring [the obj] (simple); parameters = [the number of parameters in the command] aw = [the likely second noun][close bracket][line break]";
            save the action to be; [ Is this necessary? I don't believe so. ]
            if the number of parameters in the command is zero:
                unless the likely second noun is either nothing or the used-up object:
                    now this object's score is the disambiguating score for the obj combined with the likely second noun;
                otherwise:
                    now this object's score is the disambiguating score for the obj combined with nothing;
            otherwise:
                now this object's score is the disambiguating score for the parser's returned noun combined with the obj;
            restore the action to be;
            decide on this object's score.

        

    [ Once you enter the ==1 or ==2 if-statements in here, you don't get back out. ]
    [ ChooseObjects obj code l i swn spcount;
        if (code<2) rfalse;

        if (cobj_flag == 1) {
            .CodeOne;
            if (parameters > 0)
            { #ifdef COBJ_DEBUG; print "[scoring ", (the) obj, " (second)]^"; #endif;
                return ScoreDabCombo(parser_results-->INP1_PRES, obj);
            } else
            { #ifdef COBJ_DEBUG; print "[scoring ", (the) obj, " (first) in ", alt_match_list-->0, " combinations]^"; #endif;
                l = 0;
                for (i=1: i<=alt_match_list-->0: i++)
                { spcount = ScoreDabCombo(obj, alt_match_list-->i);
                    if (spcount == (+ the maximum possible does-the-player-mean score +))
                    { #ifdef COBJ_DEBUG; print "[scored ", spcount, " - best possible]^"; #endif;
                        return spcount;
                    }
                    if (spcount>l) l = spcount;
                }
                return l;
            }
        }
        if (cobj_flag == 2) {
            .CodeTwo;
            #ifdef COBJ_DEBUG; print "[scoring ", (the) obj, " (simple); parameters = ", parameters, " aw = ", advance_warning, "]^"; #endif;
            @push action_to_be;
            if (parameters==0)
            { if (advance_warning > 0)
                    l = ScoreDabCombo(obj, advance_warning);
                else
                    l = ScoreDabCombo(obj, 0);
            } else
                l = ScoreDabCombo(parser_results-->INP1_PRES, obj);
            @pull action_to_be;
            return l;
        }

        #ifdef COBJ_DEBUG; print "[choosing a cobj strategy: "; #endif;
        swn = wn;
        spcount = pcount;
        while (line_ttype-->pcount == PREPOSITION_TT)
            pcount++;
        if (line_ttype-->pcount == ELEMENTARY_TT)
        {
            while (wn <= num_words)
            {
                l = NextWordStopped(); wn--;
                if ( (l ~= -1 or 0) && (l->#dict_par1) &8 ) { wn++; continue; } ! if preposition
                if (l == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD) { wn++; continue; }
                
                SafeSkipDescriptors();
                ! save the current match state
                @push match_length; @push token_filter; @push match_from;
                alt_match_list-->0 = number_matched;
                COBJ__Copy(number_matched, match_list, alt_match_list+WORDSIZE);
                ! now get all the matches for the second noun
                match_length = 0; number_matched = 0; match_from = wn;
                token_filter = 0;
                SearchScope(actor, actors_location, line_tdata-->pcount);
                #ifdef COBJ_DEBUG;
                print number_matched, " possible second nouns]^";
                #endif;
                wn = swn;
                cobj_flag = 1;
                ! restore match variables
                COBJ__SwapMatches();
                @pull match_from; @pull token_filter; @pull match_length;
                pcount = spcount;
                jump CodeOne;
            }
        }
        pcount = spcount;
        wn = swn;
        
        #ifdef COBJ_DEBUG; print "nothing interesting^"; #endif;
        cobj_flag = 2;
        jump CodeTwo;
    ]



    To decide what number is the disambiguating score for (first item - an object) combined with (second item - an object) (this is ScoreDabCombo):
        save the action in progress;
        save the person requesting;
        save the noun;
        save the second noun;
        now the action in progress is the action to be;
        now the person requesting is the player;
        if the action's nouns swapped places is true:
            now the noun is the second item;
            now the second noun is the first item;
        otherwise:
            now the noun is the first item;
            now the second noun is the second item;
        let result be did the player mean this;
        restore the second noun;
        restore the noun;
        restore the person requesting;
        restore the action in progress;
        if the choose objects debugging option is active, say "[bracket][the first item] / [the second item] => [the result][close bracket][line break]";
        decide on the result.

    [ ScoreDabCombo a b result;
        @push action; @push act_requester; @push noun; @push second;
        action = action_to_be;
        act_requester = player;
        if (action_reversed) { noun = b; second = a; }
        else { noun = a; second = b; }
        result = CheckDPMR();
        @pull second; @pull noun; @pull act_requester; @pull action;
        #ifdef COBJ_DEBUG;
        print "[", (the) a, " / ", (the) b, " => ", result, "]^";
        #endif;
        return result;
    ]