Determining where backdrops are

That’s pretty much exactly what backdrops are; internally, they are also referred to as “floating objects” since they are silently moved into the player’s location as she moves.

Surely the I6 code to populate a list with the contents of an object’s found_in array isn’t that difficult? The only complication would seem to be manipulating the list in I6, but there are helper functions for that. I don’t have time right now to give it a go, but maybe someone who’s quicker with I6 than I could try rolling it out?

Or maybe I’m missing something…?

–Erik

Exactly. Only these would be mine.

Found_in isn’t an array. It’s a function that tests the global location variable.

Went with Vyznev’s solution as the least objectionable of a bad lot. I7 emits slight wheeze and a billow of steam, but no alarming clunking noises as yet. Will monitor closely.

I see. It still seems as though one ought to be able to test that function w/o moving the player. That should be a lot faster: just one function call per location in the game rather than going through all of the processes of moving the player through all the rooms. Unfortunately, I tried a couple of different ways to implement this, and didn’t succeed:

  1. Based solely on zarf’s description (“found_in is a function that tests the global location variable”), I tried caching the location variable, changing the location to an arbitrary room, calling found_in for the backdrop, e.g., sun.found_in or sun.found_in(), and then restoring the location. Unfortunately, this seems to always return true.
  2. I tried to adapt some of the library code (from MoveFloatingObjects) to this purpose and found that my implementation always returns false… :frowning:

Here’s what I came up with for #2 in case anyone is interested:

[spoiler][code]House is a room. Garden is a room. Field is a room.

Sun is a backdrop. Sun is in Field and Garden.

To decide whether (B - a thing) is a floating object in (R - a room):
(- TestFloatingObjects({B},{R}) -)

Include (-
[ TestFloatingObjects o r k l m address flag;
address = o.&found_in;
if (address ~= 0 && o hasnt absent) {
if (ZRegion(address–>0) == 2) {
m = address–>0;
.TestPropositionally;
if (m.call(r) ~= 0) return true;
}
else {
k = o.#found_in;
for (l=0 : l<k/WORDSIZE : l++) {
m = address–>l;
if (ZRegion(m) == 2) jump TestPropositionally;
}

	}
}
return false;

];
-)

When play begins:
if the Sun is a floating object in the Field, say “It’s in the field!”;
if the Sun is a floating object in the House, say “It’s in the house!”;[/code][/spoiler]

I think you just forgot if (m == r || m in r) rtrue; after the jump to TestPropositionally. It seems to work fine for me otherwise.

I could also make Vyznev’s solution more efficient by using the jump-the-player technique only once for each backdrop, and using that to populate a list of rooms for each backdrop, which would be referred to thereafter.

(Of course, I could just write all the lists out in advance: but that would introduce lots of opportunity for transcription errors.)

So I did, and so it does! Thanks for taking a look!

Here’s the full implementation/example for maga’s request:

[code]House is a room. Garden is a room. Field is a room.

Sun is a backdrop. Sun is in Field and Garden.

To decide whether (B - a thing) is a floating object in (R - a room):
(- TestFloatingObjects({B},{R}) -)

Include (-
[ TestFloatingObjects o r k l m address flag;
address = o.&found_in;
if (address ~= 0 && o hasnt absent) {
if (ZRegion(address–>0) == 2) {
m = address–>0;
.TestPropositionally;
if (m.call(r) ~= 0) return true;
}
else {
k = o.#found_in;
for (l=0 : l<k/WORDSIZE : l++) {
m = address–>l;
if (ZRegion(m) == 2) jump TestPropositionally;
if (m == r || m in r) rtrue;
}

	}
}
return false;

];
-)

To decide what list of rooms is the list of loci for (B - a backdrop):
let L be a list of rooms;
repeat with locus running through rooms:
if B is a floating object in locus, add locus to L;
decide on L.

When play begins:
say “[List of loci for the Sun].”;[/code]

Works like a dream. Many thanks, all.

I’m afraid this does not work when the backdrop is set to a region. That’s the case when found_in tests location rather than its argument. Yes, it’s inconsistent.

You need to do something like this:

To decide whether (B - a thing) is a floating object in (R - a room):
   (- WrapTestFloatingObjects({B},{R}) -)

[ WrapTestFloatingObjects b r res tmploc;
	tmploc = location;
	location = r;
	res = TestFloatingObjects(b, r);
	location = tmploc;
	return res;
];

Thanks, zarf, that makes this a general-purpose solution for anyone who stumbles onto this thread.

I came across this problem when updating Conditional Backdrops. I think there might have been an Inform bug involving the found_in property - like it’s supposed to take an argument, but it ignores the argument and uses the location instead. I think I fixed that, with Zarf’s guidance… which makes the problem a simple matter of writing an I7 wrapper for found_in.

inform7.com/extensions/Mike%20Ci … index.html

Hmm, now I’m encountering a weird bug with this. It works fine when backdrops are in only a few locations; but for backdrops that are in a lot of locations (I think at least 16), it adds every location to the loci list.

I’m perplexed. Any ideas?

Test it without dynamic lists in the mix.

repeat with locus running through rooms:
if B is a floating object in locus, say B.

It still thinks that those backdrops are in every room.

Have you been able to reproduce this in a test project?

–Erik

I bet I7 switches over from a found_in array to a routine when the number of rooms becomes large. (Because of Z-code limits on property array lengths.)

However, I haven’t built a test case to check this guess.

This seems to be the minimal code to replicate the behaviour. (There are 17 rooms. foo is only in the first 16 of them, but the test thinks it’s in every one).

[code]“Room for Improvement” by Sam Kabo Ashwell

room1 is a room. room2 is a room. room3 is a room. room4 is a room. room5 is a room. room6 is a room. room7 is a room. room8 is a room. room9 is a room. room10 is a room. room11 is a room. room12 is a room. room13 is a room. room14 is a room. room15 is a room. room16 is a room. room17 is a room.

foo is a backdrop. foo is in room1, room2, room3, room4, room5, room6, room7, room8, room9, room 10, room11, room12, room13, room14, room15, room16.

To decide whether (B - a backdrop) is a floating object in (R - a room):
(- TestFloatingObjects({B},{R}) -)

Include (-
[ TestFloatingObjects o r k l m address flag;
address = o.&found_in;
if (address ~= 0 && o hasnt absent) {
if (ZRegion(address–>0) == 2) {
m = address–>0;
.TestPropositionally;
if (m.call® ~= 0) return true;
}
else {
k = o.#found_in;
for (l=0 : l<k/WORDSIZE : l++) {
m = address–>l;
if (ZRegion(m) == 2) jump TestPropositionally;
if (m == r || m in r) rtrue;
}

  }

}
return false;
];
-)

When play begins:
let X be 0;
repeat with locus running through rooms begin;
now X is X + 1;
if foo is a floating object in locus, say “[X]: [foo] is in [locus][line break]”;
end repeat;[/code]

Okay, remember my correction at https://intfiction.org/t/if-archive-hugo-downloads/59/1 ? You need to do that.

And that works beautifully. Thanks again.