printing plural items within a container

I would think that a common need is to group items together, such as 12 arrows should say 12 arrows, and not
arrow
arrow
arrow

I see that taking inventory already does this but the powers that be have kept how that is done secret. Can someone tell me how I can group like items together when listing things in a container?

How are you listing things in a container? By default, I will say that Inform can group things while examining containers.

The garden is a room.
An arrow is a kind of thing. There are 12 arrows in the garden.
The chest is a container in the garden.

Are you just saying a list, or are you “listing the contents of”? Both seem to have decent luck grouping things, though the latter option might help you in other respects.

You can see this in the code of the Print Standard Inventory rule, for instance:

Carry out taking inventory (this is the print standard inventory rule):
	say "[We] [are] carrying:[line break]" (A);
	list the contents of the player, with newlines, indented, including contents,
		giving inventory information, with extra indentation.

I recommend reading through the Standard Rules extension, which all Inform 7 games include by default. It helps to pinpoint the source of a desired (or undesired) behaviour so that you can bend it towards your own ends!

Edit: As you can see here, the listing behaviour is actually robust in this respect. Even if I change the traits of the arrow, change its printed name, put new arrows in, put non-arrow things in and then new arrows, it adapts just fine. I’m curious what kinds of arrows you are using, in addition to how you are listing contents.

The garden is a room.
An arrow is a kind of thing. There are 12 arrows in the garden.
The chest is a container in the garden. A rock is a thing in the garden. The ball is a thing in the garden.

When play begins:
	let L be a random arrow;
	now the L is scenery;
	now the printed name of the L is "golden arrow";
	move L to the chest;
	move the rock to the chest;

Carry out examining the chest:
	say "[a list of things in the chest][paragraph break]";
	list the contents of the chest, with newlines, indented, including contents,
		giving inventory information, with extra indentation;
	rule succeeds;

1 Like

Thank you. I will give this a try.
btw, I notice that inventory of the player comes out differently than listing contents of a container.

Yes. That’s because of the phrase options chosen while telling Inform to “list the contents of [something or other]”.

list the contents of the chest, with newlines, indented, including contents,
		giving inventory information, with extra indentation;

See all of this stuff like “with newlines, indented, including contents […]”? Each of those changes how the listing will take place.

To quote §11.14. Phrase options’s Equipment List example:

“With newlines” tells Inform to put a new line before each listed object. Indented tells it to indent contents of objects, when listing these.

“Giving inventory information” means to append information such as (closed) or (being worn) to objects.

“As a sentence” means to put “and” before the last object and commas between them; this is usually not used in conjunction with newline listing. “As a sentence” obeys whatever conventions about the use of the serial comma we may have established with the “Use serial comma” option.

“Including contents” means to list the contents of open or transparent containers and all supporters, whereas including all contents means to list the contents of all containers, even opaque closed ones.

“Tersely”, perhaps unexpectedly, puts parentheses around objects listed as the contents of other objects.

“Giving brief inventory information” omits most of the inventory tags, such as “(open)” and “(worn)”, but does list “(closed)” for closed containers which might not otherwise be obviously openable.

“Using the definite article” means prefixing objects with “the”, if applicable, rather than “a”.

“Listing marked items only” means including only objects that have already been declared “marked for listing”.

“Prefacing with is-are” means that Inform will write “is” before the list if it contains only one item, and “are” if the list contains more than one.

“Not listing concealed items” means to omit from the list anything which is scenery.

Finally, “with extra indentation” means that the whole list should be indented slightly, in emulation of the default inventory listing.

2 Likes

If you do need to customized exactly how items are grouped, there’s a way to do so in the listing contents activity. See §18.13 of the manual. The only downside is that it allows for grouping things that normally wouldn’t be, but not for not grouping things that normally would be.

1 Like

I understand the adornments in Section 18, but that is only syntax. I needed to know how to group the identical items, which is done behind the scenes.

Also, this is truly mystifying and redundant:

list the contents of the chest, including contents;

I get the item count with this line, but I do need to customize it, to print properties of each item in the container. I don’t know how to access an individual item, or tell the “list contents” activity to run paragraph on.

I have something like this:

After printing the name of equipment (called E) while listing contents of armor showcase:
	let price be ChrCostBuying for cost of E;	
	let W be the weight of E;	
	let AC be the AC of E;	
	say 	"      [price to 1 decimal places]      [W]      [AC][line break]"; 


Instead of examining armor showcase in Emporium:
	say "QTY   ARMOR          	COST (gp)     	WEIGHT (lb)     AC[line break]";
	list the contents of the armor showcase, with newlines, indented, including contents, giving inventory information, with extra indentation;

Ironically, the “After printing the name of” activity only works for single items; multiple items are left blank.

That isn’t describing the contents of the chest. It’s describing the contents of the contents of the chest.

If we add a box to the chest (and remove the redundant listing for my previous example):

The garden is a room.
An arrow is a kind of thing. There are 12 arrows in the garden.
The chest is a container in the garden. A rock is a thing in the garden. The ball is a thing in the garden. The box is a container in the chest.

When play begins:
	let L be a random arrow;
	now the L is scenery;
	now the printed name of the L is "golden arrow";
	move L to the chest;
	move the rock to the chest;

Carry out examining the chest:
	list the contents of the chest, with newlines, indented, including contents,
		giving inventory information, with extra indentation;
	rule succeeds;

If we removed “including contents” from our carry out rule, we get this instead:

It’s a bit confusingly named, but the example I quoted earlier explains it a bit. Thankfully not all that mystifying or redundant in practice!

That’s probably because you’re not printing their name, but the plural name of their kind (arrows). You can see that in how it doesn’t add “golden” to my arrow after it is in a group.

Part of it is because a lot of I6 stuff is happening in the background of this.

What properties are you trying to list?

Edit: Apologies, you already answered that question. I was jumping around a lot while writing this.

2 Likes

So printing the plural name of something is a completely different activity than printing the name of it. You can write rules for after printing the plural name of something, just like printing the name of it.

After printing the plural name of an arrow:
	say " (1lbs each)";

garden
You can see eleven arrows (1lbs each), a chest (in which are a rock and a box (empty)) and a ball here.

If your listed properties don’t rely on the exact number of, say, arrows present or you’re willing to work with this kind of output then you might be good to go with that.

EDIT: Hah! Dug up a way to grab the number of arrows:

After printing the plural name of an arrow:
	say " ([listing group size]lbs)";

You can see eleven arrows (11lbs)

I was messing around with the grouping activity for a bit, but this thread made me realize that listing group size is also set for this kind of automatic grouping! “Listing group size” should be very helpful for you if you need to list any values dependent on how many of them there are (like weight and possibly cost).

1 Like

Okay, I get it now. Thanks for explaining.

1 Like

I have this working, and it is short, a little mysterious as to why it works.

Instead of examining outfitting showcase in Emporium:
	say "QTY  EQUIPMENT          	COST (gp)     	WEIGHT (lb)[line break]";
	repeat through the Table of Emporium Outfitting:
		let price be ChrCostSelling for cost entry; 
		say "[qty entry]      [Item entry]      [price to 1 decimal places]      [weight entry][line break]"; 

I get this. Except for the formatting, it is what I want. I can extend the “table” to other properties too. I don’t know how it knows about the qty of items.

EDIT: Oh wait. This is reading a table. I want the print output to reflect the actual items in the room (The Emporium), not this table which changes with each BUYING / SELLING transaction.

However, notice that the plural items are printed as singles, so that the “After printing the plural name of” never gets triggered. Why doesn’t printing the single name get triggered, like it did for chain mail.

If you are working with stringent spacing, you might want to consider switching to and from a fixed width font.

This…

say "[fixed letter spacing]"

…can offer that, and this…

say "[roman type]"

…will bring you back!

You can see as much here:

After printing the plural name of an arrow:
	say " [fixed letter spacing]([listing group size] lbs)[roman type]";

The garden is a room.
An arrow is a kind of thing. There are 12 arrows in the garden.
The chest is a container in the garden. A rock is a thing in the garden. The ball is a thing in the garden. The box is an openable container in the chest.

image

Yeah. Your best bet might genuinely be taking advantage of “after printing the plural name of” and “listing group size“ to get the correct output.

Edit: This example might demonstrate fixed letter spacing a bit more cleanly. See how large a space is compared to roman type’s version? That’s because spaces are afforded the same width as everything else! I use fixed width in ascii art printing, which benefits from predictable spacing.

image

1 Like

I tried doing exactly that. Apparently, listing contents lists the group of items as a single with the listing group size prepended (behind the scenes).

After printing the plural name of equipment (called E) while listing contents of armor showcase:
	let price be ChrCostBuying for cost of E;	
	let W be the weight of E;	
	let AC be the AC of E;	
	if listing group size > 0:
		say 	"      [price to 1 decimal places]      [W]      [AC][line break]"; 

Instead of examining armor showcase in Emporium:
	say "QTY   ARMOR          	COST (gp)     	WEIGHT (lb)     AC[line break]";
	list the contents of the armor showcase, with newlines, indented, including contents, with extra indentation;

I got the qty and the item name, but the rest of the line was blank, implying that list group size was 0; or it never printed plural name.

Okay, A little experiment. It also shows that “listing group size” does not work as expected.

Instead of examining armor showcase in Emporium:
	say "[fixed letter spacing]QTY   ARMOR          	COST (gp)      WEIGHT (lb)     AC[roman type][line break]";
	repeat with E running through equipment in armor showcase:
		let price be ChrCostBuying for cost of E;	
		let W be the weight of E;	
		let AC be the AC of E;	
		say 	"[fixed letter spacing][listing group size]      [printed name of E]      [price to 1 decimal places]      [W]      [AC][roman type] [line break]"; 

yields this output

This tells me that Inform keeps all objects separate and only tallies a group listing when it needs to display. However, I don’t know what that mantra is.

I’m hoping that I can group plural items together and that will tally the listing group size.

Yes, grouping seems to mostly be a thing during saying certain lists. Repeating through a list isn’t going to trigger it, I don’t think. I believe it’s tied to “coalescing” behaviour in I6 that I haven’t examined in much depth (and aren’t sure is reasonable to isolate).

While listing contents, however, this seems to work just fine? (I attempted to convert your code to something I could compile, since a lot of this is referring to things you’ve written elsewhere. The rough ideas still apply, however.)

A thing has a number called price.
A thing has a number called weight.
A thing has a number called AC.

The garden is a room.
An arrow is a kind of thing. The price of an arrow is usually 2. The weight of an arrow is usually 1. There are 12 arrows in the garden.
The chest is a container in the garden.

After printing the plural name of an arrow (called E) while examining the chest:
	let price be the price of E;
	now price is (Price * listing group size);
	let W be the weight of E;
	now W is (W * listing group size);	
	let AC be the AC of E;	
	if listing group size > 0:
		say 	"      [price to 1 decimal places]g      [W]lbs      [AC]AC[line break]"; 
		
Carry out examining the chest:
	list the contents of the chest, with newlines, indented, including contents,
		giving inventory information, with extra indentation;
	rule succeeds;

When play begins:
	repeat with item running through arrows:
		now the item is in the chest;

garden
You can see a chest (in which are twelve arrows) here.

>examine chest
twelve arrows 24.0g 12lbs 0AC

So it is possible, and reasonably easy… so long as you’re operating within the bounds of listing like this.

The code looks good for a single item, but I have dozens of items. I don’t want a dozens of “After printing the plural name of” rules. Is there a way to generalize it?

I have three showcases in the Emporium, one each for Weapons & Ammo, Outfitting equipment like rope and backpacks, and Armor. I have all these items in showcases so that they don’t show up as a huge list when one “looks” at the Emporium description. The room description shows up, followed by “Ganon, Weapons showcase, Armor showcase, and Outfitting showcase are here.”

This all works really well. Thanks for your assistace.

Carry out examining armor showcase in Emporium:
	say "[fixed letter spacing]QTY   ARMOR   COST (gp)   WEIGHT (lb)   AC[roman type][line break]";
	list the contents of the armor showcase, with newlines, indented, including contents, with extra indentation;
	rule succeeds;

After printing the plural name of armor (called E) while listing contents of armor showcase:
	let price be ChrCostBuying for cost of E;	
	let W be the weight of E;	
	let AC be the AC of E;	
	say 	"[fixed letter spacing]     [price to 1 decimal places]     [W]     [AC][roman type]"; 

After printing the name of armor (called E) while listing contents of armor showcase:
	let price be ChrCostBuying for cost of E;	
	let W be the weight of E;	
	let AC be the AC of E;	
	say 	"[fixed letter spacing]     [price to 1 decimal places]     [W]     [AC][roman type]"; 

with following result:

Notice that I removed the listing group check. It seemed to do nothing.

Now, one final quibble. How can I change “a chain mail” to “1 chain mail”?
I’ll have to find out why my chain mail has no weight too.

1 Like

Could you say:

The indefinite article of the chain mail is "1".

Maybe you would want to do it for all your equipment.

1 Like

Yes, I would want that. I’ll give you suggestion a try.

Yes, that worked great! Thanks.

By the way, if you want the spacing to come out nicely it can help to make comparisons to the things being printed. This code is still just for plural named things but you could adapt it fairly easily for printing regular names as well: it’s mostly just a proof of concept.

Rule for printing a number of something (called the item) while examining the chest (this is the my standard printing a number of something rule):
	say "[listing group size] ";
	if the listing group size is less than 10:
		say " ";
	carry out the printing the plural name activity with the item;
	rule succeeds;
	
To CreateNumberedSpace (N - a number) times:
	while N is greater than 0:
		say " ";
		decrement N;

A thing has a number called price.
A thing has a number called weight.
A thing has a number called AC.

The garden is a room.
An arrow is a kind of thing. The price of an arrow is usually 2. The weight of an arrow is usually 1. There are 12 arrows in the garden.
A wooden shield is a kind of thing. The price of a wooden shield is usually 16. The weight of a wooden shield is usually 6. The AC of a wooden shield is usually 2. There are 2 wooden shields in the garden.
The chest is a container in the garden.

After printing the plural name of something (called E) while examining the chest:
	let price be the price of E;
	now price is (Price * listing group size);
	let W be the weight of E;
	now W is (W * listing group size);	
	let AC be the AC of E;
	let SpaceTest be the number of characters in the printed plural name of E;
	now SpaceTest is 16 minus SpaceTest;
	CreateNumberedSpace SpaceTest times;
	say 	"[price to 1 decimal places]";
	if price is less than 10:
		CreateNumberedSpace seven times;
	otherwise:
		CreateNumberedSpace six times;
	say "[W]";
	if W is less than 10:
		CreateNumberedSpace eleven times;
	otherwise:
		CreateNumberedSpace ten times;
	say "[AC]"; 
		
Carry out examining the chest:
	say "[fixed letter spacing]  QTY   ARMOR        COST (gp) WEIGHT (lb) AC[line break]";
	list the contents of the chest, with newlines, indented, including contents, with extra indentation;
	say roman type;
	rule succeeds;

When play begins:
	repeat with item running through arrows:
		now the item is in the chest;
	repeat with item running through wooden shields:
		now the item is in the chest;

Wooden shields’ name is pretty much twice the length of arrows, but it still lines up thanks to the dynamic spacing!

This involves a few assumptions: you have to know the longest item name in the game so you can properly decide the upper limits of SpaceTest. This is also assuming that the player can never have more than 99 arrows and that the total cost/weight of a stack can never exceed double digits (but it seems like you’re using this for a shopfront of some sort, so you probably don’t want to multiple cost and weight for this anyways). But yes! This is a nice, easy way to line things up.

I’m sorry to hear that listing group size isn’t working for you. I don’t know why. That being said, it doesn’t sound like you need to reference it, anyways.

Congrats on getting things working on your end! Hope you don’t mind me offering a little more help with lining everything up.