Can't understand 'Before' response (newbie)

My player has a coin with which to pay NPC Amy. I don’t want to pay Amy twice so I wrote:

Before giving the coin to Amy:
	if the player is not carrying the coin:
		say "can't";
	otherwise:
		move the coin to Amy;
		say "Amy says ta".

In play, I get this and I don’t understand why:

>give the coin to amy
Amy says ta
(first taking the coin)
That seems to belong to Amy.

I expected that once Amy had said ‘ta’ the action would finish, but it seems to be trying again. Could someone kindly explain why?

Just to be clear, I’m not asking how to do this; I have a solution (though a shorter one would be welcomed). My solution is:

Before giving the coin to Amy: 
	unless the player carries the coin:
		say "You already paid Amy!";
		stop the action.
		
Instead of giving the coin to Amy: 
	move the coin to Amy;
	say "Amy smiles and thanks you".
	

My question is, why did my first attempt produce an inexplicable result?

Before rules are checked first (in other words, before the real action is carried out) and the rule sequence continues after you run one, by default, unless you stop it manually with something like 'rule fails / stop the action / instead do BLAH '.

So in answer to your question – you’re running the inventory check on the player with the before rule. The game then either says ‘can’t’, or it actually usurps the job of the GIVING action itself, putting the coin on Amy, and has Amy say ‘ta.’ And either way… the action of GIVE COIN TO AMY continues to run after your Before rule, and goes through all the built-in mechanisms in the GIVING action. So now it checks if the player has it, sees they don’t (if your before rule already handed it to Amy), tries to pick it up (because it’s visible on Amy?), and is blocked by default, because default behaviour is not to allow this kind of theft.

Basically, GIVE COIN TO AMY is an action that will mostly be handled by Inform’s built in mechanisms. You don’t have to manually move the coin to Amy - the giving action does that.

What is not default is Amy saying ‘Ta.’

The usual way to handle a special case like this is with an After rule. A Report rule is for giving the default response of the action, which in this case would be something like ‘You give the coin to Amy.’ But you want her to say ‘Ta’ instead, or as well.

So all you need for the entire thing to work is this:

After giving coin to Amy:
    say "You hand the coin to Amy. She says, 'ta.'";

The before rule is not needed. Manually programming the coin to go to Amy is not needed. It’s not a great use case for an Instead rule either, though some people would do it that way.

Here’s a good post summarising the rulebook processing order and behaviour:

-Wade

5 Likes

Before rules don’t stop the action by default, so it continued on and tried to do an implicit take of the coin. Putting the “Stop the action” or adding instead after the says would cause the action to stop, which is why your second version works.

Note that instead rules do stop the action by default (instead of doing the action, do …) and so do after rules.

Are you trying to stop the implicit take? The easiest way to do that is to remove the coin from play, that way it won’t be in Amy’s hands all the time.

"Payments"

Laboratory is a room.

A coin is a thing. The coin is carried by the player.

Amy is a person. Amy is in the Laboratory.

The block giving rule does nothing when noun is the coin and second noun is Amy.

Report giving the coin to Amy:
	say "Amy takes the coin graciously and thanks you, 'Ta mate.' She secretes it about her person somewhere.";
	Remove coin from play;
	Rule succeeds.

Test me with "give coin to Amy/again".

Edit: Damn, @severedhand was not only quicker, he was clearer too.

1 Like

@Stephen
Thanks all the same - and I like your Amy, she has style.

Thomas

After giving coin to Amy: say “You hand the coin to Amy. She says, ‘ta.’”;

Thanks severedhand. But your rule, though very compact, doesn’t quite work. I now have:```

After giving coin to Amy:
say “You hand the coin to Amy. She says, ‘ta.’”;


But the response is:

give the coin to amy

Amy doesn’t seem interested.


Looking at the entry for ‘give’ in the docs, I I found this: “... giving something to somebody is not like putting something on a shelf: the recipient has to agree.” Does Amy’s lack of interest mean she didn’t agree? If so, how do I persuade her?

Or have I quite misunderstood?

That’s where you need the line below, to stop blocking giving, that’ll make Amy accept the item.

The block giving rule does nothing when noun is the coin and second noun is Amy.
2 Likes

Sorry, I forgot that by default, give attempts to NPCs are ultimately blocked !

If you open up the installed extension ‘Standard Rules’ and find the ‘giving it to’ section, you’ll find this:

"The Standard Rules implement this action fully - if it reaches the carry
out and report rulebooks, then the item is indeed transferred to the
recipient, and this is properly reported. But giving something to
somebody is not like putting something on a shelf: the recipient has
to agree. The final check rule, the 'block giving rule', assumes that
the recipient does not consent - so the gift fails to happen. The way
to make the giving action use its abilities fully is to replace the
block giving rule with a rule which makes a more sophisticated decision
about who will accept what from whom, and only blocks some attempts,
letting others run on into the carry out and report rules."

and then a series of Check rules the action has to make it through to succeed.

You’ll see one of them is ‘Check an actor giving something to (this is the block giving rule):’. That stops all give attempts. And @Stephen has shown how you can deactivate that rule. He’s deactivated it for your particular circumstances (the coin, to amy). You could also deactivate it in general for your game if you had wanted, with this line:

The block giving rule does nothing.

-Wade

1 Like

Oh well, thanks for trying. I now understand why my first attempts failed, and my existing pair of rules, though maybe long-winded, do the job, so I’m a happy bunny.

It’s not that they’re long-winded, but they’re not really the right tools for the job. I think Stephen or I have tried to show you the theory a bit more.

If you use an approach like this (a Before rule that’s kind of pointless, and an Instead rule actually performing the job it’s instead of) you will tend to run into more problems down the line. In Inform in general, or just in more stuff involving Amy and coins and giving in this game.

-Wade

3 Likes

@severedhand OK, I’m warned! I’ll try to avoid simplistic solutions. But I’m afraid your proposed solution doesn’t fully meet my needs.

First thing is, I want Amy to end up with the coin, rather than removing the coin from play. That way I can later have different outcomes depending whether she has the coin, rather than someone else.

Second thing is, if I try giving the coin twice, the second time Inform says “You can’t see any such thing” rather than “you already paid her”.

Dear me. There’s more to Inform than I quite bargained for.

Sorry, my Instead advice was potentially a bit harsh. It’s kind of a pain to have to know to turn off or overcome a rule (the block giving rule) rather than write an Instead that goes around it. But on the other hand, I’ve seen other people who were new here soon after say the main thing they wish they knew early on was not to just go crazy with the Instead rules :slight_smile:

Now, between what Steven and I said, Amy should be receiving the coin as a result of a successful give action. And you shouldn’t be getting ‘You can’t see any such thing’ for trying to give again, UNLESS you’re not in the same room as Amy. I’ll share a demo below. This leaves the last bit you wanted to attend to to deal with – having the game remember we gave it to her.

In the default situation, when you try to give her the coin (that she already has) Inform starts with the assumptions that you can’t give what you don’t have, and can’t even try to give what you can’t see. But by default, the player can see what other people are carrying, scope-wise. There’s no sign of this if you type X AMY (which is what made you think she hasn’t got it), but trust me, she got it! After giving her the coin, type the test command SHOWME AMY. You’ll see the coin in her inventory tree.

So now she’s got it, attempts to give it to her again do all they can to try to make this happen – they first try to take the coin they can see, which she’s holding. This fails because this kind of stealing is blocked automatically.

This is actually where a Before rule might be good… we want to kill the attempt to take the coin from Amy in these circumstances before it even begins. In these circumstances, an Instead rule happens too late, trying to intervene after Inform’s decided we want to try taking the coin off her. That’s not something I knew off the top of my head, I just found it out when I tried.

So here’s a demo that puts all this together. If you copy-paste it to a project then run it and type TEST ME, it will try the test commands in order. The Before rule does the job for the moment, but if you had more coins around, or more people to give them to, it might need more clarification. It works great for now because there’s only one coin.

lab is a room.

Amy is a woman in lab.

player holds coin.

The block giving rule does nothing when noun is the coin and second noun is Amy.

After giving coin to Amy:
	say "Amy says, 'Ta.'";

Before giving coin to Amy when Amy carries coin:
	say "I already gave it to her.";
	rule fails;[In a Before rule, we have to manually stop an action from going any further]

Test me with "give coin to amy/x amy/showme amy/give coin to amy/get coin".

-Wade

3 Likes

I don’t want to pile on, but there’s one more thing that hasn’t quite been explicitly explained yet: Unless the player starts out holding the coin and is not allowed to drop the coin, it is possible for the condition of “trying to pay Amy when not carrying the coin” to come about in situations where the player actually has not paid her yet, which is why the ideal solution involves checking whether she has the coin instead.

1 Like

The most efficient way to troubleshoot these situations is the ACTIONS command which only works in the IDE or a “release for testing” compile. This gives you insight to the action-firing process and what order it happens in and is usually where you can determine what rules are conflicting or if you’re encountering an action synonym you’re unaware of.

Laboratory

You can see Amy here.

>actions

Actions listing on.

>give coin to Amy

[giving the coin to Amy]

Amy says ta

(first taking the coin)

[(1) taking the coin - silently]

That seems to belong to Amy.

[(1) taking the coin - silently - failed the can't take people's possessions rule]

[giving the coin to Amy - failed the carrying requirements rule]

Similarly RULES can be helpful as well, but often you’ll need to dig through because you’ll get a list of every Standard Rule being considered even if it doesn’t actually do anything.

This is why it’s often helpful to name your new rules; otherwise they are easy to miss in the stack.

Before giving the coin to Amy (this is the Amy only knows the word ta rule):

Otherwise this rule would be called “the before giving the coin to Amy” rule which makes it a little harder to find in the list.

Laboratory

You can see Amy here.

>rules

Rules tracing now switched on. Type "rules off" to switch it off again, or "rules all" to include even rules which do not apply.

>give coin to Amy

[Rule "declare everything initially unmentioned rule" applies.]

[Rule "announce items from multiple object lists rule" applies.]

[Rule "set pronouns from items from multiple object lists rule" applies.]

[Rule "before stage rule" applies.]

[Rule "Amy only knows the word ta rule" applies.]

Amy says ta

(first taking the coin)

[Rule "announce items from multiple object lists rule" applies.]

[Rule "set pronouns from items from multiple object lists rule" applies.]

[Rule "before stage rule" applies.]

[Rule "instead stage rule" applies.]

[Rule "investigate player's awareness before action rule" applies.]

[Rule "player aware of his own actions rule" applies.]

[Rule "check stage rule" applies.]

[Rule "can't take yourself rule" applies.]

[Rule "can't take other people rule" applies.]

[Rule "can't take component parts rule" applies.]

[Rule "can't take people's possessions rule" applies.]

That seems to belong to Amy.

[Rule "A first turn sequence rule" applies.]

[Rule "every turn stage rule" applies.]

[Rule "A last turn sequence rule" applies.]

[Rule "notify score changes rule" applies.]

As everyone has expressed, ideally you want to avoid doing the work of the parser, which is why AFTER rules are the best here since you’re just wanting to print a custom message instead of the default report and the Standard Rules will handle world modeling/moving things around. (And also why you don’t want to usurp the parser with complicated INSTEAD rules that make exception to the Standard Rules which are intended to keep track of where everything is and what’s happening and whether actions are possible.)

It’s best to think of BEFORE like AFTER - you either want to print a message before the action even starts, or you want to stop anything even being tried - such as if your player hasn’t yet learned how to cast spells, you don’t want rule-checking and preparations to cast spells to even happen.

Before casting:
     if the player does not carry the spell book:
          say "Dude, magic isn't even real." instead.

“Before” rules genuinely precede checking of any kind. They also differ from instead rules in that they do not automatically stop the action in its tracks. Rather, they are provided as an opportunity to ensure that something else is done first. For example:

Before taking the napkin, say "(first unfolding its delicate origami swan)".

whence

GET NAPKIN
(first unfolding its delicate origami swan)
Taken.

Or for convenience:

Before doing anything to the computer:
     if the computer is not switched on:
          try switching on the computer.
4 Likes

Good point. Player does start put holding the coin but I haven’t thought about dropping it. Hmmm! Thanks.

1 Like

Thanks HanonO, I didn’t know about actions or rules. That will be very helpful.

Bit of a learning curve to inform 7, isn’t there! But it’s obviously a helpful community.

3 Likes

Yep, that seems to fit the bill. Clear and succinct, and does the job. Thanks!

So the author has to know – or has to have explained to him, as you have – that (1) there’s a rule that prevents giving things to NPCs, (2) that said rule can be blocked, and (3) the sequence of events when an action rule is triggered. OK. I think we’re there; and thanks to everyone who’s contributed.

By way of context, I’m co-writing a book about notations, notations of many different sorts (at least, ones that aren’t too demanding), and one section talks about IF; I chose Twine and Ink as the other two IF notations, and set up the same very short story in each one, to see what emerged. So much more to think about in Inform! But more interesting.

1 Like

To my gratification, Inform can cope:

lab
You can see Amy here.

>drop coin
Dropped.

>give coin to Amy
(first taking coin)
Amy says, "Ta."

So it seems I don’t need a special rule. But thanks for the heads-up.

2 Likes

I didn’t say you needed a “special rule,” I said ideally the one rule that you have should check whether Amy is holding the coin and not whether the player is holding it, because it’s preferable to have the rule checking the thing you actually want to check, instead of using a related thing as a proxy. The latter opens up the possibility for the related condition to be fulfilled some other way, without the thing you actually want to check being true, and it’s generally best practice to close that possibility off if you can do so easily. Which in this case, you can: checking whether Amy is carrying the coin is not in any way more complicated than checking if the player is carrying it.

If the actual game, unlike the test code, has more than one room and the player can go to another room before they pay Amy, then the possibility to get the “already paid Amy” response when you have not in fact already paid Amy is still there, because if the coin is not in scope the implicit actions won’t help. If Amy is in the starting room and you cannot leave until you have paid her, then checking whether the player is carrying the coin will work okay as long as nothing changes about that scenario, but there’s still no reason not to check the thing you actually want to check intead.

Edit:

Basically, what I’m suggesting is a change to just a few words of a single line of your code:

Before giving the coin to Amy: 
	if Amy carries the coin:
		say "You already paid Amy!";
		stop the action.
2 Likes

I see. That seems very similar to Wade’s code:

lab is a room.

Amy is a woman in lab.

player holds coin.

The block giving rule does nothing when noun is the coin and second noun is Amy.

After giving coin to Amy:
	say "Amy says, 'Ta.'";

Before giving coin to Amy when Amy carries coin:
	say "I already gave it to her.";
	rule fails;[In a Before rule, we have to manually stop an action from going any further]

Test me with "give coin to amy/x amy/showme amy/give coin to amy/get coin".

Although maybe I haven’t grasped the difference between your suggestion and Wade’s.

The actual story is tiny: two rooms. Player starts in A, with coin; goes to B, a shop; takes a postcard, gives coin to shopkeeper, returns to room A. If the player drops the coin in A, before going to B, Inform doesn’t let the player give the coin to the shopkeeper - “You can’t see any such thing”. If you want to, you can try it: https://tgworkshop.me.uk/bookdemos/interactivefiction/inform7/
I haven’t updated that version with any of the community’s excellent suggestions, but it will clarify the context.

Thomas

2 Likes

Oh, no, it’s not meaningfully different at all, I just had the impression you wanted to change your code as minimally as possible. If you’re using Wade’s code now, then mine has no additional benefit. Sorry!