[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  General
. . -> [Subject]  How to make a multiline trigger

How to make a multiline trigger

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Whininguser   Canada  (30 posts)  [Biography] bio
Date Fri 22 Oct 2010 05:52 PM (UTC)
Message
I've just read a lot on regexp, but I'm still lost...Any help would be appreciated.

How can I make a trigger fire only after the following happens:

You eat some food.
You are full.


Below is my failed attempt:

You eat some food\.\nYou are full\.

And I did have the "regular expression" box checked. Thanks for any help :)

[Go to top] top

Posted by Twisol   USA  (2,257 posts)  [Biography] bio
Date Reply #1 on Fri 22 Oct 2010 06:03 PM (UTC)

Amended on Fri 22 Oct 2010 06:05 PM (UTC) by Twisol

Message
You also need to have the "multiline" checkbox checked, with a value of 2. This lets MUSHclient know that the last two lines get parsed, not just the most recent.

Also, your regexp isn't anchored. That is, it could match on this:
ILLUSION: You eat some food.
You are full. (ILLUSION)


I believe you want to do something more like this, although I haven't used multiline triggers very extensively.
\AYou eat some food\.\nYou are full\.\Z

\A only matches at the start of the target, so there can't be anything before the "You". Likewise, \Z only matches at the end of the target, so there can't be anything after "full.".

Little note: When you use single-line triggers with regular expressions, you usually use ^ instead of \A, and $ instead of \Z. ^ matches the start of a line, and $ matches the end of one. Because MUSHclient guarantees that you're only going to get one line in a single-line trigger, this is safe and more idiomatic.


[EDIT] Disclaimer: This is untested, I don't have access to MUSHclient at the moment.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
[Go to top] top

Posted by Whininguser   Canada  (30 posts)  [Biography] bio
Date Reply #2 on Fri 22 Oct 2010 06:18 PM (UTC)

Amended on Fri 22 Oct 2010 06:22 PM (UTC) by Whininguser

Message
Your trick worked! Thank you for the fast and detailed reply!

[Go to top] top

Posted by Whininguser   Canada  (30 posts)  [Biography] bio
Date Reply #3 on Fri 22 Oct 2010 07:04 PM (UTC)

Amended on Fri 22 Oct 2010 07:32 PM (UTC) by Whininguser

Message
I have another question. Suppose the output could be either


You eat some food.
You are full.


or just


You eat some food.



How can I make a trigger fire only when "You eat some food" happens but not when both lines happen?

Once again, my codes failed:


You feel slightly better\.(?!\nYou are now fully healed\.)



You feel slightly better\.\n(?!You are now fully healed\.)


I also tried placing (\A \Z) and (^ $) at different places.
Thanks for any help :)


[Go to top] top

Posted by Twisol   USA  (2,257 posts)  [Biography] bio
Date Reply #4 on Fri 22 Oct 2010 07:37 PM (UTC)

Amended on Fri 22 Oct 2010 07:44 PM (UTC) by Twisol

Message
Yep, this is a trickier situation. MUSHclient can't automatically deal with variable-line triggers, but your first example is two lines, and the second is one.

But let me ask you this. At the point where you get "You eat some food", how do you know what's coming next? You can't tell if that's all there was, or if there's still more coming (perhaps due to network latency). If you only got "You eat some food", you can't assume that's all there is.

Now, I assume your MUD has a prompt line that comes after pretty much everything. That means we have something a bit more like this:

You eat some food.
You are full.
100h 100m >

or

You eat some food.
100h 100m >

Now, this is what I would do: I would have one trigger for each of these lines. (Be sure to set "Keep evaluating", or other triggers won't be able to match the prompt.) Only the first is enabled to begin with. When it matches, it enables the other two. Next, if we get "You are full.", we set a variable to true. Lets call it is_full.
is_full = true


Notice that the fullness trigger doesn't actually do anything yet. We wait until the prompt trigger to do that:
if is_full then
  -- do stuff for being full
  is_full = false -- reset is_full for next time!
end
-- do more stuff whether we're full or not
EnableGroup("this_group_here", false) -- disable the triggers again


With this approach, by the way, you don't use multiline triggers. I call this technique a "gate" or a "guard", because you have to match one trigger before you can match another. It's a more general solution than multiline triggers: anything that can be done with a multiline can also be done with gates (and more besides).

[EDIT]: Lots of little fixes and additions to this post.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Fri 22 Oct 2010 07:44 PM (UTC)
Message
This worked for me:


<triggers>
  <trigger
   enabled="y"
   group="forum"
   lines_to_match="2"
   match="\A(?&lt;!You eat some food\.)\nYou are full\.\Z"
   multi_line="y"
   regexp="y"
   send_to="2"
   sequence="110"
  >
  <send>********* Full.</send>
  </trigger>

  <trigger
   enabled="y"
   group="forum"
   lines_to_match="2"
   match="\AYou eat some food\.\n(?!You are full\.)\Z"
   multi_line="y"
   regexp="y"
   send_to="2"
   sequence="110"
  >
  <send>********* Eaten.</send>
  </trigger>

  <trigger
   enabled="y"
   group="forum"
   lines_to_match="2"
   match="\AYou eat some food\.\nYou are full\.\Z"
   multi_line="y"
   regexp="y"
   send_to="2"
   sequence="110"
  >
  <send>********* Eaten and full.</send>
  </trigger>
</triggers>


The last one is what you had before. The first uses a negative lookbehind assertion to check that "You are full" is not preceded by "You eat some food".

The second uses a negative lookahead assertion to check that "You eat some food" is not followed by "You are full".

Template:pasting For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Fri 22 Oct 2010 07:46 PM (UTC)
Message
Of course, these are all still 2-line triggers. So simply getting "You eat some food" will not cause anything to happen (because we don't know yet whether it will be followed by "You are full", or not).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Twisol   USA  (2,257 posts)  [Biography] bio
Date Reply #7 on Fri 22 Oct 2010 07:50 PM (UTC)
Message
Nick Gammon said:

Of course, these are all still 2-line triggers. So simply getting "You eat some food" will not cause anything to happen (because we don't know yet whether it will be followed by "You are full", or not).


This doesn't work for me, though:
/Simulate("You eat some food.\r\nHmm.\r\n")

If I remove the "Hmm." (but leave in the second \r\n), it works.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
[Go to top] top

Posted by Whininguser   Canada  (30 posts)  [Biography] bio
Date Reply #8 on Fri 22 Oct 2010 08:07 PM (UTC)

Amended on Fri 22 Oct 2010 10:48 PM (UTC) by Whininguser

Message
Problem solved. Thank you both!
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Fri 22 Oct 2010 08:27 PM (UTC)
Message
Twisol said:

This doesn't work for me, though: ...


I think this amended one works for that case:


<triggers>
  <trigger
   enabled="y"
   group="forum"
   lines_to_match="2"
   match="\A.*(?&lt;!You eat some food\.)\nYou are full\.\Z"
   multi_line="y"
   regexp="y"
   send_to="2"
   sequence="110"
  >
  <send>********* Full.</send>
  </trigger>

  <trigger
   enabled="y"
   group="forum"
   lines_to_match="2"
   match="\AYou eat some food\.\n(?!You are full\.).*\Z"
   multi_line="y"
   regexp="y"
   send_to="2"
   sequence="110"
  >
  <send>********* Eaten.</send>
  </trigger>

  <trigger
   enabled="y"
   group="forum"
   lines_to_match="2"
   match="\AYou eat some food\.\nYou are full\.\Z"
   multi_line="y"
   regexp="y"
   send_to="2"
   sequence="110"
  >
  <send>********* Eaten and full.</send>
  </trigger>
</triggers>


I needed to add ".*" to the negative assertions to absorb the stuff they there were not.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Twisol   USA  (2,257 posts)  [Biography] bio
Date Reply #10 on Fri 22 Oct 2010 08:40 PM (UTC)
Message
Nick Gammon said:
I needed to add ".*" to the negative assertions to absorb the stuff they there were not.

You'd probably want Keep Evaluating, too, or the .* lines will never be matched by lower-sequence triggers. Looks good! I still think multi-lines are pretty fiddly though.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Fri 22 Oct 2010 09:25 PM (UTC)
Message
Twisol said:

You'd probably want Keep Evaluating, too, or the .* lines will never be matched by lower-sequence triggers.


Good point.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Whininguser   Canada  (30 posts)  [Biography] bio
Date Reply #12 on Thu 28 Oct 2010 11:27 PM (UTC)

Amended on Fri 29 Oct 2010 06:34 AM (UTC) by Whininguser

Message
Edit:
The problem has been solved. Just in case anyone is replying to this post, I won't delete it. However, if you have a better solution, please post. Thanks :)
-------------------------------------------------

I have another long question: How can I make a trigger for a 3-line output like below?

1. The first two lines can be anything except "one" and "two"
2. The last line must be "last"

(In short: !one and !two and last)

Examples:

Match:
any
thing
last

No match:
one
two
last

No match:
any
two
last


I tried these and none worked:


\A(?!one)\n(?!two)\nlast\Z

\A(?!one)\n(?!two)\nlast.*\Z

\A(?<!one)\n(?<!two)\nlast\Z

\A(?<!one)\n(?<!two)\nlast.*\Z


Regexp was checked and multi-line was set to 3.

Thanks for any help :)


---------------------------------------------
Edit: This one finally worked :D
\A(?!one).*\n(?!two).*\nlast.*\Z

[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


28,113 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]