Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IE-0015: World model enforcement #15

Merged
merged 1 commit into from
Jan 17, 2023

Conversation

zedlopez
Copy link
Collaborator

@zedlopez zedlopez commented Jan 17, 2023

  • Proposal: IE-0015
  • Authors: Graham Nelson
  • Language feature name: --
  • Status: Draft
  • Related proposals: --
  • Implementation: Experiments in progress

Summary

WorldModelKit and the Standard Rules, together with support hard-wired into the if module of the Inform compiler, collectively provide a "world model". At present it is not as consistent or as well-enforced as we would like, and this leads to unexpected and unhelpful behaviour. IE-0015 gathers up a set of changes to improve (though not fully fix) matters in one place, rather than leaving these in scattered responses to bug reports.

@curiousdannii curiousdannii merged commit f608a42 into ganelson:main Jan 17, 2023
@curiousdannii curiousdannii changed the title minimal whitespace change as basis for PR IE-0015: World model enforcement Jan 17, 2023
@curiousdannii curiousdannii added the formal-proposal A formal proposal that has been accepted for consideration by the core Inform team label Jan 17, 2023
@curiousdannii curiousdannii removed the request for review from ganelson January 17, 2023 05:23
@zedlopez
Copy link
Collaborator Author

As noted in I7-2211 the world-model violations go beyond holding, wearing, and carrying; they also apply to supporting and containment. Is discussing those, also, in scope for this proposal?

The current proposal gives us different meanings of hold for each of assertions, now-phrases, and conditionals, all of which differ from the implied "hold" of both holder of and first thing held by.

  • In assertions, things continue as today: only persons can hold and it means carrying.
  • In now-phrases, only people, containers, and supporters can hold, and it means carrying, containment, or supporting, respectively.
  • In conditionals, it means the same 5 relations holder of covers, except for always being false for non-things.

We're left without a verb corresponding to checking whether one region is the direct parent of another; that would have to be checked with holder of.

in 10.1, neither of X holds Y and the holder of Y is X implied the other.

They come really close, though, the sole exceptions being when X is a non-person quantifier or a description of objects that's not a description of people.

I'm making a plea for having hold in conditionals continue to have its current meaning (but for changing the exception noted above), i.e., for it to correspond to holder of, bringing us from 5 different meanings to 4.

As I noted in I7-2220, this parallels enclose (except for some edge-cases regarding floating objects and regions with rooms). In its introduction to enclosure, Writing with Inform invokes the term "indirect containment" (a holdover from I6, of course) to explain it. I think implying a different meaning to "containment" there than the one that applies in Inform muddies the water. But it does make sense to explain enclosure in terms of it being either direct or indirect... something. And today we have such a something, holding. It makes both of them easier to understand and to explain. And it at least reduces the number of exceptions that need to be noted to provide a full explanation of them.

And it's useful (as demonstrated by the Fallout Enclosure example, for one).

I expect the thing-requirement would break some existing programs, albeit a small number. But the chance of code breaking due just to changing the person requirement in the cases cited is much smaller still: I think it'd be reasonable to expect it to be nil.

I would sympathize with the rationale, at least, of changing its meaning to make it consistent with one or both of the other uses of hold as a verb. But it doesn't even have that to recommend it. I don't see what putative advantage restricting if X holds Y to things offers.

@ganelson
Copy link
Owner

Yes, the containment, support, enclosure and incorporation relations will come next. Today we settle all relations business.

When regions contain each other, that can be tested with containment. If we have Nirvana is a region. Shangri-La is a region. Nirvana is in Shangri-La. then Nirvana is contained by Shangri-La and Nirvana is in Shangri-La are both true. But as you imply, that includes indirect containment. I don't think it's really problematic to omit this: "to hold" is a pretty odd choice of verb for this - would anyone naturally write if Shangri-La holds Nirvana?

If we allow if X holds Y to include non-things, while continuing to define the relation's domain as being (thing, thing), we go right back into the linguistic inconsistencies and logical errors pointed out in the original bug report. And I still don't really like saying that a room holds a thing. Hmm.

@zedlopez
Copy link
Collaborator Author

If we allow if X holds Y to include non-things, while continuing to define the relation's domain as being (thing, thing), we go right back into the linguistic inconsistencies and logical errors pointed out in the original bug report.

I'm suggesting that the relation's domain be (object, object) but that its usage in assertions and now-phrases be special-cased. In the proposal as written, assertion-hold and conditional-hold are already special-cased relative to now-phrase-hold. So this suggestion doesn't increase the amount of special-casing in the world, it just makes now-phrase-hold a special case instead of conditional-hold.

And I still don't really like saying that a room holds a thing.

Inform will be continuing to say that via the holder of and thing held by phrases. (And "hold" has always been an even more awkward hypernym to embrace things incorporating things than it is in regard to rooms containing things.)

Excising one little bit of sub-optimal English usage in a single case of where a word applies such that the word has a separate meaning in every context in which it may appear constitutes a net loss for comprehensibility and usability.

@curiousdannii
Copy link
Collaborator

Would this proposal turn holding into a generic (object tree based) relation any objects could use? If so that could be the solution for the spawning relation for Glk Windows (#12 (comment)).

@ganelson
Copy link
Owner

I think I basically agree that (object, object) achieves better consistency, and experiment seems to suggest that this works well (at any rate, it breaks nothing in the test suite). Since this means embracing the idea that the verb is used more widely than just for things, I've made a more permissive now X holds Y, which distinguishes between objects used in the spatial world model from objects which are more abstract.

This may be a useful idea when we come to the harder problem of improving the consistency of contains.

@ganelson
Copy link
Owner

To pose a question: given

https://inform7.atlassian.net/browse/I7-2219

should we alter HolderOf so that it returns nothing for direction objects? Given the current state of to hold in IE-0015, it's no longer true that nothing holds north (for example). But it's really very strange that direction objects seem to have a holder, and moreover, one with no natural description in Inform.

In an ideal world, the pseudo-object Compass would not exist, but it's not easy to get rid of. The parser depends on it, and has done since Inform 1.

@zedlopez
Copy link
Collaborator Author

I favor HolderOf returning nothing for directions. It's hard to imagine that that change would break anyone's code. I had been going to bring it up, having noticed the inclusion of direction and region among spatial objects, but without further discussion. I'm guessing you were saving regions for discussion alongside containment. And I assume the spec will get explicit about how doors and backdrops will fit into the revised spatial relation scheme (beyond "awkwardly").

@ganelson
Copy link
Owner

I've now made this change, and documented it in IE-0015. It caused no problems with the test suite. On further reflection, I'm sure this was a good change to make: it guarantees that holder of a spatial object is another spatial object. Previously, the Compass pseudo-object contradicted my claim yesterday that if X holds Y then either both are spatial objects or neither: because Compass is not a spatial object.

@drpeterbatesuk
Copy link

drpeterbatesuk commented Jan 19, 2023

Thanks Graham & Zed for this.

I see that there had already been a change between 9.3 and 10 such that 'Nirvana is in Shangri La' became true in 10.1, whereas it was false in 9.3 (where the compiler generally assumed regional containment as the meaning of 'in' or 'contains' in phrases like this, so conditions about one region containing another were always false unless the containment relation was forced, which could be done by the containing region being in an object variable (if <obj-variable> contains ) or the condition being expressed obliquely as '<containing-region> relates to <contained-region> by the containment relation'). Is this change documented somewhere? If not, is it worth documenting here?

The current proposal confuses me where it says that something means some object and therefore something holds the player is false. Surely a room is an object, holding the player? Shouldn't this say something means `some thing'?

Am I right in thinking that 'holds' now exactly corresponds to 'ParentOf()`?

How do you envisage authors reorganising the object tree of abstract objects at runtime if 'now X holds Y' is restricted to spatial objects?

@drpeterbatesuk
Copy link

On the subject of spatial relations, is there a good reason why it's not possible to move rooms from one region to another at runtime (except through subterfuge, by 'manually setting' their map region property)?

Inform currently throws an error suggesting that moving a room to a region would imply that it would appear in all rooms in that region, like a backdrop, but plainly that isn't the case. If there are two regions, Indoors and Outdoors, then I board up the Verandah and set its map property to Indoors, it is simply now contained and regionally-contained by the Indoors region instead of the Outdoors. Does this cause a potential difficulty? And if not, why not allow 'now the Verandah is in Indoors?

@drpeterbatesuk
Copy link

Another thing I've just noticed- since Ver 10, a region now appears in 'the list of objects to which it relates by the regional-containment relation' i.e. it appears to regionally-contain itself- which I assume is unintentional

@drpeterbatesuk
Copy link

drpeterbatesuk commented Jan 19, 2023

Also, for some reason the compiler's parser struggles with:

if the region which relates to Verandah by the containment relation is Indoors:
but bracketing works:
if (the region which relates to Verandah by the containment relation) is Indoors:
similarly,
if Indoors is the region which relates to Verandah by the containment relation:
doesn't compile, but
if Indoors is (the region which relates to Verandah by the containment relation):
does

@drpeterbatesuk
Copy link

drpeterbatesuk commented Jan 19, 2023

Another change from 9.3 to 10 I've noticed: Regions now regionally-contain other regions that they enclose, which was not the case in 9.3.

In 9.3, regions contained, held and/or enclosed other regions but never regionally-contained them (despite what the docs said)

@drpeterbatesuk
Copy link

Ah. And, I see, that's the explanation for my first observation- the reason that 'Nirvana is in Shangri La' is now (since Ver. 10) true is not because the compiler has changed its interpretation of the condition- it's still testing for regional-containment and not containment- it's just that regions can now regionally-contain each other (and even, it would seem, themselves!)

@drpeterbatesuk
Copy link

Consequently, to test for direct containment of a region there is still no easy alternative to 'holds' or 'holder of'

@zedlopez
Copy link
Collaborator Author

Would something like the following be desirable?

Include (- Property spatial; -).
An object can be spatial or abstract. An object is usually abstract.
The spatial property translates into Inter as "spatial".
A direction is always spatial. A region is always spatial.
A room is always spatial. A thing is always spatial.

It seemed so to me when I first thought of it. On reflection, I realized there are good reasons to lump rooms and doors together, or, more generally, rooms and things, or even rooms, things, and regions; the only time I ever want to lump all of the spatial objects together is when I'm testing I7 behavior. But I thought I'd toss it out in case someone else can think of why there would be a compelling reason for it.

@ganelson
Copy link
Owner

I was thinking about a "spatial" attribute just for efficiency reasons (testing X has spatial is quicker than X ofclass room or thing or region or direction), in fact.

Defining this at the I7 level as well is appealing in a way, but does occupy the nouns "spatial" and "abstract": we might want more obscure wording, and do we really want authors to be able to cause chaos by giving or removing this property at runtime?

@zedlopez
Copy link
Collaborator Author

Defining this at the I7 level as well is appealing in a way, but does occupy the nouns "spatial" and "abstract": we might want more obscure wording

representative / informative ? Tough to thread the needle of obscure enough, but not too obscure. (In my own code, I've sometimes defined a diegetic adjective and created a struct kind of object for other things to be subkinds of... but I wouldn't inflict them on others.)

do we really want authors to be able to cause chaos by giving or removing this property at runtime?

The latter doesn't trouble me so long as there's explicit documentation regarding "this is possible, but don't ever do it".

I've been assuming it's too radical a change to be plausible, but in case I'm wrong, I'll ask it: could the spatial objects' kinds be subkinds of a game object kind? It and abstract object would be the only two direct subkinds of object in this fever dream. I expect it would break the small number of extensions that have, say, K2_thing hard-coded, but I don't know whether it would also utterly break everything.

@ganelson
Copy link
Owner

Yes, I think that's a pretty feverish dream, as they go. I basically tremble at the thought of how many places in the code expect room and thing, etc., to be top-level kinds of object (in the compiler as well as the kits, not to mention who knows where in extension).

@ganelson
Copy link
Owner

So I have been looking at the regional containment relation this evening, prompted by Peter. Even this is not trivial. Firstly, I think it's quite right that regions should regionally-contain all regions they enclose: not doing so was just a bug in Inform 9.

But I think saying that a region regionally-contains itself is a bug in Inform 10.1, so I've fixed this.

Peter also notes that regional containment cannot be directly changed in 10.1. In fact, some slightly odd maneouvres could be done, but others couldn't. There's an argument against, but I've implemented now X is in R in cases where X is a room or another region, and this seems to work satisfactorily. See IE-0015 as revised.

Tonight's moral conundrum: Should holder of M, where M is a room, return the region which that room is in, rather than nothing? Equivalently: should a room be held by its (immediate) region?

@zedlopez
Copy link
Collaborator Author

Tonight's moral conundrum: Should holder of M, where M is a room, return the region which that room is in, rather than nothing? Equivalently: should a room be held by its (immediate) region?

If we were spec-ing this out from scratch, I don't think the question would even come up: of course it should. Regions enclosing but not holding their rooms are one of the unfortunate anomalies in the current state of affairs.

As much as I'd like to see this change happen, there probably is code in the wild that could break in weird ways if the holder of a room ceased to be nothing. while loops advancing via holder of would be easy enough to spot, but it's easy to imagine it coming up much more subtly. And the effect, from an author's perspective could be the extremely frustrating "this thing that used to work now fails but only in some rooms."

All that said, it'd be so frustrating to not remove the inconsistency here that I lean toward yes, so long as a lantern is hung on the change, for instance a prominent notice in the IDEs. Maybe the first page of the docs, instead of its very neutral Change Log link could have a short message to the effect of: "10.2 (? 11?) cleans up some fundamentals regarding relations. It's possible, if unlikely, that stories written for previous versions may have depended on the previous messier behavior. See changes since 10.1 to check whether it affects you."

@drpeterbatesuk
Copy link

drpeterbatesuk commented Jan 20, 2023

Tonight's moral conundrum: Should holder of M, where M is a room, return the region which that room is in, rather than nothing? Equivalently: should a room be held by its (immediate) region?

All that said, it'd be so frustrating to not remove the inconsistency here that I lean toward yes

No, no, a thousand times no. This is something that's not broken in any important way and does not need fixing, IMHO.

I can't see many circumstances where it would be really helpful. And it would break SO much code I suspect, both old and new, both I6 and I7, that assumes rooms are held by nothing- even more so if this were to be implemented by the logical and pure method of doing away with the map region property and making rooms a child of their map region in the Object Tree.

I think the decision NOT to do this that was presumably taken when regions were first introduced to Inform was the only reasonable one at the time and much more so now, and the odd relations between rooms and regions that exist as a consequence should be regarded as an ancestral evolutionary quirk akin to the human hip joint- it's not how you'd design it from scratch, and it has a few weaknesses, but it basically works well and given its evolved interrelationships with other structures and mechanics we are where we are and it is is best not redesigned by overenthusiastic surgeons and their collaborators.*

*50 years of experience in the joint replacement field has proven this to be true

@ganelson
Copy link
Owner

Well, always good to reach a consensus.

Enclosure is defined at runtime by the function IndirectlyContains. It's not quite the transitive closure of holding, but close. There seem to be two carved-out exceptions: (i) a room encloses a door if either side of the door abuts it, and (ii) a backdrop is never enclosed by anything. I'm dubious of (ii), but backdrops are very difficult to make sense of in any of the spatial relations. It would be possible to do something parallel to (i): i.e. a room encloses all the backdrops present in it. But perhaps the reason we currently say no is that backdrops cannot be fully enclosed by a room. If a river flows through three rooms, would we say that none of the three enclose it, or that all of them do? Some of this gets to the awkward point that the name of the function, "indirectly contains", is perhaps a different idea than the name of the relation, "encloses".

Currently the code looks like this:

[ IndirectlyContains o1 o2;
	if ((o1 == nothing) || (o2 == nothing)) rfalse;
	if ((o1 ofclass K1_room) && (o2 ofclass K4_door)) {
		if (o1 == FrontSideOfDoor(o2)) rtrue;
		if (o1 == BackSideOfDoor(o2)) rtrue;
		rfalse;
	}
	if (o2 ofclass K7_backdrop) rfalse;
	for (o2 = HolderOf(o2) : o2 && o2 ~= thedark : o2 = HolderOf(o2)) if (o2 == o1) rtrue;
	rfalse;
];

It seems to me that the o2 ~= thedark clause is redundant? Surely no object is ever a child of the thedark pseudo-object. Am I wrong about that?

That leaves for (o2 = HolderOf(o2) : o2 : o2 = HolderOf(o2)) if (o2 == o1) rtrue; which means that, with the exceptions cleared out of the way, enclosure is the transitive closure of holding. This has a pleasing clarity.

This I think is the real significance of the issue of whether a region can be the holder of a room. At present, a region can only enclose another region. Surely a region does enclose a room which is part of it, and therefore also anything in that room? (I note that, at present, a region is the container of a room, but not the holder of that room.)

So today I have two questions:

(a) Should we make a room enclose any backdrop found in it?

(b) On the subject of regions enclosing stuff, which is the more attractive option?

  • Making enclose the transitive closure not of HolderOf but of some modified function, RegionFixedHolderOf, say, in which a room does return its region.
  • Make the holder of a room its region after all.
  • Declare that a region doesn't enclose anything.

@drpeterbatesuk
Copy link

drpeterbatesuk commented Jan 21, 2023

Surely no object is ever a child of the thedark pseudo-object. Am I wrong about that?

It's an awkward thing to arrange in I7, and I doubt any existing code makes use of this remote possibility- particularly since I7 has already deviated from I6 in that in I7 when in darkness children of the dark remain off-stage and out of scope.

(a) Should we make a room enclose any backdrop found in it?

Do you mean all rooms which would be returned by inspecting the backdrop's I6 found_in property would enclose it? or just the room (if any) the backdrop is currently a child of in the Object Tree?
If the former, my initial thought is that this would mainly be helpful as a means to knowing if a backdrop would be moved to a location if the player were there. Currently, I think this requires either making a call to BackdropLocation() in I6 or perhaps: surreptitiously move the player to the room in question, update backdrop positions, make the check, then surreptitiously move player back to their starting location. The potential downside to implementing this particular solution to that gap in I7 is that loops in existing code that iterate over things enclosed by a room, which are probably quite common, might begin to have unexpected results, or cause runtime errors due to attempted illicit manipulation of backdrop objects.

I would be in favour of an inbuilt I7 verb- 'found in' is probably as good as any- to mean where doors and backdrops would appear if the player were to be that location, but without making rooms enclose backdrops.

Making just the room currently holding a backdrop also enclose it would tidy up the nice 'enclosure'=='(indirectly) hold', 'hold==parent of' paradigm, but it may be best to abide by the principle of 'if it ain't broke don't fix it' and leave things as they are.

(b) On the subject of regions enclosing stuff, which is the more attractive option?

  • Making enclose the transitive closure not of HolderOf but of some modified function, RegionFixedHolderOf, say, in which a room does return its region.
  • Make the holder of a room its region after all.
  • Declare that a region doesn't enclose anything.

There already exists an indirect relation that transcends the region/room barrier- regional containment- and which now encompasses all of regions, backdrops, rooms and their contents, direct and indirect. I'm not sure much is to be gained by extending enclosure across the region/room barrier.

So I would lean towards leaving things as they are, with the 'cascade of enclosure' broken at the region/room interface, with regional containment being the 'one relation to rule them all'.

It's already straightforward enough I think to access the 'lowest in the hierarchy of regions' region of a room, or of any of its contents, via the map region of <a-room> or the map region of the location of <an-object>.

If a river flows through three rooms, would we say that none of the three enclose it, or that all of them do?

The same concern already applies to backdrops and regions. I think the present situation is that if a backdrop is 'found in' any of the rooms regionally contained by a region, the backdrop is said in conditions to be 'regionally in' said region, whether its current position in the Object Tree reflects that or not.

@ganelson
Copy link
Owner

Something unfortunate which I should give notice of, though: Looking more carefully at how regions and backdrops are implemented, I think we have to take a firm stance that rooms cannot change region, and that regions cannot be moved to other regions, with now. I was always a little queasy about allowing this, but thought, well, why not. What I now realise is that it's much more problematic than it looks to do that, because of the regional_found_in property, where the compiler essentially represents the set of rooms in a region by compiling an indicator function for that set. If the regions can move around, that's going to fail, and result in subtle bugs where backdrops are still located where the previous region arrangement would suggest that they ought to be. So tomorrow I'll force regions and rooms to be immutable in the object tree.

@ganelson
Copy link
Owner

No, I take it back. On closer inspection, regional_found_in functions work through the regional-containment relation, and therefore do continue to work when regions or rooms are moved around. So I think we can indeed keep the ability to do this.

@zedlopez
Copy link
Collaborator Author

Just to be sure of desired behavior in the concealment (iv) case:

If a box is a container that conceals a note, and a player takes the box, then the default behavior will be that they will see nothing other than the usual "Taken." and the next time they do an inventory they'll see

a box
  a note

(all of which is the same as today) but now the note will be in scope, right?

@ganelson
Copy link
Owner

Okay, that seems wrong, doesn't it? I would have naively thought that the correct thing is for the note to be not only out of scope but also not listed in the inventory. Is there some reason why we don't want to do it that way?

@zedlopez
Copy link
Collaborator Author

I had thought the previous discussion indicated that what the player encloses shouldn't be concealed from the player. Is it merely that what the player directly holds isn't concealed from the player?

@ganelson
Copy link
Owner

Um, so if the player conceals the box, but the box does not conceal the note, then we should get the inventory:

a box
    a note

But if the box conceals the note, the inventory should surely be:

a box

I think the idea here is that concealment is about holders, not enclosers.

@drpeterbatesuk
Copy link

I think Graham's idea of this is what naive authors would instinctively expect, also what would be most useful to experienced authors, so I would support it on both those grounds.

Further, as Graham suggests, it fits with the idea that things (along with their contents) are functionally concealed only by their direct holder- so if actors can't conceal their direct possessions from themselves, likewise the contents of those possessions should be unconcealed unless the possessions themselves do their own concealing.

@drpeterbatesuk
Copy link

drpeterbatesuk commented Jan 31, 2023

As things stand at present, it is already the case that concealment of things enclosed by an actor works in this way (which is, of course, why concealed things enclosed by the player, and their contents, are out of scope). It's just that at present by default inventory lists things concealed from the actor, and their contents. But I guess you knew that :-)

@zedlopez
Copy link
Collaborator Author

zedlopez commented Feb 1, 2023

OK. That's the same behavior currently in Concealer and I agree that it's better (I was never advocating for the behavior I described above; I had misread Graham's comments as indicating it would be the desired behavior.)

@zedlopez
Copy link
Collaborator Author

I'm polishing the concealment code. I'm not sure what call to make for this case: The Undescribed test case has a glass jar with 3 undescribed scraps of paper inside. By the current behavior, they're not mentioned; if one searches or examines the jar, one is told it's empty. But if one drops another container alongside it, it'll have the '(empty)' tag in the room description and the jar won't, and, of course, the paper is in scope. On balance, I think it's probably better to have the '(empty)'. Any thoughts?

@ganelson
Copy link
Owner

Yes. It seems hard to argue with the point that a container with only undescribed contents should look the same as a container which is actually empty, which argues for printing the '(empty)', even though in some sense this is a lie. It's weird to be effectively transmitting side-channel information to the player who is sufficiently au fait with Inform's internals, i.e., that because we don't print '(empty)' now we are in effect signalling that the container must contain something undescribed.

It's interesting that we used the term "undescribed" and not, say, "invisible". At some point it was conceptually a little less clear-cut than simply not being seen. This no doubt goes back to the "concealed" attribute in Inform 1.

@zedlopez
Copy link
Collaborator Author

zedlopez commented Jul 9, 2023

Revenge of the World Model!

I found another way a person can end up enclosing a person.

lab is a room.
parlor is north of lab.

the can't push people rule does nothing.
the player is pushable between rooms.

Gallant is a person in the lab.
Persuasion rule for asking Gallant to try doing something: persuasion succeeds.

->

gallant, push me north
Gallant arrives from the south, pushing yourself in front, taking you along.

parlor (in Gallant)

>

OK, but it took deactivating a standard rule, so maybe it doesn't count. But...

lab is a room.
parlor is north of lab.

sled is an enterable pushable between rooms supporter in lab.
the player is on sled.

Gallant is a person in the lab.
Persuasion rule for asking Gallant to try doing something: persuasion succeeds.

->

>gallant, push sled north
Gallant goes north, pushing sled in front, taking you along.

parlor (on sled) (in Gallant)
parlor (on sled)
You can see Gallant here.

>

The actor becomes the holder of the thing being pushed, and thus encloses the player during the implicit look that's part of the going action below...

[ ConvertToGoingWithPush i oldrm newrm infl;
        i=noun;
        if (IndirectlyContains(noun, actor) == false) { move i to actor; infl = true; }
        move_pushing = i;
        oldrm = LocationOf(noun);
        BeginAction(##Go, second);
        newrm = LocationOf(actor);
        move_pushing = nothing; move i to newrm;
        if (newrm ~= oldrm) {
                if (IndirectlyContains(i, player)) TryAction(0, player, ##Look, 0, 0);
                RulebookSucceeds();
        } else RulebookFails();
        rtrue;
];

this seems like a reasonable and parsimonious patch for this, but I'm testing further. (Found this while working on fixing I7-1995.)

before looking when the player is enclosed by something enclosed by a person who is not enterable: instead do nothing.

@ganelson
Copy link
Owner

ganelson commented Jul 9, 2023

I'm shocked, shocked I say. That would probably win the prize for the most eldritch rule in the Standard Rules, but it seems a reasonable solution to me. Would we give it a name? (I cannot imagine what.)

@erkyrath
Copy link
Collaborator

erkyrath commented Jul 9, 2023

This no doubt goes back to the "concealed" attribute in Inform 1.

It certainly does, and "undescribed" remains untidy to this day. (SCORE__UNCONCEALED in Adjudicate(), etc.)

@zedlopez
Copy link
Collaborator Author

zedlopez commented Aug 6, 2023

now X does not hold Y is never permitted.

This is problematic for the abstract object case: there's no non-I6 way to undo the holding relation.

@zedlopez
Copy link
Collaborator Author

zedlopez commented Aug 17, 2023

This may have already been argued as much as that most controversial "describe what's on scenery supporters in room descriptions rule", so my apologies if revisiting it is unwelcome. If you search a container or supporter (the container or supporter in question can be scenery or not), held scenery things are equivalent to undescribed or concealed things: unless there's something directly in or on the thing that's none of scenery, undescribed, concealed, then upon searching it, the default is that the player is told "[The container] is empty" or "There is nothing on [the supporter]". The same "[The container] is empty" message is given when examining containers that contain scenery but either contain nothing else or only contain other things that are concealed or undescribed.

This seems off to me for the scenery case. Scenery is de-emphasized but it seems weird to explicitly deny its existence. I think in the searching case that the default should be that the player is told about scenery things in or on the thing being searched (and they hold that are neither concealed nor undescribed, and so on) or in containers being examined.

I'm not suggesting changing any of looking's behavior, or anything else about examining's or searching's behavior in this regard.

@erkyrath
Copy link
Collaborator

Scenery is de-emphasized but it seems weird to explicitly deny its existence.

Hm. Scenery is (as a rule) not hidden from the player. The point of scenery is that it's already accounted in the room description, so it should be hidden from the LOOK action.

That doesn't mean we should hide a scenery object from the SEARCH action. However, both LOOK and SEARCH are going to do a bit of "list the contents of the container" business. It would be both fussy and surprising if that contents list included or excluded scenery objects depending on the current action.

If I recall correctly, that "scenery is equivalent to concealed" logic was added because of a bug report reading like:

The trophy case contains.

(All contents were scenery, therefore all skipped.)

@erkyrath
Copy link
Collaborator

To be sure, I've long since decided to only use scenery for top-level objects, never for objects in a container or supporter. For exactly these sorts of reasons!

@zedlopez
Copy link
Collaborator Author

I just noticed another weirdness of the existing concealment behavior that my fixes in 10.2 didn't change:

an item can be all of concealed, lit, and the only light source in the room, and it'll remain concealed but the player won't be in darkness.

My thinking is that the room should remain in darkness. Certainly one could say that it's more "realistic" that a lit concealed item in a dark room would thus reveal itself, but that would mean trumping the author's concealment rules, which I wouldn't want to do.

But I think if concealment-trumps-litness is chosen and implemented the docs should call attention to being the case that if an author creates a situation where a concealed lit item might be the only light source in a dark room, they're on their own regarding what to do about it.

@zedlopez
Copy link
Collaborator Author

@ganelson My draft outlining further suggestions for World Model enforcement is now available in a branch on my fork of this repo. (Fear not, everyone; I won't be making a pull request.)

https://github.com/zedlopez/inform-evolution/blob/world_model/proposals/0015-world-model-enforcement.md#implicit-taking

@CelticMinstrel
Copy link

The description of changes to the support relation sounds like it would break the Rideable Vehicles extension, since it redefines the relation in terms of a supporter, yet neither rideable vehicle nor rideable animal are kinds of supporter. Was this tested?

@zedlopez
Copy link
Collaborator Author

Rideable vehicles are kinds of supporter.
Rideable animals aren't, but they have the I6 supporter flag.

There are problems with rideable animals. These work:

  • try mounting the horse;
  • move the player to the horse;
  • if the holder of the player is the horse...
  • if the horse holds the player...
  • if the horse encloses the player...

This doesn't:

now the player is on the horse

*** Run-time problem UsedSpatialRelationOnNonThing: INTERNAL/Inter/WorldModelKit/RTPs
*** Holding, wearing and carrying are for things only.
*** Attempted to move yourself to foo.

Testing if the horse supports the player or if the player is on the horse compiles and runs without complaint, but is always false.

@zedlopez
Copy link
Collaborator Author

zedlopez commented Apr 15, 2024

You can still move x to y in the general case, including moving the player to any thing that isn't off-stage. This is a feature, because it lets us use the object tree in subkinds of object, but maybe MoveObject should block moving anything ofclass K2_thing to anything but a room, or something with the supporter or container flags, which would make rideable animals (which have the supporter flag) remain ok (and there would still be an exception to block moving the player to nowhere or to anything off-stage, of course).

Additional work would be necessary to make the support relation work.

@zedlopez
Copy link
Collaborator Author

zedlopez commented Apr 16, 2024

Hmm. If rideable animal were a kind of supporter that was usually animate, male, not neuter, the only things I can think of that you'd lose would be:

  • a rideable animal couldn't relate to things by carrying, wearing, possession; tests would need to be in terms of "supports / is on"
  • wouldn't be a person, so wouldn't trigger many check rules involving other people
  • couldn't assign a rideable animal to the player variable
    The loss of wearing might be a pain point, but the others don't seem so bad.

@zedlopez
Copy link
Collaborator Author

actually, I was confused. There isn't a problem. It's a bug in versions before current development that one can say now the player is on the horse because the support relation never applied. if the horse supports the player should always be false. In both 10.1 and current development, now the horse carries the player and if the horse carries the player work.

@CelticMinstrel
Copy link

Is it at all possible to give "on" a different meaning when used with rideable animals? Right now it looks like the compiler rejects using the same verb for two different relations, but it would definitely be convenient if "on the horse" were translated to the carrying relation, and with the support relation defined only on supporters, it's not as if that would actually be ambiguous (it can be disambiguated in the same way that the containment and regional-containment relation already is).

I suppose it's not that big of a deal if that can't be done or is just too complicated. That said, the Rideable Animals documentation should maybe mention explicitly that rideable animals carry you rather than support you.

@zedlopez
Copy link
Collaborator Author

Is it at all possible to give "on" a different meaning when used with rideable animals?

No. A perhaps helpful sort-of-mitigation might be:

ridership relates a thing (called rider) to a thing (called ridden) when ridden is vehicular and ridden holds rider.

The verb to ride means the ridership relation.
The verb to ride in means the ridership relation.
The verb to ride on means the ridership relation.

with that player rides the horse, horse is ridden by the player, player rides on the unicycle, player rides in the popemobile all work as expected. And then RV could encourage use of ride/ridden by rather than carries/carried by or supports/is on.

@CelticMinstrel
Copy link

And then RV could encourage use of ride/ridden by rather than carries/carried by or supports/is on.

That sounds great, except that the relation is not assertable, right? So RV would still have to make it clear that rideable vehicles support their passenger(s) while rideable animals carry them.

@zedlopez
Copy link
Collaborator Author

Yes, it could only be used in conditionals, not in assertions or with now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
formal-proposal A formal proposal that has been accepted for consideration by the core Inform team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants