Quick Tip: Synonyms and Redundancy

Overcat
07 Jul 2006, 09:49
Hey all. I just thought I'd share something handy. You can get the Quest interpreter to ignore redundant words when parsing commands. For instance, 'the' is a redundant word, since it contributes nothing to the meaning of a command. It merely conforms to English language rules. 'Get key' and 'Get the key' are equivalent, and should be treated as such in a game. If you don't want to code for both instances, just do the following:

define synonyms

the =

end define


If you are unfamiliar with synonyms, since I know there are many new forum members, you can look it up here

Freak
07 Jul 2006, 13:43
I disagree that "the" adds nothing to the command; in some cases, it clarifies the meaning of a sentence.

For example, in an Inform 6 game with an old man, an old book, and a new book, "give old man the old book" will be understood immediately; "give old man old book" will need to go through disambiguation.

paul_one
07 Jul 2006, 15:42
What overcat is saying, is that while YOU type that - we as programmers can ignore the "the" really easily.
You can still type it - but it doesn't mean we exactly need to use it.

I like it overcat!

Overcat
07 Jul 2006, 15:44
The irreducible bits of the sentence 'give old man the old book' and 'give old man old book' are 'give', 'old man' and 'old book'. The 'the' is redundant. The only time ambiguity is a concern is if you type 'give old old', leaving out 'man' and 'book'.

For instance, 'put old key on old cabinet' succeeds in ASL. (The way I have it coded.) 'put old on old cabinet' disambiguates the first old, but not the second. 'put old key on old' disambiguates the second old, but not the first. 'put old on old' disambiguates both, because both share the word 'old'.

Granted, I have coded my own GetObject function, and created a new diambiguation process, bypassing the built-in one. With what I had coded, 'put old key on old cabinet' would work, but interjecting a redundant 'the' - 'put the old key on old cabinet' or 'put the old key on the old cabinet' - would fail. So I essentially deleted 'the' from the parser's vocabulary, allowing it to pass over the 'the' with no distinction. 'The' is invisible.

I'm not sure how Inform 6 works, though I believe it, too, is object-oriented. (I'm studying Emily Short's WaterElement.h library.) In any case, the parser must make distinctions differently.

paul_one
07 Jul 2006, 16:06
Could I just ask overcat, how do you have the ambiguity setup? Does it come up with a numbered list? Does it just ask you for each ambiguity - asking you to type in the full name/etc?

Overcat
07 Jul 2006, 16:39
Your first guess was correct. A numbered list is presented to the player. They choose something from the list by typing in a number, which then disambiguates. The GetObject function attempts to return a single object. If mutliple objects are found, the disambiguity menu appears with as many numbered choices as objects were found, +1.

IE, 3 objects found:

Which object do you mean?

1. Object A
2. Object B
3. Object C
4. None of the above

I only started to implement this because I wanted the disambiguation menu to appear as text in the main window, rather than text in a popup. As it turns out, this required a moderate amount of coding, and became an integral part to a plethora of commands. Every command dealing with item object interaction now uses GetObject, rather than the built-in functionality. This substantiated an additional 'alts' property to replace the current 'alt' property, since that could not be read as a string.

GetObject(#text input#; #location to look in#; #object type, if any#; #contained in object, if any#; #wearer, if any#; #equipper, if any#; #object this is under, if any#)

As of now this disambiguates between objects in the same room. Anything you are wearing, holding, or carrying are all in the same room. This may have to be changed, however, since I can be carrying a 'gold coin' in the inventory room, and there can be another 'gold coin' in the current room. Typing 'put coin in piggy bank' would need to disambiguate the two coins.

Freak
07 Jul 2006, 17:35
If you're not doing anything special, in that situation, Inform 6 will parse the first command as "give / old man old / book", and parse the second as "give / old man / (the) / old book". (By default, Inform 6 doesn't care about word order within a noun phrase, and uses as many matching words as it can on the first phrase; this is an unusual case where that behavior fails. In the first case, it will accept the first three words as referring to the old man; in the second case, it won't recognize "the" as referring to the old man, so it will only use two words.)

For comparison, could you port The Flower Garden ( http://www.geocities.com/ralphmerridew/Flower.zip , Inform 6, TADS 2, and ALAN 2 sample sources and binaries) to Quest?

Important criteria:
1) The phrases "red flower" and "tulip" must be acceptable names for the tulip. (Likewise with the other flowers.)
2) The system should be consistent about what phrases are acceptable names for an object.
3) Any two successful commands that cause the same action should have identical results.

Overcat
07 Jul 2006, 17:56
Judging by the output, this can be ported to quest. Quest does not, by default, support 'it' as a substitute for the last object referred to, though I think I can get this to work with a little code.

Freak
07 Jul 2006, 18:07
It doesn't?

From http://www.axeuk.com/quest/qfeat.htm

You don't have to keep retyping object names - Quest's pronoun support means you can type "LOOK AT BOOK" and then "TAKE IT", so there's no need to type the name of the object twice.



Though "it" support isn't directly important; however, if "it" is supported, it should be consistently supported.

Also, port from the source, the Inform version preferably.

davidw
07 Jul 2006, 18:12
Quest does support 'it', though (I think) only if the author specifies it during the object creation. Some of the recent games I've played have allowed me to refer to the previous object as 'it', whereas others have required me to type their name in full.

paul_one
07 Jul 2006, 18:23
I don't know why you used so many options for the disambiguation. It shouldn't matter if it's under or ontop of another object... Surely, if it's available for interaction then it'd be ambiguated - otherwise the player can't interact with it anyway.
If it's under an object then it'd be unavailable (dependant on the programmers choice) while ontop should be fine.
Also object types shouldn't really matter.
In your instance, if you said "give old to old" and had; old man, old book and old key, then how would you use the type ambiguation..
I guess type ambiguation is good if, say;
fill car with pet, and you had petrol, pet cat and pet dog... As you could distinguise between the petrol and animals... But still, I see it as something which doesn't need to be there.
The same for wearer, equipper and inside object.

I'd personally use "#object.ref#;#location#[;#extra.properties#[;...] ]".
Where, inside containers/inside object, would look in #location#.
a Wearer would be carrying the object (for me) - same with equipper.
Objects underneath wouldn't be interactive, and so would be excluded (at least until examined/revealed).
And the properties would enable me to include only objects with these certain properties.
I suppose you could have a certain flag which would include/exclude those properties.

Your opinions?

Overcat
07 Jul 2006, 19:43

Quest does support 'it', though (I think) only if the author specifies it during the object creation. Some of the recent games I've played have allowed me to refer to the previous object as 'it', whereas others have required me to type their name in full.



Then it must support it. This didn't work for me on a quick check. Perhaps objects must be referred to with @'s in command definition blocks in order to 'fill' the pronoun? In which case, I don't use them.

I don't know why you used so many options for the disambiguation. It shouldn't matter if it's under or ontop of another object... Surely, if it's available for interaction then it'd be ambiguated - otherwise the player can't interact with it anyway.



I use the GetObject function in different commands. For instance, 'get object' would direct the function to only look for objects that are generally available in the current room. 'get object from under object2' would direct the function to only look for objects that are underneath object2.

Also object types shouldn't really matter.
In your instance, if you said "give old to old" and had; old man, old book and old key, then how would you use the type ambiguation..



I wouldn't. Only the first two parameters of the GetObject function are necessary. In the previous pseudo-code, the remaining parameters had the qualifier 'if any', meaning they could be omitted from the function. I include all of the parameters for added functionality. I may want to use GetObject for NPC's, say. George is looking for food object types, because he's hungry. The type parameter would definitely be useful, no? Note that disambiguation is not used in this example. In fact, the first parameter, #text input#, is disregarded. Perhaps I should have clarified this.

The same for wearer, equipper and inside object.



These parameters are useful when looking only for objects that are worn or equipped. And not just for the PC, but for NPC's too. In fact, there are a whole smattering of possible uses for these parameters. IE, it is raining. Q: What objects on the PC or NPC get wet? A: Only objects that are equipped or worn. Anything else, packed away, is safe from the water. In this case, disambiguation is not called, since that doesn't matter.

paul_one
07 Jul 2006, 23:36
NPC's wouldn't use type disambiguation..
You'd probably just pick a random object from a list of objects with that 'type'.

How would you get your NPC to disambiguate a type using the procedure? Unless it gives just a list of names or something.

'get object' would direct the function to only look for objects that are generally available in the current room. 'get object from under object2' would direct the function to only look for objects that are underneath object2.

OK. So you go into a room, and go "look under rug", and get "there's a key under the rug!" (the room description would probably change after this). Typing "get key" or "pick up key" would lead to "I see no key" and so you'd type "get key from under rug"?

I suppose you'd have;
> "look under dresser"
"there's a small rug under the dresser!"
> "get rug"
"you can't get the rug - it's under the dresser."
> "get rug from under dresser"
"the dresser is holding the rug down"
> "pull rug from under dresser"
"You pull the rub away from under the dresser"... But you can still do that without having to use the 'under' option in your function.

Only the first two parameters of the GetObject function are necessary

I saw that.. I just didn't see much point in having - or coding - those extra 'optional' parts.

And in most cases, you can just do a basic include/exclude of objects with or without certain properties (as I suggested).

I don't mean to ridicule - but just ask why you went through creating 6 or 7 extra functions which aren't needed for ambiguity - and also when you could have had 4, with less internal coding.

Overcat
08 Jul 2006, 02:19

I don't mean to ridicule - but just ask why you went through creating 6 or 7 extra functions which aren't needed for ambiguity - and also when you could have had 4, with less internal coding.



Hey, that's okay. This is how we all get better at things - communication. (By the way, it's just one function, not 6 or 7.)

But the crux is here:

NPC's wouldn't use type disambiguation..



The GetObject function is not just for disambiguation. It's for finding objects in general. For the PC and for the NPC. I happen to use it everywhere, even when ambiguity is not an issue. In the instance where ambiguity is a issue, a Disambiguate function is called. This only ever occurs for the PC, not NPC's (obviously).

George is looking for food object types, because he's hungry. The type parameter would definitely be useful, no? Note that disambiguation is not used in this example.



'get rug from under bed'

What if there is a rug under the bed, and a rug beside the bed? GetObject needs to filter out any rugs that are NOT under the bed for disambiguation. I don't want to disambiguate the two rugs when this command is typed. It's obvious which rug the player is referring to. If there are two rugs under the bed, I want to disambiguate just those two rugs, and not any other rugs in the room.

It shouldn't matter if it's under or ontop of another object... Surely, if it's available for interaction then it'd be ambiguated - otherwise the player can't interact with it anyway.



The thing is, they are available for interaction, regardless if they are hidden underneath another object - but only with a certain set of commands. For instance, if there were only one rug underneath the bed (no other rugs anywhere else), and I typed 'get rug', this would result in a denial. But 'get rug from under dresser' would result (possibly) in a success (or a further complication, as in your example).

My concept of an object being beneath another object, however, is that you cannot see the first object. (Like a key or an apple under a bed.) With a rug and a bed this is not the case. The bed can be seen, and so can the rug, without having to type 'look under bed'.

paul_one
08 Jul 2006, 09:19
I'm just saying; you wouldn't know an object is under it unless you looked underneath.
And *I* don't want to write out the full "get #obj# from under #obj#".
I'd personally just type "get #obj#".
It's, IMO, the more natural thought you have in your brain.
"there's something under the bed - let's pick it up".

Also, if there are 2 rugs under the bed, and one out on the side - you'd have to look under the bed to make the 2 rugs available and put them into a disambiguation.
For rugs under a certain object - and not anywhere else in the room, then the 'underneath #object#' part of the command comes in to play.. You can either check in the "get ## under ##" command, after you get a list of objects in the room - not one of my favourites - or simply use a property value (I'd use an under.#object# - simply because it's a true/false value).

one function

Yeah, I mean technically there's one function :P . I meant parameters (functions meaning functionality).

I kind of made the half-way guess that getobject returned a string-list (or array name - which I'd personally prefer.. I think you can use #(arrayname.in.string)[index]#).

Overcat
08 Jul 2006, 11:34

I'm just saying; you wouldn't know an object is under it unless you looked underneath.
And *I* don't want to write out the full "get #obj# from under #obj#".
I'd personally just type "get #obj#".
It's, IMO, the more natural thought you have in your brain.
"there's something under the bed - let's pick it up".



You have a point, there. 'get rug' could disambiguate by:

Which rug do you mean?

1. Green Rug
2. Red Rug (under the bed)
3. None of the above

I kind of made the half-way guess that getobject returned a string-list (or array name - which I'd personally prefer.. I think you can use #(arrayname.in.string)[index]#).



It returns an objects_found array. (Which I find terribly useful for manipulating specific sets of objects). The Disambiguate function disambiguates that array, if disambiguation is necessary.

paul_one
08 Jul 2006, 12:02
Oh, that's also another reason you can't use #@object#.. cos it automatically comes up with a disambiguation box (from what I remember reading in the help file).

Overcat
08 Jul 2006, 13:57
Righto.

I have lost, however, pronoun (it) functionality as a result. I'll have to see if I can code my own pronoun parsing.

Freak
09 Jul 2006, 22:02
Something I didn't think to mention:

The Flower Garden was originally written as a quick way to compare how the various IF systems handle ambiguity by default. Since it looks like writing the Quest version may need a moderate amount of special coding, I'd appreciate seeing a most direct implementation (least amount of "special handling") and a most polished implementation.

Overcat
09 Jul 2006, 22:21

The Flower Garden was originally written as a quick way to compare how the various IF systems handle ambiguity by default.



I thought it was some form of standard...

Since it looks like writing the Quest version may need a moderate amount of special coding, I'd appreciate seeing a most direct implementation (least amount of "special handling") and a most polished implementation.



I'll check it out. Anyone else going to?

Alex
09 Jul 2006, 22:28
Here's my stab at it - seems to cover everything:


define game <Flowers>
asl-version <350>
start <porch>
command <smell #@thing#> if action <#thing#; smell> then doaction <#thing#; smell> else msg <It doesn't smell of anything.>
command <drop all> for each object in <inventory> {
move <#quest.thing#; #quest.currentroom#>
msg <#@quest.thing#: dropped.>
}
end define

define room <porch>
prefix <the>
look <A plain porch. The garden is north of here, and the house is to the south.>
north <garden>
south msg <But you want to stay out and sniff the flowers!>
end define

define room <garden>
look <A mostly empty garden; the house is back to the south.>
prefix <the>
south <porch>

define object <rose>
prefix <a>
take
properties <hasbee>
alt <flower; white>
look if property <rose; hasbee> then msg <A bee crawls across the rose.> else msg <It's a beautiful white rose.>
action <smell> {
if property <rose; hasbee> then {
property <rose; not hasbee>
msg <Ouch! As you sniff the rose, you disturb a bee that was crawling on it. Angered, it stings you then flies away.>
}
else msg <You're wary of sniffing it again, after what happened last time.>
}
end define

define object <daffodil>
prefix <a>
take
alt <flower; yellow>
look <A typical looking yellow daffodil.>
action <smell> msg <It has the usual daffodil scent.>
end define

define object <tulip>
prefix <a>
take
alt <flower; red>
look <An ordinary red tulip.>
action <smell> msg <It smells like a tulip.>
end define

end define

Overcat
09 Jul 2006, 22:35
Yeah, that does it. No special coding there! :)

Freak
09 Jul 2006, 22:50
I consider "DROP ALL" to be special coding, but I wasn't testing "ALL" here.

Overcat
09 Jul 2006, 23:29
I assumed t'was irrelevant to the port, and could be ignored.

paul_one
10 Jul 2006, 11:44
and how is that using ambiguity?

Overcat
10 Jul 2006, 15:10
Type 'smell flower'.

And by the way, Freak, could you give a definition of what 'special coding' is? Is it just text-editor coding as opposed to QDK interface coding? Or is there some other distinction...

paul_one
10 Jul 2006, 17:40
Yeah, sorry - I didn't see the alt tag having "flower" in there.

Freak
10 Jul 2006, 20:51
I thought I had a clear idea when I wrote that post, but I don't think I can express it concretely; it essentially boils down to not manually parsing.

WalksLikeFlay
09 Aug 2006, 14:27
Hello folks, am currently fiddling around with my first effort at a game. I've rooted through a range of IF systems, and whilst none of them seem perfect for me, I feel that I can work with Quest with reasonable competence.

I've been trying to use this blank synonym method, but I can't quite get to grips with it.

As far as I can tell, nothing happens if I make, "the" a sysnonym for "" (nothing). If I want "the" to be pulled out of inputted commands, I have to make the synonym into " " (a space rather than nothing at all). Is this bit correct, or am I doing something silly?

The problem is that if I have a range of words all being turned into " " (a space), the commands I want to use refuse to work.

I'm trying to make the inputs "look at city", "look at the city", and so on, all respond to the command "look city", the plan being that my game won't care how shoddy the input grammar is - it'll get the basic idea. However, I can't make "look at the city" equal "look city" - instead, by blanking the words into spaces, I end up with "look city" (with three spaces). Is there a way to make Quest interpret any number of spaces as a single space?

Or am I going about this in entirely the wrong way?

paul_one
10 Aug 2006, 12:01
Erm, I can't really reply to that as such.

BUT I would like to just go back to the second post in which I remember Quest doesn't like:
command <give #object# #object2#> too much.
It'll look at "give old man old book" and seperate it into:
"give [old] [man old book]"

Does it actually work or not?

The only way I can see this working IS by coding a command with "the".
eg.
command <give #object# the #object2#>

Overcat
08 Mar 2008, 23:50
Well, well. It seems this handy trick no longer works with the newer versions of Quest. Sad. It seems that instead of 'the =' returning a null, it returns an actual " ". This means that 'look at the door' turns into 'look at__door', whereas before it turned into 'look at_door'. (_ = empty space.) Also, when I try to parse out double-spaces (or triple, quadruple, etc.) from player commands in the beforeturn script, I can't seem to get single spaces stored in a string variable. This is also mildy depressing. Can anybody think of a solution?