Found_in equivalent in I7

I have a box that I want to be in multiple locations simultaneously. Normally the backdrop class (or kind, or whatever nonstandard jargon I7 insists on using) is designed for exactly this problem; but since I7 handles this sort of thing via classes and doesn’t allow multiple inheritance, I can’t simply declare such a backdrop to also be a container. Is there an I7 equivalent of the found_in property in I6, or is there another, idiomatic way to get around this limitation?

2 Likes

Under the hood, a backdrop is inform is just a scenery object that physically follows the player around in a region. So when you move to a room it checks if you’re in the right region; if you are, it moves the object into that room.

So you could just replicate that yourself, like “if the player is located in Region A: now backdrop_box is in the location of the player” (or whatever the exact phrasing is)

3 Likes

Thanks, I’ll try that. I’m a bit concerned about that rule firing at the appropriate time, particularly if the player is moving between rooms or after a scene, but I guess it’s one of those things that can be hammered out with testing (and, in true I7 style, only by testing and hoping for the best.) Failing that, I can dig up whatever the backdrop rules are and try to slip my code changes in, assuming that they’re freely modifiable by the programmer.

2 Likes

Probably the easiest way is to make the box part of a backdrop. Something like this:

The box-holder is a backdrop. The box-holder is not scenery.
The box is a container. It is part of the box-holder.
Rule for writing a paragraph about the box-holder:
	say "The magic teleporting [box] is here.";
	now the box-holder is mentioned.
6 Likes

Yep, this is the way the documentation suggests doing it. The “is part of” (incorporation) relation is a good way to deal with the limitations of the single-inheritance model. Can’t have your trunk be both a container and a supporter? Give it an “inside” part and a “top” part.

2 Likes

Some fussy details to cover our tracks:

I’d suggest adding ‘set pronouns’ here:

Rule for writing a paragraph about the box-holder:
  say "The magic teleporting [box] is here.";
  set pronouns from box;
  now the box-holder is mentioned.

or “it” is left meaning the box-holder after looking (if it’s the only or last thing present). And I’d also throw in

Include Scopabiliy by Brady Garvin.

The box-holder is unscopable.

'cause otherwise if you issued a naked “examine” or “take” when the box-holder was there and nothing else was, the parser would default to the box-holder.

And if you tried to take box you’d get That seems to be a part of the box-holder. So…

Instead of taking the box, say "[We] [can't] take that."
2 Likes

My solution to the “scopability” problem would have been to make the box-holder an in-world object of some sort, such as a plinth or a statue, associated with the box. I’d mention it in the description, and then I wouldn’t have to worry about it turning up in library messages. (I didn’t know about Include Scopability, I’ll have to look into that.)

I always forget to deal with pronouns.

3 Likes

The found_in machinery is still present and working (at least in 6M62). It can be used with a special declaration. Here’s an example:

"Floating Object Container"

A room can be buckety.

Place is a room.

Other Place is east of Place. Other Place is buckety.

Yet Another Place is east of Other Place. Yet Another Place is buckety.

A container called a magical bucket is in Place.

Include (- with found_in [; if ((GetEitherOrProperty(location, (+ buckety +)))) rtrue; else rfalse; ]  -) when defining the magical bucket.

The call to GetEitherOrProperty() is a hedge against the I7 compiler deciding to represent the “either/or property” as an I6 property instead of an I6 attribute.

There are other ways to go about setting up the condition to decide whether or not the floating container is present in a room, if desired.

5 Likes

Messing about with this to see if it worked in Ver 10.1 led me to the discovery that trying to include I7 object name expansions in I6 property definitions like this elicits a compiler bug.

E.g.

Include (- with found_in (+ Lab +), -) when defining the flask

leads the compiler to crash with a ‘no current sentence’ error when compiling to 6M62, and when compiling to 10.1.2 leads to a truncated I6 object name reference:

with found_in I_Lab,

when the I6 object name is actually I_Lab_U1, causing I6 compilation to fail with the error 'no such constant as I_Lab.

Although now deprecated, this syntax is supposed to be still functional in 10.1.2.

In this instance the code can be made to successfully compile in 10.1.2 with this ugly fix, in which case found_in does function as expected:

Include (- with found_in (+ Lab +)_U1, -) when defining the flask

However, GetEitherOrProperty() appears to have disappeared from 10.1.2, so your code doesn’t compile

1 Like

Interesting. I still haven’t made the switch to 10.1, but I’m dabbling.

Following is a version that determines floating presence based on a relation instead of a property, which survives cursory testing in under 10.1.2.

"Found In v10.1.2"

Place is a room.

Other Place is east of Place.

Yet Another Place is east of Other Place.

Floating presence relates various things to various rooms. The verb to be found in means the floating presence relation. The verb to host means the reversed floating presence relation.

Include (-

[ FloatPresence obj loc ;
    if (obj && loc)
	    return (Relation_TestVtoV(obj, (+ floating presence relation +), loc, false));
    else
	    rfalse;
];

-).

A floating container is a kind of container.

Include (- with found_in [ toroom obj ; return (FloatPresence(obj, toroom)); ]  -) when defining a floating container.

A floating supporter is a kind of supporter.

Include (- with found_in [ toroom obj ; return (FloatPresence(obj, toroom)); ]  -) when defining a floating supporter.

A floating thing is a kind of thing.

Include (- with found_in [ toroom obj ; return (FloatPresence(obj, toroom)); ]  -) when defining a floating thing.

A floating animal is a kind of animal.

Include (- with found_in [ toroom obj ; return (FloatPresence(obj, toroom)); ]  -) when defining a floating animal.

There is a floating container called a magical bucket.

The magical bucket is found in Other Place and Yet Another Place.

There is a portable floating supporter called a magical tray.

The magical tray is found in Place and Other Place.

A cloud is a floating thing. Every room hosts it. The initial appearance of the cloud is "A lone cloud slowly crosses the sky."

A bird is a floating animal. The initial appearance of the bird is "A bird wheels far above you."

Every turn:
    if the remainder after dividing the turn count by three is zero:
	    now the bird is found in nowhere;
	    now the bird is found in a random room;
	    update backdrop positions;
	    if the player can see the bird and the player could not see the bird, say "A bird glides into view."
    
After jumping:
    if the magical bucket is found in the location:
	    now the magical bucket is not found in the location;
    otherwise:
	    now the magical bucket is found in the location;
    update backdrop positions;
    say "Bucket presence changed."

After waving hands:
    if the magical tray is found in the location:
	    now the magical tray is not found in the location;
    otherwise:
	    now the magical tray is found in the location;
    update backdrop positions;
    say "Tray presence changed."

Test me with "e  / e / wave / l / jump / l / w / wave / l".


Include (-

[ MoveFloatingObjects toroom i k l m address flag;
    if (toroom == nothing) toroom = real_location;
    if (toroom == nothing) return;
    objectloop (i) {
        address = i.&found_in;
        if (address ~= 0 && i hasnt absent) {
            if (ZRegion(address-->0) == 2) {
                m = address-->0;
                .TestPropositionally;
                if (m.call(toroom, i) ~= 0) move i to toroom; ! MODIFIED
                else { if (i in toroom) remove i; }
            } else {
                k = i.#found_in;
                for (l=0 : l<k/WORDSIZE : l++) {
                    m = address-->l;
                    if (ZRegion(m) == 2) jump TestPropositionally;
                    if (m == toroom || m in toroom) {
                        if (i notin toroom) move i to toroom;
                        flag = true;
                    }
                }
                if (flag == false) { if (i in toroom) remove i; }
            }
            if ((i ofclass K4_door) && (parent(i) == nothing)) {
            	move i to ((i.door_to).call());
            }
        }
    }
];

-) replacing "MoveFloatingObjects".

The variety of floating <X> kinds is to avoid interfering with the native found_in property for backdrops.

This is all very neat!

I’m also in transition to 10.1, and still struggling with all the minor changes to how things are done.

Interesting that your modified 6M62 MoveFloatingObjects routine appears to run OK in 10.1, as the 10.1 routine it replaces uses a number of different idioms to express equivalent statements- e.g. k=(_final_propertylength(OBJECT_TY, i, A_found_in)) instead of k = i.#found_in and m(toroom) instead of m.call(toroom). Presumably going forward these are the approved ways of doing things…

The goal of Inter seems to be to support as much of I6 syntax as possible, so if .# and .call are currently supported, I doubt they’re going to be removed.

I thought that, too, while checking things before posting, but when I tried to use that I6 code, it wouldn’t compile under 10.1.2. Also, if you look at the produced auto.inf, the code generated does look like the new version that you’re citing. My guess is that it’s a product of the I6-to-inter-to-I6 conversion.

I think you’re right- looking at [ MoveFloatingObjects...] in the 10.1 WorldModelTemplate it’s the same as in the 6M62 template (k=i.#found_in etc.)

grump. Last night I discovered that in v10 you can’t get at I7-defined properties from within I6 code with obj.(+ i7-property-name +) like you used to be able to do. I don’t know yet if there’s a workaround.

Graham’s been working to purge as many uses of the (+ +) syntax from the language as possible, and I suspect this is a casualty of that.

The alternative is to say:

A thing has a number called zork.
The zork property translates into Inter as "zork".

Then it has a known name at the I6 level which you can reference.

1 Like

As a KISS alternative, one could just include an equivalent of GetEitherOrProperty() into a 10.1 project to make your original code work…

However, in 10.1 that functionality seems to be superseded by the following function:

[ _final_propertyvalue K o p t;
    if (K == OBJECT_TY) {   !### properties/attributes for objects
        if (metaclass(o) == Object) {
            t = p-->0; p = p-->1;   !### get property/attribute type ID and move p to pointer to property 
            if (t == 2) { if (o has p) rtrue; rfalse; } !### type ID of 2 == attribute: return attribute value
            if (o provides p) return o.p; !### return property value
        }
        rfalse;  !### invalid object, or object does not provide property requested
    } else {     !### properties for kinds of values
        t = value_property_holders-->K;
        return (t.(p-->1))-->(o+COL_HSIZE);
    }
];

which returns the value of a I6 property/attribute of an object, or the value of a property of a value-
it is called with K (kind- (OBJECT_TY for objects, or the kind of value for values), o (the object or value), p (a property ID- which in the case of objects is used as an index to look up in an array the property/attribute type ID (with 2 indicating an attribute) together with a pointer to the actual property, then retrieves the attribute/property value as appropriate.

Unfortunately, like the .inf version of [MoveFloatingObjects;…], this can’t be compiled as an I6 inclusion in source because it seems to depend on structures (like the property type ID/property pointer array) created in the final iteration of inter->I6 conversion and which are not present in the original kit I6.

GetEitherOrProperty(object, property/attribute) depends in 6M62 on a hacky method (that is unavailable in 10.1.2) for deciding whether the second parameter is an attribute or a property, and I don’t know a way of determining in 10.1.2 source whether an I7 boolean property has been compiled as an I6 property or an attribute.

One hacky way round this would be to define a three-way property in I7 (including a redundant null value) rather than a boolean, or to define bucket-status as an (enumerated) value with 2 values buckety and non-buckety then assign rooms a bucket-status property, either of which would guarantee compilation as a property:

"test_Floating_Objects" by PB

bucket-status is a kind of value. The bucket-statuses are non-buckety and buckety.  Every room has a bucket-status.

Other Place is east of Place. Other Place is buckety.

Yet Another Place is east of Other Place. Yet Another Place is buckety.

A container called a magical bucket is in Place.

Include (- with found_in [; return (real_location.(+ bucket-status +)) -1; ]  -) when defining the magical bucket.

One neat solution is assign the buckety property from a table, which also ensures that even boolean properties are compiled as I6 properties rather than attributes:

"test_Floating_Objects" by PB

Some rooms are defined by the Table of Locations.

Table of Locations
room	buckety
Place	false
Other Place	true
Yet Another Place	true

Place is a room.

Other Place is east of Place.

Yet Another Place is east of Other Place.

A container called a magical bucket is in Place.

Include (- with found_in [; return real_location.(+ buckety +); ]  -) when defining the magical bucket.

EDIT as long as at least one instance of the property is defined in a table, the property will compile to an I6 property rather than an attribute. Elsewhere in the code property values can be asserted in the usual way, e.g. `The buckety of Other Place is true.’

I haven’t had a chance to test it, but I believe the “translates into Inter” syntax helps here too—it ensures the property is defined as a property (not an attribute) with a name you can reference in I6 code.

Ah- haven’t come across that yet- will explore!

It seems to be the preferred way to use I7 object, property, etc constants in I6 code now (rather than (+ +)).