Printing a room description of a distant room // Relations advice

I’m currently trying to cobble together a version of Zork II’s Crystal Spheres.

If you’re not familiar, looking into a orb prints the room description of the room enclosing the ‘next’- peering into the blue orb shows you the room enclosing the red orb, peering into the red orb shows you the room enclosing the clear orb, etc.

My Question:

How can I ask Inform to print the room description of a room the player isn’t currently in?

I’ve read a little about putting things in Scope, but that seems like it would introduce some problems. The action of “peering” should do three things:

  1. say a brief preamble (as you look into the sphere, your vision swirls as…etc)
  2. give the room description of wherever the ‘paired’ orb is
  3. say a brief postscript (your vision clears; you are once again standing in… etc)

…which means that “look” or “examine” actions relating to the other room should always fail, and i’m not sure how to bring a room into scope and back out again before the player’s next action…

BONUS QUESTION:

This one’s a little more broad.

Rather than write a ton of specific If-loops for every orb, it seems like I should be able to create a relation that pairs them unidirectionally. Since the purpose behind this is to learn more about Inform, I figure taking the ‘harder’ path might be the better option here, but I’m really struggling!

Writing a linked / linked-to relation between orbs was easy enough, and checking the >relations debug confirmed that inform understands what i mean. Here’s my setup:

An orb is a kind of thing.

[a bunch of lines making orbs in different places]

linking relates one orb to one orb.

The verb to link to means the linking relation.

The Red Orb links to the Blue Orb. The Clear Orb links to the Red Orb. The Black Orb links to the Clear Orb. The Void Orb links to the Black Orb.

I’m just really struggling to actually use this relation, for some reason? Any action or definition I try and insert it into seems to understand that it’s a relation between a specific kind of thing called “orb,” but still won’t allow it as an input. Am I just misunderstanding the use-case for relations…? Is there a better way to do this…?

I think the most economical way to show another room is to secretly teleport the player to that room, then put them back after. The moment they are moved, the new room description will print unless we suppress it. So for the outbound journey, we don’t suppress it, but when putting them back, we do. The advantage of doing things this way is you leverage everything dynamic that Inform would normally print about the target room without having to recreate it. (Well, almost everything.)

I wrote a demo that uses this approach, with the orbs and their connections that you mentioned. In this code, I put an alternate introduction to each room in its description that only prints when ‘peering into’ the room (signalled by the peerflag temporarily being true). This alt text could be optimised or systematised somehow, but for this demo it gets the idea across.

As for the relations, someone better at them can probably show you how to do it using them, but I’d say this is not actually an ideal case for them. What you want can be expressed really simply with a table listing the orbs and the orbs they link to. So that’s what I’ve done in my demo. (Maybe you’ll learn about tables instead of relations!)

This demo actually has one bug I haven’t solved yet – if you peer into an orb that’s in the room you’re standing in, that orb is not seen in the vision. My guess is it’s something to do with the noun (that orb) being mentioned already, but trying to un-mention it hasn’t worked. So someone else might be able to tell me what’s happening there.

Summary
an orb is a kind of thing.

Forest is a room. "[if peerflag is true]Peering into [the used-orb], you see a beautiful forest[otherwise]A beautiful forest[end if]. The castle is east of here.".

the blue orb is an orb. player holds the blue orb.

player holds some garlic.

player holds an opaque container called my bag. the void orb is an orb in my bag.

Castle is east of forest. "[if peerflag is true]Peering into [the used-orb], you see a lonely castle[otherwise]This lonely castle is deserted[end if]. The forest is west and the desert to the east.".

the clear orb is an orb in the castle. "A clear orb sits here.".

Desert is east of castle. "[if peerflag is true]Peering into [the used-orb], you see a bleak desert where nothing grows[otherwise]Nothing grows in this bleak desert[end if]. The castle is west and the dungeon is east.".

the black orb is an orb in the desert.

Dungeon is east of desert. "[if peerflag is false]The dungeon is dark, wet and foul. You can retun to the desert to the west[otherwise]Peering into [the used-orb], you see a dungeon dark, wet and foul[end if]."

a sword is in the dungeon. "A sword lies on the floor.".

the red orb is an orb in the dungeon. "A red orb sits here.".



peerflag is initially false.

the used-orb is a thing that varies.

peering into is an action applying to one thing.

Understand "peer [something]", "peer in/into [something]" as peering into.

Check peering into:
	if the noun is not an orb:
		instead say "You can't scry using [the noun].";
		
Instead of peering into the void orb:
	say "You peer into the void orb. It remains dark.";

Carry out peering into:
	now used-orb is the noun;
	let SOURCE-ROOM be the location;
	now peerflag is true;
	let TARGET-ORB be the target corresponding to a source of the used-orb in the table of orblinks;
	now used-orb is marked for listing;
	move the player to the location of TARGET-ORB;[target room desc. appears now]
	now peerflag is false;
	move the player to SOURCE-ROOM, without printing a room description;
	say "... the vision fades.";

Rule for printing the name of a room when peerflag is true:
	do nothing;

Table of orblinks
target	source
red orb	blue orb
clear orb	red orb
black orb	clear orb
void orb	black orb

Test me with "i/peer blue/peer garlic/peer void/e/e/e/peer red/get sword/w/drop sword/w/peer clear/e/peer black".

-Wade

2 Likes

For a version using relations, you can add your code above ("linking relates ..." etc.) to Wade’s scenario, and just change this line (in the Carry out peering into rule):

let TARGET-ORB be the target corresponding to a source of the used-orb in the table of orblinks;

to:

let TARGET-ORB be a random orb which links to the used-orb;

That will produce an identical transcript for the given scenario.

The “random” sounds weird, but it’s necessary here, as far as I see, because otherwise Inform complains about the value not being specific enough – it doesn’t know that the orb which links to the used-orb is unique here. So we choose a random one, which will in our case of course always be the one that’s actually linked.

4 Likes

It’s often possible to name the element on one side of a relation, which makes it less awkward to access. The relation must be such that the named side can have only one choice for a given value of the unnamed side. So something like the following seems appropriate:

Linking relates an orb to an orb (called viewing destination).

That particular assertion generates a specialized Problem Message because, in the case of a 1-to-1 relation like this, the named side must be the left side (i.e. first thing) for some reason. So:

Linking relates an orb (called viewing destination) to an orb.

But the fact that the order of the orbs in the relation is the opposite of what you want means that you want to set up your associated verb as indicating the reversed relation:

The verb to be able to scry means the reversed linking relation.

Then you can naturally say:

The red orb can scry the blue orb.

to set up the link, and you can naturally refer to:

the viewing destination of <an orb>/<phrase that evalutes to an orb>

The Standard Rules already define the commands >LOOK INTO… and >LOOK THROUGH… and map them to the searching action. They also define a blocking rule to prevent searching anything but containers or supporters. Following severedhand’s suggestion to quickly move the player back and forth so as to take full advantage of built-in machinery (including light level detection, enclosure within containers, etc.):

The can't search unless container or supporter rule does nothing when the noun is an orb.

Report searching an orb (called viewer):
    say "You peer into the depths of [the viewer]...";
    let old view be the holder of the player;
    let new view be the holder of the viewing destination of viewer;
    move the player to new view;
    move the player to old view, without printing a room description.

EDIT: Oops, I didn’t keep the named side of the linking relation consistent between example assertions and example rule. Fixed, and sorry for any confusion.

4 Likes

You have the line:

now used-orb is marked for listing;

but this doesn’t affect the way that the used-orb has already been set to mentioned by room descriptions such as:

Forest is a room. "[if peerflag is true]Peering into [the used-orb], you see a beautiful forest[otherwise]A beautiful forest[end if]. The castle is east of here.".

Getting at the place where the mentioned property for used-orb is set is a little tricky since there’s no special activity set up for printing a room description. However, the way that the Standard Rules are structured makes it not too hard to set one up since there’s luckily a unique phrase in use:

Printing the description of a room is an activity.

[Next two phrases modify logic from Standard Rules to provide new activity context for printing a room description. See "the room description body text rule" for usage of second phrase.]
To print-or-run the description property of (R - room):
    (- PrintOrRun({R}, description); -).

To print the location's description:
    begin the printing the description of a room activity;
    print-or-run the description property of the location;
    end the printing the description of a room activity.

After printing the name of the used-orb while printing the description of a room: [see WWI 18.4]
    now used-orb is unmentioned.
2 Likes

Here’s how Scroll Thief does it:

The scrying flag is a truth state that varies. [This prevents infinite recursion.] The scrying flag is false.
The current viewpoint is an object that varies. The current viewpoint is yourself.
The temporary scrier is a privately-named scenery person. [The player is changed to this person to show a different viewpoint through a scrying device.]

Instead of examining or searching a scrying device (called the glass):
	take full time;
	if the glass is not magical, say "Nothing appears any more.";
	if the glass is damaged, say "The glass is shattered and covered in cracks. It seems to reflect a strange flickering darkness, like ash in water." instead;
	if the glass is inactive, follow the mirror description rule instead;
	if the mystical relative of the glass is damaged, say "Instead of a reflection, [the glass] shows a strange vision: a web of thin black shadows, with swirls of color twisting between them like oil on water." instead;
	if the security lockdown is happening, say "[The glass] [show] only the words [tt]SECURITY LOCKDOWN - SCRYING PREVENTED[/tt] in glowing red letters." instead;
	let the far glass be the mystical relative of the glass;
	let the far side be the holder of the far glass;
	let the far ceiling be the visibility ceiling of the far glass;
	if [the far glass is off-stage or] the glass can see the far glass:
		say "Through [the glass] you see only darkness.";
		rule fails;
	if the far ceiling is darkness-filled:
		say "You can make out the dim outlines of [the far ceiling], but it is too dark to perceive any details.";
		rule fails;
	say "Instead of a reflection, [the glass] seems to show a different view, as if it were a window to another world...";
	let the current location be the player;
	let V be false;
	if the location of the far glass is visited, let V be true; [Remember this to switch it back later.]
	now the scrying flag is true; [This flag is also used to avoid showing mirrors recursively.]
	now the current viewpoint is the far glass;
	move the temporary scrier to the far side;
	now the player is the temporary scrier;
	try looking;
	now the player is the current location;
	remove the temporary scrier from play;
	now the current viewpoint is the player;
	now the scrying flag is false;
	say "...you step back from the glass, and take a moment to regain your bearings.";
	[move the player to the current location, without printing a room description;]
	if V is false, now the location of the far glass is unvisited. [If the player hasn't been there in person, it shouldn't be marked as 'visited' from this.]

In other words, after a lot of conditions to make sure the orb is working, it moves a special scenery object to the holder of the other orb, changes the player to that, and calls the looking action. This ensures it gets exactly the description you’d get if you were there in person, regardless of any rules that modify looking.

3 Likes

Thank you all so much!
After reading your replies, I decided to try all three versions! ^^_^^

I was already semi-familiar with tables, so Severhand’s version worked easily (as did StJohn’s edit!).

Daniel’s was a little hard to grasp, but I shamelessly plundered a few of those ideas (especially the visited check, I honestly didn’t even think of that!).

Otistdog’s was the closest to my original code, and after trying a few things I got it online fairly easily!

2 Likes

I’d like to ask a follow-up question, if that’s alright!

I tried setting up something similar to the code you had printed, but using a specificly defined “peering” action to avoid having to redefine searching rules. (Obviously in a real game intended for other people it’s best to cover “look through/look into/search” etc, but this is just an exercize and i am lazy).

I ran into a snag- I couldn’t find a way to write a Check or Report rule for my custom action that let me define “viewer”!

I could manage “Report Peering into it:”, and even “Report peering into an orb:” (with corresponding action definintions), but never with a (called ____) addition…

Just to be sure, I ended up trying it out using searching, like in the example, and it worked perfectly!

So, my question- what exactly am i running afoul of, syntax-wise…?

I’m not sure what would cause that problem, but if you post the code that’s causing it, that should help to identify the issue.

2 Likes

Formatted as a generic action:

linking relates one orb (called viewing destination) to one orb.

The verb to be able to scry means the reversed linking relation.

The Blue Orb can scry the Red Orb. The Red orb can scry the Clear Orb. The Clear Orb can scry the Black Orb. The Black orb can scry the demon orb.

Understand “Peer into [something]” as peering into it.

Peering into it is an action applying to one touchable thing.

Check peering into it:
unless the noun is an orb:
say “It peers back at you.” instead;
if the holder of the viewing destination of the noun is the player:
say “You gaze into the [noun]… your vision swirls…[paragraph break][paragraph break]You see a dim impression… of the inside of your bag.[Paragraph break][paragraph break]After a moment, your vision clears.” instead;
if the holder of the viewing destination of the noun is a container:
say “You gaze into the [noun]… your vision swirls…[paragraph break][paragraph break]…But all you see is darkness.[Paragraph break][paragraph break]After a moment, your vision clears.” instead.

Report peering into it:
say “You gaze into the [noun]… your vision swirls…”;
let old-view be the holder of the player;
let new-view be the holder of the viewing destination of the noun;
let V be false;
if new-view is visited, let V be true;
now the viewing destination of the noun is scenery;
move the player to new-view;
move the player to old-view, without printing a room description;
now the viewing destination of the noun is not scenery;
if V is false, now new-view is unvisited;
say “[paragraph break]After a moment, your vision clears. You are once again standing in the [location].”

I tried swapping every “it” for “an orb” and it worked out okay, but trying to say something like “Check / Report peering into an orb (called ___)” wouldn’t compile…

I don’t have my computer in front of me to check, but I suspect the problem, or at least a problem, is that you’ve named your action “peering into it”. This is one of the things that is unexplained or at least underexplained in the docs, but action names should only contain an “it” if they apply to two nouns, not one. Your action definition will still compile, but you’ll start seeing errors in specific rules. So try renaming your action “peering into” and see if that works!

Oh, and it’s easier to paste in code if you use the code button - it’s the little </> above, or you can put three backticks before and after what you paste in. That preserves formatting, including tabs, which makes it easier to paste into the IDE and mess around.

4 Likes

Did a quick test- completely correct.

The built-in documentation isn’t super clear about when different syntax permutations are used, so i’ve been picking things up using the recipe book as contextual hints… This makes a lot of sense, so thank you! ^^_^^

Presented without comment, the second-ever topic I posted on this board :slight_smile: