Newbie Multi-Line Trigger

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Newbie Multi-Line Trigger

Post by Zaphob »

I tried around for some time, I read the manual on Trigger chains and filters, but still can't seem to capture anything past the first line.

I have some output like:
Ein Schmetterling ist absolut fit und ist damit absolut, unglaublich
schwaecher als Du. Er kaempft mit seinen Fluegeln. Er macht damit folgenden
Schaden: Schlaege. Damit kaempft er deutlich schlechter als Du. Ein
Schmetterling traegt keine zusaetzliche Ruestung. Damit ist er sehr viel
schlechter als Du geschuetzt.
Ein Schmetterling ist etwa 178cm gross.
Each line comes separately, the line breaks can be anywhere. I would like to put this together in a one line string, then search some regex in there, for example:
  • (ist absolut fit|sieht recht mitgenommen aus|braucht dringend einen Arzt) und ist damit
  • und ist damit (absolut, unglaublich schwaecher|etwa genauso stark|viel staerker) als Du
  • Damit kaempft (er|sie|es) (.*) (als|wie) Du.
  • etc.
The capture would end when the last line ends with " gross.", which it always does.

How can I combine all these lines in a single string, then test accordingly?

I assume, create a new trigger group, match the first regex above. Below the group, add more triggers. One of the triggers should just capture each line, add it to a collective string. Another trigger will end the collection on the word "gross". More triggers can then look at the collective string more specifically for the other regex above.

Any help is greatly appreciated.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Newbie Multi-Line Trigger

Post by Jor'Mox »

So, I'm just going to assume that you already have a trigger that can capture the beginning of this block of text and go from there.

First, you need some sort of indicator that you are starting a new capture. You could test the string to see if it matches your first line trigger, or you could have some sort of test variable that you reset when you reach the end (this seems easier). Then, on the first line, you initialize some global variables to hold the info for you, and use setTriggerStayOpen to extend trigger to capture later lines, though you need to set the fire length for that trigger to at least 1 in the GUI so that you can use that function with it. Then, for each line, you add the new text (from the line variable), and extend how long the trigger stays open to another line, until you reach the end, where you reset your check variable and do whatever you need to do once you have all the info you want.

Here is an example:
Code: [show] | [select all] lua
if not isOpen then   -- this checks for the first line, and initializes your variables
   text = ""
   len = 1
   isOpen = true
end

text = text .. line .. " "   -- this appends each line, with a space added in so that you don't get words running together
len = len + 1   -- this keeps track of how many lines the trigger is capturing

if string.match(line,"gross\.$") then   -- this checks to see if the current line ends with "gross.", and closes things out
   len = 0
   isOpen = false
   -- do other stuff here to actually work with all the text you just captured
end

setTriggerStayOpen("My Trigger Name Here",len)   -- this sets the number of lines for the trigger to capture
Edit: Removed the extra "not" in the last if statement so that the code will work, in case someone else wants to use it.
Last edited by Jor'Mox on Sun Oct 05, 2014 12:21 am, edited 1 time in total.

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Re: Newbie Multi-Line Trigger

Post by Zaphob »

Thanks Jor'Mox, this was very helpful indeed.

So here is what I did:
  • create a new trigger, which would be triggered by the first line of the text block to be captured.
  • set "fire length" to 1 in trigger GUI
  • put your code in the trigger
There was only one problem, I had to remove your "not" from the line which checks the match with "gross."
Now it works like a charm. I will continue to test this more and look into things like setTriggerStayOpen() now. Thanks again!

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Newbie Multi-Line Trigger

Post by Jor'Mox »

Heh. Downside of writing something in a text box... it is easy to make simple mistakes, particularly in logic, that would be impossible to make if I had actually tested it. I'm glad it worked for you. :)

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Re: Newbie Multi-Line Trigger

Post by Zaphob »

Jor'Mox wrote:you reach the end, where you reset your check variable and do whatever you need to do once you have all the info you want.
I solved some simpler patterns, but still struggle with the more complex regex. Here is another example:
(Er|Sie|Es) ist gegen (schneidenden Schaden|stechenden Schaden|reissenden Schaden) (sehr anfaellig|
geschuetzt|extrem gut geschuetzt)
How would I use the Mudlet "perl regex" trigger engine to match these patterns from the combined multi-line text?

Sure I can build my way around this and produce some more lua logic to translate above regex to basic lua string.match(), etc. - but maybe I can use the Mudlet perl regex triggers, as well?

(By the way, these examples I took from a script written for the TinyFugue client. Maybe there is a recommended way to import Tiny Fugue scripts and configuration to Mudlet?)

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Newbie Multi-Line Trigger

Post by Jor'Mox »

Well, given that the text can be broken into different lines arbitrarily, you can't really use the Mudlet trigger engine to do the pattern matching. So you need to use string.match function calls using the entire, collected text as the string to search, as it will then have been put all into one line, letting you do the necessary pattern matching.

Granted, the fact that I don't understand the language being used makes it difficult to really assess things, not that the actual text should really matter. But, unless you know where line breaks will be, you really can't use triggers to handle things, so you will have to use string.match. If you DO know where line breaks will fall, even if you don't know the order, then it is different, and you can use normal triggers and appropriate patterns to gather the information. In and of themselves, patterns like what you have should work just fine in the Mudlet trigger engine as regex triggers.

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Re: Newbie Multi-Line Trigger

Post by Zaphob »

Unfortunately, the line breaks are completely random aka when the line is full. Depending on length of names, etc, this can be at different places. So I will go the string.match way and see where it takes me.

Then again, pattern matching doesn't offer the exact functionality I try to recreate, some examples were listed above. So I need to rethink the logic, sometimes writing many lines where regex only needed 1. I will try to do so, unless I find a way to use the Mudlet trigger engine again.

I stumbled across this weird behavior.

I was under the impression, a pattern like (.-) would match the least possible number of characters, whereas (.*) would match the most greedy. If so, this does not make sense:
Code: [show] | [select all] lua
text = "Eine Biene ist absolut fit und ist damit unglaublich schwaecher als Du. Sie hat einen Bienenstachel gezueckt. Ein Bienenstachel macht folgenden Schaden: Stiche. Damit kaempft sie sehr viel schlechter als Du. Eine Biene traegt keine zusaetzliche Ruestung. Damit ist sie sehr viel schlechter als Du geschuetzt.  Eine Biene ist etwa 2cm gross."
weapon, damagetype = string.match(text, "%. (.-) macht folgenden Schaden: ([^%.]-)%.")
I would assume, damagetype would yield "Stiche" and weapon would yield "Ein Bienenstachel". Right? Well, wrong:
Code: [show] | [select all] lua
display(weapon)
"Sie hat einen Bienenstachel gezueckt. Ein Bienenstachel"
Why is that so greedy?

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Re: Newbie Multi-Line Trigger

Post by Zaphob »

Still not sure, why it was so greedy, but the following more specific pattern works as expected:
Code: [show] | [select all] lua
weapon, damagetype = string.match(text, "%. ([^%.]-) macht folgenden Schaden: ([^%.]-)%.")
display(weapon)
"Ein Bienenstachel"

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Newbie Multi-Line Trigger

Post by Jor'Mox »

Using .- will only be different from .* when it is followed immediately by some other pattern that is variable in size. It will yield characters to let the other pattern have them, so that the following pattern will get as big a match as possible, as opposed to forcing it to have the smallest match possible.

So, for example, suppose your pattern was this: (.*)([s]+), and you were matching it against: The snake said 'hiss'.
matches[2] would be "The snake said 'his", and matches[3] would be "s".

If instead you used (.-)([s]+), your matches would be "The snake said 'hi" and "ss" respectively.

Hopefully that makes sense.

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Re: Newbie Multi-Line Trigger

Post by Zaphob »

Thanks Jor'Mox. Here is yet another explanation I received:
because matching only goes in one direction (from left to right), you need to distinguish match start and match end, and you can only control greedyness of the end
the start is always as early (greedy) as possible
I am getting a better feeling for this .. slowly :D

Post Reply