Overriding check failures

Three questions in one night. A Trifecta.

Consider the following scenario:

Lab is a room. Garden is north of Lab.

A shirt is a kind of wearable thing.
The player carries the red shirt. The red shirt is a shirt.
The player wears the blue shirt. The blue shirt is a shirt.
	
Check going north from the lab when the player wears the blue shirt:
	say "The blue shirt seems to be okay.";
	
Check going somewhere when the player wears a shirt:
	say "You can't go there wearing a shirt." instead;	

This doesn’t work because the second check rule will always fire. AFAIK there’s no way for a successful check rule to short-circuit the rulebook and cause the other check rules not to run.

One way to get around this problem is to exclude special cases from the second check rule. But say I want my shirt code to be in an extension, so it needs to be general.

How can I produce the behavior of “skipping past the check rules” in this case? How can I make it so the player can pass between rooms while wearing the blue shirt, but not while wearing the red shirt?

Add instead after your say statement in the first check rule.

Inform’s usual rule-ranking also means that more-specific rules will override less-specific ones

Unfortunately, “instead” stops the action entirely.

The quickest way to deal with this one is to put the rules together. In other words, have one rule that deals with all the shirt-checking:

Check going somewhere when the player wears a shirt:
	if going north in the lab and player wears the blue shirt:
		say "The blue shirt seems to be okay.";
	otherwise:
		instead say "You can't go there wearing a shirt.";

Note that ‘instead’ at the head of the ‘You can’t go there…’ line. That stops the whole action process dead as it prints the message. The prior check, saying “The blue shirt seems to be okay”, has no instead and so lets the action continue its flow through the rulebooks.

If you need to add other exceptions later, you can keep poking them into this rule. e.g.

Check going somewhere when the player wears a shirt:
	if going north in the lab and player wears the blue shirt:
		say "The blue shirt seems to be okay.";
	otherwise if going west in the beer garden and player wears red shirt:
		say "The red shirt will be fine for the beer garden.";
	otherwise:
		instead say "You can't go that way wearing a shirt.";

If you keep adding exceptions and the rule becomes too cumbersome for your taste, there are other mechanisms you can replace it with. Like setting up an object based rulebook for shirts; see the example that starts with the line “The flotation rules are an object based rulebook” in 19.9 of the docs. You could say “The dress code rules are an object based rulebook”, then create rules for each special shirt and the room it lets you into. But to begin with, what I’ve suggested will be fine.

-Wade

2 Likes

Ah, this is what I want. The problem with the initial approach is that I want the general shirt handling code to be in an extension, and the exceptions to be in the actual story using the extension. The rulebook approach offers the extensibility I need.

@Zed would doubtless say that you should create a various to various relation property here, relating shirts to rooms… :rofl:

Lab is a room. Garden is north. Potting Shed is east.

A shirt is a kind of wearable thing.
The player wears a shirt called the red shirt.
The player carries a shirt called the blue shirt.

A room has a relation of a shirt to a room called dress-restriction.

When play begins:
	now the dress-restriction of the Lab relates the red shirt to the Garden.
	
Definition: a room (called the target) is inaccessible:
	repeat with shrt running through worn shirts:
		 if the dress-restriction of the location relates shrt to the target, yes.
			
Check going to an inaccessible room:
	say "[We] [can't] go there dressed like that." instead.

To seem is a verb.	
First report going when the player wears a shirt:
	[only say something if there is at least one shirt restricting this movement]
	if a shirt relates to the room gone to by the dress-restriction of the room gone from:
		say "[The list of shirts worn by the player] [seem] to be okay.".
	
Test me with "n/remove red. wear blue/n/e".
1 Like

Ah yes. I did note you making this point in the first post, but I realise that what often happens when I’m giving a long answer is, I start writing a bit of an essay, realise it’s going the wrong way, erase it, start again. And by the time I’ve done all that I’ve lost track of details from the original query :slight_smile:

-Wade

TIL (related to this problem):

Check going when the player encloses something pluggable (called 
the plug) and something (called the socket) accepts the plug and 
the player does not enclose the socket:

The rules engine does not loop over all pluggable things enclosed by the player. It chooses one, and if that one doesn’t satisfy the rest of the conditions, well, too bad for you.

I am sometimes capable of considering something to be overkill. :smiley:

I’m guessing your intent is to check for the player trying to take a plugged-in thing out of the room without also enclosing the thing it’s plugged into. So maybe something like…

Lab is a room.
Parlor is north of lab.

The socket is a thing in the lab.
The player holds the plug.

Plugging relates one thing to one thing.
The verb to be plugged into means the plugging relation.

Definition: a thing is plugged in if it is plugged into something.

Definition: a thing is tethered:
  if the player does not enclose it, no;
  if it is not plugged in, no;
  let socket be the thing to which it relates by the plugging relation;
  if the player does not enclose the socket, yes;
  no;

Check going when the player encloses a tethered thing:
  instead say "nyet".

instead of jumping: now the plug is plugged into the socket.

test me with "n / s / jump / n"
1 Like

There is.

Check going north from the lab when the player wears the blue shirt:
	say "The blue shirt seems to be okay.";
	rule succeeds;
1 Like

That ends the entire action, not just the check rulebook.

1 Like

doh. Right. Works for carry out and report, but not the others (and, of course, ending the action and ending the report rules aren’t terribly distinct from each other).

For those interested in the minutiae of why, see this post:

tldr: the rules calling the Carry out and Report rulebooks follow those rulebooks, whereas the others abide by the rulebooks they call (and therefore there can be no simple way to prevent a rule that explicitly terminates Before, Instead, Check, or After from terminating the calling rulebook and thereby the whole action)*.

* except by modifying and replacing the Before stage rule, Instead stage rule etc. so that they too follow rather than abide by the relevant rulebook, which opens a whole new can of worms

From a higher level:

The Check rulebook is a bunch of possible reasons an action might fail (or at least stop-with-a-message). It’s supposed to be additive – that is, adding a new Check rule shouldn’t require you to think about all the others. Except for deciding what order they’re checked in.

It would be weird if there were a “skip the rest of the checks” feature. You’d wind up in a situation where you added a completely separate check (say, “Check going when the player is chained to the wall”) but it got skipped because you were wearing the right color shirt.

Creating a new rulebook is the right solution here.

(This kind of thing is a known problem with Inform’s “every turn” rulebook, which is also supposed to be additive, but you can skip some every-turn rules if you write “rule succeeds” in one of them. This inevitably leads to bugs.)

2 Likes

It looks like you’re going with an object based rulebook, which sounds right for your needs. For completeness, I would add that you can always add special exceptions in your game code to ignore a particular rule from an extension in certain cases.

Lab is a room. Garden is north of Lab.

A shirt is a kind of wearable thing.
The player carries the red shirt. The red shirt is a shirt.
The player wears the blue shirt. The blue shirt is a shirt.
	
Check going north from the lab when the player wears the blue shirt (this is the blue shiprt exception rule):
	say "The blue shirt seems to be okay.".
	
Check going somewhere when the player wears a shirt (this is the Shirt Extension must not wear shirts rule):
	say "You can't go there wearing that shirt." instead.

The Shirt Extension must not wear shirts rule does nothing if the player wears the blue shirt and the player is in the lab.

test me with "n / s / take off shirt / s / wear red / n".
1 Like

Yeah, I didn’t mention it- but I moved the code to report on successful movement-with-a-shirt to the Report stage, where it more naturally would sit. As a general rule, text printed in Check rules reports on actions that failed a check and were therefore halted at the Check stage. (A rule, like all coding rules, made to be broken if circumstances demand.)

Yeah, this can be pretty powerful. It’s something I only started getting used to or using recently, and I don’t always remember it’s available.

-Wade

1 Like