I7: Custom "physical" relations

If I understand correctly, when I use one of Inform 7’s built-in relations involving physical juxtaposition of objects (containment, support, etc.), the effect is to treat one object as a “branch” of the other on the “tree” which represents how Inform handles objects. Thus, if the bed is a supporter and a blanket is on the bed, the blanket is now a sub-branch of the bed branch, which in turn branches from the bedroom branch of the world tree.

Suppose I create a new relation to reflect one object being under another. I can create the relation, as well as a “putting it under” action, and can code the consequences of the dust bunny being under the bed (in terms of how it responds to various commands). However, if I understand correctly, the dust bunny would not be conceptualized as a sub-branch of the bed branch; rather, as far as Inform is concerned, the dust bunny would only be in the bedroom (and even that would only be the case if I manually specify that it is, either as an assertion statement in the initial state of the world or as part of the “putting it under” action).

My question is two-fold: First, does any of this really matter? In other words, are there any real consequences to the dust-bunny being a sub-branch of the “bed” branch, as opposed to just being in the bedroom? Second, if it does matter, is there a way to make custom relations such as this behave like the built-in relations?

Or I am totally misunderstanding what is going on here?


Robert Rothman

I have never actually tried to do something with this, so my understanding may be completely wrong. But this is my guess:

I don’t think there is a “tree” in Inform somewhere. These are the built in relations (manual 13.18):

and I suspect that verbs like “encloses” and “is in” are defined in terms of these relations. (E.g., A is in B if B either has, contains, supports, carries, wears of incorporates B.) In order to add a relation that behaves the same way as the built in relations, you’ll have to find the definitions of “is in” and “encloses” (and perhaps others) in the Standard Rules, and replace them with definitions that involve your new relation.

Edit: there are consequences of putting the dust bunny in the bedroom rather than under the bed in a more robust sense, but only if you are ever testing whether the dust bunny is enclosed by (or in) the bed, or ask for the “holder of the dust bunny”. If you don’t make those kinds of test, there is no consequence and you don’t need to fiddle with the standard rules.

Well, I think the issue is that (for instance) if your code for killing an NPC involves moving everything that the NPC carries to the holder of the NPC, then whenever you kill an NPC under the bed, their possessions will wind up on the floor unless you write a special case for that. And I think you do have to write a special case for that; my approach would be write a phrase along the lines of “To move X to the real-holder of Y” that checks if Y is under anything, moves X to Y’s holder, and puts X under anything that Y is under.

Also there will be various reaching, accessibility, and possibly visibility rules that you can get to work for containers and supporters that you’d probably have to hand-code for undersides. Depending on what you want to do, maybe one approach would be to make the underside of the bed a container (with appropriate redirects so that putting something under the bed meant putting it in the container, getting under the bed meant entering the container, etc.)


Although the I7 docs don’t describe the various enclosure relations this way, the underlying i6 code does use what is referred to in the DM4 as the “object tree” to track enclosure relations. (Although I don’t think “branches” is used in its terminology, but rather “parent, child, and sibling.”) In fact, from an i6 standpoint, this tree describes all standard forms of containment (other than incorporation) using attributes to specify which type. For example, in i6 when a person is the parent of something, that thing is automatically “carried” unless it has a clothing and a worn attribute that are both true – in which case the thing is being “worn.” (The I7 concept of incorporation is handled by a separate “component parts tree” which is unrelated to the object tree; it is essentially an old i6 scoping hack which has been added to the core I7 syntax and functionality.)

Short Answer: Yes, but admitting it is the first step.

Long Answer: What I mean is that it does matter, but it’s not a big deal for a specific game. A general implementation like an extension, however, will require understanding and testing of weird edge cases. Containment is a fundamental part of the Inform world model; in addition to the scope issues that Matt W. mentioned, the position of objects in the object tree affects other things at the template (i6) level, such as light - transmission, output from the list writer, and in some cases even disambiguation.

I don’t think you can modify or piggyback on the existing forms of enclosure using purely I7 syntax. (I can’t find the quote in the manual so this might not be true anymore.) You can hack containment with pretty simple i6 inclusions if necessary.

Final Relevant Answer: If you’re just interested in modelling an underneath relation, check out Eric Eve’s “Underside” extension which uses I7 - containment to simulate this. I think it would be easier to modify this extension for a specific use than to build an alternate implementation from the ground up. If you’re interested in a different type of containment, post the details or PM me. I have a working general implementation of “indirect holders” (tweezers, butterfly nets, etc.) which was inspired by Jim Aikin’s “holder” extension for i6. It needs an update for the current build as well as documentation. (Like Matt, I’m also still working on Endosphere’s multiple persuasion problem. I’ll probably just post what I have soon since this type-safety thing is killing me.)

Thanks. Ultimately, I have to give some thought to how far I want to go with this. I will look into the Underside extension, although at first glance it seems like it may be a bit of overkill for my purposes. Basically, I have one puzzle which will require the player to put something under something else; once I build the concept of “under” into the game, however, I feel like I should at least deal with the possibility that a player may try to put other things underneath something. The easy way would be just to block any attempt to put anything under something else, except in the one case where it is required. The hard way would be fully to implement the concept and to allow a player to put anything under anything else (at least in those cases where it is a physically reasonable thing to do). I suspect I may take something of a middle ground.

Robert Rothman

I was working on an extension for modeling ropes and gave up. Can you do ropes with your indirect holders?


My first reaction to this was, “Hm, I never considered that – but no, I don’t think so.” After scanning some of your rope - related posts though, now I’m thinking some of the ideas used in my extension might be adaptable to your scenario. It seems like you started out with incorporation as the principle (assertable) relation working in tandem with a subsidiary conditional relation, but that you abandoned this approach in favor of a new “connection” relation. I also started modeling indirect holders using incorporation, only to give up for the reasons alluded to in my post upthread. I started again by mildly hacking containment at the i6 level (using the “container” attribute) and virtually all of my problems disappeared automagically.

Leaving aside other issues (divisibility, multi - room connectivity, etc.) which I’m assuming we’re not really discussing here, I think “indirect holders” could be used to model some aspects of ropes – if not the ropes themselves, then perhaps their ends or knots. At the very least, you might get some ideas from the way I had to deal with certain edge cases. I’ll try to get a version with some coherent documentation up on another thread in a few days.

I thought the connection relation worked reasonably, but I got stuck on two things:

  1. Making sure actions take rope-connections into account. This can mean doing a pathfinding search along rope connections to find out whether items can be dragged along with a rope or whether objects are held in place via a rope. I was also uncertain whether to allow tying a rope to another rope, and whether that meant using up an end of each rope, or just of one of them.

  2. Making the grammar friendly. I probably overdid it, but I was trying to get the “tie” and “untie” verbs to work regardless of noun order, create automatic dropping and removing actions that deal with ropes reasonably based on preference properties, and even implement some form of “tie X to Y” when neither X nor Y is a rope, but a rope is available. Oh yeah, and I also tried to set up custom reporting so that some ropes are described as “tied” and others might be described as “chained” or “stuck”, etc.

Most games only have one rope. For an extension, though, I wanted to allow multiple ropes, and therein lies a world of hurt.

I’ve decided to create a separate “underness” relation rather than implementing the concept by defining the underside of appropriate objects as a container. Almost immediately, I ran into an odd compilation error.

Underness relates various things to one thing.  The verb to be under implies the underness relation.

The first sentence compiles just fine. When I add the second sentence, however, I get an error message which suggests that something is conflicting with the “looking under” action which is (minimally) defined in the standard rules. Specifically, I get the following:

Any suggestions on how to fix? I’m scared to death of making any changes to the standard rules themselves, so if possible I’d like to find a fix that doesn’t require doing so.


Robert Rothman

It’s probably easiest just to change the verb to avoid the conflict: Underness relates various things to one thing. The verb to be underneath implies the underness relation.
There are already some bugs filed about this kind of misunderstanding by the compiler, and, depending on how they are resolved, you might not have this problem in the next build.

Thanks. Your solution is like the answer to a really good IF puzzle: I never even thought of it, but with hindsight it seems obvious.

Robert Rothman