Formalising aural and visual adjacency between rooms.

Now that sounds snotty.

Is TADS fully open source now? It seems to me that development of the I7 language goes slowly because it’s a closed process. But I appreciate the unity of design that produces.

My sense is that there’s no single viewport extension because it’s not as important as some people seem to think it is. I7 is about solutions that fit the narrative, not simulations that fit an abstract world model.

I would be highly suspicious of the first solution continuing to work as you’d expect. It would be great if there were a “such that” clause in I7, but to my knowledge, the phrase “there is a viewport (called X)” will pick any viewport at random and call it X. It’s just a matter of luck whether or not X is the particular viewport that satisfies the following conditions.

The last syntax is probably closest to what you need, but there is some ambiguity (and bugginess) in how I7 interprets a string of phrases representing multiple relations. For anything complex like this, I like to create a multi-line “to decide whether” phrase, and then use that in the definition of the relation.

I tried to work out a reasonable way to do it, but I’m running into weird errors. Here’s as far as I got:

[code]A viewport is a kind of door.

Visual contact relates a room (called A) to a room (called B) when A can be viewed from B.

To decide whether (A - a room) can be viewed from (B - a room):
say “testing whether [A] can be viewed from [B].”;
showme the list of viewports adjacent to A;
showme the list of viewports adjacent to B;
showme the list of rooms adjacent to the metal grille;
Repeat with X running through viewports that are adjacent to A:
showme X;
if X is adjacent to B, yes;
no.

The verb to be in visual contact with implies the visual contact relation.

The Gloomy Room is a room. The Bright Room is a room. The Metal Grille is a viewport. The Metal Grille is east of the Main Room and west of the Gloomy Room.

When play begins:
showme whether or not the gloomy room can be viewed from the main room;
showme whether or not the gloomy room is in visual contact with the main room;
showme whether or not the metal grille is adjacent to the gloomy room;
showme whether or not the metal grille is adjacent to the main room;[/code]

I was wrong fortunately. See zarf’s post above. (Thanks zarf!)

I’m trying to figure out why “the metal grille is adjacent to the Main room” is true and yet the “list of viewports adjacent to the Main Room” is empty. Any ideas?

Okay, I’ll dial back the snottiness. To answer your question, though – yes, TADS is open source. I just checked. You can download the C++ source code for the compiler and interpreter. Not sure about the Workbench source, as I don’t see it on the downloads page.

I’m a little bemused (if I can say this without sounding snotty) that you feel Inform 7 has “unity of design.” My impression is that the extensive usage of 3rd-party extensions, and Graham Nelson’s evident preference for encouraging the development of same, produces exactly the opposite of “unity of design.” But maybe you mean something different by that phrase than I do.

I agree with what I take to be your implied point, which is that it’s often easier to fake the visibility of an important item in a nearby location using a distant-view-of object, rather than trying to implement full-on viewability of adjacent locations. In other words, only implement a distant view when it actually makes sense for the story. On the other hand, when you do it that way, you (the author) bear full responsibility for keeping the actual game object and the distant-view-of object in sync. This can get rather messy. The advantage of a full simulation designed on the basis of an abstract world model is that, once you’ve set it up, you don’t need to worry about it. If you want Bob (who is on the lawn) to be viewable and perhaps conversable with while the player is on the porch, when Bob wanders away an abstract simulation model will see to it that he’s no longer visible from the porch. When Bob picks up the Uzi, the abstract simulation model will automatically report, “Bob is carrying an Uzi.”

For my part, I want the abstract simulation model because I’m writing a game that involves stuff like rooms separated by soundproof glass walls, crawling around in ductwork and spying on people through the vents, security camera feeds, and so forth. It’d be a huge pain to special-case every instance.

Are we looking for the code to calculate visibility in order to test what would be visible in the next room? It seems to me that the simplest way to do that might be along the lines of example 81 in the documentation (“Unblinking”): create a dummy object and, when you need to check for what’s visible in the next room, move the object to the room and check what it can see. As the documentation for “Unblinking” points out, you’d need to do something special for backgrounds somehow, but it’d probably be easier than trying to recreate the visibility code by hand.

The adjacency rules for doors seem to behave very unpredictably in any case other than asking whether a specific, named door is adjacent to a specific, named room. I think I have a workaround, though:

[code]section 0 - rules

Liminality relates a door (called A) to a room (called B) when B is the front side of A or B is the back side of A. The verb to be a threshold of implies the liminality relation.

A viewport is a kind of door.

Visual contact relates a room (called A) to a room (called B) when A can be viewed from B. The verb to be in visual contact with implies the visual contact relation.

To decide whether (A - a room) can be viewed from (B - a room):
if A is B:
decide no;
repeat with X running through viewports that are a threshold of A:
if X is a threshold of B:
decide yes;
decide no;

section 1 - testing

The Main Room is a room. The Bright Room is a room. The Gloomy Room is a room.

The metal grille is an unopenable scenery viewport. It is east of the Main Room and west of the Gloomy Room. The thick glass is an unopenable scenery viewport. It is west of the Main Room and east of the Bright Room. The door to nowhere is an openable scenery viewport. It is north of the Main Room.

The player is in the main room.

When play begins:
showme list of viewports that are a threshold of the Main Room;
showme list of viewports that are a threshold of the Bright Room;
showme list of viewports that are a threshold of the Gloomy Room;
showme list of rooms that are in visual contact with the Main Room;
showme list of rooms that are in visual contact with the Bright Room;
showme list of rooms that are in visual contact with the Gloomy Room;[/code]
The front side and back side properties appear to be much more reliable. There’s actually an example in the manual that does things this way (the liminality relation is lifted directly from the text), but it doesn’t explain why the adjacency relation of the door is avoided, so I’d overlooked its significance at first.

Point taken! :laughing:

I gave this a shot, but it seems to create complications when you use it to decide what characters other than the player can see, particularly when there are many NPCs in a game. However, after some further testing, it may not be necessary after all. Simply placing a room in scope seems to respect all of the obvious visibility cases; it doesn’t place the contents of a closed, opaque container that happens to be in the room in scope, for example, nor does it place the concealed possessions of an NPC who is in the room in scope. Unless I run into a major edge case that isn’t covered in this fashion, I’ll leave it as-is.

Okay, silly question time: is there any way to explicitly pull something out of scope? I can see how to explicitly place something that would normally be out of scope in scope, but not vice versa.

No. Scope is an iteration through a tree. You can add calls to the iteration (adding more branches to the tree) but there’s no such concept as removing things. You’d have to modify the existing behavior at a given object to do less.

Hmm. Well, if I understand the object hierarchy properly, everything in a room is going to be of kind “thing”, so I suppose I can iterate over things in a room and go from there.

Oh, dear - I seem to have backed myself into a corner again.

I’ve just about got it all figured out, but then (because I am apparently insane) I decided to add support for soundproof containers. Being inside a transparent, soundproof container is intended to be analogous to interacting with an object in a room that’s visually but not aurally adjacent, or through a viewport that’s visually but not aurally transparent. Conversely, I’ve also got code handling cases where a player tries to interact with something in a location that they can hear, but not see, so opaque, non-soundproof containers need to be handled as well.

This is what I’ve got:

To decide whether (the listener - a thing) can hear (the subject - a thing): if the location of the listener is the location of the subject: if the listener is enclosed by a closed soundproof container (called the enclosure): if the subject is enclosed by the enclosure: decide yes; otherwise: decide no; otherwise if the subject is enclosed by a closed soundproof container: decide no; otherwise: decide yes; otherwise if the location of the listener is aurally adjacent to the location of the subject: if the listener is enclosed by a closed soundproof container or the subject is enclosed by a closed soundproof container: decide no; otherwise: decide yes; otherwise: decide no;
As long as we’re dealing with something in a room that’s aurally adjacent to the location of the listener, we have all of our bases covered - a container can’t be in two rooms at once. Likewise, a simple check allows us to catch the case where the listener and the noisy thing are in the same room, but inside two different soundproof containers.

However, there’s one edge case that will cause the above code to erroneous conclude that the listener can hear the subject: what if the listener and the subject are in the same room, inside the same soundproof container, and either one of them is also inside a second soundproof container inside the first one?

I don’t expect this scenario to ever arise in practice in the game I’m actually writing, but the perfectionist in me won’t allow it to stand.

Can anyone give me a few pointers on how to handle this situation?

I’d recommend trolling through the Standard Rules (and probably the template layer too) and teasing out every reference to “opaque” containers. Then modify that so that “opaque” means something different when the current action involves sound.

It’s ambitious. You might be better off leaving that up to the game author, since there’s likely to be very small number of soundproof containers, and an even smaller number of enterable ones.

Yeah, you’re probably right. It’s a stupid little edge case - what are the odds that you’ll end up with nested soundproof containers, the outermost of which is enterable? - and it’s probably not worth delaying getting this thing wrapped up by another week while I wrestle with it.

I think you can do this pretty simply. I commented out the code for adjacent rooms because I didn’t want to program that in my scenario, but this seems to be working:

[code]A container can be soundproof. A container is usually transparent.
To decide whether (the listener - a thing) can hear (the subject - a thing):
if the location of the listener is the location of the subject:
if a closed soundproof container that encloses the listener does not enclose the subject:
decide no;
otherwise if a closed soundproof container that encloses the subject does not enclose the listener:
decide no;
otherwise:
decide yes;
[otherwise if the location of the listener is aurally adjacent to the location of the subject:
if the listener is enclosed by a closed soundproof container or the subject is enclosed by a closed soundproof container:
decide no;
otherwise:
decide yes;
otherwise:
decide no;]

Rubbermaid Factory is a room. The clapper is a thing in the Rubbermaid Factory.
The hunormous tub is an enterable soundproof closed openable container in Rubbermaid Factory. The giant tub is an enterable soundproof closed openable container. It is in the hunormous tub. The wicker stand is an enterable closed openable container. It is in the giant tub. The yellow big tub is an enterable closed openable container. It is in the giant tub. The green big tub is an enterable closed openable container. It is in the giant tub. The cardboard box is an enterable closed openable opaque container. It is in the yellow big tub.

Instead of singing:
if the clapper can hear the player and the player can see the clapper:
say “The clapper flashes excitedly.”;
otherwise:
say “You sing a bit.”

Instead of listening:
if the player can hear the clapper:
say “You can hear the almost subliminal hum of the clapper’s workings.”;
otherwise:
say “You can’t hear anything special.”[/code]

If the antecedent contains all the desiderata of the blocking container – that it contains the subject but not the listener, or vice versa – then we don’t need to worry about whether we pick the wrong container for “enclosure.”

I found something hinky while testing this – since the “listen” action is redirected to listening to the room, whenever you listen from inside a closed container (soundproof or not!) you get “The hunormous tub isn’t open,” because you can’t touch the room. You probably want to come up with a fix for that, if you haven’t already.

ETA: This scenario produces a truly ridiculous room description.

Wow - thank you. That’s exactly what I was looking for. I’d tried something like that at one point, but I couldn’t figure out how to phrase the conditions correctly.

And yeah, the reachability rules are a pain. Just about everything to do with sound - listening, asking, telling, etc. - is set up to require a touchable subject. I think I’ve got it all worked out, though. Puzzlingly, the only sound-related thing that isn’t set up that way is asking an NPC to do something; out of the box, an in-scope but untouchable NPC can’t be spoken to except when you’re ordering them about.

(I had to special-case that one via the persuasion rulebook.)

If you want to get around a whole bunch of touchability requirements, check out my Flexible Action Requirements extension:

eyeballsun.org/i/Flexible%20Acti … ements.i7x

It’s a work in progress, but it’s functional.

Nifty - I’ll give that a spin. Thanks.

Unrelated question: is there any circumstance in which a door can end up inside a container? My reading of the documentation suggests “no”, but I thought I’d double-check.