As I start to tidy up my Comp game, I notice that one reviewer had issues when using the ‘take all’ command. I never use this command, so it never occurred to me that I need to disallow it. Unfortunately, that’s harder than it might appear.
The adv3Lite library defines Take as allowing multiDobj. That’s appropriate, as the player might want to ‘take rug and matches’ in a single command line. So I tried this:
VerbRule(TakeAll)
(('take' | 'get' | ('pick' 'up') | 'grab') ('all' | 'everything'))
| ('pick' ('all' | 'everything') 'up')
: VerbProduction
action = TakeAll
verbPhrase = 'take/taking everything'
missingQ = 'what all do you want to take'
;
DefineIAction(TakeAll)
execAction(cmd)
{
"Sorry -- the TAKE ALL command is not implemented in this game. ";
}
;
Unfortunately, that just plain doesn’t work. ‘take all’ still grabs all of the individual items in the room. And I don’t think there’s a way to give a priority to a VerbRule.
Next I tried using a Doer. This fails to work, however, because the syntax of a command line in a Doer requires a specific object, and ‘all’ is not an object. This causes a run-time error.
gameMainDef has a true/nil switch for allVerbsAllowAll – but this is what the docs say: “…if you set this to nil, only the basic inventory management verbs (TAKE, TAKE FROM, DROP, PUT IN, PUT ON) will allow ALL.” That’s exactly the opposite of what I want!
+ me: Thing 'you'
isFixed = true
person = 2
contType = Carrier
;
++ theAll: Unthing 'all; ; everything'
'Sorry: Commands with ALL are not allowed in this game. '
;
This has the undesirable side effect that ‘drop all’ is no longer allowed. But it does work.
What about the allowAll property of Action? The source comment in action.t says
/*
* Can ALL be used with this action? By default we take our value from
* gameMain.allVerbsAllowAll, though basic inventory-handling actions in
* the library will override this. This property is really only relevant
* on TAction and its descendents, but we define it here just to make sure
* no cases are missed.
*/
allowAll = (gameMain.allVerbsAllowAll)
Which makes me think perhaps you could just modify the Take action?
Possibly – but modify can’t be used with DefineTAction(Take). I just now tried it, and the compiler didn’t like it. Now, DefineTAction is of course a macro, but it’s not at all clear to me from the Library Reference Manual and the source code what the macro expands into, or how the allowAll line (which is in the usage of the macro) gets passed on to the actual action.
I think you meant nil, not false? Yes, this works, but I think I’m going to do it the brute-force way using an Unthing. The reason being, the point of disallowing all is to avoid letting the player shortcut (cheat) by finding out exactly what’s in the room. If I just set allowAll to nil on Take and Examine, for instance, then the command ‘feel all’ will report, line by line, everything that’s in scope.
Looking at this in the reference manual in action.t:
/*
* Get a list of all the objects this action will act on if the player
* types ALL for role (DirectObject or IndirectObject). This is the method
* actually called by the Parser. We first obtain the list of objects
* returned by getAll() and then filter out any objects for which
* hideFromAll(action) is true for this action. Subclasses should normally
* override getAll() rather than this method.
*/
getAllUnhidden(cmd, role)
{
return getAll(cmd, role).subset({x: x.hideFromAll(self) == nil});
}
It seems there is some predefined behavior to remove unseen items from the list of ‘all’. Maybe this is a more player-friendly way to write it?
Nope. That compiles, if you switch it to “modify Drop” (DropAction is not an object). But it doesn’t work. If you do that, ‘take all’ still works. I just checked.
Unlike adv3, in adv3lite the class for the “take” action is Take, not TakeAction. So just do:
modify Take {
allowAll = nil;
}
The DefineTAction macro of adv3lite does not add the Action suffix to the generated class name. So DefineTAction(Foo) creates a class named Foo, not FooAction.