"a open chest"

I’m trying to make containers be listed as “a closed chest” and “an open chest”, instead of “a chest (open)” and so on, and I’m running into something really confusing: With the follwing code, naturally the indefinite article can’t understand that it is to refer to an open chest instead of a chest, so we get “a open chest”, which is bloody impossible to correct as far as I know.
but when the chest is empty, it works fine.
We get “a open chest (containing a stone)” but “an open chest (which is empty)”.

How do I get it to work?

Chapter - Better descriptions of openable containers

Definition: a container is empty:
	If it contains something that is not the player:
		No;
	Yes.

[Doesn't work:
The indefinite article of an open openable container is "BLARGH ".]

Rule for printing the name of an openable container (called the item) when looking:
	[The indefinite article of the item is "BLARGH ";]
	If the item is open:
		Say "open ";
	Otherwise:
		Say "closed ";
	Omit contents in listing;
	Say "[printed name of the item]";
	If the item is open or the item is transparent:
		If the item is empty:
			Say " (which is empty)";
		Otherwise:
			Say " (containing [a list of things enclosed by the item])".

Well, if you want to change the indefinite article on the fly the syntax you want is “now the indefinite article of the item is…”. You need that “now” when you’re changing pretty much anything inside a rule or a phrase.

So you can change the indefinite article when you want to. The tricky thing is making sure the indefinite article doesn’t get stuck that way. I did this but there may be better solutions:

[code]Chestatorium is a room. The chest is an open openable container in chestatorium.

Chapter - Better descriptions of openable containers

A thing has some text called the default indefinite article.

When play begins:
repeat with item running through things:
now the default indefinite article of the item is the indefinite article of the item.

Definition: a container is empty:
If it contains something that is not the player:
No;
Yes.

[Doesn’t work:
The indefinite article of an open openable container is "BLARGH ".]

Before printing the name of an open openable container (called the item) when looking:
now the indefinite article of the item is “an”.

Rule for printing the name of an openable container (called the item) when looking:
If the item is open:
Say "open ";
Otherwise:
Say “closed “;
Omit contents in listing;
Say “[printed name of the item]”;
If the item is open or the item is transparent:
If the item is empty:
Say " (which is empty)”;
Otherwise:
Say " (containing [a list of things enclosed by the item])”.

After printing the name of an open openable container (called the item) when looking:
now the indefinite article of the item is the default indefinite article of the item.[/code]

This is actually a bug.

The bug is in the line:
Say " (containing [a list of things enclosed by the item])".

By listing the enclosed things with an article, Inform will also change the indefinite article for the container.

Omitting the article, like this:
Say " (containing [list of things enclosed by the item])".
…will set the correct article for the container, but naturally the list will be wrong.

You can set the property to conditional text:

The indefinite article of the sack is "[if the item described is open]an[else]a[end if]".

Defining this game-wide is a little tricky. You have to do this, which is irritatingly verbose:

The verb to indef-article-refer (it indef-article-refers, they indef-article-refer, it is indef-article-referring) implies the indefinite article property.

When play begins:
	let T be "[if the item described is open]an[else]a[end if]";
	now all openable containers indef-article-refer T.

That business with the list of enclosed things is confusing to me. I wonder if it’s related to the thing here, where printing an indefinite article always calls the routine for printing the name of an object. The behavior of articles confuses me, though; conditional substitution may often be the way to go, though I don’t know if it’ll work if the desired behavior is more complicated than can be accommodated in a conditional substitution. I suppose a custom say phrase can make the desired behavior as complicated as you like.

Here’s another perplexity:

[code]Chestatorium is a room. The chest is an open openable container in chestatorium. A rock is in the chest.

When play begins: showme the holder of the rock; list the contents of the chest.

Chapter - Better descriptions of openable containers

Definition: a container is empty:
If it contains something that is not the player:
No;
Yes.

Rule for printing the name of an openable container (called the item) when looking:
If the item is open:
Say "non-closed ";
Otherwise:
Say "closed “;
[Omit contents in listing;]
Say “[printed name of the item]”;
If the item is open or the item is transparent:
If the item is empty:
Say " (which is empty)”;
Otherwise:
say " (containing ";
list the contents of the item;
say “)”.[/code]

Output:

Why is listing the contents of the chest working in the when play begins rule but not in the rule for printing a name? Uncommenting “omit contents in listing” makes no difference.

I think there’s a blank rule for the listing contents of activity when looking to prevent walls of text from nested containers. I don’t have my Index with me, but you could check if it’s listed there.

Ok, I don’t really know why this works, but if you add the following rule:

The make named things mentioned rule is not listed in the before printing the name rulebook.

…then the output is as expected (as long as you use “Omit contents in listing”).

I’m just a dabbler who is very happy when things work out, so I’ll leave the reasoning behind this to the I7 gurus.

I think I understand now–that’s the rule that allows things like “[The apple] sits on the chest. [if familiar]…” to understand that the familiar property goes with the apple. I imagine it was using the last thing in the list to determine the article, and your example just happened to have the wrong combination of indefinite articles.

No. Inform doesn’t understand that, and that line of code won’t work. You can only abbreviate properties like that in text properties of the object.

The make named things mentioned rule gives the object in question the “mentioned” property. That’s all.

So if the object in question has the mentioned property, its contents won’t be listed in a Printing the name rule while looking?

The mentioned property is used in the “printing a locale paragraph” activity, and then the “you-can-also-see” rule. The basic goal is to make sure the object is mentioned no more than once during a “look” action.

So, if I’ve got this correct, the problem is that the contents of the item are mentioned, and so their name doesn’t print? This seemed to fix it, at least in this case:

Rule for printing the name of an openable container (called the item) when looking: If the item is open: Say "non-closed "; Otherwise: Say "closed "; Omit contents in listing; Say "[printed name of the item]"; If the item is open or the item is transparent: If the item is empty: Say " (which is empty)"; Otherwise: now everything in the item is not mentioned; [the fix] say " (containing "; list the contents of the item; say ")".

You learn something new every day. :slight_smile:

Now I have my attempt working, at least in the test case. It turns out that changing the indefinite article before and after printing the name didn’t work, but doing it before and after looking did.

[code]Chestatorium is a room. The chest is an open openable container in chestatorium. A rock is in the chest.

test me with “close chest/l/open chest/l/take chest/i/close chest/i/drop chest/look/open chest/look/take rock/look”.

Chapter - Better descriptions of openable containers

A thing has some text called the default indefinite article.

When play begins:
repeat with item running through things:
now the default indefinite article of the item is the indefinite article of the item.

Definition: a container is empty:
If it contains something that is not the player:
No;
Yes.

Before looking:
repeat with item running through open openable visible containers:
now the indefinite article of item is “an”.

Rule for printing the name of an openable container (called the item) when looking:
If the item is open:
Say "open ";
Otherwise:
Say "closed “;
Omit contents in listing;
Say “[printed name of the item]”;
If the item is open or the item is transparent:
If the item is empty:
Say " (which is empty)”;
Otherwise:
now everything in the item is not mentioned;
say " (containing ";
list the contents of the item;
say “)”.

After looking:
repeat with item running through open openable visible containers:
now the indefinite article of item is the default indefinite article of the item.[/code]

It’s probably pretty fragile, though. As zarf says, it’s easier to change the definite article to a conditional text, and if you want complicated conditional text (so that it only prints “an” when the container is open and the current action is looking) then you can always write a phrase “To say container-article” that contains that logic and use a When play begins rule to change the indefinite article of every container to “[container-article]”.

To me this is all really advanced stuff.
I’m looking at this like if it’s a bug, so I’m trying to implement a general fix by replacing one of the rules with a new patched one (in my bugfix extension), without having to invent a new property for every object.

The listing of things is (as stated previously) inside the “room description paragraphs about objects” rule in the “carry out looking” rulebook, which in turn contains the “you-can-also-see” rule in the “for printing the locale description” rulebook, which in turn contains a sort of list the contents rule.
“To list the contents of” is listed under Phrase Definitions, and promptly refers to I6 code: “(documented at ph_listcontents): (- WriteListFrom(child({O}), {phrase options}); -)”
I can’t find the listed documentation for the I6 functions online. I only found this link: firthworks.com/roger/informfaq/ww.html
The section under the title “Can I avoid printing “(which is empty)” after a container?” seems relevant, but I’m thinking that meddling with I6 libraries is way too complicated for me.
I’ll try an “uglier” patch until further notice.

I think the best source for documentation for WriteListFrom is probably Appendix B of the Inform source, which is the annotated source code for the Inform 6 templates that underlie Inform 7… maybe? Anyway it’s a bunch of Inform 6 code that goes into Inform 7 projects. The whole shebang can be found at http://inform7.com/sources/src/i6template/Woven/index.html; WriteListFrom is documented at p. 169 of the big PDF, or the ListWriter.i6t link will give you a smaller PDF that documents the ListWriter.

Of course this is all I6 and I don’t understand it. The standard I6 reference document seems to be the Inform Designer’s manual, which is from 2001 but I think I6 has been stable enough since then that it’s still OK.

Also the thing where the article reverts when you’re listing the contents does seem like a bug, and the best way to attract the attention of the people who would know what to do about it is to post it on the bug tracker. I’ll see if I can come up with a neat case and post it.

I’ve submitted the bug. It turns out that the problem isn’t specifically with making the list; invoking any indefinite article within the rule for printing the name of something will force that thing’s own article to be the article that got invoked – even if that’s not the article that you were trying to invoke.

So

[code]Lab is a room. An urn is a container in the lab. The player carries a ball.

Rule for printing the name of the urn when looking:
omit contents in listing;
say “urn”;
if the ball is in the urn:
say " with [a ball] in it".

Test me with “look/put ball in urn/look”.[/code]

will get you “a urn with a ball in it,” and there are a few more cases in the bug report.

Thanks for pointing this out!

Thank you for exploring and submitting the bug.

Meanwhile, I think I’ve come up with a temporary patch for my particular problem:

Before printing the locale description:
	Repeat with item running through openable visible containers:
		Now the item is proper-named.

After printing the locale description:
	Repeat with item running through openable visible containers:
		Now the item is improper-named.

…and then we just adjust the lines to read:

	If the item is open:
		Say "an open ";
	Otherwise:
		Say "a closed ";

This will only work if you never name a container with a proper name to begin with.

Well, if you want proper-named containers, you could create another property like “permanently proper-named” for them. (You could even set it automatically when play begins: “When play begins: now all proper-named containers are permanently proper-named.”) Then in your “after printing the locale description” rule, just have it reset the containers that aren’t permanently proper-named.

EDIT: And of course you would need to change your rule for printing the named so it didn’t say “an open” for permanently proper-named containers. Though you’d probably need to handle that differently anyway; say your proper-named container is “Taylor’s hope chest,” you wouldn’t want that to say “open Taylor’s hope chest (containing a bracelet)” or anything like that.

Patch for the reported bug:

[code]Include (-
Global short_name_case;
Global suppress_articles = false;

[ PrefaceByArticle obj acode pluralise capitalise i artform findout artval;
if (suppress_articles) {
print (PSN__) obj; return;
}
if (obj provides articles) {
artval=(obj.&articles)–>(acode+short_name_case*LanguageCases);
if (capitalise)
print (Cap) artval, " ";
else
print (string) artval, " ";
if (pluralise) return;
print (PSN__) obj; return;
}

i = GetGNAOfObject(obj);
if (pluralise) {
    if (i < 3 || (i >= 6 && i < 9)) i = i + 3;
}
i = LanguageGNAsToArticles-->i;

artform = LanguageArticles
    + 3*WORDSIZE*LanguageContractionForms*(short_name_case + i*LanguageCases);

#Iftrue (LanguageContractionForms == 2);
if (artform-->acode ~= artform-->(acode+3)) findout = true;
#Endif; ! LanguageContractionForms
#Iftrue (LanguageContractionForms == 3);
if (artform-->acode ~= artform-->(acode+3)) findout = true;
if (artform-->(acode+3) ~= artform-->(acode+6)) findout = true;
#Endif; ! LanguageContractionForms
#Iftrue (LanguageContractionForms == 4);
if (artform-->acode ~= artform-->(acode+3)) findout = true;
if (artform-->(acode+3) ~= artform-->(acode+6)) findout = true;
if (artform-->(acode+6) ~= artform-->(acode+9)) findout = true;
#Endif; ! LanguageContractionForms
#Iftrue (LanguageContractionForms > 4);
findout = true;
#Endif; ! LanguageContractionForms

#Ifdef TARGET_ZCODE;
if (standard_interpreter ~= 0 && findout) {
    suppress_articles = true;
    StorageForShortName-->0 = 160;
    @output_stream 3 StorageForShortName;
    if (pluralise) print (number) pluralise; else print (PSN__) obj;
    @output_stream -3;
    acode = acode + 3*LanguageContraction(StorageForShortName + 2);
    suppress_articles = false;
}
#Ifnot; ! TARGET_GLULX
if (findout) {
    suppress_articles = true;
    if (pluralise)
        Glulx_PrintAnyToArray(StorageForShortName, 160, EnglishNumber, pluralise);
    else
        Glulx_PrintAnyToArray(StorageForShortName, 160, PSN__, obj);
    acode = acode + 3*LanguageContraction(StorageForShortName);
    suppress_articles = false;
}
#Endif; ! TARGET_

Cap (artform-->acode, ~~capitalise); ! print article
if (pluralise) return;
print (PSN__) obj;

];
-) instead of “Object Names II” in “Printing.i6t”.
[/code]
(Thanks, matt w, for the very clear bug report!)