A host of troubles (rantish)

Hey all. I’ve attempted to work on my I7 project for the last two days, the vast majority of which has been spent careening between frustration, obtuseness and bafflement. In fact, I’m nearing my wit’s end; it seem that whenever I want to accomplish something seemingly trivial, Inform tells me it isn’t possible, and during the ensuing attempt to fix the issue regardless of the warning I inevitably get smacked with new, completely incomprehensible roadblocks.

A cage is a kind of container. A cage is transparent, openable, lockable, and enterable.

The Penitentiary is a room.
A cell is a kind of cage. A cell is closed and locked.

Nearness relates various things to various things. The verb to be close to implies the nearness relation.
Definition: a cell is the player's if it contains the player.
Definition: a cell is other if it does not contain the player.
Definition: a cell is closest if it is close to the player's cell and the number of cells close to the player's cell is not 2.
Definition: a thing is grabbable if the thing is close to the player's cell.

Understand "this" as a thing when the item described contains the player.
Understand "middle/center cell" as Cell Two.
Understand "left-most/left-hand/lefthand/leftmost/left cell" as Cell One.
Understand "right-most/right-hand/righthand/rightmost/right cell" as Cell Three.
Understand "closest/nearest/nearby" as a thing when the item described is closest.
Understand "farthest/distant/opposite" as Cell Three when the player's cell is Cell One.
Understand "farthest/distant/opposite" as Cell One when the player's cell is Cell Three.

The corpse is a thing. The corpse is in Cell Two.

Rule for printing the name of the player's cell when the reason the action failed is can't exit closed containers rule:
	say "the cell".

Cell One is close to Cell Two. Cell Two is close to Cell One. Cell Two is close to Cell Three. Cell Three is close to Cell Two.

Cell One is a cell. Cell Two is a cell. Cell Three is a cell. 
Cell One is in the Penitentiary. The printed name of cell one is "the left-hand cell". 
Cell Two is in the Penitentiary. The printed name of cell two is "the middle cell".
Cell Three is in the Penitentiary. The printed name of cell three is "the right-hand cell".

Ane is a woman. Ane is in Cell Three. The player is Ane. Understand "your cell" as Cell Three.

The first thing I started with was the creation of a prison. I wanted to allow the player to interact with things that were close to the door, therefore I decided there had to be cells with bars. Since I don’t want to hard-code all the given items by hand, it being an ideal breeding place for bugs, I decided, “why not create objects that mimic this behaviour instead”?

My first attempt was to model any situation in which such cell cages could be stacked, wall to wall, in a line. It would have the following behaviours associated with itself:

  • Close to was to mean thing close enough to affect by someone in a given cell. Originally, the only reason for that was to that was handling cage-to-outside actions, but it gained an additional use in showing which other cell was in range.
  • The occupied cell would be referred to, and understood as, “your cell”, “this cell”, and sensible variations thereof.
  • “The closest cell” or “the other cell” would be understood as the cell closest to your own, but only as long as you were in a cell, and only as long as there was exactly one cell in contact with your cell.
  • “the left-hand cell” or “the right-hand cell” was going to be understood as relative to the cell the player was inside, but only if there was in fact a cell to the right or to the left.

So far, a veritable cavalcade of craziness has ensued. Some choice highlights:

  • The word “other” defies any attempt at alteration by Understand statements, as far as I can see. I can find no documentation on this, but sadly, that makes it no different from most other issues. Once again, bringing out the trusty regular expression hacksaw seems the only way.
  • “Your cell” as a word in the above text will never be properly capitalized during error messages and the like. It seems that the printed names of things aren’t treated like proper names, for reasons beyond my understanding.
  • On a similar note, I can find no clear way of affecting names echoed during certain rule failures. This means the parser will always say “your cell is closed and locked.”, sans capitalization. If you do capitalize, the error instead crops up in the header and quite likely later on.
  • Examining a translucent container will cause it to revert to the “search” action - unless, of course, you provide the container with a description. If you do so, the command will instead examine the container as usual; it does so even when the description text contains a list of its contents. Have found no explanation for this behaviour.
  • Just an aside, but I still find it quite bizarre that we can declare “[action] is [x]”, as in “talking to someone is disobedient behaviour”, yet lack the ability to limit those conditions. Instead, we have to go the way of “instead of engaging in disobedient behaviour at the Inn” in order to box in the declaration and prevent it from wreaking havoc within the game world. I understand why it is so, but it is one more instance where the natural language approach hampers my progress.
  • Largely defeated, I vowed to at least implement some measure of my idea. Accordingly, I scaled it down to three cells, and set the relations between them manually. This is where the vexation regarding printed name and “other” appeared, and neither would be appeased. Thus, it was also where I admitted defeat.

Bitching about I7 isn’t what I want to do, really. It’s a marvellous system in so many ways, and it really has made me wish to learn all I can. I want to create, not throw tantrums. However, at this point, I feel trapped and unable to do anything else.

I don’t know if the solution is to learn I6. I also don’t know whether I should even try, because there’s literally no way for me to know which parts of I6 is rendered redundant or explosive in an I7 context. I don’t know what will happen if/when I manage to finish this room; without ability to encapsulate the code, it may wreak changes both far-reaching and fatal. I could create a wonderful 98% of a game before realizing (as I have before, in some shape or form) that it suddenly no longer works, and hasn’t for quite some time. At which point, of course, the game is effectively beyond saving.

I don’t know which things are impossible or which are dead simple (quite often, official solutions seem to consider a problem solved when it is solved once, in a way that can’t easily be generalized). I don’t know whether implementing a thing will take five minutes or five days. And I don’t see myself improving on that score, either, because there’s only so much reading of the manual and forums one can do before knuckling under.

“This was a simple room,” I thought. “The player is imprisoned. There’s another cell, and through the bars she can barely reach something in that other cell which will allow her to escape.” That is, of course, where the complexity lay. But… still. Complexity, true, but overwhelming? Since I can specify its behaviour quite well using meta-code, that is not likely to be the issue.

So I guess a rather embarrassing diatribe now segues into these questions:

  1. Is I6 the only way out of this mire? Is there a way at all?
  2. What parts and conventions of I6 will no longer work and/or destroy I7 when introduced to it?
  3. How do I make a printed name behave like an actual name?

Hi, Eleas. I don’t think any of your problems stem from Inform’s natural language syntax. Instead, I think they stem from unfamiliarity with portions of the library and of the system. This wouldn’t be improved by switching to I6; the libraries are comparable.

The main problem folks face in learning the intermediate and advanced aspects of in Inform is that there is no really accessible documentation of the I7 library code. The closest thing is Appendix A, which is an annotated version of the Standard Rules. It’s good documentation of the code (which is all it aspires to be), but it doesn’t really bridge the gap between the manual and what you’d get out of just reading the code.* (Jeff Nyman is working on a manual, or series of mini-manuals, that should go a good way toward rectifying this; at least they will if the chapter he put together on descriptions and locales is an indication of what’s to come.) For now, though, only asking questions, smart testing–using debugging commands such as RULES and ACTIONS, as well as the Rules and Actions tabs in the Index–and delving into the more obscure parts of the documentation (e.g., appendices, syntax crib, flow of play diagram) can get you over the hump.

The problem with “other”, for example, is quite simple: the reason that “other” doesn’t work as you want it to is that the player is constrained by the container she’s in; the library, specifically the “can’t reach outside closed containers rule”, prevents her from doing anything to items outside, including examining them. Add this:

The can't reach outside closed containers rule is not listed in any rulebook.

… and that problem will go away. (Actually, destroying the rule like this is probably overdoing it–you’d probably want to write rules that bypass the can’t reach outside closed containers rule, but only in certain circumstances, such as when the player is in the Penitentiary.)

So, how would you have found this on your own? The best way would be to go to Appendix A/the Standard Rules and read about containers. To discover that you need to do this, though, use the RULES and ACTIONS commands. Type both, then examine the middle cell. This will clearly indicate that the

[code]>x middle cell
[examining the middle cell]
[Rule “examine undescribed containers rule” applies.]
[(1) searching the middle cell]
The right-hand cell isn’t open.
[(1) searching the middle cell - failed the basic accessibility rule]

[Rule “report other people examining rule” applies.]
[examining the middle cell - succeeded][/code]

This clearly indicates that the “examine undescribed containers rule” has forwarded the action to the searching action. Look up both that rule and that action in the Standard Rules, and you’ll find what you need to selectively disable the library behavior.

Similarly, as you’ll see if you type “RULES” before examining a cell (this single technique is probably the most valuable for tracking down issues where you’re getting output you don’t understand), the reason that you get a list of the objects in a cell when you examine it is that same “examine undescribed containers” rule:

>x middle cell [Rule "examine undescribed containers rule" applies.] [Rule "can't search unless container or supporter rule" applies.] [Rule "can't search closed opaque containers rule" applies.] [Rule "standard search containers rule" applies.] In the middle cell is a corpse.

You ask why Inform forwards things to the searching action–it’s because a listing of the contents makes sense as a response to examining a transparent (or open) container, and listing the contents of things is what the searching action does. And so a rule to forward the examining of containers to the searching action was written into the library. You can override this behavior, as you discovered, by giving a description to the container. (You can list the contents yourself in that description, which will give you more interesting prose in any case.) If you want a totally different, procedurally generated description, you’ll need to bypass the examine undescribed containers rule to provide your own rule for describing a container.

–Erik

  • Appendix B goes even deeper, into the I6 Template.

Hi, erik.

First, thanks simply for deciding to reply. Part of me had feared it wouldn’t happen for a few more days at the very least.

Yeah, I gather it’s a matter of the libraries, and that they are comparable. This is also the reason why I considered whether it would be wise to learn I6; not in order to switch systems, but in order to understand I7 better and on a deeper level, and hopefully break the deadlock.

That desire is tempered, though, by the niggling worry that I7 and I6 have already sufficiently diverged. I know that, for instance, I7 adds additional functionality in its libraries, so that methodology seen in DM4 will often be redundant, and not a few times destructive, if introduced into I7 code.

Hence my worry - is it at all profitable to learn I6, in terms of time? How much can I change in I7’s behaviour (in terms of early-stage parsing or the illumination handling, say) by use of I6 code, when speaking of things that can’t be readily changed by vanilla I7 programming?

As it is now, I don’t have enough information to make a judgement call. During the last two weeks, I learned both VB.net and C#, so learning I6 should not be beyond me. It would be bitter, however, to discover that after I was done, what I wanted to do was in fact impossible.

I get the sense of this as well. It’s still a beta, of course, but I recognize what you’re saying - in fact, more or less I got the impression of Appendix A being more or less a glossary. There’s that, and the way the text is disposed and structured, which tends to play havoc with ADD tendencies.

I think the old idea of an “Inform 7 guide to programming” that I read about on rec.arts.int-fiction was a good suggestion, although I do recognize the need to break from old practises. You mention Jeff Nyman’s new efforts, and judging solely by his previous work, I’m quite excited to see what he has in store.

I’m doing this at the moment, albeit partially. I think the presence of I6 here remains a hampering influence. Understanding something that already requires new ways of thinking is difficult as it is. Knowing that there is a lot of stuff working behind the hood that kinda sorta almost is this other language that you might as well learn and which might work or destroy all you’ve made… well. That’s a distraction, to put it mildly. When I don’t understand something in I7, I tend to suspect it’s buried in I6 code somewhere.

I hate to make this rejoinder, but that alteration doesn’t work. It does in the code I sent earlier, surprisingly enough (I tried that technique earlier on without success; must have made changes later on that reenabled it, somehow). Regardless, the idea is good, but fails to work in the example below.

The can't reach outside closed containers rule is not listed in any rulebook.
A cage is a kind of container. A cage is transparent, openable, lockable, and enterable.

The Penitentiary is a room.
A cell is a kind of cage. A cell is closed and locked.
Nearness relates various things to each other. The verb to be close to implies the nearness relation.

Definition: a cell is the player's if it contains the player.

minë, atta, neldë, canta, lempë, enquë, and otso are cells in the Penitentiary.
Understand "other cell" as atta.

When play begins:
	let M be the list of cells in location;
	let num be the number of entries in M - 1;
	let y be a number;
	repeat with x running from 1 to num:
		let y be x;
		increase y by one;
		now entry x of M is close to entry y  of M.

Ane is a woman. The player is Ane. Ane is in minë.

Had I known why things were this way, or where to look (I will now check the library, as per your recommendation, but I can’t really grasp why the differences here should make for substantial difference), I’d have had a day to spend on developing story or characters, instead of cursing the interpreter. As you can tell from the above code, I figured even Quenya would fail to make the situation worse.

…and now, I’m suddenly getting the sinking feeling that must be the answer, regardless of previous testing on regular-looking cell names. Ah well.

This is also something that I’ve really strained to do, but which I find massively difficult to attain in practise, because in the vast majority of cases, stacking conditions of that kind result in parser errors. In more than one instance, where it was really necessary, I had to nest Definition: or To Decide: statements in order to get an end result that the parser would accept.

I did this earlier, but left it out of my source code in the interests of brevity (and, to be honest, out of sheer exhaustion). One attempt that I managed to get to working used this, and was intended to allow for simply examining the cells, which was why I had to disable both reaching out and reaching in behaviours to get a transparent box description in the first place. Both actions and rules reporting were very helpful in that regard.

I will add (and this was of course not at all self-evident, for which I apologise) that I don’t tend to post raw source code when an error crops up; I post a code that demonstrates the error. This one was a bit sloppy and wordy, because there was no single back-breaking error but several tiny issues, one of them being the printed name issue of which I still cannot make head nor tail.

Thank you, most interesting. One vexing aspect of traditional IF is that all these conventions are ubiquitous, yet largely unexplained to newcomers. Beginners first learn the meanings of the compass keywords, “up” and “down”, inventory and taking. That’s easy. However, though I’m past that stage, I still remain largely uncertain as to whether examining an object implies that I hold it or not, just to pick an example. The full (and unstated) implication of “search” was something I didn’t know until just now.

This, I think, might be a useful thing to elaborate on in a manual, or maybe a companion piece. There’s a real danger in refusal to make games accessible, and some time-honoured IF conventions are cruft, despite praiseworthy efforts toward innovation. If we are to praise the power of natural language - and I think we should - how can we then praise the effort of neutering said language as a wonderful step toward “stringency” or “economy of language”? It does not scan. One can be stringent without being rabid about it.

</random tangent>

Thank you. The knowledge of what could be done was nice - the explanation, however, was of immense value. I think someone on the forum referred to the old adage about teaching a man to fish; that’s rather how it feels. In order to do the programming equivalent, one must teach why something happens, not just simply that it does.

Anyway, thanks for taking the time to reply, and for putting up with no small amount of whining. I blame this week and my wavering journey between hard-case OOP and I7… and the fact that the syntax autocoloring in both editors looks somewhat alike. Regardless, however, I will reiterate - I’m not going to use this as part of some sinister or drive a wedge between practitioners of proper IF; I’m not (or so I would like to think, at least) complaining for it’s own sake. And as for my comments on newcomers and IF, I may well hope to offer some variation to the theme later on, but, in all honesty, right now I’m just trying to see what works best for me.

EDIT: Gah. Apologies for massively editing this, but, being tired, spelling errors and bizarre phrasing was abundant.

The Programmer’s Guide was moved to… well heck, why don’t I just stick that into my sig?

Voilá:

What I meant was that there’s as much library to learn with I6 as there is with I7, so learning I6 wouldn’t be any easier. The only real difference is that in I6, the entirety of the library code is written in the same language as the language you’re programming in, whereas large parts of I7 is using a tweaked I6 under the hood. I’d say that learning I6 to understand I7 is a bit like learning Latin to understand English. Interesting, and you’d definitely gain a historical perspective on certain pecularities of Inform (e.g., the parser), but you there’s no real reason to do it. The I7 library is its own thing, and now differs in many ways from I6. (Learning I6 to provide functionality not available in I7 is a different story–I’ve learned bits and pieces of the way I6 works in order to implement Glulx multimedia functionality, for example, or to hack the undo system–but you generally don’t need to understand the entire system to do that.)

Well, I don’t think anything you’ve mentioned in this thread has anything to do with the I6 library. The things you’re having trouble with are fully implemented at the I7 level, and everything you want to do (if I read it correctly) is also possible in I7. I think you can safely concentrate on finding your way around I7. (On the other hand, you mentioned OOP; if you think you might be interested in switching to a more object-oriented language, you might have a look at TADS 3–just be aware that it has an even bigger standard library!)

Re the documentation: If you PM me with your email address, I’ll send you a copy of the document of Jeff’s that I mentioned. It comes close to touching on some of these topics; more importantly, I think there’s a chance it might help you harmonize your thinking with the way Inform works.

No, it works just fine (and it’s not “surprising” that it works, either! :wink: It’s necessary, based on the way the rulebooks are structured). Compare these two examples of play:

Without removing the can’t reach outside closed containers rule:

[code]Penitentiary (in minë)
You can see atta (closed and empty), neldë (closed and empty), canta (closed and empty), lempë (closed and empty), enquë (closed and empty) and otso (closed and empty) here.

x atta
Minë isn’t open.

x canta
Minë isn’t open.[/code]

Now we remove the can’t reach outside closed containers rule:

[code]Penitentiary (in minë)
You can see atta (closed and empty), neldë (closed and empty), canta (closed and empty), lempë (closed and empty), enquë (closed and empty) and otso (closed and empty) here.

x atta
Atta is empty.

x canta
Canta is empty.[/code]

We can now look into the other cells, which we couldn’t do before; before we disabled the rule, Inform was telling us, effectively, that we couldn’t see beyond the walls of our own cage (“Minë isn’t open”).

As for ways of selectively “disabling” this and other rules (or writing around them), you mentioned piling up conditions or write nested definitions/to decide phrases. But in cases similar to those we’ve been discussing, you can do this with rules and particularly with the ordering of rules within rulebooks. For example, for the present situation, you need to allow the player to look and act outside her cell when she’s in the penitentiary. But outside, maybe you have an elevator that’s implemented as a container. You don’t want her to be able to see or act outside of the elevator. So, we need a way to limit the exception to the penitentiary. The can’t reach outside closed containers rule is in the “reaching outside” rulebook. We can just add a rule like this:

A reaching outside rule when the location is the penitentiary: allow access.

The condition tacked onto the end makes this more specific than the can’t reach outside closed containers rule, so it will be considered before that rule, and thus supersede it when the player is in the pentientiary. Note: it is important to use the phrasing “when the location is the penitentiary” rather than “when the player is in the penitentiary” because Inform only looks one step up the object tree when we use “when the player is in”–in other words, Inform will see Ane as in the cell, not in the penitentiary. “Location” is always the room, and that’s what we want here. (On the other hand, if only one of the cells was an open cage, while the others were closed chambers, we might wish to specify the cell, e.g. “A reaching outside rule when the player is in Atta”. Now we can only look out of Atta.)

By the way, as you proceed with working on this scenario, you might find it useful to look at Jon Ingold’s Far Away extension:

inform7.com/extensions/Jon%20Ing … doc_0.html

–Erik

By the way, if anyone has been itching to write an Inform 7 tutorial but couldn’t figure out to write about: The number of questions posted both here and at rec.arts.int-fiction on topics like these strongly suggests that a guide to Inform interventions–ways of identifying and changing the standard library behavior–would be useful to a lot of folks…

–Erik

Oh. I see! Food for thought, indeed. I may find I6 fun to learn as a side project, then, and it may in certain situations improve my understanding, but I should be fine with I7 as it is. That’s fine. I can certainly work with that.

Question regarding I6 extensions and statements embedded into I7 source, though - do you you feel that practice is lessening? It seems to require knowledge of I6 in some shape or form.

Size is seldom a problem to me. Problems tend to crop up in terms of structure, legibility, and documentation, but size alone is just opportunity.

Thank you! If it’s the Well-Versed-Foundations.pdf file released on rec.arts.int-fiction recently, I downloaded it already, so you don’t have to go to the trouble. If it’s some other file, I’ll happily PM you my address.

I see the problem. We were talking about two different things. I (probably without being clear about it) talked about having implemented that already, but that when I did so, the understood statement “the other cell” or variations thereof including the word “other” failed to work. And that remains true, in the second example given. Understand “other cell” as atta will not be accepted. That was what I pointed out as failing to work, as it yields

>x other cell
You can't see any such thing.

>x atta
Atta is empty.

whereas the first gives us

>x other cell
(the middle cell)
the right-hand cell isn't open.

However, it outputs that regardless of what you set “other” to be understood as, or even if you put in ‘Understand “other cell” as [something]’ at all. And so, in point of fact, neither examples at all work the way they’re supposed to, in the context of that pronoun.

Yes indeed. But it isn’t enough by far, because you could not be expected to let the character reach freely around the penitentiary from any cell. Thus the need to specify by words like “and the cell containing the player is close to the noun”, and such things do seem to be hit and miss.

I did not know that. Thank you; it’ll come in handy.

I hadn’t realized, but yes, Far Away does seem to offer a step toward the solution.

Anyway, the remaining problems raised by the scenario are:

  • The pronoun “other”.
  • The issue with understanding left/right relative to a given cell (I believe I can make that work myself).
  • The issue with printed names not being treated as real names in terms of capitalization and the like.

Where do I go toward solving at least the first and last issue?

:open_mouth:

You guys rock. All that spare time will certainly come in handy now. :smiley:

No, it’s a different file. Jeff had it up at his old website, but the site has gone down, and the file with it.

Ah, I didn’t even consider that you were talking about “other” here, since the effect of the can’t reach outside closed containers rule really doesn’t have anything to do with whether “Understand ‘other’ as” works or not. It’s what I think of as a gatekeeper rule–it prevents the player from acting on anything outside the container. I guess you could say that bypassing the can’t reach outside closed containers rule is a necessary but not sufficient condition for “other” to work.

The fact that “other” happened to work (or appeared to work) with your previous example blinded me to the reason that it doesn’t work here. It turns out that “other”, along with “another”, is hardcoded directly into the parser (the hardcoding of certain words into the parser–which prevents them being redefined by authors–is one of the I6 legacies I was talking about before). I wasn’t even aware that Inform parsed “other”; along with a few other words (such as “every”), “other” and “another” put the parser into a mode where it looks for indefinite matches for the noun, instead of a single, definite object. In other words, it handles such input as “Put another coin into the box.” I think you can read more about this in the DM4 (another missing piece of documention for I7 would be the parser itself–what kinds of input does it understand?).

Anyway, now that we know that “other” is actually built into the parser, we also know that we need to work with Inform’s definition of the word, which is doable. To get the equivalent of this to work (from your latest example):

Understand "other cell" as atta when the player is in a cell.

you can do something like this:

Understand "cell" as a cell. Does the player mean doing something with atta: it is very likely.

The first line enables the player to type “cell” and have it refer to any cell. Prior to this, “cell” was not understood at all. (N.B. You could also just include “cell” in the names of each of the cells, which would have the same effect; this is in fact why “other cell” appeared to work in your first example.) Because “cell” is now a concept the parser understands, this means that “other”, “another”, “every”, etc. will work with it. The second line ensures that when the player types “other cell”, the parser will decide that she means Atta.

However, because the word “cell” is ambiguous, that “does the player mean” rule will also have the effect of directing the player’s input to Atta not only when she types “examine other cell”, but even when she types simply “examine cell.” That’s not desirable at all, since surely most of the time she’ll be referring to her own cell when she types something like that. Since Inform doesn’t have special parsing rules for the indefinite vs. definite situation (I don’t think it does anyway–missing feature?), we need to do a little hacking:

[code]Understand “cell” as a cell.

Does the player mean doing something with the player’s cell:
if the player’s command matches the text “other cell” or “another cell”:
it is very unlikely;
it is very likely.

Does the player mean doing something with Atta when the player is in a cell:
it is likely.[/code]

Thus, we direct the player’s input to another cell if the word “other” has been used in the input; otherwise we assume that the player is referring to her own cell. We also suggest Atta as a likely candidate in any situation where “other cell” is used. This works nicely.

I think that should point you toward a solution for the “other” issue. I have other things that I’m neglecting, so I won’t try to comment on the printed name issue, except to say that I think you’ll either need to find ways to intervene with “rule for printing the name of” for various situations, or rewrite offending library messages to work as you want them to. However, I’m not positive about this; someone else might have better advice.

Given the length (in words) of this thread, though, you might want to start a new thread–we may well have lost some folks with the torrent of words here!

–Erik

Absolutely. In all honesty, what you’ve given me seems more than sufficient alone to solve these problems, and your recommendations have opened quite a lot of different areas worthy of study. Most of all, I think, is that I can now move forward with a degree of confidence I couldn’t summon up before. Instead of feeling as if my complaints were somehow self-invented and/or a natural consequence of IF, I now get the sense they’re simply new aspects to play around with.

Thanks for getting me past this hurdle. I’ll pop you a PM with my mail address.

On the issue of capitalization, as far as I know the only way to address that is to write a general “to say” correction statement. For example:

To say capset for (modword - a thing): let modtext be indexed text; let modtext be "[modword]" in sentence case; say "[modtext]".
and then utilize it in every particular case where capitalization will be an issue. For example say we have some body parts, whose names are printed according to a rule like:

Before printing the name of a bodypart that is incorporated by a person (called owner): if owner is the player: say "your "; otherwise: say "[owner]'s ".
When a case occurs where the printed name of a part, then, will start a sentence it must be dealt with on a case by case basis:

Carry out examining an ear that is incorporated by a person (called xee): if xee is the player: say "[capset for the noun] seems pretty normal."; otherwise: say "[The noun] seems pretty normal.".
Unfortunately I’ve never found a more general way to effectively deal with this issue myself.

Ah. Yeah, I was attempting that route. What was bothering me was mainly that some error messages put the word in the beginning, others in the middle of the error message. Among other things, that means you get messages like “You can’t get out of the closed the cell,” which requires further workarounds.

There is a better way of dealing with the capitalized “your” issue, and it is to include this:

The indefinite article of the cell is “your”.

(See section 3.18 in the documentation.)

This deals with capitalization (“You’re stuck in your cell” vs “Your cell is closed”) and will also change to “The/the cell” if Inform is translating “[the cell]” rather than “[a cell]”.

Also, incidentally: the thing of converting examine to search is a feature of the library we’re revising to the next build. It made sense in the original implementation of Inform 6, sort of, but you’re not alone in finding it a bit baffling, and there are a handful of cases where it produces actively stupid/erroneous output. (For instance, if I EXAMINE a closed glass box with things in it, that converts to a SEARCH, which then fails because the box is closed – even though I can perfectly well examine the things in the box individually.)

So we’ve rewired the behavior of this and a few other legacy features of the library in the hope of making them a bit more friendly or sensible.

This is wonderful news. Thank you so much.

The extension “Mentioned in Room Description” has a few capitalization-related devices in it. For example, the [^] say phrase that capitalizes whatever comes next. The solution presented within doesn’t used indexed text, it uses some stuff built-in to Inform 6, so it’s much gentler with the Z-machine.

Mind, capitalization issues are a hydra: as soon as you think they’re solved, a fresh problem rears its ugly head.