Dealing with other kinds of "not touchable" things

I had a problem I was wrestling with today. I eventually found a solution in the source code for Alabaster. I tweaked it a bit to work with my code, but I thought it would be useful for others who have the same problem, so I am posting it here.

The problem is dealing with actions that act upon touchable things, when your definition of “not touchable” is different than Inform 7’s definition of “not touchable”, which is primarily concerned with local accessibility, such as whether or not a thing is locked in a glass case.

In this case, my definition of an untouchable thing was something that is too far away for the player to touch. For example, the sky or a tree top. This code creates a new “distant” adjective to deal with the problem. Here’s some sample code (tweaked from Alabaster) that presents the solution:

A thing can be distant or nearby. A thing is usually nearby.

This is the distant-reach rule:
	if the action requires a touchable noun and the noun is distant:
		say "[We] [can't] directly interact with [the noun] because [regarding the noun][they] [are] too far away from [us]." instead;
		rule fails;
	if the action requires a touchable second noun and the second noun is distant:
		say "[We] [can't] directly interact with [the second noun] because [regarding the second noun][they] [are] too far away from [us]." instead;
		rule fails;

The distant-reach rule is listed before the basic accessibility rule in the action-processing rules.

Front yard is a room. "You are standing in your front yard with blue sky above you and green grass below."

The blue sky is distant scenery in the front yard. "It's the blue sky!".

The green grass is scenery in the front yard. "It's green grass!"

Test me with "touch grass/touch sky".

This code can also be expanded to include other reasons for “not touchable” things. For example, introducing a “intangible” adjective to deal with things like fog or shadows.

4 Likes

Addendum: This is a blanket solution, so what happens if you have a thing that is distant but you still want to have an action interact with it? Contrived example: admiring the sky.

I originally, and erroneously, assumed that all I needed to do is not have the word “touchable” in my action definition. In other words, instead of writing:

Admiring is an action applying to one touchable thing.
Understand "admire [something]" as admiring.
Report admiring:
	say "You admire [the noun].".

I write:

Admiring is an action applying to one thing.
Understand "admire [something]" as admiring.
Report admiring:
	say "You admire [the noun].".

But this doesn’t work. I can tell by looking at the actions index for my admiring action that it still expects to act on a touchable noun:

It seems like the “touchable” word does nothing. Correct me if I am wrong on this.

Regardless, not including the word “touchable” doesn’t solve the problem. The way to solve the problem is to use the word “visible”:

Admiring is an action applying to one visible thing.
Understand "admire [something]" as admiring.
Report admiring:
	say "You admire [the noun].".

As can be seen by the updated actions index:

Now, I can admire the sky even though I defined it as a distant object.

1 Like

“Touchable” is the default, so specifying it makes no difference. The deal is that when you declare a verb:

Admiring is an action applying to one [...] thing.

… the reachability requirement for the object is either “touchable” or “visible”, and if you don’t say, it defaults to “touchable”. It’s a boolean flag – “visible” really just means “not required to be touchable”.

4 Likes

Addendum: Smelling and Listening

One last problem I needed to deal with and it is this: objects in the distant can still potentially be heard and smelled. I am not including the last sense, taste, because my PC is not a snake :grin:.

So, I poked a couple of holes in my blanket solution to account for these two actions:

A thing can be distant or nearby. A thing is usually nearby.

This is the distant-reach rule:
	if the action name part of the current action is listening to action:
		make no decision;
	if the action name part of the current action is smelling action:
		make no decision;
	if the action requires a touchable noun and the noun is distant:
		say "[We] [can't] directly interact with [the noun] because [regarding the noun][they] [are] too far away from [us]." instead;
		rule fails;
	if the action requires a touchable second noun and the second noun is distant:
		say "[We] [can't] directly interact with [the noun] because [regarding the second noun][they] [are] too far away from [us]." instead;
		rule fails;

The distant-reach rule is listed before the basic accessibility rule in the action-processing rules.

Front yard is a room. "You are standing in your front yard with blue sky above you and green grass below."

The blue sky is distant scenery in the front yard. "It's the blue sky!".
The green grass is scenery in the front yard. "It's green grass!"

Instead of smelling the sky:
	say "The blue sky smells of ozone. Is there a storm on the way?".
	
Instead of smelling the green grass:
	say "The grass smells like grass. Not surprising."

Test me with "touch grass/touch sky/listen to grass/listen to sky/smell grass/smell sky".

Okay, I think that’s everything. Let me know if I made a grievous error somewhere. Hopefully, this will be useful to others.

2 Likes

FYI, while I haven’t actually used it yet myself, I did spot an extension in the index a little while ago that seems related: Far Away by Jon Ingold

3 Likes

Oh yeah, good point. You know, I have that github archive on my local machine. I did a search on the internal extension files and on the extensions included with Inform 7, but I forgot to search my local archive as well.

Looks like the code is pretty similar to what I found in the source code for Alabaster. Thanks for the heads up.

When I saw this question, I thought “Isn’t this what the accessibility rules are for?” After looking through the documentation, and then the source code for the standard rules, and then the I6 template code, I can’t say for sure: it seems like they were intended to be used this way, but the documentation isn’t consistent with the implementation and some of the tools aren’t provided at the I7 layer.

In any case, here’s an alternative implementation:

"Access" by David Menendez

The touch target is a thing that varies.
The touch target variable translates into I6 as "untouchable_object".

silent touch check is a truth state that varies.
The silent touch check variable translates into I6 as "untouchable_silence".

A thing can be distant or nearby.

An accessibility rule (this is the can't reach distant things rule):
	if the touch target is distant:
		if the actor is the player and silent touch check is false, say "[The touch target] [are] too far.";
		stop the action.


The Lab is a room. 

The moon is a distant thing in the Lab.

The player carries a doodad.

test me with "examine moon / touch moon / insert doodad into moon".

Note that examination succeeds, but touching and inserting both fail as they require a touchable noun and second noun, respectively.

This works because the basic accessibility rule checks whether the action requires a touchable noun or second noun, and then checks the accessibility rules as needed. What is unfortunate is that the accessibility rules work by setting an I6 global variable untouchable_object to the thing you are trying to touch, but the Standard Rules don’t give an I7 equivalent. (Hence the need to define touch target.)

Note that the accessibility rules are also used by phrases such as if the moon can be touched, so we get consistency there as well. (Hence the need to define silent touch check, so that we don’t say anything in that context.)

Another strange thing is that the Inform documentation does give an example of an accessibility rule in example 216, “Waterworld”, but that rule redundantly checks whether the action requires a touchable noun and second noun. (This seems like it would cause trouble with use of can be touched, as well, since there is no reason to assume the thing you are checking is the noun or the second noun.)

3 Likes

Maybe this is because, as you pointed out, the Standard Rules do not expose the I6 untouchable_object variable, so the noun (and second noun) is the only way to refer to the object being touched (e.g. if you want to say it). (But as you also pointed out, it causes trouble with can be touched.)

Anyway, thanks for that snippet, it is very useful, and well worth a feature request/bug report in my opinion.

Thanks for the Inform 6 take on this problem. As you already pointed out, there are certain aspects of the Inform system that no amount of Inform 7 syntactic sugar is going to completely overcome. You really need to understand the underlying Inform 6 code if you don’t want to do a ton of Inform 7 acrobatics. Another aspect similar to this is the fact that you can’t easily kiss inanimate objects – so, I guess the Blarney Stone is just going to have to wait :).

My plan, eventually, is to venture into the realm of Inform 6 once I feel more comfortable with Inform 7. So, I appreciate someone else doing it for me for now.

Blarney Castle Battlements is a room.
Blarney Stone is fixed in place in Blarney Castle Battlements.  "The Blarney Stone stands before you."
Understand "kiss [something]" as kissing.
Instead of kissing the Blarney Stone, say "You kiss [the stone].  You feel your tongue loosening.  Perhaps now you can tell the Count what you really think of him!"

Test me with "kiss stone"

It’s pretty straightforward to alter the default behaviour entirely within I7.

Having said that, it is quite valuable to know your way around the internals of the Standard Rules (the Index tells you most of what you need to know, but not quite everything), and occasional delving into I6 can be necessary for esoteric cases. But not really all that often.

1 Like

Yes. The standard actions are defined to work in the most default ways an author would expect - usually recognizing superfluous or odd actions but rejecting them. If an author doesn’t have anything to attack in the game and doesn’t think about implementing it, that’s why it gives the default “Violence isn’t the answer.” refusal to hitting or breaking something, which is a natural action players might try.

You can type ACTIONS in the IDE and then try an action to see if it’s pre-defined, and what the name of the rule is if it is blocked. It’s a simple matter then to use that rule name to remove it The block attacking rule is not listed in any rulebook. (I didn’t look it up specifically, but that’s how it’s done if the author needs to completely re-make an existing action beyond what an INSTEAD rule will do.)

Index → Actions → Commands is your best friend for that – it will show you all the commands that are recognised, then you can click on one to see the underlying action, all the other commands that lead to it, and any rules that modify its behaviour. And gives you quick links to unlist rules or alter their response text.

Although another useful trick is to only conditionally disable the block rules – for example, if you want the standard ban on giving things to actors to normally apply, but to allow giving a specific item to a specific actor, you can make a special exception:

The block giving rule does nothing if the noun is the crown and the second noun is the Princess.

(Without the block rule, the standard actions will then have the Princess take the item and hold it, and print a generic response, either of which you could customise further, as an alternative to writing an Instead rule.)

1 Like

This works, but getting there is really pretty abstruse! It’s easy to go down a long path of fiddling with check rules or accessibility rules – none of which help – before realizing that this is what you need to do. And if you go looking for the reason that it works, you wind up very deep in the I6 parser code.

So I agree that I6 is not quite as buried as I7 wishes it was.

1 Like

It’s not really that obscure. I went to the Index, noticed that kissing was declared as kiss [someone], so declared a new grammar rule to understand kiss [something] as well.

In this case there’s no conflict between the two so it just works. In some other cases you might need to remove an old command first – for example I had a case where I wanted to route hit [someone] and hit [something] to different actions (and not the standard attacking action). But that’s still just a line or two.

Huh…well, it does work, although I don’t understand why it works. I thought Inform 6 stopped the kissing of anything inanimate immediately. If you use the rules command without having the Understand statement in there, kiss doesn’t even go through any rules before being rejected. Don’t see why an Understand statement would override that.

Like Gavin said, the justification for the command rejection exists on I7 level. If you look in the Standard Rules the only grammar rules for kissing are:

Understand "kiss [someone]" as kissing.
Understand the commands "embrace" and "hug" as "kiss".

When you command KISS STONE there are no grammar rules that would match (the stone isn’t a person so it doesn’t match [someone]) and the parser shows a rejection message. A “kiss [something]” grammar does match the stone so adding that will make the command valid for that action.

The only detail that’s hidden in the I6 level is that the error message specifically says the action isn’t valid with inanimate objects, so the parser does match the grammar but only to determine that the noun is the wrong kind.

4 Likes

Okay, I understand now. The command parser throws the error and the action is never even reached so the rules never fire off. Thanks for the clarification.

If I had to guess, I’d say this was most likely an oversight or a design change that got lost in the shuffle before it was finished.

I agree that this should be posted as a bug. If anyone reading this has the ability to do so, please go ahead an post a link here. (I would do it myself, but I don’t have an account.)

(This thread has gone around a few times…)

You’re talking about the ability to define new rules in the accessibility rulebook? Replacing the “access through barriers” rule?

Yes, I should have included more context.

I consider example 216 “Waterworld” to be buggy. The accessibility rule it demonstrates is misleading, because it works (by coincidence) when checking actions, but does not work at all when using phrases such as the player can touch the rope.

Modified code for Waterworld 4, with sample transcript
"Waterworld 4"

A view is a kind of backdrop.

The can't touch views rule is listed before the access through barriers rule in the accessibility rulebook.

Accessibility rule (this is the can't touch views rule):
	if the action requires a touchable noun and the noun is a view:
		say "You are too far from [the noun] to do anything but look." instead;
	if the action requires a touchable second noun and the second noun is a view:
		say "You are too far from [the second noun] to do anything but look." instead;

The player carries a rope.

The sun is a view. It is everywhere. The description is "A blazing sun makes you wish you had never been born."

The Sahara is a room. North of the Sahara is More Sahara. North of More Sahara is Yet Further Sahara.

Test me with "x sun / get sun / n / x sun / n / x sun / tie rope to sun".

[added by me]
Every turn:
	if the player can touch the rope, say "You can touch the rope.";
	otherwise say "The rope is beyond your grasp."

With the new every turn rule, we can see that things are not working as intended:

>x sun
A blazing sun makes you wish you had never been born.

You can touch the rope.

>touch sun
You are too far from the sun to do anything but look.

You are too far from the sun to do anything but look.
The rope is beyond your grasp.

Additionally, it would be nice if untouchable_object and untouchable_silence were exposed in I7 and if the documentation described how to properly write an accessibility rule, but that feels more like a feature request than a bug.

1 Like