Changing default response for multiple objects

I have a collection of things that I want to take (later, to buy) but I don’t like the response. I use here arrows as an example. When I take three arrows,
then I get the default response
> take 3 arrows
arrow: taken
arrow: taken
arrow: taken

I will be taking larger groups later and don’t want to see a string of taking responses. Does anyone know how to change the response to something like this?
> take 3 arrows
3 arrows taken

I have read through 6.15 in the Recipe Book but it seems to discourage turning off the individual responses.

I noticed that if I collect ten arrows and then check inventory, it does not itemize them, but groups them together:
You are carrying
ten arrows.

How can I get that grouping effect while taking?

Unfortunately, the behavior of actions on multiple items is buried deep in the parser. You can sort of work around it—the Left Hand of Autumn example in the manual does this—but it’s finicky and fragile at the best of times. (Since it only resets its flags “before reading a command”, for example, it’ll act weird with multiple commands in a single input—that’s true for most I7 parser hacks.)

Counterfeit Monkey uses a lot of tricks to avoid hundreds of repeated error messages when trying to do things with multiple objects, replacing them with a single error, but it is not very well documented, and I only have a vague recollection of how it works.

Perhaps it might still provide some inspiration?

https://github.com/i7/counterfeit-monkey/blob/master/Counterfeit%20Monkey.materials/Extensions/Counterfeit%20Monkey/Actions%20on%20Multiple%20Objects.i7x

I’ve created a solution system using the multiple action processing rules, a table and a temporary list.

I haven’t tested this super-hard, but I’ve tested it a bit and it seems decent. I tested getting all and dropping all with both a mix of multi-items and unique items at the same time, and getting all from a container.

With this code in place, whenever you take, drop, remove it from, or remove, multiples of things, any that have the same printed plural name will be grouped together.

Here’s the code (written in 10.2):

Summary
MULTI-ACTION-LIST is a list of objects that varies.

Table of multi-item trackings
entity(a thing)	plural-name(text)	amount(number)
--	--	--
with 99 blank rows.


MULTI-ACTED is initially false.

First multiple action processing rule:
	now MULTI-ACTED is false;
	now the MULTI-ACTION-LIST is the multiple object list;

To deal with (ITEM - a thing) during multiple action processing:
	if taking or removing or removing from:
		now player carries ITEM;
		now ITEM is handled;
	otherwise if dropping:
		now ITEM is in location;

A multiple action processing rule:
	let DELETION-LIST be a list of things;
	let DETECTED-MULTIPLES be false;
	let LINES-WITH-MULTIPLES be 0;
	blank out the whole of the table of multi-item trackings;
	;
	[say "MULTI-ACTION-LIST going in: [MULTI-ACTION-LIST].";]
	repeat with ITEM running through MULTI-ACTION-LIST:
		let PLURAL be "[printed plural name of ITEM]";
		if PLURAL is a plural-name listed in the Table of multi-item trackings:
			now MULTI-ACTED is true;
			if amount entry is 1:
				increment LINES-WITH-MULTIPLES;
			increment amount entry;
			if entity entry is not listed in DELETION-LIST:
				add entity entry to DELETION-LIST;
				[say "ADDED ORIGINAL ITEM TO LIST.";]
				deal with entity entry during multiple action processing;
			add ITEM to DELETION-LIST;
			[say "ADDED DUPE ITEM TO LIST.";]
			deal with ITEM during multiple action processing;
			now DETECTED-MULTIPLES is true;
		otherwise:[make a new entry]
			choose a blank row in the Table of multi-item trackings;
			now entity entry is ITEM;
			now plural-name entry is PLURAL;
			now amount entry is 1;
			[say "ITEM NOTED.";]
	if DETECTED-MULTIPLES is true:
		repeat through the table of multi-item trackings:
			if amount entry > 1:
				let TITLE-CASED be "[amount entry in words]";
				now TITLE-CASED is TITLE-CASED in title case;
				say "[TITLE-CASED] [plural-name entry]: ";
				if taking or removing or removing from:
					say "Taken. ";
				otherwise if dropping:
					say "Dropped. ";
				decrement LINES-WITH-MULTIPLES;
				if LINES-WITH-MULTIPLES > 0:
					say line break;
		repeat with Z running through DELETION-LIST:
			remove Z from the MULTI-ACTION-LIST;
			if number of entries in MULTI-ACTION-LIST is 0:
				say line break;
			[say "Removed [Z] from list.";]


Last multiple action processing rule:
	alter the multiple object list to the MULTI-ACTION-LIST;
	if MULTI-ACTED is false and the multiple object list is empty:
		if taking or removing or removing from:
			say "There's nothing I can take.";
		otherwise if dropping:
			say "I have nothing.";
	otherwise if MULTI-ACTED is true and number of entries in multiple object list is 1:
		say "[entry 1 of MULTI-ACTION-LIST]: [run paragraph on]";

It scans everything that’s about to be acted on, makes item counts in a temporary table, manually deals with the getting or dropping of items which share the same plural name - taking the opportunity to print their names in a group fashion while at it - removes those items from the master list of things to be acted on, then lets Inform act on the rest as usual.

One thing to note is that the Table of multi-item trackings should have at least as many blank rows as the number of uniquely-named items the player could ever hold at once! I’ve started it with 100.

EDITS - I just realised my code was missing a line defining the MULTI-ACTION-LIST. Now fixed.

Bigger problem - it doesn’t respect a lot of rules that would block taking or dropping (or presumably, the other actions too) certain things. I noticed it wouldn’t even try to take a fixed in place thing (good) but it would happily drop things that had ‘Instead of dropping’ rules on them.

EDIT EDIT - I made my own version better, but I realise now the brick wall on this approach is it just can’t be made to respect all rules applying to an item unless the items are acted on and checked one at a time, the way the multiple object processing rules normally handles them. The closest I got was checking if one could be acted on, and if it could, acting on the whole group. But what if taking arrow 3 trips an inventory or space limit, or there’s suddenly no more stock? I couldn’t intercept that stuff with my approach, so I’m downing tools.

-Wade

2 Likes

I’m using a plural examining action adapted from Left Hand of Autumn, so I’m interested in hearing more about this. It looks like if I enter more than one “x [multiple things]” command in the same line of input, only the first one is acknowledged. Is there anything else I should test? Do authors do anything special to deal with this, like not allowing multiple commands in the same line?

That’s the one that breaks with multiple-examining, yeah. If you ever have “before/after reading a command” rules that are meant to be tied to one specific action, you should try:

  • YOUR ACTION THEN SOMETHING
  • SOMETHING THEN YOUR ACTION
  • YOUR ACTION THEN YOUR ACTION

The first one will usually work, the second one will break if you’re trying to do specific command parsing in an “after reading a command” rule, and the third one will break if you’re resetting variables in a “before/after reading a command” rule.

For another example, Counterfeit Monkey will choke if you WAVE X-REMOVER AT SOMETHING THEN WAVE Y-REMOVER AT SOMETHING, because it uses an “after reading a command” rule to check what letter the remover should be set to. In 99% of cases, “after reading a command” rules are a dangerous trap; they’ll work just barely well enough that you won’t realize all the hidden assumptions they break.

The easiest solution is to forbid THEN and periods, but I’m not fond of that; it’s just spackling over the problem and annoying players to hide the bug. The real solution would be to add a new activity that runs every time parsing starts on a new command—that is, at the beginning, and after finding a THEN or a period—but the way the guts of the parser work makes this also difficult.

(Hmm…though not too difficult any more, in Inform 10. Maybe I could make an extension to do it…)

In particular, there’s a block of code right at the start of “Parser Letter A” that checks if held_back_mode is true—that is, if we’ve saved a new command to run after the last one—and if so, sets wn (the word number under consideration) to hb_wn (the “held back word number” where the previous command left off).

When this happens, it fills in the buffer before that command with spaces, retokenizes it, and parsing begins again from the top. If we ran a new activity right after that, I think it would do exactly what we need.

The problem is, Parser__parse is a monstrously huge routine, and you can no longer replace individual sections of routines in an Inform 10 extension. So it would be a bit of a logistical nightmare, and would conflict with any other extension that modifies the parser.

Still…this might be worth it.

Yes, Counterfeit Monkey was illuminating. I would love to have a multiple action rule for taking and buying, but how do I invoke those rules. Do I need to create a new action for multiply-taking and multiplying-buying? I couldn’t find that in the CM code.

I need only the reporting to change, which is AFTER the action, but the reporting is in a TAKING loop, so doesn’t stop the cascade of repeated messages.
I was thinking of capturing the number taken, then reduce the multiple objects list to one item (the noun), then an AFTER TAKING rule will say "[N] [noun]s taken". However, that still gives the message cascade. Also, if I reduce the multiple object list too early, the items taken are not put in the inventory. :frowning:

Not for me, I think. It is not critically important to have if the player can put up with an occasional message cascade. Ugly and inelegant, but the price to pay, it seems.

btw, I looked at the Left Hand of Autumn re reporting rules but I can’t get them to even compile. I cut-n-pasted the following:

The silently announce items from multiple object lists rule is listed instead of the announce items from multiple object lists rule in the action-processing rules. 

This is the silently announce items from multiple object lists rule: 
    unless multiply-examining or multiply-examining something from something: 
        if the current item from the multiple object list is not nothing, say "[current item from the multiple object list]: [run paragraph on]".
**Problem.** The phrase or rule definition 'This is the silently announce items from multiple object lists rule'  is written using the 'colon and indentation' syntax for its 'if's, 'repeat's and 'while's, where blocks of phrases grouped together are indented one tab step inward from the 'if ...:' or similar phrase to which they belong. But the phrase 'if the current item from the multiple object list is not nothing' , which ought to begin a block, is immediately followed by 'say "[current item from the multiple object list]: [run paragraph on]"'at the same or a lower indentation, so the block seems to be empty - this must mean there has been a mistake in indenting the phrases.
*See the manual: 11.7 > 11.7. Begin and end*

---

**Problem.** The phrase or rule definition 'This is the silently announce items from multiple object lists rule' is written using the 'colon and indentation' syntax for its 'if's, 'repeat's and 'while's, where blocks of phrases grouped together are indented one tab step inward from the 'if ...:' or similar phrase to which they belong. But the tabs here seem to be misaligned, and I can't determine the structure. The first phrase going awry in the definition seems to be 'unless multiply-examining or multiply-examining something from something', in case that helps.

This sometimes happens even when the code looks about right, to the eye, if rows of spaces have been used to indent phrases instead of tabs.

This seems to be an increasingly recurring problem with the docs not matching the current compiler.

Never mind. Cut-n-pasting the code in the docs puts in spaces, and not the correct tabs. Sorry for the complaint.

Wade, thanks for the effort. I was running into some of the same problems. In my case, there will not be a lot of restrictions so I am happy with my own CHECK rules for multiply-taking.

1 Like

Thanks!

No need to do it for my sake, anyway. I’m not using Inform 10.

Well, there already is an action for taking multiple items in the standard rules:

Section SR4/10 - Grammar

Understand "take [things]" as taking.

Which is how by default TAKE ALL works in an Inform game. So you would only have to add an equivalent Understand line for buying:

Understand "buy [things]" as buying.

But I have a hunch that is not quite what you mean. To avoid listing identical items on separate lines, you would probably first of all have to implement a multiple action processing rule when taking and a multiple action processing rule when buying and do your multiple object list hacking inside them.

Wouldn’t it work to run through the list of items, silently try taking X for each, and then checking which ones actually ended up in the player’s inventory, before printing the custom message?

1 Like

You need to deal with objects that have custom “take” responses.

Also, it will work out weirdly if one of the objects teleports you or kills you. You want to do additional checks after every action.

That’s where I got to in my more advanced WIP version that I haven’t posted, but I faced too many additional problems that various folks have been describing.

I was using one of a kind (e.g. the first arrow of ‘arrows’) to do a TAKE test, then if that succeeded, grab all the rest behind the scenes by teleporting them to the player. Then print one line saying ‘12 arrows: Taken’ and remove them all from the multi-list.

Inversely, if one didn’t work, I’d print ‘12 arrows: (single failure message)’.
:grinning_face_with_smiling_eyes:
That was inaccurate in that each arrow could fail for different reasons and the failure message was only taken from one which happened to be listed first. And I couldn’t format it to not print tons of extra lines in some circumstances. And (other problems continuing)

-Wade

That’s where I got to in my more advanced WIP version that I haven’t posted, but I faced too many additional problems that various folks have been describing.

Yes, this is not something that is easy to do in Inform. Counterfeit Monkey does the trick of silently trying to take all essential things in a couple of places, to prevent soft locks, but it works there because it is rare for a thing to be present but not possible to take in that game. There are no lockable containers, they will all open automatically when you try to take something in them, as will the car when you try to take something outside of it. There is no darkness, and so on. There will still be the odd message out of order, but nothing too bad.

1 Like