Trigger match failed for the sequential of wait.regexp() and Execute()

Posted by Zhenzh on Sat 20 Jul 2019 04:38 PM — 20 posts, 71,756 views.

China #0
Sometimes, I find my trigger(whhich has successfully worked for hundreds times) doesn't work thought the output from the screen has matched the trigger. And it will get work again when a new line includes matched string comes.

I guess there may some issue during mush client pass the exact data to the trigger form back-end such as interrupted by some unexpected ASCII character.

Is it possible to print out those back-end data which is used for trigger matching before they are processed and shown in front-end screen by mush client?
USA Global Moderator #1
Try: Edit menu -> Debug Packets
Australia Forum Administrator #2
Template:version
Please help us by advising the version of MUSHclient you are using. Use the Help menu -> About MUSHclient.


See https://www.gammon.com.au/scripts/showrelnote.php?version=5.06&productid=0 -> point 13.

Also see: http://www.gammon.com.au/forum/bbshowpost.php?id=13797
China #3
I have found out the root cause of my trigger issue. It should be caused by the new line not being separated.

Here's the data received when trigger works

Incoming packet: 450 (968 bytes) at 星期一, 七月 22, 2019, 12:24:53 上午

.[1;36m.........   1b 5b 31 3b 33 36 6d c4 e3 b4 f3 ba c8 d2 bb c9
................   f9 c1 a2 ca b1 ce e4 b9 a6 d5 d0 ca c6 c6 e6 bb
................   c3 ce de b7 bd a3 ac b5 b6 bd a3 d5 d0 ca c6 c4
......
0m )...[0;0m> ..   30 6d 20 29 0d 0a 1b 5b 30 3b 30 6d 3e 20 ff f9
................   c4 e3 b4 d3 cf d6 d4 da c6 f0 d3 c3 d0 fe cc fa
................   bd a3 b7 a8 d7 f7 ce aa bb f9 b1 be bd a3 b7 a8
...............[   b5 c4 cc d8 ca e2 bc bc c4 dc a1 a3 0d 0a 1b 5b
0;0m> ..           30 3b 30 6d 3e 20 ff f9

Incoming packet: 451 (40 bytes) at 星期一, 七月 22, 2019, 12:24:53 上午   (the line to be matched by the trigger)

................   0d 0a b5 d2 bf f8 ee b8 b5 b9 d4 da b5 d8 c9 cf
................   a3 ac d5 f5 d4 fa c1 cb bc b8 cf c2 be cd cb c0
........           c1 cb a1 a3 0d 0a 0d 0a


And here's the data received when the trigger doesn't work

Incoming packet: 13787 (583 bytes) at 星期日, 七月 21, 2019, 10:39:21 下午

...[0;36m.......   0d 0a 1b 5b 30 3b 33 36 6d c4 e3 b5 b1 d0 d8 c6
................   bd c6 bd b4 cc b3 f6 d2 bb bd a3 a3 ac ca b5 d4
................   da ca c7 ba c1 ce de c8 ce ba ce b1 e4 bb af a3
......
..............(    bd a6 b5 c3 c2 fa b5 d8 a3 a1 a3 a1 0d 0a 28 20
.......[0;31m...   d3 a2 ce ed bc b0 1b 5b 30 3b 33 31 6d d2 d1 be
................   ad cf dd c8 eb b0 eb bb e8 c3 d4 d7 b4 cc ac a3
................   ac cb e6 ca b1 b6 bc bf c9 c4 dc cb a4 b5 b9 d4
......[0;0m )...   ce c8 a5 a1 a3 1b 5b 30 3b 30 6d 20 29 0d 0a 0d
................   0a d3 a2 ce ed bc b0 b5 b9 d4 da b5 d8 c9 cf a3
................   ac d5 f5 d4 fa c1 cb bc b8 cf c2 be cd cb c0 c1
.......            cb a1 a3 0d 0a 0d 0a


Compare the two data, I find the match line "b5 b9 d4 da b5 d8 c9 cf a3 ac d5 f5 d4 fa c1 cb bc b8 cf c2 be cd cb c0 c1 cb a1 a3 0d 0a 0d 0a" which is expected to be a single line was not successfully separated to a new line by the mush client. Which may cause the trigger match failure.

How's the mush client judge a new line from data sent by the mud server?
Australia Forum Administrator #4
Did you read this thread?

http://www.gammon.com.au/forum/?id=13797

It looks like your match is failing when there is an ANSI code in the middle of the packet: \[0;0m

Are you using Unicode (UTF8) or Big5?
Australia Forum Administrator #5
Zhenzh said:

How's the mush client judge a new line from data sent by the mud server?


When it gets a newline character (0x0A). Any wrapping you see on the screen is "soft" wrapping that should not affect triggers.
Australia Forum Administrator #6
Zhenzh said:

which is expected to be a single line was not successfully separated to a new line by the mush client. Which may cause the trigger match failure.


What do you mean by "successfully separated to a new line"?
China #7
The word "separated to a new line" I mentioned may not accurate, it should be thought as a new incoming packet, isn't it?

As I pasted, the good trigger received the match line as a individual packet, head with "Incoming packet: 451 (40 bytes)", while the bad trigger merge the match line with previous output in one packet. That's the only difference I found between the good and bad cases.

I used to think that's the root cause. But I don't think so now. As I find no metter a match line in a new packet or not, both good and bad case may happen.
China #8
I'm using GB2312.

I have read the link http://www.gammon.com.au/forum/bbshowpost.php?id=13797 and find there is a plugin help to processing ANSI color codes. Seems it's for big5 only?

I have never considered the issue is caused by some ANSI color code. Though some color cod such as "[0;0m )" appear in my Chinese MUD, the line used for my trigger matching do not contain any color code.

Anyway, I can have a try to see if the color_remove plugin helps fixing such issue if a version supports GB2312 is available.
Australia Forum Administrator #9
The client is designed to ignore packet breaks. The underlying TCP/IP system may break packets anywhere. Therefore there is a state machine that seamlessly handles data, whether or not it is in the same packet.
China #10
After some test, I have isolated the issue.

The issue only occurs at trigger created by wait.regexp.

I have two triggers created for the test. One is manually created from trigger menu and the other is created by wait.regexp. The manually created trigger works every time while the wait.regexp trigger has chance get trigger failure.

I guess it may caused by the point of time the trigger is created.

I used to use wait.regexp like below:

Execute("say it is a test")
wait.regexp("it is a test")


The manually created trigger definitely exists before the match line coming. So it's able to work every time.

While the wait.regexp creates the trigger just after the match line is generated. There is a chance that the match line comes while trigger has not been created by wait.regexp.
China #11
I know using DoAfter over Execute() may be a work around to solve such issue. There still be a chance the wait.regexp can not create the trigger in time for some network issue.

Is there a better way to use the wait.regexp() to ensure the trigger will always be created before the match line generated by Execute()?
Australia Forum Administrator #12

I can’t help thinking this is an XY Problem.

What are you really trying to do here?

You are saying “this is a test” and then afterwards you are making a trigger to detect that. Why not make the trigger before?

wait.regexp basically sets up a trigger.

China #13
If do wait.regexp first, the script will be paused to wait the match line coming so that the next action, Execute() will not be happened until the regexp detecting the match line or timeout.

While the problem is the match line is generated by the action of Execute(). So the regexp will never be triggered as the action to generate match line is held by regexp itself.
Amended on Fri 26 Jul 2019 06:57 AM by Zhenzh
China #14
Such case may be happened in some MUD's job system.
User asks job npc some questions, and the npc reply you information about the job he will provide. Base on the answer of the npc, the user will decide the next action like go to some place or kill someone.

I my use case, it looks like:

Execute("ask harry about job")                                     <- this action will get the npc answer your question, in
                                                                      which job information is included. For example, the
                                                                      answer may be: Harry said: please go to the room 1.
l,w = wait.regexp("Harry said: please go to the room (.*)", 10)    <- in this step, I'd like to match the answer line and
                                                                      capture the room number.
Execute("go to room w[1]")                                         <- then do the next action based on the trigger capture


You can find if I do wait.regexp first, the action "ask harry about job" will be held as wait.regexp is waiting for the match line, "Harry said: please go to the room 1" coming. While the npc's answer will never come for the ask action has not been done.
Amended on Fri 26 Jul 2019 08:26 AM by Zhenzh
USA Global Moderator #15
Quote:
While the wait.regexp creates the trigger just after the match line is generated. There is a chance that the match line comes while trigger has not been created by wait.regexp.

I don't think this is true. MUSHclient only has one thread, so all processing happens sequentially. The order of events from your example should always be "send message to mud, create trigger, process response from mud after trigger is created" even if the MUD manages to respond so fast that the response comes back in the nanosecond between your two lines of code (this is actually impossible).
Amended on Fri 26 Jul 2019 08:00 PM by Fiendish
Australia Forum Administrator #16

If do wait.regexp first, the script will be paused to wait the match line coming so that the next action, Execute() will not be happened until the regexp detecting the match line or timeout.

Yes, I understand that. However there is nothing stopping you making a trigger to match the expected text, sending the message and then exiting this particular script. Then when the trigger fires you can process it.

All that the wait module basically does it simplify this procedure:

  • It makes a Lua coroutine
  • It make a trigger (for the match)
  • It makes a timer (for the timeout)
  • The coroutine suspends, passing control back to the client

Then when the trigger (or timer) fires the coroutine resumes at the next line in your script.

You can unwind that and do it manually:

  • Make a trigger
  • Make a timer if you want to handle time-out
  • Send your message

Now things are in the right order, the trigger is there if the response comes back quickly.

When the trigger fires you process it. This effectively gives you two lots of script: One to make the trigger and send the message, the second to process the trigger.

Australia Forum Administrator #17
Fiendish said:

I don't think this is true. MUSHclient only has one thread, so all processing happens sequentially.


In the case of the wait module, though, control passes back to the client as the coroutine suspends, thus the next line in the script is not actually processed sequentially.

Although the trigger would appear to exist at this point, perhaps a higher-priority trigger gets to the line first.
China #18
Fiendish said:

The order of events from your example should always be "send message to mud, create trigger, process response from mud after trigger is created"


I used to think so until I had a simple test.

wait.make(function()
    Execute("say this is a test")
    wait.time(5)
    l,_ = wait.regexp("this is a test", 10)
    Note(l)
end)


I manually added a wait.time() action between Execute() and wait.regexp() to simulate network issue.

The test result shows the trigger will fail as the point of time the trigger created is after the time the mud server response Execute()
China #19
Nick Gammon said:

You can unwind that and do it manually:
•Make a trigger
•Make a timer if you want to handle time-out
•Send your message


Yes, I processed my script in such way as work around using AddTriggerEx(),Execute() instead of Execute(),wait.regexp().

I just wonder if there is a formal way to process such case.

For the wait.regexp() is an import and useful function in most cases. Such issue may get it unreliable in some scenario.

I'd like to adjust the wait module, adding a fourth parameter which is action users may want to be executed during AddTriggerEX() and coroutine.yield() in function regexp(). So that the wait.regexp() can get reliable in the Execute(),wait.regexp() cases and end user do not need to manually addtrigger,addtimer,execute,yield each time.

What's your opinion?