Take all (adv3Lite)

Here’s a pretty little problem. The PC is carrying a BagOfHolding, which may contain quite a number of things. When the player types ‘take all,’ the library will proceed to grab, one by one, everything in the BagOfHolding, after which, soon enough, most everything will get put back in the bag.

It’s awfully messy, and it’s needless. But Take is defined simply enough with a multiDobj:

VerbRule(Take)
    ('take' | 'pick' 'up' | 'get') multiDobj
    | 'pick' multiDobj 'up'

I’m thinking I need to use filterResolveList. The comment in the code says, “To change the list of matches, manipulate the np.matches list.” I can give my Portables class some code that will remove a given object from the list if it’s in the BagOfHolding – but I have no idea how to check whether the command included ‘all’. If I simply filter objects out of the list when cmd.action == Take, then it will never be possible to remove anything from the bag. Not good.

So how do I get at ‘all’?

I haven’t gone deep down the path (written test code, tested it out, etc.), but have a couple of pointers that might lead to an answer for you:

  • You can override/modify hideFromAll(action) in your Things. This gives you the ability to hide specific items, or classes of items, from ALL.
  • You can override/modify getAll(cmd, role) in the Take Action (or any Action, for that matter). The default implementation is liberal:
    getAll(cmd, role)
    {
        /* by default, return everything in scope */
        return World.scope.toList();
    }

So, you could take the list returned by World.scope and whittle it down with your own criteria.

To put it together, when the parser is resolving ALL, it calls getAll() on the Action and then filters that list using hideFromAll():

    return getAll(cmd, role).subset({x: x.hideFromAll(self) == nil});

Finally, another possibility is to modify the Take Action’s allowAll property and set it to nil. This is the nuclear option, obviously.

3 Likes

Thanks! That seems to work perfectly. Defining this on my portables class:

hideFromAll(action) {
        if ((action == Take) && isIn(shoppingBag)) return true;
        return nil;
    }
2 Likes