Replacing procedural rules

@Ron

You bring up several useful technical points that everyone should always keep in mind. In the case of the example I used of the light-stick, though, that device already functions exactly as I intended–the player is meant to discover that the item is a device, and only after such occurs is an update of its on/off status appended to its description. In other words, it’s by intention that the item was designed to utilize the special “report examining the lightstick01 rule” in addition to (rather than instead of) the standard report examining rule. For example, an interaction with the item may (hopefully) play out like this (demonstrating why tacking an “instead” on to the end of the report rule would interfere with its intended behavior):

[code]>x cylinder
A transparent cylinder, apparently made of an ultra-hard polymer material. The cylinder is about eight inches long and filled with what seems to be a viscuous green liquid. A small seam runs around the middle of the cylinder.

get cylinder
Taken.

i
You are carrying:
a cylinder filled with viscuous green liquid[/code]
Although the item was culled from my scratchpad rather than an actual game, if it were included in a real project my intention at this point would be for the player to think (perhaps prodded by some additional clue found elsewhere) “Hmm… what’s this seam thing on there? Maybe I could twist the ends?”

[code]>twist cylinder
You switch the light stick on.

x cylinder
A light-stick made of a very hard yet transparent polymer material. Twisting the ends of the cylinder either causes the thick gel inside to emit a dull green light, or causes the device to stop emitting light if it is currently so doing.

The light stick is currently turned on, emitting a pale green glow.[/code]
On the other hand if the “report examining the lightstick01” rule was written as you suggested, the player would initially see:

[code]>x cylinder
A transparent cylinder, apparently made of an ultra-hard polymer material. The cylinder is about eight inches long and filled with what seems to be a viscuous green liquid. A small seam runs around the middle of the cylinder.

The cylinder filled with viscuous green liquid is currently turned off.[/code]
thereby giving away its true nature too soon.

In any case I only used that example in the context of furthering the discussion about replacing procedural rules, rather than as something I was struggling with (although we can discuss that code if you like, since you’re the OP in this thread and may take it in any direction you like).

I’ve admittedly forgotten a few things after not looking at I7 for several months. Although your points about tacking an “instead” on to a reporting rule are useful for everyone even though they didn’t apply to the particular example I raised, I seem to recall there is some potential pitfall associated with disrupting the turn sequence when “instead” is used in a report rule. At the moment, though, I can’t recall the nature of any such problem. Does anyone else know what I may be talking about on that issue?

@emshort

There’s no need to rush anything on my part, as I already fixed both extensions for my own use. I think the only change required for Deluxe Doors was to rewrite the paragraph:

Setting action variables: if the noun is a door which is a half-door of a door (called real target) begin; if real target is in the location of the actor, change the noun to real target; end if; if the second noun is a door which is a half-door of a door (called real target) begin; if real target is in the location of the actor, change the second noun to real target; end if.
as:

Setting action variables: if the noun is a door which is a half-door of a door (called real target) begin; if real target is in the location of the actor, now the noun is real target; end if; if the second noun is a door which is a half-door of a door (called real target) begin; if real target is in the location of the actor, now the second noun is real target; end if.
In regard to the more general issue of the I7 documentation, I think the issue isn’t that “instead” rules are introduced too early–rather the issue is that they’re the only sort of action rules discussed at all until one proceeds quite far into the documentation. Hence when I have answered questions in the past on this forum from inexperienced folks who are still struggling with the basics, I have usually found myself trying to explain why their posted examples (full of “instead” rules) may not be the best way of going about things. Typically any discussions of check/carry out/report rules elicit the response “Really? I’m only on chapter (3, 4, 5, etc) in the instructions, and I never heard about that stuff.”

Just personally, I encountered it in “Entrapment” (which was example 154 but probably isn’t anymore), in this rule:

Instead of embarrassing behavior: if the player is nervous, now the player is embarrassed; if the player is confident: say "Before you can act, you hear movement from the inner office. You freeze, not quite ready to be discovered in this situation. But no one comes out, and you begin to breathe more easily."; now the player is nervous instead; continue the action.

This was in section 10.2. So then I was wondering what that “…instead” syntax meant until I hit the explanation in chapter 18. But chapter 10, which is about scenes, clearly wouldn’t be the place to introduce it – a forward reference would be the most I could expect.

By the way, is there any difference between this and “stop the action,” other than that this fits on one line?

@matt w

The distinction is usually fairly literal–do we want to do something instead of something else, or quit if we can’t have our first choice?. There are many cases where the two can be used interchangeably, but there are other cases where one or the other is more appropriate. For example consider the following rules (culled from an old project), which use both:

[code][Filtering out the cryptic verbiage, this is a check for wearing corrective lenses]

Check an actor wearing an ocular (this is the broad-sweeping check ocular wearing rule):
if the noun is broke:
if the actor is the player or the player can see the actor:
say “[The noun] [is-are] badly damaged, and unlikely to be of any use.” instead;
otherwise:
stop the action;
if the noun is trinketish:
if the noun is monocle:
unless the actor embodies a zeye:
if the actor is the player or the player can see the actor:
say “[if the actor is the player]You don’t[otherwise][The actor] doesn’t[end if] have any eyes, and therefore won’t benefit in any way from wearing [the noun].” instead;
otherwise:
stop the action;
otherwise:
try the actor trinketwearing the noun on a random zeye embodied by the actor instead;
otherwise:
unless the actor embodies a zgeyes:
if the actor is the player or the player can see the actor:
say “[The noun] isn’t designed to fit [if the actor is the player]your[otherwise][the actor]'s[end if] anatomy.” instead;
otherwise:
stop the action;
otherwise:
try the actor trinketwearing the noun on a random zgeyes embodied by the actor instead.


[This is a check for plugging a corded appliance into an electrical source]

Check an actor connecting something to something (this is the general check precursors for connecting rule):
if the noun is the second noun:
if the actor is the player or the player can see the actor:
say “That’s irrational.” instead;
otherwise:
stop the action;
unless the actor is intelligent-life:
if the actor is the player:
say “You try to concentrate, but the task seems too hard and you are quickly distracted.” instead;
otherwise:
if the player can see the actor:
say “Such tasks are beyond [the actor]'s mental capacity.” instead;
otherwise:
stop the action;
if the actor is movement-restricted:
if the actor is the player:
say “You’re not currently able to move well enough to try that.” instead;
otherwise:
if the player can see the actor:
say “[The actor] can’t move well enough right now to try that.” instead;
otherwise:
stop the action;
if the noun is a backdrop:
unless the noun is backdropinteractive:
if the actor is the player or the player can see the actor:
say “That’s highly implausible.” instead;
otherwise:
stop the action;
if the second noun is a backdrop:
unless the second noun is backdropinteractive:
if the actor is the player or the player can see the actor:
say “That’s highly implausible.” instead;
otherwise:
stop the action.


[Here’s a check for whether food is too hot or too cold to eat]

Before an actor eating something (this is the temperature check for eating rule):
if the temperature of the noun is less than -50:
if the actor is the player:
say “[The noun] is too cold to even pick up; attempting to eat it at this time would injure you.” instead;
otherwise:
if the player can see the actor:
say “[The noun] is too cold for [the actor] to even handle at this time; eating it is out of the question.” instead;
otherwise:
stop the action;
otherwise if the temperature of the noun is greater than 149 and the temperature of the noun is less than 201:
if the actor is the player:
say “[The noun] is scalding hot, and trying to eat it at this time would certainly injure you.” instead;
otherwise:
if the player can see the actor:
say “[The noun] is scalding hot, and [the actor] is unable to safely eat it at this time.” instead;
otherwise:
stop the action;
otherwise if the temperature of the noun is greater than 200 and the temperature of the noun is less than 401:
if the actor is the player or the player can see the actor:
say “[The noun] is literally burning hot; attempting to eat or even handle it at this time would definitely result in a serious injury.” instead;
otherwise:
stop the action;
otherwise if the temperature of the noun is greater than 400:
if the actor is the player or the player can see the actor:
say “[The noun] is heated to a temperature of several hundred degrees; touching it at this time would certainly result in a serious injury, and ingesting it could result in an agonizing death.” instead;
otherwise:
stop the action.[/code]
Basically an “instead” usually redirects the current action to some other action, while a “stop the action” does exactly what its name implies. In the above examples, for the most part “instead” is used where we want to stop the current action and then do something else (namely, print some message). On the other hand “stop the action” is used above for actors behaving independently in a different room than the player-character; since the player-character can’t see these actors, the player isn’t given an update regarding their current activities (or failure to perform activities).

While this is only one sort of distinction between “instead” and “stop the action,” hopefully it will give you some idea of the ways in which they differ.

But would this behave any differently than the corresponding part of your code?

Check an actor wearing an ocular (this is the broad-sweeping check ocular wearing rule): if the noun is broke: if the actor is the player or the player can see the actor: say "[The noun] [is-are] badly damaged, and unlikely to be of any use."; stop the action;

Unless I’ve goofed up, “Stop the action” will get called whenever the noun is broke, but the “say” phrase will only get called when the actor is the player or the player can see the actor – is that right?

(Don’t mean to disparage the trailing “instead,” just trying to get clearer on how it works.)

@matt w

You’re not misunderstanding anything (maybe in fact I misunderstood your original question). In the narrow sense we’re talking about here, there isn’t much difference between adding an “instead” on to the end of a sentence and following a sentence up with “stop the action.” In this context “instead” is simpler if a clause in your rule only has one line, while “stop the action” allows for easier design if a clause considers several lines. As I mentioned before, the main difference is that you must use an “instead” if you wish to redirect to another action (“stop the action,” as implied, won’t handle that). In a case where the redirection is simply to print some text (as it often is in the examples I posted), preferring either “instead” or “stop the action” is a trivial choice.

Depending upon how heavily you rely on the default library messages (“X is unable to do that” and so forth), here’s either a mildly useful example or else a highly contrived example where “instead (at the end of a line)” and “stop the action” are truly used for different purposes:

[code]The Hallway is a room. The Office is a room.

A door called the office door is east of the hallway and west of the office. The office door is locked and not lockable. The description of the office door is “An ancient door with rusty hinges. It seems to be jammed.”

The matching key of the office door is the silver key. The the silver key is in the hallway.

Eddie is a man in the hallway.

Persuasion rule: persuasion succeeds.

Knocking is an action applying to one thing. Understand “knock on [something]” as knocking.

Report an actor knocking:
say “[if the actor is the player]You knock[otherwise][The actor] knocks[end if] on [the noun].”

Check someone opening a door (called blocker):
if the noun is locked:
let tool be the matching key of the blocker;
if the person asked has tool:
try the person asked unlocking blocker with tool;
unless blocker is unlocked:
stop the action;
otherwise:
try the actor knocking the noun instead.

Test door with “eddie, open door / eddie, get key / eddie, open door / x door”.[/code]
I’m sure you get this already, but for the benefit of any others who may be having trouble following along we’re definitely not talking at all about “instead rules” in the sense of:

Instead of xxxx: do yyyy.
written by themselves, which of course have many dramatic effects on the turn sequence.

I don’t think there’s any functional difference. The phrase “stop the action” (from the Standard Rules) and this form of “instead” (which seems to be internal to the compiler) both translate to “rtrue” in I6.

Actually, “try singing; stop the action” works just like “try singing instead”.

Ah, this is very helpful: the difference is that “stop the action” can be used without an accompanying effect, as the sole result of a conditional or something, and “instead” needs to be attached to something. Which makes sense given the syntax.

I was fooling around some more, trying out 6E59 by going through the documentation and writing some sample code as I move along in an effort to determine what syntax has changed. I’m trying to write code at the level of the material found only up to the point where I’m at in the documentation (currently chapter 6), but it’s hard to limit things that way and I’m not really succeeding on that point. In any case I found myself (unwittingly) making an example that seems relevant to the discussion we’ve been having here about replacing procedural rules. Perhaps the example may also be generally useful to anyone browsing through the various posts of the forum.

The general idea of the test project is that the player-character has been abducted by <aliens, a baleful government agency, the girl scouts, whatever> and wakes up in a strange complex where, it would seem, his intelligence and reasoning skills are being tested by a serious of (very) simple puzzles that must be solved before moving further into the complex (and presumably toward an eventual door with an “exit” sign above it).

The example puzzle discussed here involved several cases where I may formerly have used a procedural rule, but now declined to do so since I’ve got the “Use no deprecated features” option active. The example involves a hallway with a door at one end; a mathematical notation is written on the door. At the other end of the hallway is a room with a numeric keypad. The player must enter the solution to the (very simple) equation into the keypad to remotely open the door. Sorry for the rough edges (deviating from the provided “test stuff” will quickly break things) and disorganized presentation of code, but after all it’s only an example in a test project (intended for my own use) rather than something from a polished game:

[code]Chapter 8 - Dark Hallway

There is a room called the Hallway Junction. [Description omitted as too confusing to post here]

There is a room called the Eastern Lab.

The door04 is a door. The door04 is north of the Hallway Junction and south of the Eastern Lab. The description of the door04 is “A doorway set in the wall at the northern end of the corridor. The door itself [if closed ]appears to be [otherwise]is[end if] a mechanical sliding hatch that retracts sideways into the wall when open. [unless open]Something is written on the surface of the door in dark red letters[otherwise]The door is currently open.[end if].” The door04 is privately-named. The printed name of the door04 is “sliding door”. Understand “door” or “sliding door” or “hatch” as the door04. The door04 is locked and not lockable. The door04 is scenery.

Some password01 are scenery in the Hallway Junction. The password01 are privately-named. The printed name of the password01 is “red numbers”. Understand “numbers” or “red numbers” or “writing” or “painted numbers” as the password01. The description of the password01 is “Written or painted on the door in large characters with some sort of dark red ink or dye is the following:[paragraph break]62 + 43[command clarification break]”.

Understand the command “read” as something new.

Reading is an action applying to one thing. Understand “read [something]” as reading.

Instead of reading the door04:
if the door04 is closed:
try examining the password01;
otherwise:
say “The door has retracted into the wall.”.

Instead of reading the password01:
try examining the password01.

Chapter 9 - Keypad Room

A room called the Device Room is south of the Hallway Junction. [The Device Room is a dark room.] The description of the Device Room is “A dark, square-shaped room, about twenty feet wide. The walls are made from a dense white material the with the consistency of very thick, hard rubber that nonetheless reflects light as though it were polished metal. A small device of some sort is built into the eastern wall about three feet off the floor.”

A keypad01 is in the Device Room. The keypad01 is scenery. The keypad01 is privately-named. The printed name of the keypad01 is “key pad”. Understand “small device” or “device” or “keypad” or “key pad” as the keypad01. The description of the keypad01 is “A numeric keypad, made of the same odd white material found throughout the area, is built into the eastern wall of this room. The keypad consists of eleven buttons as well as a small display of some sort set over the keys. This display currently reads: [kp01text of the keypad01].” The keypad01 has some indexed text called the kp01text.

[I’ll come back to fix that display for cases when the text string is empty at a later point in writing, likely using a simple say statement]

Report examining the keypad01 for the first time:
say “All but one of the buttons of the keypad are labelled with a numeral; the remaining button is labelled with the word ‘Send.’ The buttons are laid out in the following configuration:[paragraph break][fixed letter spacing]1 2 3[line break]4 5 6[line break]7 8 9[line break]0 Send[variable letter spacing][paragraph break]”

Instead of reading the keypad01:
try examining the noun.

An alphanumkey is a kind of thing. An alphanumkey has some text called the aklabel. The aklabel of an alphanumkey is usually “”. The description of an alphanumkey is usually “A button on a numeric keypad. This key is labelled: [aklabel of the item described].” Understand “key” or “button” as an alphanumkey.

Instead of reading an alphanumkey:
try examining the noun.

An alphanumkey called a one key is part of the keypad01. The aklabel of the one key is “1”.
An alphanumkey called a two key is part of the keypad01. The aklabel of the two key is “2”.
An alphanumkey called a three key is part of the keypad01. The aklabel of the three key is “3”.
An alphanumkey called a four key is part of the keypad01. The aklabel of the four key is “4”.
An alphanumkey called a five key is part of the keypad01. The aklabel of the five key is “5”.
An alphanumkey called a six key is part of the keypad01. The aklabel of the six key is “6”.
An alphanumkey called a seven key is part of the keypad01. The aklabel of the seven key is “7”.
An alphanumkey called an eight key is part of the keypad01. The aklabel of the eight key is “8”.
An alphanumkey called a nine key is part of the keypad01. The aklabel of the nine key is “9”.
An alphanumkey called a zero key is part of the keypad01. The aklabel of the zero key is “0”.
An alphanumkey called a send key is part of the keypad01. The aklabel of the send key is “Send”.

Carry out pushing the send key:
if kp01text of the keypad01 exactly matches the text “105”:
now the door04 is open;
now the door04 is not openable;
remove the password01 from play;
otherwise:
now the kp01text of the keypad01 is “”.

Report pushing the send key:
if the kp01text of the keypad01 exactly matches the text “105”:
say “You press the ‘Send’ key. Off to the north, you briefly hear a soft metallic clank.” instead.

[It was particularly hard to discern the syntax necessary for the next rule, since the “change x to y” formulation has been deprecated and “now” seems to be very sensitive when working with texts]

Carry out pushing an alphanumkey which is incorporated by the keypad01:
unless the noun is the send key:
let mendru be indexed text;
let mendru be “[kp01text of the keypad01][aklabel of the noun]”;
now the kp01text of the keypad01 is mendru.

Report pushing an alphanumkey which is incorporated by the keypad01:
unless the noun is the send key:
say “You press [the noun], causing a ‘[the aklabel of the noun]’ to appear on the small display above the keypad.” instead.

Inputting it into is an action applying to one topic and one thing. Understand “input [text] on [something]” as inputting it into. Understand “input [text] into [something]” as inputting it into. Understand “type [text] on [something]” as inputting it into. Understand “type [text] into [something]” as inputting it into. Understand “enter [text] on [something]” as inputting it into. Understand “enter [text] into [something]” as inputting it into.

A thing can be input-compatible. A thing is usually not input-compatible. The keypad01 is input-compatible.

Check inputting it into:
unless the second noun is input-compatible:
say “That doesn’t make sense in this context.” instead.

Check inputting into the keypad01:
let keycheck be indexed text;
let keycheck be “[the topic understood]”;
unless keycheck exactly matches the regular expression “send”, case insensitively:
if keycheck matches the regular expression “\D”:
say “Apart from the ‘Send’ button, only the numbers 1-9 and 0 are available on the keypad,” instead;
otherwise:
try pushing the send key instead.

[It was particularly hard to discern the syntax necessary for the next rule, since the “change x to y” formulation has been deprecated and “now” seems to be very sensitive when working with texts]

Carry out inputting into the keypad01:
let weldru be indexed text;
let weldru be “[kp01text of the keypad01][the topic understood]”;
now the kp01text of the keypad01 is weldru.

Report inputting into the keypad01:
say “You enter [the topic understood] using the keypad. The display above the buttons now reads: [the kp01text of the keypad01].”

Test stuff with “x door / read door / s / press one button / type 05 on keypad / press send key”.[/code]
The things that stood out in regard to the discussion here were:

a) In the past, I might have made exceptions to the Standard “report an actor pushing” rule for the keypad buttons; however tacking on an “instead” to the end of each unique report pushing rule was easy enough and seemed to take care of things in this case;

b) In the past, I would have designed the custom “inputting” action with a blocking check rule, such as

Check inputting it into (this is the general block useless inputting rule):
say “That doesn’t make any sense in this context.” instead.

and then made individual exceptions for kinds or things to which I wanted the inputting action to apply. I briefly considered applying emshort’s “activities” approach discussed earlier in the thread, but decided it wouldn’t be a true test of efficiency as “inputting” is only relevant for one device at this point. Writing one line giving the keypad an “input-compatible” property that all other things (at this point) lack and considering this property in the general blocking rule seemed to be an effective solution in this case.

A minor related point is that while it may seem like an aesthetically attractive idea not to go on a wild property-creating spree, something I learned while trying to work around some bugs in 5Z71 is that there’s no practical reason to be stingy with either/or properties. I had (by the standards of an average IF comp game) a shockingly large project where every single item (of which there were several thousand in existence due to heavy use of automatic generation) in the game world literally had scores of (mostly unused and inapplicable) either/or properties. I never saw any sort of performance degradation whatsoever related to such an approach (and I usually work on an old computer less powerful than a top-of-the-line cellphone). Thus using an either/or property as a foundation for simple blocking rules would seem to be yet another way to avoid using procedural exceptions.