Something Wrong With Giving?

As part of my current WIP I have been putting the giving it to action through its paces. I’ve looked closely at the Standard Rules for the action, and now I’m working out any additional check rules I might need to add along with the revised report rules. I have identified one problem and a solution. Now I’ve found another problem that defies logic.

Consider:

The Magic Shoppe is a room. "The name above the door suggests this shop is full of magic items, but all [we] see is junk arranged in a disorganized mess. [Our] eye catches a stack of magical staves in one corner."
The shopkeeper is a woman in the Magic Shoppe.
The pile of junk is a backdrop. It is everywhere.
The group of staves is scenery. It is in the Magic Shoppe.
The book of magic is a thing in the Magic Shoppe.
The hitchhiker is a man in the Magic Shoppe.
The player wears the jacket.

Instead of giving the pile of junk to someone:
	say "Dude! The entire shop? Try to be more selective."

Test giving with "x junk / x staves / x book / x shopkeeper / x hitchhiker / x jacket / give junk to shopkeeper / give staves to shopkeeper / give book to shopkeeper / give me book / i / give me shopkeeper / give shopkeeper to junk / give hitchhiker shopkeeper / give staves hitchhiker".

When you run the test, all the items are there. The game responds as expected until you get to the last two commands. The response is not what I expected:

>give shopkeeper to junk
You can’t see any such thing.

>give staves hitchhiker
You can only do that to something animate.

I know these two commands are mistakes. The problem is, they are the same mistake using different syntax, and they have different responses. Neither response is the response the Standard Rules provides in the “the can’t give to a non-person rule”.

The first case follows the standard syntax of “give [something preferably held] to [someone]”. The second case follows the alternate, nouns reversed, syntax of “give [someone] [something preferably held]”. Because both specify the second noun must be a person, both should respond with the “can only do that to something animate” command parser error and never even reach the check rule. One does that. The other appears to fail at the determining the scope stage.

Anyone know what’s going on here?

I haven’t dug through it line by line, but the “can only do that to something animate” parser error is a kind of a hack. (The modern Inform idiom would be a check rule to rule out non-animates, rather than a grammar token.)

I think the situation is that the parser tries both grammar lines (“give X Y” and “give Y to X”), records an error on both of them, and then has to choose which error to report. There’s a precedence list, which is usually not interesting but this example demonstrates it.

This seems to fix it:

Understand the command "give" as something new. 
Understand "give [something preferably held] to [something]" as giving it to.
Understand "give [something] [something preferably held]" as giving it to (with nouns reversed).

At least, the responses are consistent. The carrying requirements rule ruins everything by responding with “I don’t suppose the shopkeeper would care for that.” to everything. (I know how to fix that one, though.)

You’re running into artifacts of the grammar lines for the actions, which mean that the end result of parsing is a parser error instead of an action.

There are two declarations in the Standard Rules defining the grammar lines for the giving it to action:

Understand "give [something preferably held] to [someone]" as giving it to.
Understand "give [someone] [something preferably held]" as giving it to (with nouns reversed).

These translate into the following grammar lines at the I6 level:

[line 0 * creature held -> Give reverse]
[line 1 * held 'to' creature -> Give]

The designation “creature” means that the parsed object in that position must be a person in I7. If this requirement is not met, the grammar line fails with the can only do that to something animate error parser error (see WWI 18.35 Printing a parser error).

As the parser goes through grammar lines, it takes note of the type of failure. Each failure has an internal numeric error code. When multiple grammar lines fail, the parser error reported is the one with the highest internal code.

The most basic code is the didn't understand error parser error, with numeric code 1. This is the code returned if it sees a word that doesn’t seem correct for what it’s trying to match at any point.

The can only do that to something animate error parser error has a higher numeric code of 4.

The can't see any such thing error parser error has an even higher numeric code of 5.

For >GIVE STAVES HITCHHIKER command:

  • Line 0 fails with the can only do that to something animate error parser error because it was able to make sense of the word “staves” as referring to the group of staves, but the group of staves is not a person.
  • Line 1 fails because, after understanding “staves,” it doesn’t see the required preposition “to” so it fails with a didn't understand error.
  • The higher numeric code is 4, so the error issued complains about animate status.

For >GIVE SHOPKEEPER TO JUNK:

  • Line 0 fails but in a different way. The parser thinks it’s on the right track with “give” and “shopkeeper” matching the required pattern, but the words “to junk” can’t be translated into the object that will become the noun. The result is the can't see any such thing error parser error.
  • Line 1 fails with the can only do that to something animate error parser error.
  • The higher numeric code is 5, so the error complains about not being able to see a matching object.

Your redefinition of the grammar lines addresses the issue nicely.

4 Likes

To pile on, I’d suggest that the Standard Rules in the next version of inform include the new grammar lines (the ones you wrote) and a Check rule to prevent giving things to things which are not animate. We’ve been making other grammar line updates for similar problems – I made a patch for confusing remove errors recently along the same lines – so you might as well submit a bug to Jira, and submit a patch, and fix this one in Core Inform too. (If nobody else gets around to doing it I might submit that eventually.)

I’m working on that. In the case of giving it to, there’s a bit more work to it–check rules need rearranged and a couple re-written. Then there’s the whole carrying requirements rule thing.

Nathanael,
I’m curious about your patch. When I implement your changes, any attempt to REMOVE ALL FROM {something} somehow triggers the “exclude people from take all rule”, and the response is “There are none at all available!” That response comes from the parser error “not enough of those available error”.

If I remove the “don’t remove things not there rule” from your patch, REMOVE ALL FROM {something} works as expected.

Here’s the code I used:

The Magic Shoppe is a room. "The name above the door suggests this shop is full of magic items, but all [we] see is junk arranged in a disorganized mess. [Our] eye catches a barrel of magical staves in one corner."
The shopkeeper is a woman in the Magic Shoppe.
The counter is a scenery supporter in the Magic Shoppe.
The pile of junk is a backdrop. It is everywhere.
The barrel is a open unopenable scenery container in the Magic Shoppe.
The book of magic is a thing on the counter.
The hitchhiker is a man in the Magic Shoppe.
The player wears the jacket.
The magic apple is an edible thing carried by the hitchhiker.
The fire staff is a thing. It is in the barrel.
The ice staff is a thing. It is in the barrel.
The water staff is a thing. It is in the barrel.

Test removing with "x barrel / x counter / remove ice staff from barrel / remove book from barrel / remove ice staff from barrel / put ice staff on counter / remove all from counter / i / remove jacket from me / remove apple from hitchhiker / remove all from barrel".

Understand "take [things] from [something]" as removing it from.
Understand "take [things] off [something]" as removing it from.
Understand "get [things] from [something]" as removing it from.
Understand "remove [things] from [something]" as removing it from.

Rule for deciding whether all includes a thing (called item) while removing (this is the don't remove things not there rule):
	if the holder of the item is not the second noun:
		it does not;
	otherwise:
		make no decision.
1 Like

That’s very interesting. Yep, you’ve found a fascinating bug. I now know what the issue is: the second noun is “nothing”, because the parser only does lookahead to parse the second noun if it’s got a “multiinside” token. (Sigh.) (Or a “multiexcept” token… hmm…)

This also explains how I had it working previously… I had BOTH grammar tokens in place.

So coding it that way with a separate remove mistakenly action works but it doesn’t give quite the right error messages for remove all from <inappropriate object> because those are hard-coded into the Inform 6 parser only with the specific ##Remove action. That’ll probably be my long-term plan but that’ll take a while. I’m going to see if I can find something sneakier to do…


OK. Now I have a repaired solution which (a) doesn’t break anything and keeps all the REMOVE ALL FROM BARREL stuff working including the error messages, (b) gives a sane error message if the player types REMOVE BOOK FROM BARREL when the book isn’t in the barrel, but (c) still says You can't see any such thing if the player types REMOVE ICE STAFF AND BOOK FROM BARREL.

Solving case (c) is going to require some deep hacking to make more of the I6 parser tuneable from I7, which is not a today thing, but solving case (b) while keeping case (a) working was easy enough.

2 Likes