Closed curiousdannii-testing closed 2 years ago
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by zarf :
This is true but I'm not sure how the system can avoid it. It's always been like this.
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by zarf :
Caching has its own pitfalls. What if one object's print-name routine calls another's? (Not entirely implausible; say a game implements ownership to be able to say "the palace of the Grand Vizier".)
(Not saying your solution is bad, just that this is not a simple problem.)
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by mattweiner :
Oops, I accidentally pasted in some irrelevant things from a code sandbox (commented out). Please delete everything before "Crossroads is a room" from the minimal source text.
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by mattweiner :
A workaround for this particular case, using the extension Print Stage Detection by Taryn Michelle (https://github.com/i7/extensions/blob/master/Taryn%20Michelle/Print%20Stage%20Detection.i7x):
Include Print Stage Detection by Taryn Michelle.
The cached preface is some text that varies.
Before printing the name of the traffic signal when the print-stage is article-choosing:
now the cached preface is the substituted form of "[one of]green[or]amber[or]red[cycling] ".
Before printing the name of the traffic signal:
say the cached preface.
Crossroads is a room. A traffic signal is in the Crossroads.
Test me with "l/l/l/l/l".
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by mattweiner :
Well, one possible solution would be along the lines of what Print Stage Detection accomplishes. When printing the name of something for the sake of determining what the article should be (when print-stage is article-choosing), cache the result of the rules for printing the name. When printing the name of something for real (when print-stage is name-printing), just print the cache instead of running all the rules again.
At the very least, I think the effects of using indefinite articles should be mentioned in the documentation. That would make it easier to find workarounds for cases like this:
Crossroads is a room.
A traffic signal is in the Crossroads.
After printing the name of the traffic signal: say ", which is [one of]green[or]amber[or]red[cycling],".
Test me with "l/l/l/l/l".
where we can fix the problem by setting the indefinite article directly, since it's always the same:
The indefinite article of the traffic signal is "a".
But I do think that the caching solution should be looked into; it should be much easier to put it directly into the I6 template than it is to do by hacking the I6 template.
For what it's worth, my current workaround is at http://www.intfiction.org/forum/viewtopic.php?f=7&t=20813&p=116496#p116496 (for Glulx only, I haven't tried to implement I6 modifications necessary for z-machine). The part that's of interest is the last section, using Print Stage Detection, and the code implementing I6 Buffer, as well as the modifications that Print Stage Detection makes to the I6 template and the code that copies text into I6Buffer in LanguageContraction (which requires PrefaceByArticle to set buflen and pass it to LanguageContrction). Most of the rest of that code is for calling the initial sound rulebook from within LanguageContraction rather than just doing a quick check on the first letter of the text argument of LanguageContraction. I hope to get a cleaned-up and commented version of that on Github sometime.
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by mattweiner :
Anyway, I posted an attempt to fix this via caching the results of printing the name on Github: https://github.com/MattWeiner/Indefinite-Article-Substitution-Fix/blob/master/Indefinite%20Article%20Substitution%20Fix.i7xp/Source/extension.i7x (for Glulx only).
557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:
Comment by mattweiner :
Well, I'm not saying that my solution necessarily works--more putting it forward as something for people who understand this to work with. Still, I certainly understand why the devs might not want to touch the code in this case; my minimal suggestion here is that this behavior should be documented, as it seems like it could be a source of really perplexing bugs. (Someone somewhere made a comment about being careful with say phrases that have effects, because of issues like this, but [cycling] and [random] have to have the effects they have, if that makes sense.)
For what it's worth, having one print-name routine call another's does seem to work with my code:
Include Indefinite Article Substitution Fix by Matt Weiner.
Lab is a room.
A plate is a kind of thing. A plate can be iron, steel, or titanium (this is its metal property). Understand the metal property as describing a plate.
There is an elephant. There is a tiger.
Depicting relates various plates to one thing. The verb to depict means the depicting relation.
After printing the name of a plate (called slab) when the slab depicts something (called depictee): say " (engraved with [a depictee])".
Before printing the name of a plate (called slab): say "[metal of the slab] ".
One steel plate is in Lab. It depicts an elephant.
One iron plate is in Lab. It depicts a tiger.
though I'm not sure if that's the exact issue you're thinking of, and I'm also not sure exactly why it works. I think maybe what's happening is that at the article-checking phase, it goes through all the print-name routines and puts the whole thing in the cache; then when it's time to print the name, it just prints the cache and doesn't bother calling the routine for the elephant? I worried a bit that this might interfere with things being set to mentioned but it doesn't seem to.
Anyway, I wouldn't be surprised if there were a problem in here somewhere; certainly before anything is done with my solution it should be looked at by someone who really understands the template. (If that doesn't evoke Palmerston on Schleswig-Holstein.)
Fixed via this commit: https://github.com/ganelson/inform/commit/6e394e56da52b9fb81e68bca0eb203c0b2231e04
Comment by Graham Nelson:
A cautionary tale has been added to Writing With Inform, which is the best we can do for now. One day we might restructure how this works in BasicInformKit, but this is not that day.
Reported by : mattweiner
Description :
When the rules for printing the name of a thing call a text substitution, and the name of the thing is printed with an indirect article, the text substitution is evaluated once silently when determining what the indirect article should be, and another time in order to print the name of the thing. This means that the substitution is evaluated twice.
It also means that the indirect article that is produced will not always match the printed text, because the substitution that is fed into the code for determining the indirect article will not always be the same as the substitution that actually gets printed.
Steps to reproduce :
Additional information :
Output:
Crossroads
You can see a amber traffic signal here.
>test me
(Testing.)
>[1] l
Crossroads
You can see a green traffic signal here.
>[2] l
Crossroads
You can see an red traffic signal here.
>[3] l
Crossroads
You can see a amber traffic signal here.
>[4] l
Crossroads
You can see a green traffic signal here.
>[5] l
Crossroads
You can see an red traffic signal here.
>
Note that "an red" is being printed when the last printed color was green; Inform is seeing "amber traffic signal" when evaluating the indirect article (I believe PrefaceByArticle loads this into StorageForShortName and then calls LanguageContraction on it, though I don't understand exactly), so LanguageContraction decides that the article should be "an"; but when it comes time to print the name of the signal the substitution gets called again and "red traffic signal" gets printed.
The same behavior occurs in 6G60, so it's not a result of the changes made to fix bug 1370.
imported from: [Mantis 1972] printing with an indirect article double-calls text substitution and can yield incorrect indefinite article