Page 1 of 1

Never matching parse$

Posted: Thu Dec 15, 2011 3:39 pm
by Flimbo
Help... I'm going nuts!

I'm comparing parse$ against some specific words, but even if it's EXACTLY the same, the comparison is never true.

What am I doing wrong?

Posted: Thu Dec 15, 2011 6:00 pm
by Roody_Yogurt
Yeah, parse$ can be a real pain (as implied in that other thread). What verb grammar are you using for "type"? What words are you trying to match it to?

There are several things that could be going on here so I'll need that info first.

Posted: Fri Dec 16, 2011 2:57 pm
by Flimbo
Hi Roody.

This time the verb is 'press'. Here's the grammar definition:

Code: Select all

verb "press", "tap"
  *                                     DoVague
  * (kbd_keys) "on" keys_equipped       DoPress
  * (kbd_keys)                          DoPress
Both the infamous 'PC' and the 'keyboard' are suitable xobjects for the verb (in fact both have the keys_equipped attribute).
As you can guess by the grammar definition, I also coded a 'keyboard keys' object, because the player must press some specific keys in order to do some things on the pc.

Here's the object definition:

Code: Select all

scenery kbd_keys "keyboard keys"
{
	in office
	nouns "key", "keys", "button", "buttons"
	adjectives "f1", "f2", "f3", "f4", "f5", "f12", "esc", "escape", "keyboard"
	article "the"
	is plural
}
I just didn't like the standard "You don't see that." when, for instance, you try 'press f1' outside of the office location... so I changed ParseError at case 11 this way:

Code: Select all

print CThe(actor); " don't see any ";
if InList(kbd_keys, adjective, parse$)
	print "keyboard";
else
	print parse$;
print "."
RESULT: regardless of the input, InList always returns false, finding no match whatsoever between parse$ and any of the adjectives. I tried all of them.
The printout is always: "You don't see any F1" .. or similar, which is possibly even worse than "You don't see that."

I'm puzzled... again.

Posted: Fri Dec 16, 2011 6:11 pm
by Roody_Yogurt
Whoa, that is an interesting way of doing keyboard input (using objects like that). Looks nice.

The problem I'm seeing with the Parse stuff is only not-understood words go to parse$, so checking parse$ like that isn't going to work. I'm actually kind of surprised that you are getting "F1" (or whatever else) to print at all there.

I started playing around with my own ParseError, but my initial attempts started turning into cans of worms.

There are ways to do it, but you are so, so better off just dropping the issue.

Posted: Fri Dec 16, 2011 8:11 pm
by Roody_Yogurt
Ok, I know I said just don't do it, but hey, I like that there are questions being asked on this forum and I don't like giving up on problems too easily (even if I don't think the default response would make any regular player blink twice).

It occurred to me that this is one of the times where one could use the rarely-used using-routines-in-grammar-tokens feature.

You'd have to change your grammar to the following:

Code: Select all

 verb "press", "tap"
  *                                     DoVague
  * (CanPress) "on" keys_equipped       DoPress
  * (CanPress)                          DoPress
Then, add the following routine:

Code: Select all

routine CanPress(obj)
{
if obj ~= kbd_keys
	{
	ParseError(12, obj)
	return false
	}
elseif location = office
	return true

print CThe(actor); \
MatchPlural(actor, "doesn't", "don't");
print " see any ";
local a,b,c
a = 2
c = 2

if words > 2
{
	while a <= words
	&#123;
	a++
	if &#40;word&#91;a&#93; = "", "on"&#41;
		&#123;
		--a
		break
		&#125;
	&#125;
&#125;

b = InList&#40;kbd_keys, nouns, word&#91;a&#93;&#41;

while c <= a
&#123;
print word&#91;c&#93;; 
if c<a or &#40;a=c and not b&#41;
	print " ";
c++
&#125;

if not b
	"key";
print "."
return false
&#125;
I added code to add the word "key" to any command that didn't have it, and of course, it needs the keyboard object to be "known".

You should be able to modify that to your uses.

Posted: Sat Dec 17, 2011 1:28 pm
by Ice Cream Jonsey
I had no idea you can do (Canpress) there. Wow.

I put in a good fight, but let's all acknowledge that Roody Yogurt is now the world's most informed Hugo programmer on earth.


TO ROODY!

Posted: Sat Dec 17, 2011 2:06 pm
by Bainespal
Ice Cream Jonsey wrote:I put in a good fight, but let's all acknowledge that Roody Yogurt is now the world's most informed Hugo programmer on earth.


TO ROODY!
*clap**clap**clap**clap**clap**clap**clap*

And ICJ is the world's best Hugo game author.

Posted: Sat Dec 17, 2011 4:29 pm
by Roody_Yogurt
Heh, thanks.

re: the routine thing-
When I was researching grammar tokens for HxE, it took me a fair amount of time to figure out how routines-as-grammar-tokens work. When I did eventually get it working, my initial thoughts were, man, nobody is ever going to use that (since it doesn't allow redirection to a different verb routine or anything).

Despite that, I've ended up using that feature at least a couple times. In my version of Christopher Tate's conversation system. I use it so the conversation system doesn't automatically replace DoAsk, DoTell, etc., allowing both conversation options to coexist peacefully. It actually worked out quite well.

So yeah, it's not a bad trick to have up one's sleeve.

Posted: Sun Dec 18, 2011 7:21 am
by Flimbo
Thanks Roody.

I agree with the others. That clears up how a verbroutine can be exploited as token in grammar definition.

This section of code is unclear to me, though.
Which particular case does it test?
while c <= a
{
print word[c];
if c<a or (a=c and not b)
print " ";
c++
}
I still wonder why checking parse$ against a specific word (or variable) always returns false.

Surely Kent Tessman knows.
Hopefully he's reading and let us know.

Posted: Sun Dec 18, 2011 12:41 pm
by Roody_Yogurt
That section is for printing whatever words the player used to refer to the keyboard object (kbd_keys). Like I said, words only get set to parse$ if they are not understood (or if the expected grammar token is string and the word or phrase is in quotation marks).

So, in this case, the only way to print the exact words that the player used is to check the word array one word at a time.

Posted: Sun Dec 18, 2011 12:56 pm
by Roody_Yogurt
Also, if the words you are checking against weren't previously declared in some object, the mere act of checking a word against parse$ (if parse$ = "slappy") *adds* that word to the dictionary table, thereby making it an understood word (which won't get stored in parse$).

Posted: Sun Dec 18, 2011 4:34 pm
by Flimbo
But here is what's happening on my screen.
I modified the pertaining ParseError section at case 11 this way:

Code: Select all

print CThe&#40;actor&#41;; \
" don't see any ";
if InList&#40;kbd_keys, adjective, parse$&#41;
	print "keyboard";
else
	print parse$;
print "."

"\nSearching parse$ among kbd_keys adjectives returns&#58; ";
print number InList&#40;kbd_keys, adjective, parse$&#41;

print "parse$ = "; parse$
print "word&#91;1&#93; = "; word&#91;1&#93;
print "word&#91;2&#93; = "; word&#91;2&#93;
"Comparison between parse$ and word&#91;2&#93; returns ";
if parse$=word&#91;2&#93;&#58; "TRUE"
else&#58; "FALSE"
... and here's a paste of the output when I type 'press esc' outside of the office location:
>press esc
You don't see any esc.

Searching parse$ among kbd_keys adjectives returns: 0
parse$ = esc
word[1] = press
word[2] = esc
Comparison between parse$ and word[2] returns FALSE
That I just don't understand.
Despite parse$ and word[2] are IDENTICAL, comparing one against the other returns false.

Posted: Sun Dec 18, 2011 4:50 pm
by Roody_Yogurt
I don't really know why parse$ even equals 'esc' in that example, but I actually think I can help with that other thing.

word[2] is going to be filled with a dictionary entry. parse$, by definition (I think), is not a dictionary entry. When dealing with parse$, games almost always write it to a string first before doing anything else to it. In your case, I'd then use StringDictCompare.

So, something like this:

Code: Select all

array parsestring&#91;10&#93;
string&#40;parsestring, parse$, 9&#41; ! write parse$ to string 
local a
a = StringDictCompare&#40;parsestring, word&#91;2&#93;&#41;
"Comparison between parse$ and word&#91;2&#93; returns ";
if not a &#58; "TRUE"
else&#58; "FALSE" 
(not tested)

EDIT: Tested. OK, yeah, it works.

Posted: Mon Dec 19, 2011 2:49 pm
by Roody_Yogurt
Also, I did play around with that other thing, and it seems that- for certain parse error case numbers- the engine (before ParseError is called) also throws whatever the player typed for the last object into parse$.

So, like in the above example where we are calling parse error case 11 (known object being referred to is not visible to player), parse$ gets set to whatever the player typed ("esc", "esc key", "esc button", etc.). Interestingly, the object global variable is not set at all.

Anyhow, I was trying to think of how somebody could use this feature to his advantage. Of course, the most obvious is change the style of parser error messages. I haven't yet thought of anything worthwhile and clever, though. Oh well.