Multiple Item Actions

Been playing around with multiple item actions. It bugs me when taking a bunch of the same thing and I get:

I tried to group the taking by borrowing shamelessly from the “Western Art History 305” example as follows:

[code]The plural of shiny is shinies. A shiny is a kind of a thing.

A multiple action processing rule when the action name part of the current action is the taking action (this is the getting shinies rule):
let L be the multiple object list;
let F be L;
let the shiny count be 0;
repeat with item running through L:
if the item is a shiny:
silently try taking the item;
if the player encloses the item:
increment the shiny count;
remove the item from F;
if the shiny count is greater than zero:
say “[Shiny count in words] shin[if shiny count is one]y[otherwise]ies[end if]: Taken.”;
if the number of entries in F is less than the number of entries in L:
alter the multiple object list to F.

Cave of Wonders is a Room.
Twelve shinies are in the Cave.
A transparent container called a crystal pumpkin is in the cave. The pumpkin contains three shinies. The pumpkin is closed. The pumpkin is fixed in place.[/code]
It works fine until there are shinies that can’t be taken for some reason. Here’s what I get with the above code:

There must be a better way. I mean, it would be really cool if it said “The crystal pumpkin isn’t open” just once. Or maybe is there a way to check to see if an item is retrievable without actually trying to take it?

What’s the preferred way to do this?

Here’s one rather crude way. (I haven’t altered your rule, except to add a couple of lines. [*])

A container can be shiny-barred.
A rule for reaching inside a shiny-barred container when the noun is a shiny: deny access.
Every turn: now every container is not shiny-barred. 

A multiple action processing rule when the action name part of the current action is the taking action (this is the getting shinies rule):
	let L be the multiple object list;
	let F be L;
	let the shiny count be 0;
	repeat with item running through L:
		if the item is a shiny:
			silently try taking the item;
			if the player encloses the item:
				increment the shiny count;
			otherwise if the holder of the item is a container:                                             [*]
				now the holder of the item is shiny-barred;                                                  [*]
			remove the item from F;
	if the shiny count is greater than zero:
		say "[Shiny count in words] shin[if shiny count is one]y[otherwise]ies[end if]: Taken.";
	if the number of entries in F is less than the number of entries in L:
		alter the multiple object list to F.

By the way, you don’t need to tell Inform the plural of “shiny”.

I don’t think this helps much in this case, but I wrote an extension Actions on Groups that automates some aspects of doing actions on multiple things. It’s more designed for things like The Left Hand of Autumn, though, which is an example where you need to special-case some particular combinations (like “take bell, book, and candle”). Also it was written for the version of I7 before the multiple action processing rulebook was included, so it bypasses it.

Checking if something is takeable without taking it is quite an undertaking. There’s an extension, I think Hypothetical Questions by Jesse McGrew, which allows for this sort of thing by doing something like doing the action and then hacking the undo buffer to restore the action while retaining the information about whether it succeeded.

If you’re looking for super general solutions, another thing you can try is running Text Capture by Eric Eve to gather up all the failure messages without printing them, reorganize them somehow into some more sensible output, and print them out at the end. Again, complicated stuff.

So the best thing to do is probably what jrb did–if the specific reason you’re getting multiple messages has to do with a shiny being stuck in a container, set a flag that prevents you from trying to take any more shinies from that container. Or whatever is specifically causing problems, set a flag so that problem only happens once.

Thanks to both of you.