[I7][6G60]: Controlling the Order Objects are Listed

A while back, a very kind soul on this forum helped me with my perennial obsession with controlling the order objects are listed in rooms.

Consider this little game:

[code]“Test Game” by “C.E.J. Pacian”

The Vague Room is a room. “Who could ever leave this room?”

The Other Room is east of the Vague Room. “Actually, this room is better.”

The apple is a thing in the Other Room.

The chair is an enterable supporter in the Other Room.

The cute puppy is an animal in the vague room. “A cute puppy follows you, as ever.”

After going to a room:
now the cute puppy is in the location;
try looking.[/code]
If we play this we get the following:

Which displeases me endlessly, because I want the puppy to be listed last in the room description.

Adding the following code:

[code]After choosing notable locale objects:
if the cute puppy is a notable-object listed in the Table of Locale Priorities:
now the cute puppy is mentioned.

The list-the-sidekick rule is listed after the you-can-also-see rule in the for printing the locale description rules.

This is the list-the-sidekick rule:
if the location of the cute puppy is the location of the player:
say “A cute puppy follows you, as always.”;
continue the activity.[/code]
Changes the result to this:

Perfect! Until we do this:

Based on the fact that the initial appearance is shown when you sit on the chair, it seems that the puppy’s initial appearance is getting displayed during some internal activity where I don’t want it to.

The rules command shows that the extra text is generated by the “describe what’s on scenery supporters in room descriptions rule”, but I have no idea what I can do with that information.

(Is controlling the order of things easier in the new version of I7? This has always seemed like a fundamental feature to me, but I realise that my opinion of what is fundamental seems be pretty unusual.)

Instead of using the list-the-sidekick rule, try:

Rule for writing a paragraph about the cute puppy: say "A cute puppy follows you, as always."

Do you mean replace my second bunch of code:

[spoiler][code]After choosing notable locale objects:
if the cute puppy is a notable-object listed in the Table of Locale Priorities:
now the cute puppy is mentioned.

The list-the-sidekick rule is listed after the you-can-also-see rule in the for printing the locale description rules.

This is the list-the-sidekick rule:
if the location of the cute puppy is the location of the player:
say “A cute puppy follows you, as always.”;
continue the activity.[/code][/spoiler]
With

Rule for writing a paragraph about the cute puppy: say "A cute puppy follows you, as always."

?

That stops the text being printed extra times, but returns to printing it first instead of last.

Look, let’s change my example a bit:

[code]“Test Game” by “C.E.J. Pacian”

The Vague Room is a room. “Who could ever leave this room?”

The Other Room is east of the Vague Room. “Actually, this room is better.”

The bone is a thing in the Other Room. “Someone has left a bone here.”

The cute puppy is an animal in the vague room. “[if the location is the location of the bone]The cute puppy gnaws on the bone.[otherwise]A cute puppy follows you, as ever.[end if]”

After going to a room:
now the cute puppy is in the location;
try looking.[/code]
This gives us:

Now it seems to me that output would be better if I could just swap those last two sentences. How do I go about doing this?

After some kicking and whapping the code on the side, I came up with this (in 6L32):

[code]“Test Game” by “C.E.J. Pacian”

The Vague Room is a room. “Who could ever leave this room?”

The Other Room is east of the Vague Room. “Actually, this room is better.”

The apple is a thing in the Other Room.

The chair is an enterable supporter in the Other Room.

The cute puppy is an animal in the vague room. “A cute puppy follows you, as ever.”

After going to a room:
now the cute puppy is in the location;
try looking.

After choosing notable locale objects:
if the cute puppy is a notable-object listed in the Table of Locale Priorities:
now the cute puppy is mentioned.

Rule for printing the locale description (this is the list-the-sidekick rule):
if the parameter-object is the holder of the player:
if the location of the cute puppy is the location of the player:
say “A cute puppy follows you, as always.”;
continue the activity.

The list-the-sidekick rule is listed after the you-can-also-see rule in the for printing the locale description rules.[/code]

Now, the parameter-object thing may be somewhat undocumented, but what it appears to be is this: The printing the locale description activity relies on something called the parameter-object (which is an I6 call) to keep track of what it’s printing the locale description of. When printing the locale description is happening, it actually runs not only for the room but for any containers/supporters the player may happen to be in/on, to make sure that the player’s fellow-contents get described. And when the player enters something, the printing the locale description activity runs so as to make sure that anything that’s in the player’s new holder gets described.

So in this case, we can just check to see if the parameter-object is the holder of the player–the room if the player isn’t in/on anything, whatever the player’s in/on if they are–and that’ll be the last locale description, so we save printing the line about the puppy till then.

This has the disadvantage that the line about the puppy gets printed when we enter the chair, which I guess you don’t want. We could tweak it:

Rule for printing the locale description (this is the list-the-sidekick rule): if the parameter-object is the location of the player: if the location of the cute puppy is the location of the player: say "A cute puppy follows you, as always."; continue the activity.

But if the chair has actual contents (try e/get apple/enter chair/drop apple/l) then the contents will be listed after the puppy.

Of course it seems as though the simplest thing here is just to put the puppy message in a “last carry out looking” rule and I’m not sure why we’ve been goofing around with all this complicated activity stuff:

[code]The Vague Room is a room. “Who could ever leave this room?”

The Other Room is east of the Vague Room. “Actually, this room is better.”

The apple is a thing in the Other Room.

The chair is an enterable supporter in the Other Room.

The cute puppy is an animal in the vague room. “A cute puppy follows you, as ever.”

After going to a room:
now the cute puppy is in the location;
try looking.

After choosing notable locale objects:
if the cute puppy is a notable-object listed in the Table of Locale Priorities:
now the cute puppy is mentioned.

Last carry out looking when the location of the cute puppy is the location of the player: say “There is a cute puppy here, as usual.”[/code]

Why is it that Room Description Control isn’t working for you here? Not sufficiently updated?

Thanks, matt w – it looks as though Pacian’s original code stemmed from the Priority Lab example, which didn’t address the question of what happened when a player got onto the chair. I’m revising the example to reflect this, and explain the parameter object a bit more.

From the last time this was discussed, I think RDC and its dependent extensions proved a bit more complex than Pacian wanted to dig into. Tailored Room Description is now in better shape than it was then – it handles adaptive text now, so obeys tense/person change rules automatically – but only if you’re using 6L02 or later. Ordinary Room Description has also been updated for 6L02, but comments on that old thread have made me poke at it a bit more, and I can see that it’s actually rather broken, and no longer fulfills its aim of replicating I7’s default output with a few tweaks. So I’ll have more of a look at that.

(And on that note: while I do glance at this board fairly frequently, I do not read every Inform help thread in detail these days – there’s enough competent help around here that I tend to assume people can look after themselves – so if people have problems specifically with an extension of mine that they want me to look at, emailing me is the best way to draw my attention to the fact.)

Okay. On review, the problem is not that we need to be checking parameter-object (though for other reasons that happens to resolve the issue, it does so largely incidentally). The problem is that the Priority Lab code allows you to set priorities even for objects that haven’t been queued up to be listed in the first place – including things in your inventory, things that have already been described to the player, and so on.

I’ve substantially revised that example, and the revised version is attached, for the curious. (It also explains what the parameter-object does do.)

PriorityLab.txt (8.43 KB)

matt w’s After looking suggestion kind of cuts the knot here anyway.

About the state of extensions: Room Description Control, Ordinary Room Description, and Tailored Room Description were all written before locale priority was added to Inform. As mentioned, ORD is kind of broken, but in any case I think RDC + ORD would nonetheless produce something only a bit more powerful than what is already built into the system, while being substantially more daunting-looking. (I want to keep Room Description Control and Tailored Room Description around because for really advanced tweaking they can do some pretty sweet things, but they’re designed for people who either like the out-of-the-box behavior or are willing to get their hands dirty.)

What I propose, therefore, is to withdraw Ordinary Room Description from circulation and instead supply a single, short extension that, using some of the same code as this Priority Lab example, offers the author an object property to make things ordinarily-described, early-described, late-described, never-described (i.e., concealed) or last-described (after the you-can-see line).

This would be less fine-grained than the control an author can currently get by messing with locale priorities by hand, but might be a good deal more comprehensible. The author could use writing a paragraph about in order to customize the text regardless of where in the priority sequence the item was to appear, and otherwise wouldn’t need to add any other rules.

Pacian, would that cover the range of control that you want, or are there other things you’d want to see included?

Not to speak for Pacian, but that sounds pretty nice! Would it also be possible to include code for reordering things within the sets, or at that point would it be just as simple for the author to directly mess with the Locale Priorities?

By the way, sorry to all if the line about “goofing around with complicated activity stuff” sounded overly snarky–that’s the sound I make when I spend a long time messing around with a complicated solution before trying the simple one. (In particular, I was trying to figure out how to test whether we were printing the locale description of a specific thing, and I was unable to do that until I stumbled across parameter-object. Is there a specific way to test something like “while printing the locale description of the chair”?)

At that point it would be simpler for the author to be hand-assigning numbers, yeah.

Unless I used a completely different way of dealing with this, which wasn’t assigning objects to simple early/late/latest groups, but used some other syntax entirely to describe how individual objects should relate. Like “The dog must be listed after the table” and “The table must be listed before the egg”.

But then sometimes you want something like “The dog must be listed after everything”, which is tricky to express; and there’s a lot of room for priority clashes, because what if you have two "must be listed before everything"s? Or “the dog must be listed after the table” / “the table must be listed after the teacup” / “the teacup must be listed after the dog” cycles?

I think checking parameter-object is it, yes, if you’re looking for “are we describing the contents of this specific supporter/container”.

Is there something similar for other activities? Is it always parameter-object? This was a bit confusing–I expected “While printing the locale description of the chair” to work, along the lines of “Before entering the chair,” but it didn’t. If that always gets stored in parameter-object that’ll give a workaround, if I ever need one.

Yes, parameter-object is a global variable.

“printing the locale description” is an activity that prints the whole locale description – that is, it’s describing everything that can be seen within a given domain, and it’s run once for the location and then a second time (if necessary) for whatever contains the player – but most of the time it’s not changing parameters a lot. By contrast, “printing a locale paragraph about” is an activity that goes through objects case by case and works out whether to show their initial appearance or writing a paragraph about activity, if appropriate.

Parameter-object is used for all activities, generally under the covers. If you want to write a rule that refers to it, it’s safer to say “For printing the locale description of a container (called C): …” That way you’re not relying on a global variable which is changed frequently.

You can write “For printing the locale description of the chair: …” That works.

EDIT-ADD, following Emily’s post: you’d do this for an enterable chair. It’s run to print the room contents when the player is in the chair.

OK, I was probably making some weird typo or syntax error when I tried it before, because I hadn’t got this to compile before but now it’s working:

Rule for printing the locale description of the holder of the player (this is the list-the-sidekick rule): if the location of the cute puppy is the location of the player: say "A cute puppy follows you, as always."; continue the activity.

That’s definitely simpler than diving down to the parameter-object.

I did not know that was a thing. :open_mouth:

Thank you.

Well, my first thought about all this was that I’d solved the problem for Love, Hate and the etc. so I’d just reuse that code, and then when I hit that bug I figured I just needed someone smarter than me to tweak it to make it work when you enter a container.

I did do some searching for other people trying to order things, and found one person using locale priorities directly and another using RDC, and of course me doing some other random way of doing it, so I figured I’d wait to see what people suggested. (Also I’m not sure exactly what files I’d need to install RDC for 6G60 or where I’d get them from. I’d be prepared to upgrade if I had to, but not if there was a simpler option.)

Honestly I feel like if I could just read a description of how to use locale priorities that was dumbed down enough that might be all I need.

[messes about for half an hour]

Okay, I think this finally clicked. What helps me is if I add the following code, which hopefully does what I think it does:

[code]A thing has a number called the precedence. The precedence is usually 5.

Rule for choosing notable locale objects:
repeat with item running through things in the location:
set the locale priority of the item to the precedence of the item.[/code]
It seems to work if I run this (testing by changing the order of declarations versus changing the order of the declarations with the precedence commented out):

[code]The Vague Room is a room. “Who could ever leave this room?”

Groucho Marx is a man in the Vague Room. “Groucho Marx is here. Huh.”

The precedence of Groucho Marx is 1.

Chico Marx is a man in the Vague Room. “And Chico too! But then where’s…”

The precedence of Chico Marx is 2.

Harpo Marx is a man in the Vague Room. “Of course: Harpo Marx is standing behind you, wearing your hat.”

The precedence of Harpo Marx is 3.[/code]
I guess it doesn’t let me put things after the “You can also see…” text, although I have the “last carry out looking” thingy for that, and it doesn’t seem to affect the ordering of things within the “You can also see…” text, which I have obsessed about in TADS 3 games, but maybe you have to draw a limit somewhere.

For messing about with the order of the “You can also see…” list you can use Complex Listing by Emily Short, which is updated for the latest version (in fact, it’s built in). Example A in the documentation does basically just that.

Okay, cool. What you’ve arrived at is basically what I would have done in an extension, minus some syntax sugar.

Mmmmyeah, sort of. Inform’s built-in “You can also see…” lists are constructed in a pretty fiddly way (because they have to do recursive content listing and so on). It would be possible to reconstruct this, but I’ve never considered it a high enough priority to go through the pain (though if lots of people secretly want it, I don’t know.)

Anyway, the Complex Listing examples mostly cope with the case where we aren’t needing to list nested containment. If we do need that, here’s a hacky approximation:

[code]Include Complex Listing by Emily Short.

The you-can-better-see rule is listed instead of the you-can-also-see rule in the for printing the locale description rules.

For printing the locale description (this is the you-can-better-see rule):
let the domain be the parameter-object;
let the mentionable count be 0;
repeat with item running through things:
now the item is not marked for listing;
repeat through the Table of Locale Priorities:
if the locale description priority entry is greater than 0,
now the notable-object entry is marked for listing;
increase the mentionable count by 1;
if the mentionable count is greater than 0:
repeat with item running through things:
if the item is mentioned:
now the item is not marked for listing;
begin the listing nondescript items activity with the domain;
if the number of marked for listing things is 0:
abandon the listing nondescript items activity with the domain;
otherwise:
if handling the listing nondescript items activity with the domain:
if the domain is the location:
say "[We] " (A);
otherwise if the domain is a supporter or the domain is an animal:
say "On [the domain] [we] " (B);
otherwise:
say "In [the domain] [we] " (C);
if the locale paragraph count is greater than 0:
say "[can] also see " (D);
otherwise:
say “[can] see " (E);
let the common holder be nothing;
let contents form of list be true;
repeat with list item running through marked for listing things:
if the holder of the list item is not the common holder:
if the common holder is nothing,
now the common holder is the holder of the list item;
otherwise now contents form of list is false;
if the list item is mentioned, now the list item is not marked for listing;
prepare a list of things which are marked for listing;
repeat through the Table of Scored Listing:
if the output entry is early-described:
now the assigned score entry is 1;
if the output entry is ordinarily-described:
now the assigned score entry is 5;
if the output entry is late-described:
now the assigned score entry is 10;
[filter list recursion to unmentioned things;]
now printing contents is true;
if contents form of list is true and the common holder is not nothing:
say a prepared list;
[list the contents of the common holder, as a sentence, including contents,
giving brief inventory information, tersely, not listing
concealed items, listing marked items only;
otherwise say “[a list of marked for listing things including contents]”; ]
otherwise:
say a prepared list;
now printing contents is false;
if the domain is the location, say " here” (F);
say “.[paragraph break]”;
[unfilter list recursion;]
end the listing nondescript items activity with the domain;
continue the activity.

Printing contents is a truth state that varies. Printing contents is false.

After printing the name of a container (called parent) when printing contents is true:
if the parent is open:
if the parent contains something:
say " (in which [is-are a list of things in the parent])“;
else if the parent is openable:
say " (open but empty)”;
else:
say " (closed)"

After printing the name of something (called parent) which supports something when printing contents is true:
say " (on which [is-are a list of things on the parent])"[/code]

…but (a) that’s pretty long-winded and (b) even all that only lets you set the order of top-tier things in the list (so if you have a bookshelf on which are four additional objects you want in a particular order, you’re out of luck).

Wait, nope, if I add the chair back into the mix then I start getting duplicated initial appearances again. :frowning:

Presumably I need to narrow down my “Rule for choosing notable locale objects:” line?

ETA:

Rule for choosing notable locale objects for the location: repeat with item running through things in the location: set the locale priority of the item to the precedence of the item.
Seems to be what I want, until I find the next case where it breaks…

If you run into other issues, my best guess is that it will be because you’re assigning locale priority to something that isn’t in the locale list to start with.

What happens here is that by the time you’re choosing notable objects, Inform has already gone through what’s visible and added things that should be included to the list (non-scenery objects that are lying around) and excluded others (your inventory, the player yourself, etc).

Likewise, when it’s choosing notable objects for a supporter that you’re on, it will pick only things that are on that supporter with you, not the rest of the stuff in the room.

But as soon as you give something a locale priority, if that thing wasn’t already in the list of things to mention, it will be added there (because it’s meaningless to have a locale priority on something that isn’t set to be listed). So if Inform is doing a locale describing pass for the chair you’re on, but you set priorities for all the objects in the location again, it will go ahead and redescribe those.

So it may be safer to do

Rule for choosing notable locale objects for the location: repeat with item running through things in the location: if there is a notable-object of item in the Table of Locale Priorities: set the locale priority of the item to the precedence of the item.

Unfortunately, that just seems to stop all the items from showing up at all.

Perhaps we’ve finally hit a difference between Inform versions?

Hrm, okay, curious. I don’t know, and can’t reinstall 6G60 right now to check. If you’re not running into problems at the moment, then feel free to ignore my apparently misguided advice!