How to make an NPC run a parsed cmd without advancing turn.

I know I can do a thing like this to get any arbitrary actor to run a command without it advancing the turn:

// For each actor in the list, have them take a red marble from the marble bag:  (Assume marbleBag is a Dispenser that can keep generating new instances of redMarble):

foreach( local a in someActorList ) {
         marbleBag );

The problem is that I would like to do something like this:

// For each actor in the list, have them put **all** marbles in the bag:

foreach( local a in someActorList ) {
         TODO: all the marbles the actor is allowed to mess with according to the relevant preConditions  - in inventory, or nested inside an open container in their inventory, etc
         marbleBag );

So, basically, I want the actors to do a “put all marbles in bag”, taking full benefit of all the work the parser does for me with that magic word “all”, rather than having to re-invent the wheel by writing my own routine to build the list of objects that an “all” would resolve into.

Is there an equivalent of nestedActorAction() that lets me pass in a long command line string and lets the parser chew on it?

There is executeCommand(), but as far as I can tell from the documentation, it will advance the turn counter and count each action of each actor as its own full turn. I wanted the equivalent of the “nested…” functionality where it doesn’t count as a new turn.

I suppose the way to do it is not to use nestedActorAction at all. Just iterate through the objects you want to move and use moveInto() on them. You say you’re trying to avoid doing that, but that’s the way I’d do it. To move objects from an Actor to a container, just iterate through the contents of the Actor, and for each item in the contents, if it’s a redMarble, do a redMarble.moveInto(marbleBag). You might want to keep track of how many marbles are thus moved, so you can then create a sentence that says, “Bob puts three marbles into the bag,” or whatever.

The reason that’s ugly is because the actor’s inventory can contain containers that contain the marbles, or containers that contain containers that contain the marbles, and so on, so it becomes a recursive function rather than a simple loop.

Yes, that makes sense, but as usually transpires in cases like this, Mike Roberts considered it already. The isIn(obj) property of the redMarble class will tell you whether it is directly or indirectly contained by the Actor. So if you iterate through all of the marble objects in the game and test which of them is contained by your Actor, the method will know which marbles to move.

You can use the allContents() method of Thing. It’s documented as:


  • Get a vector of all of my contents, recursively including
  • contents of contents…

So try to simply call allContents() on the Actor and then iterate over the returned Vector and call moveInto() only for the marbles you want.

If you want to stick with your original plan, you could try to set the actionTime property of PutInAction to 0, do what you originally intended, and then restore PutInAction.actionTime = 1. The actionTime property tells the library how much time an action should consume. 0 is a valid value, and if used, the action will consume no game time at all.

However, if you do use a nested command, you should be aware that it’s not guaranteed to succeed. If the parser for some reason thinks that the action can’t be performed, the marbles won’t be moved. If you do it manually, by means of moveInto(), then you have absolute control and don’t have to leave it to the parser.

Thanks. That’s useful. Its still not precisely what I’d like (*) but it’s better and I’m sure it will be handy to know for other things.

(*) - because the word “all” finds all objects “in scope” which doesn’t just include the inventory but also objects loose in the room, for example.

If you call allContents() on an Actor, why would that return objects in the room? It should only return objects owned by the Actor.

Yes. I know. That was my point. If you type “put all marbles on table” you don’t get the same result as you do if you have the code behind the scenes calling allContents(), taking all the hits ofKind(marble) and putting them on the table. Therefore calling allContents() is not exactly what I was looking for, but it’s close.