Understanding by properties and [things inside]

I was trying to show off how well the Inform parser worked, and… it didn’t work so well.

Kitchen is a room.

A material is a kind of value. The materials are wicker, iron, and plastic.
A basket is a kind of container. A basket has a material.  Understand the material property as describing a basket. For printing the name of a basket: say "[material] basket".

A wicker basket called a basket1 is in the kitchen. An iron basket called a basket2 is in the kitchen.

A color is a kind of value. The colors are yellow, red, orange, brown, blue, green, and purple. 

A fruit is a kind of thing. A fruit has a color. 
Understand the color property as describing a fruit. Understand "fruit" as a fruit.

A banana is a yellow fruit in basket1. A lemon is a yellow fruit in basket2. An apple is a red fruit in basket1. A cherry is a red fruit in basket2.


You can see a wicker basket (in which are a banana and an apple) and an iron basket (in which are a lemon and a cherry) here.

>take yellow fruit from wicker basket
You can’t see any such thing.

>take all fruit from wicker basket
You can’t see any such thing.

>take fruit from wicker basket
Which do you mean, the banana or the apple?

>take yellow fruit
Which do you mean, the banana or the lemon?

So “take yellow fruit” and “take fruit from wicker basket” are working separately but not together. Any idea why this is? One thing is that the “[things inside]” token that is used in

Understand "take [things inside] from [something]" as removing it from.

may be a little difficult (a surprising amount of the parser code is devoted to handling this token and [other things].)

EDIT: Maybe this is related to this bug about [things inside] and disambiguation?

Reading the linked issue, it sounds like what could be happening is that it’s separately parsing yellow fruit and wicker basket and finding that yellow fruit matches something that is is scope but isn’t inside the wicker basket, causing a rejection.

However when trying it with trace enabled, as far as I can tell it is successfully matching the wicker basket, then only looking at the items inside the wicker basket, successfully matches only the banana, and then for no readily apparent reason fails the parse anyway without any sign of error that I can see.

So I’m stumped. But then I’m not an expert by any means. :slight_smile:

1 Like

FWIW, the I6 parser appears to be failing right at the top of the block with this comment, with wn == num_words == 6, after reaching ENDIT_TOKEN.

                ! If the player has entered enough already but there's still
                ! text to wade through: store the pattern away so as to be able to produce
                ! a decent error message if this turns out to be the best we ever manage,
                ! and in the mean time give up on this line

I think this means it thinks there are extra words on the line that it hasn’t parsed yet, and that since the first of those words isn’t a then or comma, it’s rejecting the command. But I don’t know enough about the parser’s inner workings to speculate on why it would think that.

Interestingly if I hack that specific check (wn <= num_words) such that it will not trigger for this particular input, then the action proceeds as expected and the player successfully takes only the banana. But this does seem to be something peculiar to that particular command; if I generally disable that check (or eg. try changing it to wn < num_words) then it completely breaks the parsing of every other command.

1 Like

Ok, I have a better theory now.

take yellow fruit from wicker works as expected as well, without any parser hacks.

I think what’s going wrong is the order of parsing – normally Inform expects that it’s parsing left to right. multiinside is one of the things that flips that, and it parses the second noun first, then goes back to parse the noun in that context.

My best guess is that it then either resets the ‘current parsing word’ as if it successfully parsed the first word of the second noun, or minimally reparses only the first word of the second noun – which works as expected only if the second noun actually consisted of only one word, but breaks otherwise.

So it’s forgetting to count the final basket as part of the second noun and thinking that the command wasn’t properly parsed.

Or apparently the ENDIT_TOKEN appears at word 6 during parser letter G in both take yellow fruit from wicker basket and take yellow fruit from wicker, despite the num_words being different. Perhaps after the first parse of the second noun it’s stomping the second word out because the first was sufficient by itself (or perhaps replacing it by the already-parsed object somehow so that it doesn’t have to do a full reparse), but forgetting to update the word count?

Actually, it’s probably a more fundamental (and perhaps simpler) issue than that.

>get wicker basket
I only understood you as far as wanting to get the wicker basket.

>get wicker

So I think the problem is not even related to [things inside], it’s just that since wicker is considered a sufficient non-ambiguous name for the wicker basket it’s getting confused by the basket following it.

Which is interesting, since I don’t think it normally has that issue with objects that have multiple words in their understand sequence. In particular, if I replace the basket definitions with the following:

A container called basket1 is in the kitchen.  A container called basket2 is in the kitchen.
Understand "wicker" and "basket" as basket1.  Understand "iron" and "basket" as basket2.

then get wicker basket works as expected.

1 Like

Ok, apparently I’m an idiot. After all that long spiel, I spotted your problem :slight_smile:

You’re missing one very important line:

Understand "basket" as a basket.

Without that, the word basket is meaningless to the parser :grin:


Ah, and it can be solved by adding this:

Understand "basket" as a basket.

which as you can see I had already run across with the fruit; I added a similar line for that because “yellow fruit” wasn’t working without it.

In fact, if I don’t add that, then “x basket” doesn’t work. So, um, obvious oversight on my part! Should’ve tried more test cases.

EDIT: Typed as you were posting!

Yeah, I only noticed it myself by stepping back and trying to get basket, expecting an ambiguity clarification but getting the same can't see any such thing error.

I think I overlooked it because you were declaring that “a wicker basket” exists, which would normally cause those words to be understood as well, except that because “basket” is a kind it does something different.

Right, because the individual baskets are called basket1 and basket2. And that happened because I started out just declaring “One wicker basket and one iron basket are in the kitchen,” but then I couldn’t figure out a way to specify which fruits started in which baskets, so I gave them internal names, and never got around to understanding “basket.”

Oh! and I tried “take the fruit from the wicker basket” and got what I was expecting, “Which do you mean, the banana or the apple?” And then I didn’t try typing “banana” which would’ve revealed that “basket” wasn’t being understood at all. I’m not entirely sure how the parser manages to understand that it ought to ask only about the things in the wicker when “basket” is redundant, which is to say I haven’t tried to figure it out at all. Though as that bug report I linked above shows, sometimes [things inside] and disambiguation don’t mix.

In case you’re curious, the context in which I was trying to show off the parser is here (scroll up for the discussion).

If needed for the future, I believe you can do this:

There is a wicker basket in the kitchen. In it is a banana.
1 Like

Though to keep all the properties and kinds intact, you’d probably need to separate things a bit:

A banana is a yellow fruit.  A lemon is a yellow fruit.
An apple is a red fruit.  A cherry is a red fruit.

There is a wicker basket in the kitchen.  In it are the banana and the apple.
There is an iron basket in the kitchen.  In it are the lemon and the cherry.

This does assume that only one of each fruit exists; things get a bit more complicated otherwise.

Oddly, this does allow basket to be understood as part of the basket’s name, without the explicit Understand – perhaps only because it has no name of its own at all? (Perhaps this is what you were seeing over here as well.)

The extension to allow more than one anonymous fruit is fairly straightforward too:

A banana is a kind of fruit.  A banana is usually yellow [but could be green].
A lemon is a kind of fruit.  A lemon is usually yellow.
An apple is a kind of fruit.  An apple is usually red.
A cherry is a kind of fruit.  A cherry is usually red.

There is a wicker basket in the kitchen.  In it are a banana and an apple.
There is an iron basket in the kitchen.  In it are a lemon and two cherries.

(I’m impressed that Inform figured out the plural of cherry on its own. Though it’s less correct about the plural of fruit, since English is weird like that.)

Of course, anonymous objects can’t be referred to in other rules (other than in very limited ways), so it’s usually better to give them names – which in turn means that you’ll need that explicit Understand again. Otherwise while you can say something like this:

In the wicker basket in the kitchen is a lemon.

This will create another wicker basket (containing only a lemon) – it will not add a lemon to the existing wicker basket.

Yes, this is correct. It is documented (sort of) in §17.11 of Writing with Inform:

It is not ordinarily the case that a thing can be called by the name of its kind: if we put a woman called April into a room, then she can usually be called “April”, but not “woman”. (The exception is when we do not specify any name for her - in that case, Inform will give up and call her just “woman”.)