Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion Goto page 1, 2  Next
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Thu Mar 27, 2008 5:14 pm   

Some more regex trigger issues
 
Pattern: .* tells you (.*\(.*\)) '.*'

Isn't firing for tells like these:

Kadence tells you 'oh?'
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Thu Mar 27, 2008 5:33 pm   
 
Because of the brackets and spaces that aren't optional. The minimum your pattern will match is " tells you () ''", which doesn't match that tell. Use one of the more complex patterns we suggested.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Thu Mar 27, 2008 5:49 pm   
 
So something like:

Code:
^(?:(\w+) tells you(?: \(\w+\))?$
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Dharkael
Enchanter


Joined: 05 Mar 2003
Posts: 593
Location: Canada

PostPosted: Thu Mar 27, 2008 8:07 pm   
 
If its just a regular trigger something like
Code:
^(%w) tells you '(*)'$

or
Code:
^(*) tells you '(*)'$


or if its a REGEX trigger
Code:
^(.*) tells you '(.*)'$

If its a regex and you dont want to capture a subgroup
change the opening ( to (?: on that subgroup
_________________
-Dharkael-
"No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style."
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Thu Mar 27, 2008 8:17 pm   
 
Couple of problems with that:

You haven't closed all the brackets (or parens if you like :P) that you've opened. Your pattern doesn't include the speech part of the pattern, between the quotes, but does include the end of the line, so it's going to fail there too.

I suggested a pattern in another thread (don't remember which one, you've started a few :P) that worked for tells to you in languages and your tells to people and your group. I know that one works fine for all your different kinds of tells because I tested it with the text you gave.

EDIT: Ninja'd by Dhark. Just for clarification, I was talking to the OP.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Thu Mar 27, 2008 8:52 pm   
 
Alright, the one I took was from a larger one that you posted, probably explaining the unclosed brackets. At this point, there have been so many versions posted that I'm not sure which you refer to. But I may uninstall and reinstall CMUD anyways.
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Thu Mar 27, 2008 8:56 pm   
 
Post the one you're using, and I'll tell you if it'll work or not, but the one you took that part from is the one I'm talking about, IIRC.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Thu Mar 27, 2008 8:58 pm   
 
The one I'm using isn't working Razz
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Dharkael
Enchanter


Joined: 05 Mar 2003
Posts: 593
Location: Canada

PostPosted: Thu Mar 27, 2008 9:10 pm   
 
Post it anyways then we'll have a starting point.
_________________
-Dharkael-
"No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style."
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Thu Mar 27, 2008 9:20 pm   
 
I'm going to revert back to something simple

* tells you (*) '*'|* tells you '*'
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
oldguy2
Wizard


Joined: 17 Jun 2006
Posts: 1201

PostPosted: Thu Mar 27, 2008 9:26 pm   
 
That may be simple but it's about the worst thing you can do. Everyone showed you how to match the pattern.

First of all though, you should clarify a couple things.

1. At the beginning of the pattern the name of the person telling you, is it always one word like Bob tells you or do they have titles attached or multiple words like Bob, the warrior?

2. Where you have (*) for the type of language, is the language always one word like Elvish or can it be more than one word like Northern Elvish?
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Thu Mar 27, 2008 9:36 pm   
 
Language is always one word so far as I know. Name is always one word.

I don't want to use something I don't understand.
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
JQuilici
Adept


Joined: 21 Sep 2005
Posts: 250
Location: Austin, TX

PostPosted: Fri Mar 28, 2008 1:16 am   
 
The reason that oldguy2 calls that pattern 'the worst' is simply that it will be VERY slow, both to match or to reject a match, because of all the greedy '*' quantifiers. If you know that, say, the name at the beginning of the line is always a single word, you can replace that '*' with a regex that will match only letters ('%w' in zScript patterns, or \w in a regex), and the whole thing will be a lot faster.

So, let's tackle this step-by-step. You want to match:
  1. The beginning of the line
  2. Followed by a name, consisting of a single word
  3. Followed by the literal string 'tells you'
  4. Optionally followed by a language name, consisting of one word surrounded by parens
  5. Followed by an arbitrary string surrounded by single-quotes
  6. Followed by the end of the line
right?

I'm going to do this in a regex, rather than a zScript pattern, simply because I'm more familiar with them. I will also explain my thinking in extreme detail.

Step #1 - Match the beginning of the line. That's easy, it's just the special character '^'. So far, so good.

Step #2 - Match a name, consisting of a single word. Well, we could use '.*', which will match any string of characters. However, that will also match a lot of other things, and it's horribly inefficient as well. So let's use something more specific.

Wait, wait, you say....why is it inefficient? Because '*' is a greedy quantifier - it tries to match as long a string as possible, and only gives up a character at a time if it fails. So, using '.*' will cause the regex engine to absorb the entire rest of the subject string, then try to match the rest of the regex. If that doesn't work, it will put back the LAST character that the '.*' absorbed, then try to match the rest of the regex again. If that also fails, it will put back one more character, and try to match the rest of the regex. And so on, and so on. As you can see, it could do a LOT of work to decide that something doesn't match. Or even to figure out what DOES match.

So...what would be better? Well, we know that the name is a single word, consisting of letters, and no spaces. To do so, first we figure out a regex that will match ONE letter. That's easy: '[a-zA-Z]' will do the trick. Or we can use the shorthand '\w', which will actually match any letter, digit, or the underscore ('_') character. We want to match one or more of those characters in a row, so we put the '+' quantifier after the letter. Put it all together, and we have '\w+', which will match a single word.

So, our whole pattern now is
Code:
^\w+


Step #3 - The literal string 'tells you'. Literals are easy - just type 'em in. Actually, we also want to match the spaces at the beginning and end of that literal, so let's be sure they are in, too. So now, the whole pattern is
Code:
^\w+ tells you


Step #4 - An optional single word in parens. Hrm...need to break that down. We already know how to match a single word, with '\w+'. To match a word with parens around it, we just type the parens - '(\w+)' - right? Unfortunately, no. Parens are 'special characters' in a regex (more on this later), so we have to put a backslash before each one to tell the regex engine that we mean a real, literal paren, and not the special meaning of the parens. That gives us '\(\w+\)'.

So far, so good. But how do we make it 'optional'? We use another quantifier - '?' - which tells the engine to match zero-or-one instances of the regex it follows. So we have '\(\w+\)?', which will match either (a) nothing, or (b) a word inside parens...right?

Not exactly. The '?' quantifier only modifies the thing RIGHT before it...in this case, the close paren. So that pattern would match an open paren, a word, and an optional close paren. We want the WHOLE THING to be optional. How do we group the whole thing, so that the '?' will apply to it all together?

Remember that I said the parens were special characters? Well, their special meaning is to create groups for just this sort of thing. So, if we put our pattern inside parens, and put the '?' after it, then the whole expression inside the parens becomes optional together. Thus, what we need is '(\(\w+\))?'.

So our pattern is now
Code:
^\w+ tells you (\(\w+\))?


Step #5 - An arbitrary string in single quotes. The initial single quote is easy - it's another literal.

Next...an arbitrary string. Hrm. First, we need another special character - '.' - which will match any character whatsoever. And we want to match any number of them. Well, there's no help for it, we'll HAVE to use the greedy * this time. The efficiency won't really be a problem, though, since there's very little left in the pattern after this, so the greedy star SHOULD consume most of the string (if we've really got a match), and won't have to give much back. Also, since we've gotten this far into the pattern, it's fairly likely that we will have a match, so the efficiency at rejecting matches won't matter much either. So that part of the pattern is '.*'.

And we wrap up with a final literal single-quote. So our whole pattern now is
Code:
^\w+ tells you (\(\w+\))? '.*'


Step 6 - Match the end of the string. Again, easy. The '$' special character matches the end of the string. So, we've got:
Code:
^\w+ tells you (\(\w+\))? '.*'$


Great! We're done!

But...um...well, not quite. If you try that, you'll find that it matches correctly when there is a language present, but WON'T match if there isn't. Can you see why?

The problem is that we have an extra space in there if no language is present. If the 'optional' part of the regex matches NOTHING, our pattern still shows a space before AND after the 'nothing'....or two spaces. We only want to match ONE space in that case.

So, we have to fix it by moving one of the spaces inside the 'optional' part, so that that space will only be part of the pattern if the language is also there. So our final expression is:
Code:
^\w+ tells you (\(\w+\) )?'.*'$


Easy enough, right?

Final finesse: The other special meaning of parens is to create a 'backreference', which you can access afterward using the %pat() function or the %<number> predefined variables. In our current pattern, we only have one backreference (remember that the other set of parens - the ones with the backslashes - are just literals, with no special meaning). So, we could actually get the language name, if one were present, using %pat(1) or %1 inside this trigger.

But what if we want to access the name of the person doing the telling? Or the message he told? Or, for that matter, the name of the language WITHOUT the parens around it?

We just add more parens! This will allow access to all three of the interesting strings:
Code:
^(\w+) tells you (\((\w+)\) )?'(.*)'$
The name will be in %1, the language in %3 (%2 will have the language name AND the surrounding parens and the trailing space), and the message in %4.

To make it even better, we could tell the engine not to bother storing the pattern matched by the second set of parens, since we don't want it (we want the third one instead, for the language name). That uses the syntax '(?:regex)' in place of the '(regex)' we've used so far. Thus, the whole pattern now is
Code:
^(\w+) tells you (?:\((\w+\) )?'(.*)'$
and now %1 is the name, %2 is the language (if any), and %3 is the message.

See...simple! Wink
Code:
#REGEX {^(\w+) tells you (?:\((\w+)\) )?'(.*)'$} {#say name: %1;#say language: %2;#say message: %3}
_________________
Come visit Mozart Mud...and tell an imm that Aerith sent you!
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Fri Mar 28, 2008 2:39 am   
 
This looks helpful, I'll read it when I get more time :)
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 2:20 am   
 
Wow, it is simple. I feel a it stupid. I'll still make many errors I'm sure. But I have a better grip on it now. Thanks.
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 2:29 am   
 
odd...

#REGEX Ding on Tell {^(\w+) tells you (?:\((\w+)\) )?'(.*)'$} {#play C:\WINDOWS\Media\ding.wav} {General Triggers}

doesn't put it in the General Triggers class, it makes a new one with the command as the name??
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Dharkael
Enchanter


Joined: 05 Mar 2003
Posts: 593
Location: Canada

PostPosted: Tue Apr 01, 2008 2:34 am   
 
Try

Code:
#REGEX  Ding_on_Tell {^(\w+) tells you (?:\((\w+)\) )?'(.*)'$} {#play C:\WINDOWS\Media\ding.wav} {General Triggers}
_________________
-Dharkael-
"No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style."
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 2:46 am   
 
Hmm, I figured CMUD was fine with white space. I'll try it.
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 2:47 am   
 
oh wait, that was the one that worked!

It's this one...

#REGEX Tell Capture {^(\w+) tells you (?:\((\w+)\) )?'(.*)'$} {#CAP Tells} {General Captures}

Oh no, it was the one. But this one didn't work either, same problem I suppose.
Reply with quote
Dharkael
Enchanter


Joined: 05 Mar 2003
Posts: 593
Location: Canada

PostPosted: Tue Apr 01, 2008 2:48 am   
 
Code:
#REGEX "Tell Capture" {^(\w+) tells you (?:\((\w+)\) )?'(.*)'$} {#CAP Tells} {General Captures}

_________________
-Dharkael-
"No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style."
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 3:02 am   
 
Hmm... so I tried to make my own with this info:

#REGEX You_Tell {^You tell \w+ (\(\w+\) )? '.*'$} {#CAP Tells} {General Captures}

But it doesn't work...

You tell Kadence (Elvish) 'blah'

doesn't work.
Reply with quote
Dharkael
Enchanter


Joined: 05 Mar 2003
Posts: 593
Location: Canada

PostPosted: Tue Apr 01, 2008 3:13 am   
 
Use a regex similar to your "Tell Capture" trigger

Code:
^You tell \w+ (?:\((\w+)\) )?'(.*)'$
_________________
-Dharkael-
"No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style."

Last edited by Dharkael on Tue Apr 01, 2008 3:14 am; edited 1 time in total
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 3:14 am   
 
all I say see that's different is the ?: what makes it so crucial?
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Dharkael
Enchanter


Joined: 05 Mar 2003
Posts: 593
Location: Canada

PostPosted: Tue Apr 01, 2008 3:25 am   
 
You're correct you just had an extra space in your pattern
the \) )? instead of \))?

or you could look at it like you had an extra space after the \) )?
_________________
-Dharkael-
"No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style."
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Apr 01, 2008 3:28 am   
 
I put the space in because of the earlier mentioned thing about spaces being optional... why was it wrong?
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net