my pattern (does|doesnot) work

psymann
06 May 2013, 21:06
Hello all,

Is there any good thread or info about how to get the most out of command patterns?

I've managed to work out I can do:

attach tail (to|on) donkey

rather than

attach tail to donkey; attach tail on donkey


I've managed to work out I can do

attach #objecttoattach# on #objecttarget#

...although I'm not sure if I can use both of these together.

...and I am having trouble using it in scripts afterwards - should I be able to do:

if (objecttoattach.name = "tail") {
if (objecttarget.name = "donkey") {
msg ("you pin the tail on the donkey")
}
}

because that's roughly what I think I'm trying and not convinced it's working; it just gives me "that doesn't work" which implies I've got the command pattern so wrong it doesn't even know how to run the test properly or something

Too confused at the moment to ask a sensible question, so wondering if there's any guide of sorts already written? I did read the tutorial, but that doesn't deal with my requirement above to check what the #object# actually is before knowing what response to give.

Thanks,

confused psy

jaynabonne
06 May 2013, 21:23
I'm not sure what state your code is in, but this works for me:

  <command>
<pattern>attach #objecttoattach# on #objecttarget#</pattern>
<script>
msg ("toattach=" + objecttoattach + ", target=" + objecttarget)
</script>
</command>


The text "That doesn't work" is the default response for a multi-verb (which is not a command). So somehow, it's not seeing your command - or you have conflicting verb somewhere. One thing to be sure is that your command is visible in the room you're in (e.g. not tucked away in some other room) and that you haven't created something else as well that might be competing.

psymann
06 May 2013, 21:36
Aha, yep, I think one of my problems may well be a conflict - almost certainly because I'm doing something in some peverse way due to walking in blindly and coding stuff without looking properly!

I have a command that does:

attach #objecttoattach# to #objecttarget#

which ought to do the clever action I want it to do...

...but I also have a verb that does:

attach #object#

which just says "You'll need to attach it to something" to tell them they need to use the pattern 'attach ... to'.


So I guess those two things are competing. Perhaps the verb thinks I'm trying to 'attach' a 'tail to donkey' and then doesn't know what a 'tail to donkey' is, and gives me the problem? Or something.

Which almost certainly means I'm doing it the wrong way, and should be using one command to handle both the 'attach ... to' pattern and also the result when someone just does the 'attach' part withou the '... to'.

This may be related to the fact I've never yet worked out what the "multiple objects" section on the GUI for Verbs is for ;-)

psy

jaynabonne
06 May 2013, 21:49
You can do something like this:

	  <command>
<pattern>attach #objecttoattach# to #objecttarget#; attach #object#</pattern>
<script>
if (IsDefined("object")) {
msg("You need to attach " + GetDisplayAlias(object) + " to something else.")
} else {
msg ("toattach=" + objecttoattach + ", target=" + objecttarget)
}
</script>
</command>


This handles both cases. Note that you must have the less specific command second; otherwise, it will match your first case. (In other words, if you have them reversed, then it will match "attach #object#" for both cases.)

psymann
06 May 2013, 22:08
Ah, thanks jay :D


Presumably I could also do this:

<pattern>attach #objecttoattach# (to|onto|on) #objecttarget#; attach #object#</pattern>

?

What about this?

<pattern>(attach|fix|affix) #objecttoattach# (to|onto|on) #objecttarget#; (attach|fix|affix) #object#</pattern>


Or does starting with a (xxx|yyy) thingy cause problems?

psy

jaynabonne
06 May 2013, 22:16
To be honest, I wasn't sure, so I tried it. :) And it didn't work. But what you added looks more like a regular expression than a simple pattern. Perhaps this will help:

http://quest5.net/wiki/Pattern_Matching

Now I'm going to go study it as well... ;)

psymann
06 May 2013, 23:47
That page you linked me to was very helpful, thanks.

So I think the reason my code didn't work was due to about three different overlapping issues - no wonder I wasn't sure where to start ;-)


1) I had "attach with" command and also "attach" verb which conflicted with each other

2) I had tried to use the (xxx|yyy) syntax as part of a "Command Expression". I now know that this syntax only works as part of a "Regular Expression" ... to be honest until just now I hadn't even realised there was an option to select "Regular Expression" instead!

3) But if I use "Regular Expression", then I need to go the whole hog and do it entirely like that with all the little ^'s and $'s and so on - fortunately that link you gave me not only shows what needs to go in, but explains what it means, so I can follow why I'm putting in what I'm putting in.

And then the additional problem is that as soon as I use "Regular Expression", the semicolon syntax stops working, so I then can't tag on the "; attach [singlething]" on the end.


So what I now have - that works for "attach to" but doesn't work for "attach" - is this:

^(attach|fix) (?<objecttoattach>.*) (to|onto) (?<objectarget>.*)$


But the following of my best-but-useless-attempts-to-make-it-work all fail:

^(attach|fix) (?<objecttoattach>.*) (to|onto) (?<objectarget>.*)$; ^(attach|fix) (?<objectsingle>.*)

(^(attach|fix) (?<objecttoattach>.*) (to|onto) (?<objectarget>.*)$ | ^(attach|fix) (?<objectsingle>.*))

(?(^(attach|fix) (?<objecttoattach>.*) (to|onto) (?<objectarget>.*)$) ^(attach|fix) (?<objecttoattach>.*) (to|onto) (?<objectarget>.*)$ | ^(attach|fix) (?<objectsingle>.*) )


And after that, I ran out of ideas ;-)


Ah---

But I'm starting to wonder if that is indeed the right thing to be trying to do. Because if I look at the library commands, there's a "give" command, and a completely separate "givesingle" command.


GIVE COMMAND (Regular Expression): ^give (?<object1>.*) to (?<object2>.*)$

GIVE SINGLE COMMAND (Command Pattern): give #object#


So perhaps I should indeed be trying to have separate "Attach To" and "Attach" commands?
I wonder whether I then just need to make sure that the "Attach To" command is lower down in the code than the "Attach" command, so that when Quest reads the code upwards, it tries to match "Attach To" first.

...so I've just tried that, and it works for me - even though the "Attach" command is lower down than the "Attach to" command. So somehow it's able to realise that if I say "Attach tail to donkey", I want to use the "Attach to" command, yet it also knows that if I say "Attach donkey tail" that I'm looking for it to use the "Attach" command.

I have a feeling I still don't quite understand how it's doing what it's doing, which worries me a little, but I do seem to have solved the issue with your excellent help once again, which pleases me a little more :-)

psy

jaynabonne
07 May 2013, 00:02
Actually, you were very close with your second one. You had the right idea! This works:

(^(attach|fix) (?<objecttoattach>.*) (to|onto) (?<objectarget>.*)$|^(attach|fix) (?<objectsingle>.*)$)

The problem you had is that spaces *do* matter; they must exist to be matched. You had a space before and after the central |. That means it would only match the first half if there was a space after the end of line (indicated by '$'), and it would only match the second if there was a space before the start of line (indicated by '^'). Clearly, none of those cases is even possible. So I got rid of those. I also added an "end of line" character ('$") on the end just for completeness, but it worked without it.

If you prefer the separate entities and it works, then you can go for that as well.

psymann
07 May 2013, 00:46
Gah, so close but yet so far!
It's nicer having them both in the same place, so I've switched to that, thanks. :D


And my new problem, which also appears to be to do with spaces, is that although:

(attach|fix|pin) (?<objecttoattach>.*) (to|with) (?<objecttarget>.*)


works,

(attach|fix|pin|pin up) (?<objecttoattach>.*) (to|with) (?<objecttarget>.*)


doesn't work (ie the "pin up" bit doesn't work) :(


I'm wondering if the "|" operator only works with single words without spaces perhaps?

Which is a shame as there are a few commands I may have where I have a two-word 'verb'.


psy

george
07 May 2013, 06:29
The problem could be that it's matching 'pin' before 'pin up'. Try doing (pin up|pin) instead.

edit: this might help -- http://www.regextester.com/ (there are others, you'll find with a search)

jaynabonne
07 May 2013, 08:29
George has it exactly right. Change it to:

(attach|fix|pin up|pin) (?<objecttoattach>.*) (to|with) (?<objecttarget>.*)

and it should work.

psymann
07 May 2013, 09:41
It works! Oh joy!

Whoo!

Thanks!

psy