[one of] sub as entire text matches ""

Pretty sure that this is a bug, but there’s an outside chance that it’s intended behaviour, so I thought I’d raise it here.

If a text contains only certain (not all) substitutions, and that text is checked against “”, it will match. This came up in descriptions:

The description of flower is "[one of]Delightful![or]Well, it's okay, I guess[at random]"

Examining the flower in the preceding gives you the result “You see nothing special about flower”, because the examine undescribed things rule checks the text against “”. If the description is actually allowed to print, it works fine. There are obviously other circumstances in which you’d want to check a text against “”; the Standard Rules checks both against the description and against the initial appearance, both of which are the kinds of thing which are fairly likely to use total text subs.

This does not hold true for all kinds of substitution; from my experiments it seems as if it’s just the [one of] family.

A workaround might be this:

[code]The description of flower is “[flowertext]”.

To say flowertext: say “[one of]Delightful![or]Well, it’s okay, I guess.[at random]”[/code]

BTW it looks like “at random” leads to strict alternation here; if this were your use case you’d have to use “purely at random” I guess.

The [one of] substitution, since each printing can change how it looks in the future (if using [stopping] or [cycling]), has a check so that it doesn’t print anything during string comparison. It shouldn’t be too hard to make it print some dummy text in that case instead.

Instead of dummy text, I would personally want it to actually print whatever the next thing it would print is, but not change its [stopping] or [cycling] state during string comparison. My reason for this is in case one of the possibilities really is “”, then I would be pretty upset when it claims “oh yeah, I have something to say” but then it doesn’t actually. I’ve seen the code and this should be relatively straightforward? You just have to move where the comparison flag is checked.

A solution suggested by Zarf for a similar problem seems to work here as well. You can change the condition “if the description of the noun is not “”” to “if the description of the noun is not empty” in the carry out examining rule. I don’t know if this will work when the substitution runs out and offers a blank, as suggested previously.


Yes, workarounds are not difficult in themselves - it’s more that this is a case where you can write something that looks perfectly acceptable, which then fails in a confusing way. (I didn’t find this myself - I’m too much in the habit of excluding the final period from text substitutions, lest Inform’s temperamental line-breaks smite me for my impiety - but it came up for a fellow author upgrading a project to 6L02, and we spent a fair bit of time going ‘well, it’s referring to the right object, which has a description, and the description’s well-formed, so - okay, RULES says that this is what’s triggering that response… but that text doesn’t match “”. …oh, right.’)

Let me point out (per inform7.com/mantis/view.php?id=1291) that [one of] is using an important trick here – it’s shielding the counter from changing during a comparison. [first time] fails to do this, but that’s a bug.

The [one of] structure is written with the counter computation first. That is, in pseudocode:

if this is printing mode (rather than comparison mode), randomize the counter;
if the counter is:
– 1: print “Delightful”;
– 2: print “Okay”;

So in the initial comparison, the counter is 0 and this evaluates to “”. Tricky. Not easy to fix without redesigning the whole shebang.

(You might say “initialize the counter to 1”, but that doesn’t work for the [one of]…[cycling] or [stopping] cases. The counter has to start at 0 so the initial increment can set it to 1.)

Hmm. Since this is mostly an issue with authors being becroggled over good code misbehaving: rather than a full redesign, would it be acceptable to just produce a compile problem for the specific cases of description and initial appearance, which are most likely to trigger it, and explaining the workarounds? Or does the comparison against “” mean that it’s difficult for Inform itself to discover when this is happening?

(Or, ideally, a visible warning rather than a compile-halting problem - since there are a number of ways you might fix it, including changing the rules in question - but I don’t know how feasible that is.)

Would it be too unstable to change what happens when say__comp == false so that it increments the counter to figure out what the text will be and then decrements the counter again after checking?

Failing that it seems like Neil’s fix is best – check for “is not empty” rather than comparing to “”.

(Filed bug with discussion: inform7.com/mantis/view.php?id=1370 )

I’ve come around to the view that the library should always test “is not empty” rather than comparing to “”. That doesn’t fix the core problem but it addresses most of the becrogglement.

That’s hard, especially in the case of “at random”.

Now considering a solution where there are two counters, or rather a counter and a flag:

if the flag is false, increment the counter; [or randomize it or whatever]
if the counter is:
– 1: print “Delightful”;
– 2: print “Okay”;
if this is printing mode, set the flag to false;

Right, I hadn’t noticed that the counter keeps track of where you are in the substitution rather than of how it got called or something like that.

So the new proposal effectively preloads the result of the substitution when you check it and doesn’t try to calculate it again until after it’s been printed?

Yeah; that’s what it should do, anyhow. You can check it twice and you’ll still get the same result; or zero times for that matter.