Modifying the Announcement of the Multiple Object List

Hi all,

I’ve been stumped by an Inform output/line break issue.

Picture a box of coins. You “take 3 coins”. Inform wants to say “coin: Taken. coin: Taken. coin: Taken.”, but I want Inform to say “three coins: Taken.”

My approach (see below) is to modify the way the “multiple object list” is announced: when taking multiple coins, we’ll count them and only announce the first coin, disguised to look like multiple coins.

What I have here almost works, but Inform doesn’t line break correctly when giving the output and I can’t figure out why, or how to fix it. Any help would be appreciated!


(P.S. The test command “Test Problem” trips over another issue, it seems to me. If you run that first, the two identical identical commands in the test behave differently. Not sure why. Are the “every turn” rules run at the start of the very first turn?)

          • CODE - - - - -

Void is a room. The box is a container in the void.

A gold coin is a kind of thing. 10 gold coins are in the box.

Test Problem with "take 3 coins / take 3 coins".
Test One with "look / take 3 coins".
Test Two with "take all from box / drop coin / take all / drop all / take coins / put coins into box".

[The following is based on Example 400 in the Inform documentation.]

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

The coin-count is a number that varies. Every turn: now the coin-count is 0.

Coins-have-been-counted is a truth state that varies. Every turn: now coins-have-been-counted is false.

First-coin is a truth state that varies. Every turn: now first-coin is true.

This is the fancy announce items from multiple object lists rule:
	[First, count the number of coins in a multiple-object action. This number may be 0.]
	if coins-have-been-counted is false:
		repeat with temp running through the multiple object list:
			if temp is a gold coin, increment the coin-count;
	[Ensure that we only count the coins once per action.]
	now coins-have-been-counted is true;
	[We'll start with the taking action. We'll also need: dropping, inserting it into, removing it from, putting it on.]
	if taking:
		if the current item from the multiple object list is a gold coin:
			if first-coin is true:
				say "[The coin-count in words] gold coin[if coin-count is greater than 1]s[end if]: [run paragraph on]";
		otherwise if the current item from the multiple object list is not nothing:
			say "[current item from the multiple object list]: [run paragraph on]";
		if the current item from the multiple object list is not nothing, say "[current item from the multiple object list]: [run paragraph on]".

After taking a gold coin:
	if first-coin is true:
		now first-coin is false;
		say "Taken." instead. [***]

[If this After rule contains ONLY the *** line, then the word 'Taken.' appears multiple times -- which is not what we want -- but, the spacing is correct. Why would adding that conditional statement in the rule impact the line spacing of its output?]

No, they’re run (more or less) at the end of every turn. Try making them “after reading a command” rules.

Aha! At your prompting I checked the documentation and there it is: ‘One of the LAST things to happen in each turn is that Inform will apply any rules which have been set to occur “every turn”’ (Section 9.5, my emphasis). I hadn’t noticed that. Making them “after reading a command” rules fixed the problem.

Another thing I hadn’t noticed is that the default value of a truth state is false. So, another fix is to add the initialization “First-coin is true.” and keeping the “every turn” rules.

Thank you for your help – that’s one mystery less!


It sounds like you’ve fixed your immediate problem, but if you are curious to see more detail about which rules fire when, the following chart may help:

Ooh. I love the chart.

But: I’ve fixed only my “P.S.” problem, not the original problem I was working on. I’m still not sure why I lost a paragraph break when running the code in my original post. What I get is:

take 3 coins
three gold coins: Taken.

But there should be a blank line before the second prompt. I’m not sure why it’s not there. Adding an extra [paragraph break] to my After rule puts paragraph breaks in other places that they shouldn’t be (like when doing a “take all” that includes taking multiple coins).

Any thoughts about the spacing issue?


I think I have this, though it’s pretty trial-and-errory, and the line spacing rules are somewhat mysterious to me, so I don’t guarantee that it’s robust.

What is happening, I believe, is that your After rule is running for each coin (as it ought), but it’s not printing anything for the last two coins (as it oughtn’t). But somehow – and this is where I start guessing – this means that the first time through you print “Taken.” and the game is expecting you to print more text, so it just cues up one carriage return. Since nothing else is getting printed, it never prints the blank line that it would like to print after the last thing it says. Have I mentioned that I don’t really understand this?

Anyway, this seems to be working:

After taking a gold coin: if first-coin is true: now first-coin is false; issue library message taking action number 1 for the noun; otherwise: say "".

Adding the blank say statement seems to be getting the blank line to print.

By the way, it looks like in the “fancy announce items” rule, “If taking” ought to be “If taking or removing” – when you take coins from the box, the taking action gets converted to a removing action (test two should confirm this).

To me too. But, you’re suggested code seems to work great. Thank you!

Indeed. I’ve actually changed it to capture all of the actions that can take multiple objects (at least I think this is all of them): “If taking or dropping or inserting something into or removing something from or putting something on”.

Thanks again for your help!

No problem! It helped me clear up some of my puzzlement about line breaks too, maybe.

I overlooked this in the comments on your original code, but if you want to capture all the actions that can take multiple objects, why not just drop the “if” entirely? The rule will only be firing when it’s processing one of those actions.

Oh, duh. I was doing all that to mirror the structure of the example that had inspired me… but you’re totally right and it’s much so cleaner! Thanks again! :slight_smile: