Redirecting all disambiguation requests?

I’m working on a demo which runs entirely by keywords, and I’d like to be able to prevent the game from ever asking for disambiguation. So if the player just types “x,” I’d like to have the game go straight to the routine for processing an invalid keyword rather than ask “What do you want to examine?” and then go to the routine for processing an invalid keyword.

Is there a hook I can use to stop the disambiguation from happening? The following doesn’t work:

Before asking which do you mean: try wrong-keywording instead. Rule for supplying a missing noun: Try wrong-keywording instead.

(“Wrong-keywording” is what I want to happen when a wrong keyword is entered.)

The most efficient route is to go into NounDomain in Parser.i6t, and tell it to rfalse; before running any of the “which do you mean” activities.

In fact, you can probably just do one rfalse; right after the bit where it returns a match if it’s got one; that’s about ten lines from the top of the function.

cheers
jon

After fooling around with a lot of stuff that turned out to be not necessary, this is what I came up with:

[code]Section - Disable disambiguation questions

[Here we rewrite NounDomain to stop disambiguation questions.]

Include (-
[ NounDomain domain1 domain2 context
first_word i j k l answer_words marker;
#Ifdef DEBUG;
if (parser_trace >= 4) {
print " [NounDomain called at word ", wn, “^”;
print " ";
if (indef_mode) {
print "seeking indefinite object: ";
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 “seeking definite object^”;
}
#Endif; ! DEBUG

match_length = 0; number_matched = 0; match_from = wn;

SearchScope(domain1, domain2, context);

#Ifdef DEBUG;
if (parser_trace >= 4) print "   [ND made ", number_matched, " matches]^";
#Endif; ! DEBUG

wn = match_from+match_length;

! If nothing worked at all, leave with the word marker skipped past the
! first unmatched word...

if (number_matched == 0) { wn++; rfalse; }

! Suppose that there really were some words being parsed (i.e., we did
! not just infer).  If so, and if there was only one match, it must be
! right and we return it...

if (match_from <= num_words) {
    if (number_matched == 1) {
        i=match_list-->0;
        return i;
    }

    ! ...now suppose that there was more typing to come, i.e. suppose that
    ! the user entered something beyond this noun.  If nothing ought to follow,
    ! then there must be a mistake, (unless what does follow is just a full
    ! stop, and or comma)

    if (wn <= num_words) {
        i = NextWord(); wn--;
        if (i ~=  AND1__WD or AND2__WD or AND3__WD or comma_word
               or THEN1__WD or THEN2__WD or THEN3__WD
               or BUT1__WD or BUT2__WD or BUT3__WD) {
            if (lookahead == ENDIT_TOKEN) rfalse;
        }
    }
}

! Now look for a good choice, if there's more than one choice...

number_of_classes = 0;

if (number_matched == 1) i = match_list-->0;
if (number_matched > 1) {
    i = Adjudicate(context);
    if (i == -1) rfalse;
    if (i == 1) rtrue;       !  Adjudicate has made a multiple
                         !  object, and we pass it on

}

! If i is non-zero here, one of two things is happening: either
! (a) an inference has been successfully made that object i is
!     the intended one from the user's specification, or
! (b) the user finished typing some time ago, but we've decided
!     on i because it's the only possible choice.
! In either case we have to keep the pattern up to date,
! note that an inference has been made and return.
! (Except, we don't note which of a pile of identical objects.)

if (i ~= 0) {
    if (dont_infer) return i;
    if (inferfrom == 0) inferfrom=pcount;
    pattern-->pcount = i;
    return i;
}

! If we get here, there was no obvious choice of object to make.

rfalse;

]; ! end of NounDomain
-) instead of “Noun Domain” in “Parser.i6t”.

Rule for printing a parser error:
say “This is where Matt’s rules intervene.” instead.[/code]

Oh, by the way, that code runs your special rule whenever there is a parser error. This code will only run your special rule instead of a disambiguation question:

[code]Section - Disable disambiguation questions

ambiguity_alert is a number that varies. ambiguity_alert is usually 0.

[Here we rewrite NounDomain to stop disambiguation questions.]

Include (-
[ NounDomain domain1 domain2 context
first_word i j k l answer_words marker;
#Ifdef DEBUG;
if (parser_trace >= 4) {
print " [NounDomain called at word ", wn, “^”;
print " ";
if (indef_mode) {
print "seeking indefinite object: ";
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 “seeking definite object^”;
}
#Endif; ! DEBUG

match_length = 0; number_matched = 0; match_from = wn;

SearchScope(domain1, domain2, context);

#Ifdef DEBUG;
if (parser_trace >= 4) print "   [ND made ", number_matched, " matches]^";
#Endif; ! DEBUG

wn = match_from+match_length;

! If nothing worked at all, leave with the word marker skipped past the
! first unmatched word...

if (number_matched == 0) { wn++; rfalse; }

! Suppose that there really were some words being parsed (i.e., we did
! not just infer).  If so, and if there was only one match, it must be
! right and we return it...

if (match_from <= num_words) {
    if (number_matched == 1) {
        i=match_list-->0;
        return i;
    }

    ! ...now suppose that there was more typing to come, i.e. suppose that
    ! the user entered something beyond this noun.  If nothing ought to follow,
    ! then there must be a mistake, (unless what does follow is just a full
    ! stop, and or comma)

    if (wn <= num_words) {
        i = NextWord(); wn--;
        if (i ~=  AND1__WD or AND2__WD or AND3__WD or comma_word
               or THEN1__WD or THEN2__WD or THEN3__WD
               or BUT1__WD or BUT2__WD or BUT3__WD) {
            if (lookahead == ENDIT_TOKEN) rfalse;
        }
    }
}

! Now look for a good choice, if there's more than one choice...

number_of_classes = 0;

if (number_matched == 1) i = match_list-->0;
if (number_matched > 1) {
    i = Adjudicate(context);
    if (i == -1) rfalse;
    if (i == 1) rtrue;       !  Adjudicate has made a multiple
                         !  object, and we pass it on

}

! If i is non-zero here, one of two things is happening: either
! (a) an inference has been successfully made that object i is
!     the intended one from the user's specification, or
! (b) the user finished typing some time ago, but we've decided
!     on i because it's the only possible choice.
! In either case we have to keep the pattern up to date,
! note that an inference has been made and return.
! (Except, we don't note which of a pile of identical objects.)

if (i ~= 0) {
    if (dont_infer) return i;
    if (inferfrom == 0) inferfrom=pcount;
    pattern-->pcount = i;
    return i;
}

! If we get here, there was no obvious choice of object to make.

(+ ambiguity_alert +) = 1;
rfalse;

]; ! end of NounDomain
-) instead of “Noun Domain” in “Parser.i6t”.

Rule for printing a parser error when ambiguity_alert is 1:
now ambiguity_alert is 0;
say “This is where Matt’s rules intervene.” instead. [/code]

Thanks Victor and Jon! As it happens I also want to run the code whenever there’s a parser error (though I know how to do that in I7), so I can use your first code.

It looks like I also need something to replace “block vaguely going,” but that shouldn’t be a problem.

If you don’t have any use for the standard grammar at all you could just remove the part that defines it in the Standard Library, leaving just the out of world actions:

[code]Section Grammar (in place of Section SR4/10 - Grammar in Standard Rules by Graham Nelson)

Understand “score” as requesting the score.
Understand “quit” or “q” as quitting the game.
Understand “save” as saving the game.
Understand “restart” as restarting the game.
Understand “restore” as restoring the game.
Understand “verify” as verifying the story file.
Understand “version” as requesting the story file version.
Understand “script” or “script on” or “transcript” or “transcript on” as switching the story
transcript on.
Understand “script off” or “transcript off” as switching the story transcript off.[/code]
(This is what I did in Starborn and it worked quite well.)

The added benefit is that you still get the disambiguation prompt if the player uses a keyword that’s a synonym for more than one object.

Oh, very nice! This is exactly what I want, though I think I’ll drop “score.”

[EDIT: Though maybe I’ll use Victor’s code as well, because I’m not sure I want to produce a disambiguation request if the player enters “the”; if they only enter “the” then they get the wrong-keyword code, dammit. This isn’t a very gamey game.]