Determining Multi or Single Dobj

Okay, so: Somewhere in the library, a response is generated:

Sorry; multiple objects aren’t allowed with that command.

Whatever is creating that response is probably where we could find a comparison for what we need.

HOWEVER, I am still a moron!

Because both multi-noun and single-noun actions can ask for disambiguation!

So, what I’m trying to figure out (for real this time!) is if the command is dealing with plurals, or a singular noun, regardless of capability.

So, “x cup” vs “x cups”. I need to be able to detect if multiple nouns are being grabbed because “cups” applies to multiple, or if disambiguation is needed because “cup” applies to multiple, but only one was specified.

Basically, I’m trying to see if the player is trying to target a specific noun from a cluster of nouns that could apply.

However, as promised, here is the relfection-based code I found, which solves the problem stated at the start:

#include "reflect.t"

#define gActionIsMulti (cursedCore.isCurrentActionMutli())
#define commandIsMulti(cmd) (cursedCore.isCurrentActionMutli(cmd))

cursedCore: object {
    isCurrentActionMutli(cmd?) {
        if (cmd == nil) cmd = gCommand;
        local dm = cmd.verbProd.dobjMatch;
        local dmStr = reflectionServices.valToSymbol(dm);

        // Uncomment for debug reasons:
        //"<<dmStr>>\n";
        
        if (dmStr == '{obj:nounList(empty)}') return true;
        if (dmStr == '{obj:nounList(list)}') return true;
        if (dmStr == '{obj:nounList(nonTerminal)}') return true;
        if (dmStr == '{obj:nounList(terminal)}') return true;
        return nil;
    }
}

This does not solve the problem I actually have, but my original problem statement was also wrong.
However, if a future explorer is trying to determine if their verb is a single or multi, then this will do it in a hilarious way.

I will start another topic shortly with a more precise problem statement. Hope to see @johnnywz00 there.

1 Like

Check parser.t starting at line 540

1 Like

For the record, Command.verbProd.dobjMatch.Prod does not seem to be a defined symbol.

For any future explorers, check out this absolute colossus of an if-statement, lmao:

/* 
 *   We next have to ensure that the player hasn't entered
 *   multiple nouns in a slot that only allows a single noun
 *   in the grammar. If the player has entered two objects
 *   like "the bat and the ball" in such a case, the
 *   badMulti flag will be set on the command object, so we
 *   first test for that and abort the command with a
 *   suitable error message if badMulti is not nil (by
 *   throwing a BadMultiError
 *
 *   Unfortunately the badMulti flag doesn't get set if the
 *   player enters a multiple object as a plural (e.g.
 *   "bats"), so we need to trap this case too. We do that
 *   by checking whether there's multiple objects in the
 *   direct, indirect and accessory object slots at the same
 *   time as the grammar tag matching the slot in question
 *   is 'normal', which it is only for a single noun match.
 */
 
if(cmd && cmd.verbProd != nil &&                        
    (cmd.badMulti != nil 
   || (cmd.verbProd.dobjMatch != nil &&
       cmd.verbProd.dobjMatch.grammarTag == 'normal'
       && cmd.dobjs.length > 1)
   ||
   (cmd.verbProd.iobjMatch != nil &&
       cmd.verbProd.iobjMatch.grammarTag == 'normal'
       && cmd.iobjs.length > 1)                          
    ||
   (cmd.verbProd.accMatch != nil &&
       cmd.verbProd.accMatch.grammarTag == 'normal'
       && cmd.accs.length > 1)
       ))
    cmd.cmdErr = new BadMultiError(cmd.np);

These are clues, though!!! Clues!!!

Where’s @HanonO, when you need his Benoit Blanc schtick…

EDIT: Hold on, I’m breaking it down. There’s something to be learned here…

I was using abbreviations… the class is Production, and you would access it like action.verbRule.dobjMatch.np_
Or gCommand.verbProd.dobjMatch.np_

1 Like

Ah. My bad; I’m a few red bulls into a coding-since-I-woke-up day, and I have enough autism to be very direct when reading stuff sometimes.

1 Like

Notice they check dobjMatch.grammarTag and command.dobjs.length…

1 Like

Yeah, that made my ears perk up a bit.

For any future explorers, here’s an expanded version of that if-statement:

local caseGrpD = (cmd.verbProd.dobjMatch != nil &&
   cmd.verbProd.dobjMatch.grammarTag == 'normal'
   && cmd.dobjs.length > 1)

local caseGrpI = (cmd.verbProd.iobjMatch != nil &&
   cmd.verbProd.iobjMatch.grammarTag == 'normal'
   && cmd.iobjs.length > 1)

local caseGrpA = (cmd.verbProd.accMatch != nil &&
   cmd.verbProd.accMatch.grammarTag == 'normal'
   && cmd.accs.length > 1)
 
if (cmd && cmd.verbProd != nil) {
    if (cmd.badMulti != nil || caseGrpD || caseGrpI || caseGrpA) {
        cmd.cmdErr = new BadMultiError(cmd.np);
    }
}
if (cmd.cmdErr != nil) {
    throw cmd.cmdErr;
}
1 Like

BadMultiError is what shows ‘you can’t use multiple objects there’

1 Like

Okay, new code!

#define gActionIsMulti (notCursedCore.isCurrentActionMulti())
#define commandIsMulti(cmd) (notCursedCore.isCurrentActionMulti(cmd))

notCursedCore: object {
    isCurrentActionMulti(cmd?) {
        if (cmd == nil) cmd = gCommand;
        return cmd.verbProd.dobjMatch.grammarTag != 'normal';
    }
}

This should be necessary to check if an executing action takes singleDobj or multiDobj!

EDIT: Implementers beware of nil reference exceptions. This makes a lot of assumptions, but this is the comparison you would look for.

1 Like

Seems like that could be a top-level function… also, did you mean to spell it Mutli instead of Multi?

1 Like

I grew up on Java, so I keep forgetting top-level functions are a thing lmao. But yeah, you’re right, it could be.

Ooops!! lol

1 Like