Dealing with Fiddly Bits - Some Thoughts and Code

You’re playing along and you see an item with the following description:

So, naturally, you try examining things on the clock:

Yes, this example is excessive. I wrote it to make a point. These little nuisances bug me. What do you mean I can’t see any such thing? You just told me it was there!

To fix the nuisance messages, an author might choose an obvious solution and create objects for all of those things and make them parts of the clock. However, in a large body of work, doing so may lead to many pointless objects that take up valuable memory. Doing all that also bogs down the creative process. Of course, one can also try to write around the problem and never make references to nouns other than the noun of interest. That gets tedious and may actually, in some cases, be impossible. It seems that authors commonly choose to tell the game to understand each of the parts as the noun of interest. Understand “cuckoo” as the clock. Understand “face” as the clock. That leads to a very repetitive and annoying experience, especially if the item description is long. (In my example above, the word “face” has been mapped to the broken clock. Imagine if the entire parts list was mapped to the clock.) None of these solutions really appeal to me.

I decided to see if I could build a solution that provides a little better experience without heavy management or intensive memory use. I’m not sure my solution is less memory intensive than creating objects. I also would not be surprised to be told that there is a plug-in that has a better solution. Still, it was a good exercise for me. Here’s what I settled on:[code]A thing has a list of text called parts-list. A thing has some text called part-response.
The part-response of a thing is usually “That’s part of the [the item described]. It’s not really important.”

The Junk Yard is a room.

[A deliberately verbose item description]
A broken clock is in the Yard. The description of the broken clock is “The clock looks like the gable end of an old shake shingled house. Just
under the peak of the roof, a small wooden cuckoo hangs through a tiny double-doored hatch and dangles from a stretched spring. One of the
hatch doors hangs loose on a single bent hinge. The once white clock face, now yellowed with age and spotted with rust, shows only a minute
hand bent as if pointing at [us]. The hour hand snapped off long ago. The worn but still legible numbers all remain, except the five, which
someone deliberately and completely scraped away.”
The parts-list of the clock is {“gable”, “shingle”, “house”, “door”, “hatch”, “peak”, “roof”, “cuckoo”, “spring”, “hinge”, “face”, “rust”, “hand”}.
Some faded numbers are part of the clock. The description of the faded numbers is “The numbers are faded and worn except the five. It has
been deliberately and completely scraped away. Since no rust has formed, [we] guess that the scraping was done recently.”
Understand “five” as the faded numbers when we have examined the clock.

[By checking the list of fiddly bits only when the parser has finally given up, I’m not overriding anything that might be a legitimate command.]
Rule for printing a parser error when the latest parser error is can’t see any such thing error and something is visible:
let R be “”;
repeat with temp-item running through visible things:
if we have examined the temp-item:
repeat with fiddly bit running through the parts-list of temp-item:
if the player’s command matches the text “[fiddly bit]”:
now R is “[part-response of temp-item]”;
break;
if R exactly matches the text “”:
break;
if R exactly matches the text “”:
now R is “[text of parser error internal rule response (E)]”; [Can’t see any such thing.]
say “[R][line break]”.[/code]I tested this in a few ways. The full code is attached. One test involves two visible items that have duplicate fiddly bits. For example, there might be a hand and face on a broken doll in the Junk Yard as well as a hand and face on the clock. This method just picks one. Visible things without a defined parts-list are ignored. Finally, if there is an actual visible object in scope having a name that matches one of the fiddly bits, the actual object automatically takes precedence.
This resulting dialog seems much more rewarding to me:

There are still problems with this approach. For example, attempting to examine Clark Gable or the almighty mountain peak will result in the system telling me that those things are part of the clock and aren’t important. Hey, it’s an amazing clock! :laughing: That problem can be mitigated by doing an exact match instead of a containing match. The parts list just gets a little longer.

Another problem has to do with items with shared unimportant keywords. If the player tries to examine the doll’s face, he might be told that it is part of the clock and isn’t important. (If face is an actual object that is part of something, then the result is that the actual object gets examined.) I’m not exactly sure if that matters. It could lead to some frustrating attempts to get the system to tell me about the doll’s face, but I haven’t tried to solve that issue yet. I envision something simple like, “You see a face on several things. None of them are important. Keep moving.”

After playing with this code for quite some time, I noticed that a player might see that the cuckoo is wooden and try examining the wood. In this case, he would be told that he can’t see any such thing. I could put “wood” into the list of fiddly bits, but then I’m starting to get excessive. I’m realizing that no matter how hard I try, there will probably always be something I miss. There are always trade-offs, I guess.

Ultimately, it is probably important to balance descriptions with what is important to the play. I should ask myself if it is prudent to have all that description, or is it enough to be minimalist? For example: “It is an old broken cuckoo clock. The number five was deliberately and completely scraped off recently,” might be all that is needed in this case. Not every case can avoid it though. Even Zork describes a beautiful vista of mountains, but when you try to examine the mountains, you can’t see any such thing.
fiddly-bits.txt (4.01 KB)

Here’s what I would do, if I were to lose my mind and write that description! :laughing:

[rant][code]“The Deliberately Descriptive Clock”

The Junk Yard is a room.

[A deliberately verbose item description]
A broken clock is in the Yard. The description of the broken clock is “The clock looks like the gable end of an old shake shingled house. Just
under the peak of the roof, a small wooden cuckoo hangs through a tiny double-doored hatch and dangles from a stretched spring. One of the
hatch doors hangs loose on a single bent hinge. The once white clock face, now yellowed with age and spotted with rust, shows only a minute
hand bent as if pointing at [us]. The hour hand snapped off long ago. The worn but still legible numbers all remain, except the five, which
someone deliberately and completely scraped away.”

some clockwork bits are part of broken clock. Understand “gable/end/shake/shingled/house/peak/roof/small/wooden/cuckoo/bird/tiny/double/door/doors/doored/double-doored/hatch/stretched/spring/springs/bent/hinge/hinges/white/face/yellow/spot/spots/spotted/minute/hand/hands/point” as clockwork bits. The description is “[one of]That is part of the clock.[or]That is also part of the clock.[or]That’s another unimportant part of the clock.[or]The only really interesting thing is that the five is scraped off.[stopping]”

Some faded numbers are part of the clock. The description of the faded numbers is “The numbers are faded and worn except the five. It has
been deliberately and completely scraped away. Since no rust has formed, [we] guess that the scraping was done recently.”
Understand “five/number/hour/time/scraped/rust” as the faded numbers when we have examined the clock.[/code][/rant]

Reasoning:

If you’re going to write a description like that, you’d better be in for a pound and willing to synonym it. It seems extensive, but it’s simpler than making every single piece of it a part of the clock, the random text variation keeps it from being too repetitive, and also directs the player to the important part (I’m inferring the scraped off five here.) Also, just using synonyms means disambiguation will work “Which do you mean, Clark Gable, or the clockwork bits?”

WRT disambiguation when there’s not “a doll’s face”…if you’re not going to synonym the details of all your items this obsessively, that’s somewhat inconsistent and kind of blows up the whole point of being this indulgently wordy about a cuckoo clock. Unless you mean for it to be a joke.

1 Like

I’d have thought this was more likely to take up valuable memory than creating many pointless objects.

A list of words takes a bit more memory than an object, and is a bit more work for the machine to handle.

It’s probably not a difference worth worrying about. But HanonO’s solution is simpler. And note that it only creates one pointless object, plus the numbers (which are medium-pointful).

Ah. That’s a surprise, and an interesting tidbit. You are saying that, had I put 10 or so objects on the clock, with their respective descriptions, etc., that the system would be faster and smaller managing the items in a room than it would managing one object with a list of words that only gets checked on a parser error. That really is counter-intuitive to me.

…and that is why I posted. I figured there was a better way and someone would point it out. You did. I appreciate it.

Well, the point of putting the list on the things object was to allow for all things to have a simple tool for doing exactly that. The doll could have a “face” in the parts list and the clock could also have a face in the parts list. What I had failed to fix, was what happens when those two items are in the same room. My way just picked one of them. Which, as you pointed out, is inconsistent and could be frustrating. Your way works, uses the built-in disambiguation, and, as zarf pointed out, actually takes up less space. I also like your approach of guiding the reader much better than just having a slightly different message. Very nice.

Thank you!

I didn’t say a list of words was more memory than ten objects! I was comparing it to HanonO’s solution, which uses just two.

The code snippet that I quoted above creates not just one list of words, but one for every thing in the game; it would be more economical to do it only for complicated objects with lots of “parts”.

out of curio (and hoping not to excite unsavory coding…) what is, if any, the synonym limit of glulx ?

for sure HanonO’s solution has a definite limit when compiled against z-machine, whose has an 8 synonym limit…

side point, I’m in process of glulxising my I7 WIPs…

Best regards from Italy,
dott. Piergiorgio.

If there is a Glulx limit, it’s large enough not to worry about. I just compiled a game with a 300-synonym object.

Z-machine 8 seems to be OK with up to 31 synonyms.

Most of Inform’s set limits in Glulx are mostly a decorative fence for tidiness and can be expanded as necessary since memory limits aren’t as much of a factor on modern computers…unless the author is writing a stunt/freakshow game with thousands of procedurally generated rooms or some other weirdness. I have hit PROP_TABLE_SIZE in more than one game, which I think has to do with the number of objects in the world.

Trying to compile an object with 1684 synonyms brought me up against MAX_DICT_ENTRIES.

So the limit is on the total number of words understood by the game (and can be raised anyway, as HanonO points out). There seems to be no separate limit in Glulx on the number of synonyms an object can have.

An I6 synonym list is an object property containing a list of dict words. In Glulx that’s limited to 32767 entries. (Or maybe 65535, but I suspect the high bit is reserved for something somewhere.)

You can in fact get past that by writing a parse_name routine, which can contain arbitrary matching code. But of course this is up in the range of silly.

Thanks zarf.

Incidentally, trying to compile to z8 when an object has too many synonyms throws up a compiler failure, which probably counts as kind of a bug. I’ll report it, even though it’s completely trivial.

Many thanks to all of you, esp. Zarf.

OT: As HanonO noted, I think that glulx can handle rogues, but I think that rogues are still best programmed in C/C++ or other general-use languages.

Best regards from Italy,
dott. Piergiorgio.