When things work, but don't work

Who would have thought that a thing, contained in a thing you are holding, isn’t held?

We have a room. In the room is an animal that wants to be fed. The player carries the perfect meal – a little bird in a little cage. The cage is a container. The command “feed” is understood as “give”. When the player issues the command “FEED BIRD TO ANIMAL” the response is “You aren’t holding the little bird.” If the player says “DROP BIRD” the response is “You haven’t got that.”

So, we check out the Standard Rules and find that “a thing is held if the player is holding it.” We also learn that “a thing is carried if the player is carrying it.” There’s no definition extending “held” or “carried” to things inside held or carried containers, so we write one:

Definition: a thing is held if the player is holding a container containing it.

This compiles without complaint. We get to the room and say “FEED BIRD TO ANIMAL” and the response remains “You aren’t holding the little bird.” Trying to drop the bird still results in “You haven’t got that.”

More research in the Standard Rules tells us that the DROP action checks “if the actor is carrying the noun”. So, we try:

Definition: a thing is carried if the player is carrying a container containing it.

This too compiles without complaint. But, alas, there is no change. Sill the bird isn’t held or carried (at least we’re told the bird isn’t held or carried).

More research reveals that the Standard Rules for the giving it to action check “if the actor is not the holder of the noun”. One would assume that if the the noun fits the definition of held with respect to the actor, the actor would naturally be the holder of the noun. Apparently not.

I have tried every variation on this theme I could think of to get Inform to recognize the contents of a held/carried container as held/carried, and in every case the story compiled without complaint but the responses remained the same.

Anyone know what I’m missing here?

2 Likes

I made a quick attempt at coding an example for this. Your mileage may vary :slightly_smiling_face:

My initial thought was that this might be caused by the fact that the bird is in a container. Kind of like trying to eat a cookie before you take it out of a container that you are holding. The example I attempted works in that the bird is first taken by the player and then it is given to the animal. The scene is a circus tent with a lion in a cage. The player is holding a bird in a cage and can give the bird to the lion. Here is the code I wrote:

A lion is a kind of animal.  Ferocious Frank is a lion.
A bird is a kind of animal.  Pretty Polly is a bird.
There is a Gilded Cage.  Pretty Polly is in the Gilded Cage.
Circus Tent is a room.  
The description of Circus is "This is a small circus tent."  
There is a iron cage in the Circus Tent.  
Ferocious Frank is in the iron cage.
When play begins:
	Now the player is carrying the Gilded Cage.
Instead of taking Pretty Polly:
	Say "You reach into the cage and deftly grab Polly.  The small bird wrestles against your hand and looks at you in terror chirping helplessly.[line break][line break]Taken.";
	Now the player is holding Pretty Polly.	
Instead of giving an animal to an animal:
	say "You toss [noun] to the [second noun] casually and sit down to watch the fun.  [second noun] bats [noun] around for a moment, as if playing a game, and then proceeds to feast on [noun].  All you hear is silence from [noun] and bones crunching as [second noun] enjoys its meal.";
	Now the noun is nowhere.

The game play looks like this:

Circus Tent
This is a small circus tent.

You can see an iron cage (in which is Ferocious Frank) here.

>i
You are carrying:
  a Gilded Cage
    Pretty Polly

>take polly
You reach into the cage and deftly grab Polly.  The small bird 
wrestles against your hand and looks at you in terror chirping 
helplessly.

Taken.

>i
You are carrying:
  Pretty Polly
  a Gilded Cage

>put polly in cage
(the Gilded Cage)
You put Pretty Polly into the Gilded Cage.

>i
You are carrying:
  a Gilded Cage
    Pretty Polly

>take frank
I don't suppose Ferocious Frank would care for that.

>feed polly to frank
(first taking Pretty Polly)
You reach into the cage and deftly grab Polly.  The small bird 
wrestles against your hand and looks at you in terror chirping 
helplessly.

Taken.

You toss Pretty Polly to the Ferocious Frank casually and sit down 
to watch the fun.  Ferocious Frank bats Pretty Polly around for a 
moment, as if playing a game, and then proceeds to feast on 
Pretty Polly.  All you hear is silence from Pretty Polly and bones 
crunching as Ferocious Frank enjoys its meal.

>i
You are carrying:
  a Gilded Cage

>l
Circus Tent
This is a small circus tent.

You can see an iron cage (in which is Ferocious Frank) here.

>
1 Like

The command ‘feed’ is already included under the action ‘giving it to’ which assumes that the noun is carried by the player (ie. in the player’s very hand). You can get around this by using an instead rule–

Definition:  a thing is a fooditem if it is edible.
Instead of giving a fooditem to an animal:
   if the noun is not enclosed by the player:
       say "But [the noun] is not on your person.";
   otherwise:
       now the noun is nowhere;
       say "(whatever reaction you want the animal to have)";
       (followed by whatever you want to happen as a result)

Instead completely supercedes the action, allowing you to rebuild it for that instance.
‘Enclosure’ is a concept in Inform7 that includes every kind of possession that the player can have–carrying, wearing, carrying something that carries something that…, etc.

I hope that this helps.

1 Like

Okay, I was wrong, ‘giving it to’ does not assume that you are carrying the noun. It will automatically try to take the noun if the player does not have it and the noun is touchable.
So I wonder if there is something in your code before this situation that has altered the player’s ability to take an object automatically while ‘giving’ it?

The Standard Rules already define ‘carried’ as something that is directly in the player’s hands (versus something that is inside of something that is carried by the player–which is defined as ‘enclosed by the player’)

Sorry for my error in the above post. This works without error—

Animals Galore is a room.

The block giving rule does nothing.

The player is here.

A box is carried by the player.  It is a container.  It is open.

A treat is in the box.  It is edible.

Polly is an animal.  Polly is here.

After giving something to Polly:
	say "Polly says Brack!"
1 Like

Could it actually be that your cage is closed and transparent??

Maybe you’ll have to open the cage, first.

I also hit a snag because I defined a bird as a kind of animal which Inform7 considers a person and the player cannot ‘take’ a person unless you override it with instead. You can see the behavior on the lion in my example above when you attempt to take it.

>take frank
[taking Ferocious Frank]
I don't suppose Ferocious Frank would care for that.
[taking Ferocious Frank - failed the can't take other people rule]

>
2 Likes

Or, you can simply not call the bird an animal. And carefully implement it so that it acts like one.

1 Like

There is some I6 code that allows things to be treated as persons, but handled as objects–

Include (- has animate -) when defining the bird.
1 Like

If I’m understanding the problem right, you could do something like this:

Definition: a thing is indirectly held if the player encloses it and it is not part of the player and it is not held by the player.

Before doing something other than taking or removing something from when the action requires a touchable noun and the noun is indirectly held: 
	try taking the noun.
1 Like

Okay. It appears with all the verbiage of my post I wasn’t clear in communicating my problem and missed some of the parameters.

  1. It’s certainly possible to avoid the problem with instead rules, but that then requires an instead rule for any situation in which the contents of a held/carried container should be considered held/carried.
  2. I did fail to mention that my code suspends the rule against taking people for the bird. (There are some other issues with the giving it to action and that I6 code, but that isn’t the main problem).
  3. The goal is for the story to recognize any thing inside something the player holds/carries as also held/carried.

JRB’s definition might do the trick. At least it is not a definition I tried. I just can’t test it right now.

1 Like

Well, this is a bit embarrassing. You see, when I was trying to figure this problem out I used RULES to see what rule caused the response. What I did not do is pay attention to what I was reading. It turns out the “You aren’t holding the little bird.” response doesn’t come from the “giving it to” action. It comes from a “feeding it to” action that closely resembles giving it to. The major difference is that the custom feeding action isn’t understood as “feed [something preferable held] to [someone]”.

Giving it to is defined with “something preferably held” which generates an implicit take. The problem is, the implicit take comes from the underlying I6 code, which takes place before any I7 rules. You can’t stop it with an instead or before rule. (And consequently, the check rule in the SR isn’t ever applied.)

Since my “feeding it to” action is basically a copy of “giving it to” with a different syntax, the first check rule for both actions is to check if you’re holding the noun. The condition is “if the actor is not the holder of the noun”. Unfortunately, being the holder of the noun is not the same as holding/carrying the noun. In my scenario above, the holder of the noun is the cage. It will always be the cage no matter how I define the held/carried relationship. In the world model the holder of the noun is determined by a bit of I6 code that essentially returns the immediate parent of the noun – the cage for the bird, the player for the cage, the location for the player.

So, the short answer is, the definitions I tried all worked. However, none of them did what needed to be done, which is to change the defined holder of the noun.

One approach is recursively opening containers until you get to the thing you want.

Before giving a thing to a person:	
	while the thing is in a closed container (called the layer):
		try silently opening the layer.

The above will work for both give and feed (which uses give).

Here it is working when you feed someone a treat in a wrapper in a box in a cage.’

The block giving rule does nothing.

Before giving a thing to a person:	
	while the thing is in a closed container (called the layer):
		try silently opening the layer.

The Grand Tub is a room. "The largest tub room in the Bathhouse."
No-Face is an animal. It is here.
The player is here.

A gilded cage is an openable closed transparent container. It is carried by the player.
A glass box is an openable closed transparent container. It is in the cage.
A shiny wrapper is an openable closed transparent container. It is in the box.
A tasty treat is in the wrapper. It is edible.

After giving something to No-Face:
	say "No-Face says 'More!'"

Test me with "i / feed the treat to No-Face / i"

Grand Tub
The largest tub room in the Bathhouse.
You can see No-Face here.

>[1] i
You are carrying:
a gilded cage (closed)
  a glass box (closed)
    a shiny wrapper (closed)
      a tasty treat

>[2] feed the treat to no-face
(first taking the tasty treat)
No-Face says “More!”

>[3] i
You are carrying:
a gilded cage (open)
  a glass box (open)
    a shiny wrapper (open but empty)

It worked!

1 Like

Jeremy, the problem was never that the container was closed. This works as far as silently opening closed containers to get at the treat, but the story still insists on taking the treat that is clearly in the player’s inventory. From a player’s perspective this doesn’t make sense.

As I said in my previous post, my original assumption was wrong. I assumed that because the Standard Rules define “held” and “carried”, adding to the definition of held/carried would solve my problem. There are two problems with this:

  1. The giving it to action is defined in such a way that the first check to see if the noun is something you carry takes place before any I7 rules are evaluated.
  2. The check isn’t affected by changes in the definition of held or carried. I can only assume this looks at “the holder of the noun” which is always the thing immediately enclosing the noun.

Unfortunately, changing “the holder of the noun” (defined in the SR as a call to an internal I6 function) causes many more problems than it solves.

If you want to silently take something out of the container when giving, one option is to just add one line for silent taking.

Before giving a thing (called the gift) to a person:	
	while the thing is in a closed container (called the layer):
		try silently opening the layer;
	try silently taking the gift.

>[1] i
You are carrying:
a gilded cage (closed)
  a glass box (closed)
    a shiny wrapper (closed)
      a tasty treat

>[2] feed the treat to no-face
No-Face says “More!”

You can account for nested containers using “enclosed by” instead of “held” which is immediate containment.

4 Likes

The nice thing about the above approach is that it respects locked and opaque containers – so you won’t be able to accidentally give or feed things that should be unreachable. However, if you want to short-circuit the entire checking process, then you can use “enclosed by” rather than “in” / “held by”. For example, just before giving, hoist the object up into the top-level inventory if it is enclosed by the player:

Before giving a thing (called the gift) to a person:
	if the gift is enclosed by the actor:
		now the gift is held by the actor.

>[2] feed the treat to no-face
No-Face says “More!”

Edit: (Thanks @HanonO, looks like we answered at the same time.)

1 Like

An example of using enclose in this way from Counterfeit Monkey is a change to “Show appointment card even if it is in backpack”:

1 Like

I guess I am a little confused about what really makes sense from the players perspective. If you were holding a container of anything, why would you expect to be able to perform an action with something inside the container that ultimately takes place outside the container without taking that thing out of the container?

So I gave another attempt at coding an example for this. This time I address the concern of needing an implicit taking of the item by adding a property to everything called pseudocontained. For objects that can be in containers but that need to be treated as an implicit component of the players inventory without needing an implicit take to use as part of an action, these kinds of items can be considered pseudocontained. This property could be set broadly for kinds of things or set dynamically when items are inserted into a container. The goal of avoiding the implicit take of an item from a container in the characters possession is achieved by avoiding putting the object into a container in the first place and then spoofing the inventory printout to make it look like the object is inside a container.

Note: I did not handle dropping pseudocontainers in the below code.

Everything can be pseudocontained or pseudonotcontained.
A thing is usually pseudonotcontained.
Colour is a kind of value. The colours are red, green, and blue.
A widget is a kind of thing.  A widget has a colour.  The colour of a widget is usually red.  Understand the colour property as describing a widget.  The printed name of a widget is usually "[colour] widget".  A widget has a container called insideof.
A box is a kind of container.  A box has a colour.  The colour of a box is usually red.  Understand the colour property as describing a box.  Before printing the name of a box: say "[colour] ".
A widget monster is a kind of animal.  Wild Wally is a widget monster.

Container Factory is a room.  The description of Container Factory is "This is a large factory that manufactures containers and various things that go inside containers.".  There is a red widget, blue widget, and green widget in the Container Factory.  There is a red box, blue box, and green box in the Container Factory.  Wild Wally is in the Container Factory.

Instead of inserting a widget (called W) into a container (called C):
	Now W is pseudocontained;
	Now the insideof of W is C;
	Say "You put the [W] into the [C]".
	
Instead of examining anything (called A) that is pseudocontained:
	say "The [A] is inside of the [insideof of A].";
	
Rule for printing the name of something (called A) that is pseudocontained while taking inventory: 
	say "[printed name of A] in the [insideof of A]";
	
Instead of giving anything (called A) to an animal (called W):
	say "You feed the [A] to [W].  The animal happily consumes the [A].";
	Now A is pseudonotcontained;
	Now A is nowhere.

Here is how the game play looks:

Container Factory
This is a large factory that manufactures containers and various 
things that go inside containers.

You can see Wild Wally, a red widget, a blue widget, a green 
widget, a red box (empty), a blue box (empty) and a green 
box (empty) here.

>take all
red widget: Taken.
blue widget: Taken.
green widget: Taken.
red box: Taken.
blue box: Taken.
green box: Taken.

>put red widget in green box
You put the red widget into the green box
>i
You are carrying:
  a green box
  a blue box
  a red box
  a green widget
  a blue widget
  a red widget in the green box

>feed red widget to wally
You feed the red widget to Wild Wally.  The animal happily 
consumes the red widget.

>i
You are carrying:
  a green box
  a blue box
  a red box
  a green widget
  a blue widget

>

Okay, let’s try this:

The Billiard Room is a room. "We are in the billiard room."
The pool table is a supporter in the billiard room. It is fixed in place.
The snooker ball is a thing on the pool table.
The box is a container carried by the player.
The book is a thing in the box.
The notebook is a thing in the box.

Now, you’re the player and you find yourself in the billiard room. The first thing you do is check your inventory:

>i
You are carrying:
  a box
    a book
    a notebook

Being silly, you try something silly:

>drop ball
You haven't got that.

Exactly what you expected. The ball isn’t in your inventory so you haven’t got it. Next you try something sensible:

>drop book
You haven't got that.

What?! It’s right there in my inventory. The game specifically told me I was carrying it, now it says I don’t have it? The reason is because the drop action (like many other actions) looks to see if I am the holder of the noun, which is not the same as holding (or carrying) the noun.

Much of the advice authors are given regarding game-play is to make things easy for the player. All I wanted to do was make it possible for a player to feed a little bird to an animal without having to first OPEN CAGE, TAKE BIRD, FEED BIRD TO ANIMAL. I was trying to do that without “breaking containment”. I could easily eliminate the “(first opening the cage)” statement by never closing the cage. I could not eliminate the “(first taking the little bird)” statement just by changing the definition of held or carried, which is where the title of the thread comes in.

2 Likes