Bizarre bug in 6L38

This has been causing me no end of grief, but I’ve finally figured out what’s happening to enough of a degree that I can try to describe it here…

I want to test whether a text property on value is set, so I am using a test of the form:

[1]if the text-prop of the item is not "": [2] say text-prop of the item;

The problem is that, if the text property has certain “to say” substitutions in it, the test itself actually prints the text (and the test comes up false). In other words, line 1 above prints the text, while line 2 never fires. Remove those substitutions, and line 1 performs as expected, with line 2 firing as it should.

What’s more, when the test spuriously prints the text, it does so as if the text were passed by reference rather than by value (I think that’s the right way to put it). Basically–it prints the same thing every time, even if there are random variations.

By way of example, if the following variable is assigned to the property (i.e., “text-prop of X is atmospherics”), then everything works as it ought to:

Atmospherics is initially "[if a random chance of 1 in 5 succeeds][one of]Atmospheric text 1[or]Atmospheric text 2[or]Atmospheric text 3[at random].[else][run paragraph on][end if]"

But add the following, and the issues described above are triggered:

Atmospherics is initially "[if a random chance of 1 in 5 succeeds][interrupt][one of]Atmospheric text 1[or]Atmospheric text 2[or]Atmospheric text 3[at random].[resume][else][run paragraph on][end if]"

The test itself prints the text, the “say” phrase itself never fires, and the first random option chosen is chosen every subsequent time that the phrase prints text (4 out of 5 times it prints nothing, of course).

It shouldn’t really matter what the contents of the substitutions are, but I include them under spoiler:

[spoiler][code]To say interrupt:
suspend standard line input;
say run paragraph on.

To say resume:
resume standard line input;
say run paragraph on.

To suspend standard line input (this is the cancel standard line input rule):
cancel line input in the main window, preserving keystrokes.

To resume standard line input (this is the resume standard line input rule):
say “[paragraph break][command prompt][run paragraph on]”;
re-request line input in main window.

To re-request line input in main window:
(- glk_request_line_event(gg_mainwin, stored_buffer + WORDSIZE, INPUT_BUFFER_LEN - WORDSIZE, stored_buffer–>0); -)

To cancel line input in the/-- main window, preserving keystrokes:
(- glk_cancel_line_event(gg_mainwin, gg_event); stored_buffer–>0 = gg_event–>2; -)

So. In truth, I don’t need to test whether the property is set at all. I just need to print it, since printing an empty string should have no real effect. In other words, I don’t need help working around this. But boy is it weird, and very likely indicates an edge case that needs work in Inform’s new handling of text types. If anyone wants to take a crack at reproducing, that’d be great. I tried to come up with a simpler case myself but failed to reproduce it.

I think this has come up before and people suggested writing something like “is empty” rather than “is “””.

Thanks, Dannii. Using “in empty” does prevent the strange behavior.

But is “is empty” considered the only proper way to do this? It’s a bit obscure (I’ve been working with Inform 7 for close to seven years and didn’t know it existed until now!). More to the point, WI 20.3 strongly implies that “the empty text” and “” are the same entity, so it seems that both should work. Also, I can’t imagine that most authors intend that testing for equality should actually cause texts to print, and the test is failing anyway.

(I’ve searched Mantis but haven’t located a bug report for this issue.)

I think that’s related to the changes made to deal with this bug and this.

I agree that “is empty” and “is ‘’” logically should be synonyms. The fact that “is empty” doesn’t trigger substitutions is useful, but ultimately I’d call it a bug. (Possibly there should be a separate test “is completely goddamn empty”.)

Since this has come up, I’ll point out the secret trick: there’s a phrase “if expanding text for comparison purposes”. This is true if substitutions are going on for the purpose of comparing texts (rather than printing them).

Note to self: Write a definition for “is completely goddamn empty” into some future game.

Yeah, “is completely goddamn empty” is what I’m looking for, and I would guess it’s what’s wanted 90%–or more–of the time when authors are testing against “”.

I wonder if the case where texts are evaluated should be the one that is marked, e.g.:

if the text would print as ""

I disagree; I think the common case of comparisons should include substitutions. That is, ("[if cond]X[else]Y[end if]" == “X”) should be true just when the condition is true.

The most direct way this would arise in a game would be

The stick can be alight.
The description is "[if the stick is alight]It's on fire![end if]".

What happens if you EXAMINE STICK when it’s not alight? The description matches “” and you get “You see nothing special about the stick.” This seems like the intuitive behavior.

(Note that it works because the library code is roughly “…if the description of the noun is not “”: …”)

But couldn’t the library code be changed to (roughly) If the description of the noun would print “”, say “You see nothing special about [the noun].”? My feeling (based on my own intuitions) that most folks comparing against “” in their own code believe that they are testing whether something is completely goddamn empty rather than whether it would currently evaluate as empty.

But I’m not pushing for that. I just think that, as long as there are constructs that trigger state changes from text substitutions (including randomizers that can determine whether a phrase prints anything at all), there should be clear phrases that distinguish between the case when text variable/property is truly empty and when it is empty after expansion.

What if texts had a property/adjective of “set/unset” that returns whether they have any content at all. I think I side with Zarf on what the default should be. State changing substitutions aren’t very common. But perhaps a small compromise could be made if the standard rules would use the if expanding text phrase everywhere for phrases like first time only, and we then encouraged all extension authors to use it more too. It would be appropriate for learning facts in Epistemology for example.