Inventory rule leak [I7]

In manipulating how I present the player’s inventory, I set up the following rule concerning how to print it out. Mostly it lists items in a column, each preceded by " - ".

Rule for printing the name of something (called doober) while requesting inventory: say " - "; if doober is improper-named: say the indefinite article of doober in sentence case; say " [printed name of doober]"; otherwise: say "[printed name of doober]" in sentence case.

However I discovered this rule ‘leaks’ into a separate Every turn rule that fires after it in the same turn. So, if the player takes inventory, then the every turn rule fires — within the every turn rule, if I try to print the name of something, it too is preceded by a " - ", as if the inventory action has not closed. This behaviour carries on for a few lines of code, until after I choose a row from a table and print an entry from it (incidentally, the table I used in my ‘Dojo’ example.)

I’ve tried bullying Inform into knowing the inventory taking has finished, by putting in ‘rule succeeds’ and the like, but no luck.

A bug, or something I’ve missed? What might I be able to do to get around it?

  • Wade

I have no elegant solution. My only idea is to set yet another darned flag:

[code]Inventorying finished is a truth state that varies.

Before requesting inventory: now inventorying finished is false.
Last carry out requesting inventory: now inventorying finished is true.

Rule for printing the name of something (called doober) while requesting inventory and inventorying finished is false:[/code]

Ah, flags. What can’t they do?

  • Wade

What’s “requesting inventory”? It’s not a standard bit of I7 that I know (this does not mean it’s not a standard bit of I7) – is it a custom action or activity?

UPDATE: And, as a wild guess, when you choose the table and print a row, are you having an NPC try an action?

Try this.

[spoiler][code]“Test”

Include (-

Global printprefix = true;

[ WriteMultiClassGroup cl memb depth partition_class_sizes q k2 l;
! Save the style, because the activity below is allowed to change it
q = c_style;
if (c_style & INDENT_BIT ~= 0) PrintSpaces(2*(depth+c_margin));
CarryOutActivity((+ prefixing a list item +));
printprefix = false;
BeginActivity(GROUPING_TOGETHER_ACT, memb);

if (ForActivity(GROUPING_TOGETHER_ACT, memb)) {
	c_style = c_style &~ NEWLINE_BIT;
} else {

	if (memb.list_together ofclass String) {
		! Set k2 to the number of objects covered by the group
		k2 = 0;
		for (l=0 : l<listing_size : l++) k2 = k2 + partition_class_sizes->(l+cl);
		EnglishNumber(k2); print " ";
		print (string) memb.list_together;
		if (c_style & ENGLISH_BIT ~= 0) print " (";
		if (c_style & INDENT_BIT ~= 0)  print ":^";
	} else {
		inventory_stage = 1;
		parser_one = memb; parser_two = depth + c_margin;
		if (RunRoutines(memb, list_together) == 1) jump Omit__Sublist2;
	}

	c_margin++;
	@push lt_value; @push listing_together; @push listing_size;
	
	lt_value = memb.list_together; listing_together = memb;
	#Ifdef DBLW; print "^^DOWN lt_value = ", lt_value, " listing_together = ", memb, "^^";
	@push DBLW_no_classes; @push DBLW_no_objs; #Endif;
	WriteListR(memb, depth, false); 
	#Ifdef DBLW; print "^^UP^^"; @pull DBLW_no_objs; @pull DBLW_no_classes; #Endif;

	@pull listing_size; @pull listing_together; @pull lt_value;
	c_margin--;
	
	if (memb.list_together ofclass String) {
		if (q & ENGLISH_BIT ~= 0) print ")";
	} else {
		inventory_stage = 2;
		parser_one = memb; parser_two = depth+c_margin;
		RunRoutines(memb, list_together);
	}
	.Omit__Sublist2;
}

EndActivity(GROUPING_TOGETHER_ACT, memb);
printprefix = true;

! If the NEWLINE_BIT has been forced by the activity, act now
! before it vanishes...
if (q & NEWLINE_BIT ~= 0 && c_style & NEWLINE_BIT == 0) new_line;

! ...when the original style is restored again:
c_style = q;

];

-) instead of “Write Multiple Class Group” in “ListWriter.i6t”.

Include (-

[ WriteSingleClassGroup cl memb depth size q;
q = c_style;
if (c_style & INDENT_BIT) PrintSpaces(2*(depth+c_margin));
if (printprefix) {
CarryOutActivity((+ prefixing a list item +));
}
if (size == 1) {
if (c_style & NOARTICLE_BIT ~= 0) print (name) memb;
else {
if (c_style & DEFART_BIT) {
if ((cl == 1) && (c_style & CFIRSTART_BIT)) print (The) memb;
else print (the) memb;
} else {
if ((cl == 1) && (c_style & CFIRSTART_BIT)) print (CIndefArt) memb;
else print (a) memb;
}
}
} else {
if (c_style & DEFART_BIT) {
if ((cl == 1) && (c_style & CFIRSTART_BIT)) PrefaceByArticle(memb, 0, size);
else PrefaceByArticle(memb, 1, size);
}
@push listing_size; listing_size = size;
CarryOutActivity(PRINTING_A_NUMBER_OF_ACT, memb);
@pull listing_size;
}
if ((size > 1) && (memb hasnt pluralname)) {
give memb pluralname;
WriteAfterEntry(memb, depth);
give memb ~pluralname;
} else WriteAfterEntry(memb, depth);
c_style = q;
];

-) instead of “Write Single Class Group” in “ListWriter.i6t”.

Prefixing a list item is an activity.

Rule for prefixing a list item while taking inventory: say " - ".

Understand “Examine [things]” as examining.

The player carries a snorkel and a waterproof sack. The waterproof sack contains an undersea map, a diving guide, a cup, and 500 Argentine pesos. The cup contains a worm. The player wears a swimsuit and a pair of flippers. The sack is openable and open.

A Scrabble piece is a kind of thing. The X, the W, the F, the Y and the Z are Scrabble pieces carried by the player. Understand “scrabble/piece” as a Scrabble piece. Understand “pieces” as the plural of a Scrabble piece.

Before listing contents: group Scrabble pieces together.

Before grouping together Scrabble pieces: say “some [listing group size in words] tiles (”.

After grouping together Scrabble pieces: say “) from a Scrabble set”.

The Testing Room is A Room.

Test me with “i”.[/code][/spoiler]

It’s a little fiddly, but it does the task perfectly.

Hope this helps.

I’d already started trying to fix the bug before I posted this message. That name change is a just a hangover from various attempts - sorry about that.

Hm, no, I’m not. For a second I thought I was (as in game terms I’m having the npc attack), but I’m not having the npc attack codewise by ‘try Jane attacking player’, for instance. It’s handled neutrally in an activity where I set an offender, a defender, and then just say ‘follow the do battle rules.’

  • Wade

Thanks climbingstars. That is a rather spectacular looking piece of code you have given me, but I concede that since the flag solution works in 2 lines and I am very much an advocate of doing things with flags, I’ve taken the 2 line solution.

  • Wade

So, I think your original rule leak is roughly what’s supposed to be happening. According to section 17.10 of Writing with Inform:

And the current action is going to be taking inventory for the whole turn (roughly?). So if I read this right, that’s why your every turn rules are still going to trigger the rules for printing names while taking inventory.

What I don’t understand right now is why that rule doesn’t trigger after you’ve printed something from a table. It might be solvable by sprinkling some "showme the current action"s through your code at key points, but seems like the two-line flag solution works so I’d go for it.

I guess I haven’t used the ‘current action’ parlance much. I’m still hazy on what defines it. In the docs I read:

‘This phrase produces the action currently being processed as a value -’

So if the player’s command runs an action (like taking inventory), taking inventory is the action. If taking inventory calls another action inside itself, is the current action now the new action? Then taking inventory again after? How can Inform tell when to stop something being the current action? I would have thought it would be when the current action’s rulebook ends with some result, but that’s not what’s happening in my game. Anyway, it’s true that using the flag instead of the action has stopped my particular problem.

  • Wade

Yes.

“trying fooing” is effectively a function call, so the current action reverts when it ends. I’m not sure how that relates to your code, but the other important thing to note is that the (top-level) current action persists into the “every turn” phase.

There’s a “listing contents of something” activity that looks like what you probably want. You could simply condition your rule on it, as in:

Rule for printing the name of something (called doober) while listing the contents of yourself: ...

but this probably won’t produce the effect you want, since, among other issues, the “printing the name of” activity is only invoked after the article has already been printed. I suspect what you really need to do is to override the whole “listing the contents of yourself” activity:

Rule for listing contents of yourself:
	repeat with doober running through things held by yourself:
		say " - ";
		if doober is improper-named:
			say the indefinite article of doober in sentence case;
			say " [printed name of doober][line break]";
		otherwise:
			say "[printed name of doober][line break]" in sentence case.

Of course, this simple rule won’t handle things like listing the contents of carried containers; you’d have to implement such refinements yourself, if the standard inventory options don’t suit you. For inspiration, you may want to study the example in section 6.7. “Inventory” of the Inform Recipe Book.