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

Gammon Software Solutions forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Trigger text is on 2 or more lines

Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?
(New message)
Subject: Trigger text is on 2 or more lines
Name:
Your forum user name.
Register forum user name
Password:
Your forum password.
Forgotten password?
Message:
Message to be posted (in English, please).
Forum codes:
Check this if your message uses 'forum codes' or templates (auto-detected for new posts).
Forum codes Templates

Save this message ...


Subject review (reverse sequence)

Pages: 1  2 

Posted by Nick Gammon   Australia  (18,770 posts)  [Biography] bio   Forum Administrator
Date Sun 18 Sep 2011 12:22 PM (UTC)  quote  ]
Message
Quote:

So I think (and correct me if I'm wrong), but I think by having the trigger start with parenthesis, it's making my %1 and %2 variables screw up. In other words, %1 would need to become %2, and %2 would need to become %3. Is that right?


Exactly.

- Nick Gammon

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

Posted by Ada   (20 posts)  [Biography] bio
Date Sun 18 Sep 2011 11:07 AM (UTC)  quote  ]
Message
Yep, Nick is right. Simply not using the parentheses for the '>' character solves the problem because then it is no longer part of the capture group. So problem solved! :D
[Go to top] top

Posted by Blixel   (39 posts)  [Biography] bio
Date Sun 18 Sep 2011 09:35 AM (UTC)  quote  ]

Amended on Sun 18 Sep 2011 09:44 AM (UTC) by Blixel

Message
Ada said:
A trigger either matches or not matches. The compile error you're getting means it -is- matching in both cases but the associated script is not in working order. Can you paste the triggers and the text they're supposed to match here please?


To answer your second question first, 'health' or 'hea' is a game command.

>help health

The "health" command will let you see how many hit points you have left and
what your maximum hit point amount is. If you are of a magical class, it will
show your spell points and your spell point maximum. You will also be told how
many minutes you have left to eat food before you begin to starve to death. 
And, if you are diseased, it will let you know that too. Type: health or hea.


The normal output for 'hea' looks like this:

You have 95/96 hitpoints and 38/38 spellpoints.
You are middle-aged.
You will need to eat within 11 minutes.


I use that first line as a trigger to do a simple math calculation so that I will automatically drink a flask (which restores full health) when my health drops below a certain point.

Whenever a mob hits me, it sets off a trigger that automatically does this: Send ("health")

For example ... >The imp hits you for 15 hps!

That automatically triggers Send ("health")

Then I have this trigger:

^You have (.*?)\/(.*?) hitpoints(.*?)$|^>You have (.*?)\/(.*?) hitpoints(.*?)$


As you can see, that is simply evaluating what comes from the "health" command (which again, is a game command.)

This is the point where it dies if I use this as the trigger instead:

^(\>)?You have (.*?)\/(.*?) hitpoints(.*?)$


And Nick's idea of using this as the trigger:

^\>?You have (.*?)\/(.*?) hitpoints(.*?)$


...solves it as well. So for some reason, it doesn't like those parenthesis. I don't understand regular expressions well enough to know why that's the case.

So ... for the curiously minded, moving on with the flow...

The code in that trigger is:

if (%1 < (%2 * .3)) then
  EnableTrigger("FlaskEmergency", true)
  Send ("drink flask")
elseif (%1 < (%2 * .5)) then
  ColourNote ("black", "red", "Health is %1")
elseif (%1 < (%2 * .6)) then
  ColourNote ("black", "orange", "Health is %1")
elseif (%1 < (%2 * .7)) then
  ColourNote ("white", "green", "Health is %1")
else
  ColourNote ("white", "blue", "Health is %1")
end


EDIT: I think I just figured it out. Something Nick said. He said "You don't need to make it a capture...."

So I think (and correct me if I'm wrong), but I think by having the trigger start with parenthesis, it's making my %1 and %2 variables screw up. In other words, %1 would need to become %2, and %2 would need to become %3. Is that right?


The code for the FlaskEmergency trigger is:

EnableTrigger("FlaskEmergency", false)
Execute ("countflasks")
EnableTrigger("FlaskEmergencyCount", true)


The countflasks alias does this:

EnableTrigger("InvStart", true) 
Send ("inventory")


...that part is all worked out... You know what the InvStart/InvFull does because you wrote it.

So the FlaskEmergencyCount is looking for "pieces." as its trigger text.

And the whole point of this trigger is so our character can teleport to safety if he is out of flasks.

The code for the FlaskEmergencyCount is:

EnableTrigger("FlaskEmergencyCount", false)
if (flaskcount == 0) then
  giveup = true
  Send ("rub key")
  EnableTrigger("TeleportSafetyCheck", true)
elseif (flaskcount == 1) then
  ColourNote ("white", "red", "==========================")
  ColourNote ("white", "red", "WARNING: 1 Flask Remaining")
  ColourNote ("white", "red", "==========================")
end



Whew ... I think I covered everything.

The bottom line here is that one Regular Expression ... for reasons that I don't even begin to understand, one expression works, and the other completely bombs ... with compile errors.
[Go to top] top

Posted by Blixel   (39 posts)  [Biography] bio
Date Sun 18 Sep 2011 08:41 AM (UTC)  quote  ]
Message
Oh boy ... some issue or another always pops up. (I'll address the regular expression thing next, but first - I want to revisit the flask thing for a moment.)

But no worries... I actually came up with a solution on my own! I think it's a good one, but I want to run it by you.

It is sometimes the case that you will only have 1 line worth of inventory. (This is more of an issue when looking at items on the ground. Usually your inventory will span at least 2 lines, but often, the "inventory" on the ground fits on one line.)

Anyway... I found that the logic "we" (you) came up with was missing one small piece of the puzzle.

Take the following line of inventory as an example.

You are carrying a shortsword, some clothmail and 0 gold pieces.


That all fits on one line with a little room to spare.

When I run the countflasks command ... the first time I run it, it gives me this:

>inventory


You are carrying a shortsword, some clothmail and 0 gold pieces.


The second time I run it, it gives me this:

>inventory

You are carrying a shortsword, some clothmail and 0 gold pieces.
No. of flasks : 0


The problem seems to be that the trigger system assumed there would always be at least 2 lines. So here's what I did to work around it.

My main alias is called "countflasks" and it does this:

EnableTrigger("InvStart", true) 
Send ("inventory")


That will trigger the "You are carrying" trigger which now does this:

myinv = "%0"

if string.sub(myinv, string.len(myinv) - 6, string.len(myinv)) == "pieces." then
  EnableTrigger("InvStart", false)
  Execute ("FlaskCount")
else
  EnableTrigger("InvFull", true)
end


In other words, if "pieces." is the end of that first line, then we are done. We shut off the InvStart trigger and Execute FlaskCount. If "pieces." does not end the line, then we turn on InvFull which now does this:

myinv = myinv .. "%0"

if string.sub(myinv, string.len(myinv) - 6, string.len(myinv)) == "piece." then
  EnableTrigger("InvStart", false)
  EnableTrigger("InvFull", false)
  Execute ("FlaskCount")
end


This trigger effectively runs in a continuous loop until some line ends with "pieces."

When that finally happens, it shuts off both triggers and then Executes FlaskCount which does the actual counting:

flaskcount = 0

for word in string.gmatch(myinv, "flask") do
  flaskcount = flaskcount + 1
end

Note("No. of flasks : " .. flaskcount)


It seems to work. But if you have ideas for an improvement, I'm open to it.

In particular because I copied this logic verbatim when counting corpses and "chests" in a room. And I'm wondering if this logic can be consolidated:

corpsecount = 0
chestcount = 0
  
for word in string.gmatch(roomitems, "corpse") do
  corpsecount = corpsecount + 1
end

for word in string.gmatch(roomitems, "chest") do
  chestcount = chestcount + 1
end

Note("No. of corpses : " .. corpsecount)
Note("No. of chests  : " .. chestcount)


Not a big deal ... but I assume there is a way to add the corpsecount and chestcount without doing two separate for loops that loop over the same data.
[Go to top] top

Posted by Nick Gammon   Australia  (18,770 posts)  [Biography] bio   Forum Administrator
Date Sun 18 Sep 2011 08:06 AM (UTC)  quote  ]
Message
Quote:

That makes it look for this text:

^(\>)?You have (.*?)\/(.*?) hitpoints(.*?)$


Is this a plugin? In which case the symbols < > and & need to become &lt; &gt; &amp;

- Nick Gammon

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

Posted by Nick Gammon   Australia  (18,770 posts)  [Biography] bio   Forum Administrator
Date Sun 18 Sep 2011 08:04 AM (UTC)  quote  ]
Message
Blixel said:

It is often the case that when drinking a flask (or doing other things) the game will output one or the other of the following:

You don't have one!
>You don't have one!


The only difference is that leading ">"



Ada said:

The following regular expression should work:

^(\>)?You don\'t have one\!$


You don't need to make it a capture. So this also will work:


^\>?You don\'t have one\!$


Or even remove the requirement that it is at the start of the line (a little more dangerous):



You don\'t have one\!$


- Nick Gammon

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

Posted by Nick Gammon   Australia  (18,770 posts)  [Biography] bio   Forum Administrator
Date Sun 18 Sep 2011 07:59 AM (UTC)  quote  ]
Message
Blixel said:

P.S. I don't know how to preview my posts either.


You can't. Sadly the forum doesn't let you do that. :(

- Nick Gammon

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

Posted by Ada   (20 posts)  [Biography] bio
Date Sun 18 Sep 2011 07:04 AM (UTC)  quote  ]
Message
A trigger either matches or not matches. The compile error you're getting means it -is- matching in both cases but the associated script is not in working order. Can you paste the triggers and the text they're supposed to match here please?

Template:copying For advice on how to copy aliases, timers or triggers from within MUSHclient, and paste them into a forum message, please see Copying XML.


Also, what does sending 'health' to the game do? Is that an alias or a game command?
[Go to top] top

Posted by Blixel   (39 posts)  [Biography] bio
Date Sun 18 Sep 2011 06:26 AM (UTC)  quote  ]

Amended on Sun 18 Sep 2011 06:31 AM (UTC) by Blixel

Message
Ada said:
Blixel said:
You don't have one!
>You don't have one!


The following regular expression should work:

^(\>)?You don\'t have one\!$


Oddly, when I add that, I get a compile error. (Though, when I check the site you referenced, it seems to say it should work.) But here's what MUSHclient is putting up as an error:

You are standing at the foot of a rope ladder. A rune for shelter is carved on
the wall beneath an arrow pointing up.

[][]    [][]
[]  M     []
[]   up   []
[]   x    []
[]     $  []  
[][]    [][]

M - ogre

>hit ogre
You missed!
>The ogre hits you for 4 hps!
>health

You have 90/96 hitpoints and 38/38 spellpoints.
Compile error
World: Cleric
Immediate execution
[string "Trigger: "]:1: unexpected symbol near '<'
You are middle-aged.
You will need to eat within 58 minutes.
>hit ogre
Swing hits with light damage!
>The ogre hits you for 4 hps!
>health

You have 86/96 hitpoints and 38/38 spellpoints.
Compile error
World: Cleric
Immediate execution
[string "Trigger: "]:1: unexpected symbol near '<'


The line that says "The ogre hits you for 4 hps!" is a trigger itself. That trigger has been working for a long time for me.

^The (.*?) hits you for (.*?) hps\!$|^>The (.*?) hits you for (.*?) hps\!$


that triggers a health check. Simply: "health" is sent to world.

That makes it look for this text:

^(\>)?You have (.*?)\/(.*?) hitpoints(.*?)$


And that seems to be where it's bombing because when I restore that trigger to this:

^You have (.*?)\/(.*?) hitpoints(.*?)$|^>You have (.*?)\/(.*?) hitpoints(.*?)$


It works again.

Pretty weird.
[Go to top] top

Posted by Blixel   (39 posts)  [Biography] bio
Date Sun 18 Sep 2011 04:14 AM (UTC)  quote  ]
Message
Ada said:
Remove the local keyword from before the variable, that would make it available everywhere.


Ah, yes - that does work. Thanks again. But it raises another question. (Which I see you already anticipated based on your response at the bottom.)

Also, I found that in some cases, my inventory will be such that "gold pieces." does a line wrap. Arg. So the only bit of text I can absolutely rely on is "pieces." I wish I had more than that, but I suppose it all happens so quickly there isn't any chance of other text showing up first. I changed the relevant bit to this:

if string.sub(myinv, string.len(myinv) - 6, string.len(myinv)) == "pieces." then




Ada said:
The following regular expression should work:

^(\>)?You don\'t have one\!$


Adding a ? after a capture group () makes it optional. Have a look at http://regexpal.com/ for more simple help on this stuff.


Thanks. I will try this out and check out that link. I did a google search and ran into http://www.regular-expressions.info/ ... but it wasn't really that helpful to me.


Ada said:
Ohh, in your FlaskEmergencyCheck alias you're sending a command to the game and doing the math in the same place again.


Yes - you are right. I noticed this problem almost immediately. To work around it, I added another trigger in the middle. (Which I think is what you were getting at.)

The trigger in the middle is called FlaskEmergency. It is triggered by the response to drinking a flask. "You are healed!" and it does this:

EnableTrigger("FlaskEmergency", false)
Execute ("countflasks")
EnableTrigger("FlaskEmergencyCount", true)


So we drank the flask by the time we got to this point. So now we are counting the flasks, and turning on the FlaskEmergencyCount trigger which will look for "pieces\.$"

And that trigger will do this:

EnableTrigger("FlaskEmergencyCount", false)
if (flaskcount == 0) then
  giveup = true
  Send ("rub key")
  EnableTrigger("TeleportSafetyCheck", true)
elseif (flaskcount == 1) then
  ColourNote ("white", "red", "==========================")
  ColourNote ("white", "red", "WARNING: 1 Flask Remaining")
  ColourNote ("white", "red", "==========================")
end


Feels like a long way around ... but I understand why it's necessary to do it like this. My only concern is that my trigger text will prove to be too vague in some cases. Hmmm... I wonder if the trigger text could look for "^You are carrying" AND "pieces\.$" before it would act.



Ada said:
Hope my engrish makes sense! :)


Perfect English. Far better than a lot of native English speaking people I know.
[Go to top] top

Posted by Ada   (20 posts)  [Biography] bio
Date Sun 18 Sep 2011 03:18 AM (UTC)  quote  ]

Amended on Sun 18 Sep 2011 03:28 AM (UTC) by Ada

Message
Blixel said:
How do I make the flaskcount variable available outside of the trigger that created it?


Remove the local keyword from before the variable, that would make it available everywhere.

Blixel said:
You don't have one!
>You don't have one!


The following regular expression should work:

^(\>)?You don\'t have one\!$


Adding a ? after a capture group () makes it optional. Have a look at http://regexpal.com/ for more simple help on this stuff.

Ohh, in your FlaskEmergencyCheck alias you're sending a command to the game and doing the math in the same place again. Computers are fast, networks are slow and your if/then code would execute -before- any data has arrived as a result of the command sent above it. It might be a better option to trigger "You sip from a flask." or whatever line you get when you use up a flask to do flaskcount - 1 and in that trigger check if flaskcount is too low and issue a warning if it is. Hope my engrish makes sense! :)
[Go to top] top

Posted by Blixel   (39 posts)  [Biography] bio
Date Sun 18 Sep 2011 02:38 AM (UTC)  quote  ]

Amended on Sun 18 Sep 2011 02:52 AM (UTC) by Blixel

Message
Quick question.

How do I make the flaskcount variable available outside of the trigger that created it?

I thought the Expand variables checkbox might do it, but that doesn't seem to work.

I created an alias called FlaskEmergencyCheck. Here is how I'm trying to use the flaskcount variable outside of the trigger that created it.

Execute ("countflasks")
if (flaskcount == 0) then

  -- give up the fight
  giveup = true

  -- use Teleportation key to teleport to a safe place
  Send ("rub key")

  -- make sure our key didn't fail.
  EnableTrigger("TeleportSafetyCheck", true)
elseif (flaskcount == 1) then
  ColourNote ("white", "red", "==========================")
  ColourNote ("white", "red", "WARNING: 1 Flask Remaining")
  ColourNote ("white", "red", "==========================")
end


P.S. I also have a very basic regular expression question. I'm sorry I don't understand this stuff better, but I'm learning.

It is often the case that when drinking a flask (or doing other things) the game will output one or the other of the following:

You don't have one!
>You don't have one!


The only difference is that leading ">"

It should be trivial to make a regular expression that catches both, but the only way I can get it to work consistently is this:

^You don\'t have one\!$|^\>You don\'t have one\!$


I've tried things like this:

^(.*?)You don\'t have one\!$


But it consistently fails to catch one or the other. I'm not sure how to make that first ">" an optional requirement.
[Go to top] top

Posted by Twisol   USA  (2,229 posts)  [Biography] bio
Date Sun 18 Sep 2011 12:43 AM (UTC)  quote  ]
Message
Blixel said:
P.S. I don't know how to preview my posts either.

Not sure you can. I just edit quickly if something's amiss. :P

'Soludra' on Achaea

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

Posted by Blixel   (39 posts)  [Biography] bio
Date Sat 17 Sep 2011 11:54 PM (UTC)  quote  ]
Message
Ah ... perfect. Thanks. It works great now. That makes sense about not adding a wait statement. I have several triggers/aliases that have wait statements, and it feels a bit crude. If there is any lag, the wait timer isn't going to work. I'll have to work on some of my other triggers/aliases to try to eliminate that waiting.

I made one small change to your set up. I have the countflasks alias turn on InvStart, and then I have InvFull shut it off the same time it shuts off itself.

That way when I do a regular "inv", it doesn't trigger the countflasks stuff.

Thanks a lot. This was a really big help. There are a couple of other things I need to do that require this exact same logic. (Looking at the items on the floor of a room as an example. The item list wraps around to the next line. So it is essentially the same thing as doing an inventory check on the room.)

P.S. I don't know how to preview my posts either.
[Go to top] top

Posted by Ada   (20 posts)  [Biography] bio
Date Sat 17 Sep 2011 01:50 PM (UTC)  quote  ]

Amended on Sat 17 Sep 2011 02:06 PM (UTC) by Ada

Message
Erm.. in your alias,

Send ("inventory")

local count = 0
for word in string.gmatch(myinv, "flask") do
  count = count + 1
end

Note("No. of flasks : " .. count


.. you're doing the math right after sending the command, you have to actually wait a little and let it receive some data before you proceed with working on it. That's why when you hit the alias the first time you get the 'string expected' error followed by your actual inventory showing. After that, when you hit the alias again it still doesn't have nothing to work with but now it has the old data captured by the actions of the previous alias (thus no error but now we have the sequence problem because it's working on old data) heh. I'd recommend simply moving the flask counting bits to where you see the end of your inventory and where you disable the catchall alias. That would save you the trouble of using wait() or something like that since you've essentially chained the sequence of events as they occur. So to paste corrections:

<triggers>
  <trigger
   group="Inventory"
   keep_evaluating="y"
   match="^(.+)"
   name="InvFull"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>myinv = myinv .. "%0"
if string.sub(myinv, string.len(myinv) - 11, string.len(myinv)) == "gold pieces." then
  EnableTrigger("InvFull", false)
  local flaskcount = 0
  for word in string.gmatch(myinv, "flask") do
    flaskcount = flaskcount + 1
  end
  Note("No. of flasks : " .. flaskcount)
end</send>
  </trigger>
  <trigger
   enabled="y"
   group="Inventory"
   keep_evaluating="y"
   match="^You are carrying (.+)"
   name="InvStart"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>myinv = "%0"
EnableTrigger("InvFull", true)</send>
  </trigger>
</triggers>


..and the alias(es) become:

</aliases>
  <alias
   match="cf"
   enabled="y"
   group="Shortcuts"
   send_to="10"
   sequence="100"
  >
  <send>countflasks</send>
  </alias>
  <alias
   match="countflasks"
   enabled="y"
   group="Misc. Routines"
   send_to="12"
   sequence="100"
  >
  <send>Send ("inventory")</send>
  </alias>
</aliases>


P.S. How can I preview what I'm about to post here anyway? :/
[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.


2,069 views.

This is page 2, subject is 2 pages long:  [Previous page]  1  2 

[Reply to this subject]  Reply to this subject   [New subject]  Start a new subject   [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

[Home]

Written by Nick Gammon - 5K

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

[Best viewed with any browser - 2K]    [Internet Contents Rating Association (ICRA) - 2K]    [Web site powered by FutureQuest.Net]