I want to make two lamps, called "the light light" and "the heavy
light", but I can't make the parser deal with them correctly. I7 has
no problems being able to handle words which can be both verbs and
nouns, but doesn't seem to like the same word being used as both a noun
and an adjective.
For example, the following does not work:
The Boring Room is a room. The Boring Room is dark.
A light light is in the Boring Room. The light light can be lit.
A heavy light is in the Boring Room. The heavy light can be lit.
The heavy light is lit.
A heavy anvil is in the Boring Room.
I get the this behavior:
>take light light
Which do you mean, the light light or the heavy light?
Even though I explicitly said which one, it is interpeting both
"light"s as (redundant) nouns.
I've tried scores of more complicated implementations, to no avail.
The only thing that comes close to success is trying to selectively
replace the word "light" with another predefined magic word in an
"After reading a command:" rule, but this doesn't fully work because I
want to be able to "light light light" as well, and there's no way to
avoid replacing the verb as well. Strings parsing in I7 seems
annoyingly limited.
And having to solve this problem by manipulating the player's command
directly seems hackish and unsatisfactory, anyway.
Any suggestions or pointers would be appreciated.
(I'd love to see more options for tweaking the behavior of the parser
in a future version of I7, including control of the disambiguation
process.)
Anyway, my apologies that it isn't clear from the original subject that
this thread is about I7.
-Craig
That is a general problem with Google Groups. It does not show [tags]
in the
subject field.
And your "light light" and "heavy light" problems are problems with
Inform
parsing, that there's no good way to work around. If you have two
objects,
where the first object's name is a subset of the others name, the
Inform
parser cannot disambiguate. For example, you cannot have both bananas
and
banana peels in the same game.
This problem exists in both the resulting game and the I7 compiler,
so beware because the compiler doesn't warn you that it's confused
about which object you mean!
You'll just have to resign to the fact, and find other, non-conflicting
names.
Tor
The way to work around this in I6 was to write a parse_name procedure
on the *heavy* light, which failed to match if it saw the word "light"
twice. I don't think I7 is open to such procedural name parsing -- if
it is, I haven't found it yet.
> The only thing that comes close to success is trying to selectively
> replace the word "light" with another predefined magic word in an
> "After reading a command:" rule, but this doesn't fully work because I
> want to be able to "light light light" as well, and there's no way to
> avoid replacing the verb as well.
Don't replace the word "light" with your magic word if it's the first
word in the command.
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
If the Bush administration hasn't thrown you in military prison without trial,
it's for one reason: they don't feel like it. Not because you're patriotic.
The equivalent to a parse_name in I7 seems to be a "fake name" and
understand rule, like the following:
<code>
"Lights"
The Lamp Store is a room.
The light light is a thing in the store.
The heavy_light is a thing in the store with printed name "heavy
light". Understand "heavy light" as the heavy_light. Understand "heavy"
as the heavy_light.
Instead of burning something, say "You light [the noun]."
</code>
<Transcript>
Lamp Store
You can see a light light and a heavy light here.
>light light
You light the light light.
>light heavy light
You light the heavy light.
>light heavy
You light the heavy light.
</transcript>
This seems to do roughly what you want.
I don't entirely like this approach, because there seems to be no way
to prevent the object having its official name recognized (here,
"heavy_light"), but it seems to handle most situations.
On the other hand, this issue allows you to easily create two things
which are understood by the same names (but make sure they are never
both in scope!), e.g.
The ugly man is a person. The ugly ugly man is a person with printed
name "ugly man".
(Possibly useful, say, if you want to swap one object for the other at
some point.)
-JDC
I hope there is a way to do this by the time I7 is out of beta. My
case is admittedly esoteric, but the realization that you can't even
distingush something like "banana" from "banana peel", as Tor pointed
out, makes this seem like a rather serious deficiency.
It seems like the parser doesn't actually even distinguish adjectives
from nouns at all.
Given 'A banana and a banana peel are in the Boring Room.', it accepts
"take peel banana" to get the banana peel, but the only way to specify
the banana is "take all bananas but the peel". Having to change the
names of objects in the source is perfectly acceptable, but having to
change the names of objects in the game as the player sees them - not
so much.
In lieu of extending I7 to allow somethig like parse_name procdures, it
seems like the I6 sentence parser on top of which I7 is built could be
tweaked to be smarter about this type of thing by default. If the
string following a verb exactly matches the name an object in scope, it
seems like that object should be selected rather than being considered
ambiguous in the presence of other objects with this name as a prefix.
Also, any single word in the command should never match a word in an
object in scope multiple times. You sholdn't be able to type "take
banana banana banana banana banana" and have that work.
> > The only thing that comes close to success is trying to selectively
> > replace the word "light" with another predefined magic word in an
> > "After reading a command:" rule, but this doesn't fully work because I
> > want to be able to "light light light" as well, and there's no way to
> > avoid replacing the verb as well.
>
> Don't replace the word "light" with your magic word if it's the first
> word in the command.
I had thought of that, but I've been unable to find a way to do it, I7
doesn't understand 'if the player's command begins with' or 'if the
player's command starts with'. All of the examples use only 'includes'
or 'matches' in such conditions. Is there a way to express this that
isn't yet documented?
Unfortunately, I also want "take all lights" and such to work. In this
code, heavy_light isn't recognized as a light at all, and just "take
light" assumes the light light. I want it to still ask disambiguation
questions if there is more than one light in scope. Modifying your
code to accept heavy_light as a light brings back the original problem.
:-(
This problem is currently unsolved in Inform 7--an ironic
oversight. You should subtly redesign any model world including
this sort of ambiguity. How about a light lamp and a heavy lamp?
Actually, that's not quite enough:
>X LAMP
Which do you mean, the light lamp or the heavy lamp?
>LIGHT
What to you want to light?
So how about a tin lamp and an iron lamp?
I advise against trying to fiddle with the player's command. That
part of Inform 7 isn't ripe yet.
--
Neil Cerutti
Fortunately(!?!) parse_name still works in Inform 7. Here's a
prototype I put together to address the problem:
The light light is a device in the foyer.
The heavy light is a device in the foyer.
Include (-
with parse_name [ word next_word n;
while (1)
{
! I need one word of look-ahead.
word = NextWord();
next_word = NextWordStopped();
if (next_word ~= -1) wn--;
if (word == 'light') {
if (next_word == 'light')
{
return 0;
} else {
n++;
}
} else if (word == 'heavy') {
n++;
} else if (word == 'lights') {
n++;
parser_action == ##PluralFound;
} else {
break;
}
}
return n;
], -) when defining the heavy light.
We're back to the future!
This still can't handle the following:
>LIGHT LIGHT
What to you want to light, the light light, or the heavy light?
>LIGHT
What do you want to light?
Even the great parse_name is powerless in the face of this
ambiguity. However the following does work:
>LIGHT LIGHT LIGHT
This dangerous act would achieve little.
--
Neil Cerutti
Not only is he ambidextrous, he can throw with either hand.
--Duff Daugherty
Thanks very much for this solution!
It works well, and provides a clue as to how I can tap into I6 if
needed if other such problems arise.
I do still hope I7 provides rules to tune the parser natively in a
future release, though.
It's really more of an academic exercise, but I was hoping to use it in
a game as well. I have a long-held interest in NLP, and years ago in
college I wrote a natural language parser as part of a fledgling
adventure game language.
It never evolved to anything near the level of Inform or TADS, and I
never released it, but its sentence parser was quite good, and 'light
the light light' was one of my test cases. (Another was 'take all
orange objects from the table except the orange and put them in the
brown bag.")
When I stumbled onto Inform 7 a couple weeks ago, I was absolutely
amazed by it.
I feel kind of guilty that my first post about I7 was a complaint about
its parser, because I really
think it's a fantastic experiemnt in NLP and am really interested to
see how it progresses.
Graham Nelson, Emily Short, and everyone else involved deserve major
kudos for such an innovative breakthrough in IF. I'm sure if I had
heard about this project when it was just beginning, I would've been a
naysayer and highly skeptical about it. But all it took was to read a
few of Emily's examples to make me a total convert.
So naturally the first thing I tried to do was reproduce some of the
stuff I did long ago when developing in my own adventure language, and
that's how I stumbled into this parser problem.
I hope for this as well. But if that doesn't happen I hope that
ORLibrary (http://www.onyxring.com/orlibrary.aspx) will be made
compatible with I7. One of the many things I loved about the library
was its ORAdjective module, which solved this problem for I6, allowing
the parser to automatically distinquish between, say, a "glass" and a
"glass eye" object (or "banana" and "banana peel", etc).
Josh
>
> And your "light light" and "heavy light" problems are problems with
> Inform
> parsing, that there's no good way to work around. If you have two
> objects,
> where the first object's name is a subset of the others name, the
> Inform
> parser cannot disambiguate. For example, you cannot have both bananas
> and
> banana peels in the same game.
>
> This problem exists in both the resulting game and the I7 compiler,
> so beware because the compiler doesn't warn you that it's confused
> about which object you mean!
>
> You'll just have to resign to the fact, and find other, non-conflicting
> names.
>
> Tor
>
This is a common problem in IF, where you want to have, say, a garden
path, a garden shed, and "the garden" all examinable.
Actually I've found I7 is pretty good at managing this situation, you
just have to code with a little care. Have a look:
[code]
"bananas" by troubled
The steamy jungle is a room. "A rather minimalist jungle consisting of a
single banana tree."
The tree is scenery in the steamy jungle. The printed name of the tree
is "banana tree". Understand "banana tree" as the tree.
A fruit is in the jungle. The description of the fruit is "Ripe and
golden, it's a beautiful banana." Understand "banana" as the fruit. The
printed name of the fruit is "banana". The fruit is edible.
Some peel is in the jungle. The description of the peel is "It is no
longer true to say this is a banana. It is an ex-banana." Understand
"banana peel" or "ex-banana" as the peel. The printed name of the peel
is "banana peel".
Instead of eating the peel, say "Too late. Someone else has already
eaten it."
A golden crescent is scenery in the jungle. The printed name of the
golden crescent is "golden banana". The description of the golden
crescent is "I think you're in the wrong game system, mate." Understand
"golden banana" as the golden crescent.
A light is in the steamy jungle. The printed name of the light is "light
light". Understand "light light" as the light. The light can be lit.
A heavylight is in the jungle. The printed name of the heavylight is
"heavy light". Understand "heavy light" as the heavylight. The
heavylight can be lit.
[/code]
As a bonus, the game also now understands the nonsense word heavylight,
which might actually get typed if the player is a bit careless or
hurried. In other situations though, you might prefer to make the object
name more obviously different - heavy_light - or something similar.
HTH,
Jayzee
I'm not impressed with the current implementation.
You see a banana tree here.
>CLIMB BANANA
You can't see any such thing.
> Instead of eating the peel, say "Too late. Someone else has
> already eaten it."
>
> A golden crescent is scenery in the jungle. The printed name of the
> golden crescent is "golden banana". The description of the golden
> crescent is "I think you're in the wrong game system, mate." Understand
> "golden banana" as the golden crescent.
>
> A light is in the steamy jungle. The printed name of the light is "light
> light". Understand "light light" as the light. The light can be lit.
>
> A heavylight is in the jungle. The printed name of the heavylight is
> "heavy light". Understand "heavy light" as the heavylight. The
> heavylight can be lit.
> [/code]
>
> As a bonus, the game also now understands the nonsense word
> heavylight, which might actually get typed if the player is a
> bit careless or hurried. In other situations though, you might
> prefer to make the object name more obviously different -
> heavy_light - or something similar.
This is one case where natural language gets in the way. Perhaps
it will eventually be possible to assign source-code names to
objects that are not also model-world names, through some
artifice--perhaps single-quoted words, or some prefix.
The @heavylight is in the jungle.
This would create an object that, by default, provids no way for
the player to refer to it.
--
Neil Cerutti
Ushers will eat latecomers. --Church Bulletin Blooper
It's not obviously better to have "banana" refer to the tree. If the
banana (fruit) shows up, the referent will switch silently, which is
confusing to the player. (No, it's not obviously worse either.)
Also, historically, having the parsing of an object depend on testing
whether other objects are in scope is a good way to bog the parser down.
> >
> > As a bonus, the game also now understands the nonsense word
> > heavylight, which might actually get typed if the player is a
> > bit careless or hurried. In other situations though, you might
> > prefer to make the object name more obviously different -
> > heavy_light - or something similar.
>
> This is one case where natural language gets in the way. Perhaps
> it will eventually be possible to assign source-code names to
> objects that are not also model-world names, through some
> artifice--perhaps single-quoted words, or some prefix.
>
> The @heavylight is in the jungle.
>
> This would create an object that, by default, provids no way for
> the player to refer to it.
If you do this now, will any player know the difference?
(You can't do this literally, because the @ trips up the I6 parser.
But you can use a dollar sign. Any player that types "get $heavylight"
will either get what he expects, or find the result obvious anyway.)
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
When Bush says "Stay the course," what he means is "I don't know what to
do next." He's been saying this for years now.
This will only really be a problem if you have to loop through all
objects, such as 'Understand "banana" as the tree when no fruits are
enclosed by the location' (wheree fruit is a kind, or an attribute),
right? It should be safe to say something like 'Understand "banana" as
the tree when the fruit is not enclosed by the location.' (when the
fruit is a single object).
If you want to get really finicky, you can also try context-sensitive
parsing, so something like 'Understand "banana" as the tree when
climbing or the fruit is not enclosed by the location. Understand
"banana" as the fruit when not climbing or the tree is not enclosed by
the location.' But at this point you should probably ask yourself
whether anyone is really going to notice or care...
-JDC
I think that "You can't see any such thing." is worse than
selecting the one object in scope containing the word "banana".
To me, it is a bug.
> Also, historically, having the parsing of an object depend on
> testing whether other objects are in scope is a good way to bog
> the parser down.
Agreed; checking scope while matching an object's name would be
the wrong way to do it.
The following assumes that one attribute is used to keep track of
whether an item's phrase has been matched exactly (this attribute
would be maintained in NounDomain). (I removed the diagnostics
for brevity):
! ----------------------------------------------------------------------------
! MakeMatch looks at how good a match is. If it's the best so far, then
! wipe out all the previous matches and start a new list with this one.
! If it's only as good as the best so far, add it to the list.
! If it's worse, ignore it altogether.
!
! The idea is that "red panic button" is better than "red button" or "panic".
!
! number_matched (the number of words matched) is set to the current level
! of quality.
!
! We never match anything twice, and keep at most 64 equally good items.
! ----------------------------------------------------------------------------
!!! This version of MakeMatch is very similar to the
!!! standard version, with the following change to the
!!! definition of "best so far": An item is considered the best
!!! so far if:
!!! It matched more words in the input than any other object in
!!! the list (this is the standard rule).
!!! OR
!!! ( It matched just as many words as any other object in the
!!! list.
!!! AND
!!! One of it's phrases was matched exactly.
!!! AND
!!! No other object in the list has had its phrase matched exactly. )
[ MakeMatch obj quality
i p_match;
if (quality > 0 && obj has phrase_matched)
p_match = true;
if (token_filter~=0 && UserFilter(obj)==0)
{ #ifdef DEBUG;
if (parser_trace>=6) print " Match filtered out: token filter ",
token_filter, "^";
#endif;
rtrue;
}
if ((quality < match_length) ||
(quality == match_length && p_match == false && matches_in_match_list))
{
rtrue;
}
if (quality > match_length ||
((matches_in_match_list == false) &&
(quality >= match_length) &&
p_match))
{
if (p_match)
matches_in_match_list = true;
match_length=quality;
number_matched=0;
}
else
{ if (WORDSIZE*number_matched>=WORDSIZE*64) rtrue;
for (i=0:i<number_matched:i++)
if (match_list-->i==obj) rtrue;
}
match_list-->number_matched++ = obj;
];
--
Neil Cerutti
To me, it is equally a bug if a given typeable phrase jumps around in
that way. But, since one of the two bugs is inevitable, I won't argue
that one must be avoided.
Your notion of up-scoring an object whose name is exactly matched is
very sensible, and I feel dumb for not thinking of it in my previous
post. :)
Here, JDC <jd...@psu.edu> wrote:
>
> This will only really be a problem if you have to loop through all
> objects, such as 'Understand "banana" as the tree when no fruits are
> enclosed by the location' (wheree fruit is a kind, or an attribute),
> right? It should be safe to say something like 'Understand "banana"
> as the tree when the fruit is not enclosed by the location.' (when
> the fruit is a single object).
I haven't looked at the code I7 generates for this case, to see how
efficient it is. My I6 experience is that the equivalent code
(parse_name using IndirectlyContains()) is acceptable for a few
objects, but risky if many such objects show up in scope at once.
Having parse_name call TestScope() is a definite no-no.
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
9/11 did change everything. Since 9/12, the biggest threat to American
society has been the American president. I'd call that a change.
Even though you're pleading nolocontendre (or whatever that
phrase is) I'm still interested in your point of view on this,
because I don't grasp it yet.
Can you post a short transcript that demonstrates the behavior
you would consider a bug? Here's my attempt.
You see a banana tree here.
>SHAKE BANANA
A banana falls from the sky, and lands beside the banana tree.
>TAKE BANANA
Taken.
(I admit that SHAKE TREE is a far more likely input in the above
situation, however.)
That seems quite natural to me. I think players are used to
phrases having different meanings depending on context. An object
going in or out of scope is an obvious change in context.
--
Neil Cerutti
I haven't tried it yet, but judging from the code and your examples,
your modification to MakeMatch is exactly in line with the way I was
thinking it should work. It seems intuitive to me that an exact match
should always 'win' over a partial match. (This is the same way the
sentence parser I mentioned recently in another thread works, as well.)
I'm not sure I understand Andrew's objection to context-dependent
matching, either, because I think that's a normal part of English (or
any natural language) and it'll almost always work the player would
epect it to.
If Andrew or anyone else has any counter examples where this behavior
is clearly worse, I'd be interested to see them.
I'm hoping it will be generally agreed that this is a good thing and
Graham will consider adding it to a update to the library, at least as
an optional feature. ("Use preferential treatment for exact object
name matches," or some such.)
I had thought about asking the I7 team if it's possible to have a
separate instruction for the purpose of adding a unique name to an
object so that the code can refer to it unambiguously (but I didn't know
where to ask). Something like:
...
The old brown chair is a supporter in living room. The private name
of the chair is lvr_chair1. The description of the chair is ...
...
And then elsewhere in the code I can refer to lvr_chair1 and know that
i7 isn't going to get confused.
Since then though, I've wondered if it's really necessary. I mean, how
likely is it that a player is going to guess that exact word? It's just
like putting 'magic' words like xyzzy into a game. The player isn't
going to know they're there unless either (a) the game gives the
information, or (b) word gets out on the net in the form of
walkthroughs, cheats or whatever. (a) is obviously my fault, and (b)
means that I've succeeded in writing a game *that people want to play*.
Result!
One misgiving that I still have though is about encouraging authors to
make objects big targets so that players don't have to play guess the
noun. In I6 it's not much typing:
Object brchair "brown chair" test_room
with name 'brown' 'dark' 'wood' 'wooden' 'chair 'seat' 'stain'
'stained' 'mysterious' 'mysteriously',
description "A mysteriously stained dark brown wooden chair.",
has enterable supporter;
but in I7 if I want to put in all those synonyms, I either have to use
understand, which while it isn't difficult, it's a lot more typing, and
over the course of a game that sort of thing adds up, or I type:
A mysteriously stained dark brown wood wooden chair seat is a supporter
in test room.
When I write the object this way, I have to override the default printed
name, (default being to use all those words in the order typed) because
it's too wordy to be used in the game messages - UNnatural language, in
other words. I'd really like the default printed name to be (say) the
first three words only, with the others just silently added to the
objects names. If we wanted to keep the appearance of natural language,
then something a bit more complicated:
A mysteriously stained dark brown wooden chair/seat is a supporter in
test room.
With the default printed name being the last three words. If the last
word contains "/" then I7 would know to truncate the printed name at the
slash, split such words at the slash(es), and add both (all) such words
to the objects names. Obviously it would be necessary to set printed
name by hand occasionally, but that's okay. It's because I have to do it
all the time that I get cranky.
anyway, my 2c.
JZ
> Neil Cerutti wrote:
From my unfamilar perspective, it actually looks like there's another
downside to the current behaviour. Making it possible for the player to
refer to the object by the code's name seems like it would have to take
up space in the story file; if you don't need the name to be valid, not
bothering to make that possible would save the extra space.
This will become less of an issue as development moves away from the Z
machine, but in the meantime - and even afterwards, if someone
specifically wants to use the Z machine (which I could easily see
happening) - the ability to turn off the automatic transformation of the
code name of an object into a model-world name for that object could be,
for some games, enough to provide the necesary slimming to fit inside
the limited space.
For the little it's worth, I like the "@name" suggestion.
--
The Wanderer
Warning: Simply because I argue an issue does not mean I agree with any
side of it.
Secrecy is the beginning of tyranny.
Just one, specific comment -- I don't think "Understand" requires a lot
more typing than "with name":
The brown chair is an enterable supporter in test_room. The description
is "A mysteriously stained dark brown wooden chair." Understand "dark",
"wood", "wooden", "seat", "stain", "stained", "mysterious", and
"mysteriously" as the brown chair.
Understand "brown" or "dark" or "wood" or "wooden" or "chair" or
"seat" or "stain" or "stained" or "mysteriously" as the brchair.
I wouldn't say it's a *lot* more typing. You type "or" a lot. It's
wordier, as all of I7 is wordier, but I haven't found that it slows me
down.
If the IDE were Emacs, I'd write a macro to turn a space-separated
list of words into an "or"-separated list.
(Note: it's tempting to type
Understand "brown/dark/wood/wooden/chair/seat/stain/stained/
mysterious/mysteriously" as the brchair.
but this form doesn't permit combinations like "examine dark brown
chair".)
Also, because I'm paranoid, I looked at the generated parse_name for
one of these Understand lines. Turns out it's efficient. It also
avoids using a long property array, which is nice.
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
If the Bush administration hasn't shipped you to Syria for interrogation, it's
for one reason: they don't feel like it. Not because of the Eighth Amendment.
I think you've misunderstood the nature of this discussion. My
criticism was of the in-game sentence parser, not the I7 langugae
parser. And I think Neil C's proposed patch to MakeMatch is a good
solution.
I really think the existing I7 functionality for describing objects is
quite good. Shortening the printed name to the last three words seems
arbitrary to me, and doesn't seem like a useful addition.
I don't think one should be trying to declare the noun with a huge list
of all possible adjectives, and then shorten it by changing the printed
name, anyway. It's much more natural to describe the printed name
directly, and then extend the vocabulary the game accepts to describe
the object with additional 'Understand' statements. This is what the
bulk of the worked examples do. The printed name should normally only
need to be explicitly stated in special cases, such as when you want to
use extended Unicode characters, or when the printed name changes in
the course of play (i.e., now the printed name is...).
And trying to use 'programmer names' like lvr_chair is definitely a
bad idea, and counter to the spirit and intent of the language. You
might as just write in I6. Or Perl. :-)
Not to drag out the suspense, but yes, that was the example I was
thinking of.
I expect phrases to change based on context. But adding things to
context shouldn't *erase* a meaning from an object which *hasn't*
changed. I'd be left wondering why the game didn't ask me to
disambiguate the new object from the old one.
Possibly this is a good use for the parenthesized emendation:
> SHAKE BANANA
(the banana tree)
A banana falls from the sky, and lands beside the banana tree.
...although the Inform library isn't set up to do that for this case.
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
Note that this case is subtly different from the following, which
would not bother me:
You see a pile of pebbles here.
> X PEBBLE
It's a big pile of pebbles.
> TAKE PEBBLE
You take one from the pile.
> X PEBBLE
You are holding a round shiny pebble.
If you think I'm drawing excessively fine distinctions here, well,
probably.
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*