Need a better way to handle this RE...

Posted by Ogomez92 on Mon 26 Apr 2010 06:30 PM — 6 posts, 21,058 views.

#0
Hi,
I really need a much better way to handle these regular expressions...
I have some RE's that I need to trigger on my mud and there are so many different ones, that they just keep triggering, and getting the wrong matches in different triggers and stuff.

Here's what i need to match...
id really appreciate some help here cuz its been like this for years and i just don't know how to do it better:
Also the sequences seem to be screwed...
Please help

trigger 1:
match="^.* (flaming|clawed|fiery|freezing|icy|venomous|poisonous) (bite|chop|snatch|crush|fiery slash|slap|kick|pierce|pound|punch|slash|slice|leaping attack|hack|claw|blast|foot|leaping attack|splat|sweep|spit|stomp|stab|whip) (scratches|hits|wounds|injures|mauls|decimates|devastates|maims|MUTILATES|DISMEMBERS|DISEMBOWELS|MASSACRES|\*\*\* MASSACRES \*\*\*|\*\*\* DEVASTATES \*\*\*|\*\*\* OBLITERATES \*\*\*|\*\*\* DEMOLISHES \*\*\*|\*\*\* ANNIHILATES \*\*\*|\*\*\* DESTROYS \*\*\*) you[!.]$"
regexp="y"
script="fight2"
group="combat"
send_to="14"
sequence="50"

2
match="^.* (bite|chop|snatch|crush|fiery slash|slice|hack|claw|foot|splat|sweep|spit|stomp|slap|kick|pierce|pound|punch|slash|stab|whip) (scratches|hits|wounds|injures|mauls|decimates|devastates|maims|MUTILATES|DISMEMBERS|DISEMBOWELS|MASSACRES|\*\*\* MASSACRES \*\*\*|\*\*\* DEVASTATES \*\*\*|\*\*\* OBLITERATES \*\*\*|\*\*\* DEMOLISHES \*\*\*|\*\*\* ANNIHILATES \*\*\*|\*\*\* DESTROYS \*\*\*) you[!.]$"
regexp="y"
script="fight22"
sequence="51"
group="combat"

<trigger
match="^.* (scratches|hits|wounds|injures|mauls|decimates|devastates|maims|MUTILATES|DISMEMBERS|DISEMBOWELS|MASSACRES|\*\*\* MASSACRES \*\*\*|\*\*\* DEVASTATES \*\*\*|\*\*\* OBLITERATES \*\*\*|\*\*\* DEMOLISHES \*\*\*|\*\*\* ANNIHILATES \*\*\*|\*\*\* DESTROYS \*\*\*) you[!.]$"
regexp="y"
script="fight3"
sequence="51"
group="combat"

match="^Your (bite|slap|slice|chop|crush|kick|pierce|pound|punch|slash|leaping attack|hack|claw|blast|foot|splat|sweep|spit|stomp|stab|whip) (scratches|hits|wounds|injures|mauls|decimates|devastates|maims|MUTILATES|DISMEMBERS|DISEMBOWELS|MASSACRES|\*\*\* MASSACRES \*\*\*|\*\*\* DEVASTATES \*\*\*|\*\*\* OBLITERATES \*\*\*|\*\*\* DEMOLISHES \*\*\*|\*\*\* ANNIHILATES \*\*\*|\*\*\* DESTROYS \*\*\*) (.*?)[!.]$"
regexp="y"
script="fight1"
sequence="50"
group="combat"

match="^Your (.*)\s*(bite|slap|slice|chop|crush|kick|pierce|pound|punch|slash|leaping attack|hack|claw|blast|foot|splat|sweep|spit|stomp|stab|whip) (scratches|hits|wounds|injures|mauls|decimates|devastates|maims|MUTILATES|DISMEMBERS|DISEMBOWELS|MASSACRES|\*\*\* MASSACRES \*\*\*|\*\*\* DEVASTATES \*\*\*|\*\*\* OBLITERATES \*\*\*|\*\*\* DEMOLISHES \*\*\*|\*\*\* ANNIHILATES \*\*\*|\*\*\* DESTROYS \*\*\*) (.*?)[!.]$"
regexp="y"
script="fight4"
send_to="14"
sequence="49"


and the group fight trig...
For when someone in the group fights something

<trigger
match="^(.*)'s (.*) (scratches|hits|wounds|injures|mauls|decimates|devastates|maims|MUTILATES|DISMEMBERS|DISEMBOWELS|MASSACRES|\*\*\* MASSACRES \*\*\*|\*\*\* DEVASTATES \*\*\*|\*\*\* OBLITERATES \*\*\*|\*\*\* DEMOLISHES \*\*\*|\*\*\* ANNIHILATES \*\*\*|\*\*\* DESTROYS \*\*\*) (\w+)[!.]$"
regexp="y"
script="gfight"
omit_from_output="y"
sequence="100"
enabled="y"
Australia Forum Administrator #1
It might be simpler to do most of the matching in a script if you can't find what is wrong. For example, the first one is really:


(someone) (adjective) (noun) (verb) (someone)[!.]


And the adjective (flaming, clawed etc.) seems to be optional.

So the regexp could be:


^(\S+) (\w+ )?(\w+) ([A-Za-z\*]+) (\S+)[!.]$


This gives us 5 wildcards:

  1. Who is doing it (eg. the mob, or "Your")
  2. The optional adjective (eg. flaming, clawed, fiery)
  3. The noun (eg. bite, chop, snatch)
  4. The verb (eg. scratches, hits, wounds)
  5. Who it is done to (eg. the mob, or "you")


Of course this rather broad regexp might match other things like chat, so we need to check for the actual words in the script.

So you might have a table like this:


adjectives = {
"",   -- in case no adjective
flaming = true,
clawed = true,
fiery = true,
-- and so on
}

nouns = {
bite = true,
chop = true,
snatch = true,
-- and so on
}

verbs = {
scratches = true,
hits = true,
wounds = true,
-- and so on
['*** MASSACRES ***'] = true,
['*** DEVASTATES ***'] = true,
-- and so on
}


Note that words with non-alphabetic things in (like '*** MASSACRES ***') need to be put in square brackets like I showed.

Now in the fight function we can quickly check if the fight words match, eg.


function fighting (name, line, wildcards)
  if not adjectives [wildcards [2]] then
    return
  end -- if wrong adjective

  if not nouns [wildcards [3]] then
    return
  end -- if wrong noun

  if not verbs [wildcards [4]] then
    return
  end -- if wrong verb

  -- seems to match:
  
  local attacker = wildcards [1]
  local attacked = wildcards [5]

  -- handle attack here

end -- function


Now you only need a single regexp, and you can add further nouns etc. to the table. This will be a lot simpler.
Amended on Mon 26 Apr 2010 09:23 PM by Nick Gammon
#2
Hi,
Thanks so much for your help. I have been converitng most of the fight functions to the new format and it's working so far.
However there is a problem...
In some cases, mobs have no weapon. So it'd say like:
Mobname hits you.
mobname *** MASSACRES *** you!
The regexp doesn't seem to match of these of course because it seems to require aa weapon.
Would it be easy to change it without having to change this format too much? Or would I need something else?
Australia Forum Administrator #3
In that case make the noun group optional too:


^(\S+) (\w+ )?(\w+ )?([A-Za-z\*]+) (\S+)[!.]$


The extra ? make the group optional.

Now you need to add an empty string in the nouns table:


nouns = {
[""] = true,  -- in case no noun
bite = true,
chop = true,
snatch = true,
-- and so on
}


(I should have put the empty string in brackets in the adjectives table too).

Your only problem now is the trailing space, so the tests could look like this:


 if not adjectives [Trim (wildcards [2]\)] then
    return
  end -- if wrong adjective

  if not nouns [Trim (wildcards [3]\)] then
    return
  end -- if wrong noun


The Trim function will get rid of leading and trailing spaces.



Australia Forum Administrator #4
I'm a little concerned the regexp may be a bit confusing to the the trigger handler (too many optional words). If it doesn't work quite right, you may need to make 3 different ones, eg.


^(\S+) ([A-Za-z\*]+) (\S+)[!.]$



^(\S+) (\w+) ([A-Za-z\*]+) (\S+)[!.]$



^(\S+) (\w+) (\w+) ([A-Za-z\*]+) (\S+)[!.]$


They could call three slightly different functions (the tables of verbs, nouns, etc. can be shared). One expects verb, the next expects noun/verb, and the third expects adjective/noun/verb.
#5
Hi,
it's working so far, but there's one problem:
What I did was to make a function that would take the number of wildcards I had, like this:
Your slash MUTILATES him!
4 wildcards.
Your
slash
MUTILATES
him
But it won't match on stuff like
Your slash *** MUTILATES *** him!
Also, it won't match:
Some mob's slash scratches you.
I've been doing this with simulate but it should probably work anyway. I did create the 3 different regular expressions though
regexp="y"
keep_evaluating="y"
script="fighting"
group="combat"
match="^(\S+) ([A-Za-z\*]+) (\S+)[!.]$"
--
match="^(\S+) ([A-Za-z\*]+) (\S+)[!.]$"
match="^(\S+) (\w+) (\w+) ([A-Za-z\*]+) (\S+)[!.]$"
match="^(\S+) (\w+) ([A-Za-z\*]+) (\S+)[!.]$"

I'm sorry I keep asking questions, I'm just not good with regexps and this is already confusing for me so I wouldn't know how to fix it.
Thanks.