Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Lua ➜ Attempting to use wait to wait for a particular line and failing

Attempting to use wait to wait for a particular line and failing

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


Pages: 1 2  

Posted by Lilija   (9 posts)  Bio
Date Tue 27 Jul 2010 07:33 AM (UTC)
Message
Hello all,

I'm currently writing a script and am trying to capture some output from the game, then perform some math with it. Obviously the script keeps executing before the mud returns the line I'm waiting for. I read the FAQ about waiting for a trigger line, but apparently I'm doing something wrong. Here's my code for the wait, along with what string I'm trying to match and a few lines after the wait function.


	   EnableTrigger("temper_base_capture", true)
	   function cr ()
	    repeat
		 Send ("wp " .. TemperWeapon)
		 line, wildcards = 
		  wait.regexp ("^\s*Damage:\s+(\d+)\s+Precision:\s+(\d+)\s+Speed:\s+(\d+)\s*$")
		  
		  until string.find (line, "Speed")
		  wait.time (5)
		  Note ("Hopefully variables are set")
		  end
		  
		wait.make (cr)
	   EnableTrigger("temper_base_capture", false)
	   TemperDamage = GetVariable("temper_damage_base")
	   TemperPrecision = GetVariable("temper_precision_base")
	   TemperSpeed = GetVariable("temper_speed_base")
	   TemperWeapon = "axe"
	   TemperSrc = GetVariable("temper_source")
	   local FinalDamage
	   local FinalPrecision
	   local FinalSpeed
	   FinalDamage = GetVariable("temper_damage")
	   FinalPrecision = GetVariable("temper_precision")
	   FinalSpeed = GetVariable("temper_speed")
	   local DamageDifference
	   local PrecisionDifference
	   local SpeedDifference
	   
	   DamageDifference = FinalDamage - TemperDamage   
    <trigger
     expand_variables="y"
	 enabled="y"
     group="Lil_Forger_Suite"
     ignore_case="y"
     keep_evaluating="y"
     match="^\s*Damage:\s+(\d+)\s+Precision:\s+(\d+)\s+Speed:\s+(\d+)\s*$"
     name="temper_base_capture"
     regexp="y"
     send_to="12"
     sequence="100"
    > 
     <send>
	  SetVariable("temper_damage_base", %1)
      SetVariable("temper_precision_base", %2)
      SetVariable("temper_speed_base", %3)
     </send>	  
    </trigger>



The trigger captures the variables fine (I check after the error happens, and the variables are set), unfortunately, the script errors because the trigger doesn't set them fast enough. It appears that the wait isn't working to me. The error I get is that TemperDamage is a nil value. There is, literally, no pause whatsoever. Anyone have any tips for making this work? Just need the script to sit and loop/pause long enough to allow the trigger to set the variables.
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #1 on Tue 27 Jul 2010 08:02 AM (UTC)
Message
I'm not clear on where the script part you posted is. Where is that? I don't get the part about the trigger not setting the variable fast enough.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Lilija   (9 posts)  Bio
Date Reply #2 on Tue 27 Jul 2010 08:55 AM (UTC)
Message
Sorry about that, that's what I get for drinking and posting. What I'm attempting to do is pause the script in my alias until it receives a line from the game similar to this


Damage: 230  Precision: 187  Speed: 280


This trigger captures the values for the above stats and sets a variable for each.


 <trigger
     expand_variables="y"
	 enabled="y"
     group="Lil_Forger_Suite"
     ignore_case="y"
     keep_evaluating="y"
     match="^\s*Damage:\s+(\d+)\s+Precision:\s+(\d+)\s+Speed:\s+(\d+)\s*$"
     name="temper_base_capture"
     regexp="y"
     send_to="12"
     sequence="100"
    > 
     <send>
	  SetVariable("temper_damage_base", %1)
      SetVariable("temper_precision_base", %2)
      SetVariable("temper_speed_base", %3)
     </send>	  
    </trigger>


After having read the post about pausing a script until a certain line arrives from the mud, I believe I want something similar to this to keep the script from advancing until the regexp is matched and it sees the word Speed with string.find.


           function cr ()
	    repeat
		 Send ("wp " .. TemperWeapon)
		 line, wildcards = 
		  wait.regexp ("^\s*Damage:\s+(\d+)\s+Precision:\s+(\d+)\s+Speed:\s+(\d+)\s*$")
		  
		  until string.find (line, "Speed")
		  wait.time (5)
		  Note ("Hopefully variables are set")
		  end
		  
		wait.make (cr)


The following is the alias I'm attempting to trigger off the string "temper go" (which it does). It requires wait, sets a few local variables from Mushclient variables that are set, enables the trigger that should strip out the numbers from the line, does the wait function (during which I imagine the trigger ought to capture the values I want from the line), then it should disable said trigger after the wait function. After that, it should just do some math with said variables.


	<alias
	 name="lil_forger_temper_go"
	 match="^\s*temper\s+go\s*$"
	 enabled="y"
	 group="Lil_Forger_Suite"
	 regexp="y"
	 send_to="12"
	 ignore_case="y"
	 sequence="100"
    >
	 <send>
	 
	  require "wait"
	  
	   local TemperDamage
	   local TemperWeapon
	   TemperWeapon = GetVariable("weapon_number")
	   EnableTrigger("temper_base_capture", true)
	   function cr ()
	    repeat
		 Send ("wp " .. TemperWeapon)
		 line, wildcards = 
		  wait.regexp ("^\s*Damage:\s+(\d+)\s+Precision:\s+(\d+)\s+Speed:\s+(\d+)\s*$")
		  
		  until string.find (line, "Speed")
		  wait.time (5)
		  Note ("Hopefully variables are set")
		  end
		wait.make (cr)
	   EnableTrigger("temper_base_capture", false)
	   TemperDamage = GetVariable("temper_damage_base")
	   local FinalDamage
	   FinalDamage = GetVariable("temper_damage")
	   local DamageDifference
	   
	   DamageDifference = FinalDamage - TemperDamage
     </send>
	</alias>


This is the error message that I receive when I attempt to run the alias the first time.


Run-time error
World: forger test world
Immediate execution
[string "Alias: lil_forger_temper_go"]:43: attempt to perform arithmetic on local 'TemperDamage' (a nil value)


However, subsequently, if I run the alias my desired variables have been set, and it runs fine. I'd just like for them to be set the first time, hence trying to wait for the Damage/Precision/Speed line to be output from the mud before continuing to process. I've stripped down the alias some to just the parts that should be needed for troubleshooting.

Does that help? And thank you very much for the quick reply Nick. You rule!
Top

Posted by Worstje   Netherlands  (899 posts)  Bio
Date Reply #3 on Tue 27 Jul 2010 10:07 AM (UTC)

Amended on Tue 27 Jul 2010 10:15 AM (UTC) by Worstje

Message
Well, the situation is exactly as the error message says. At the time you are trying to deduct TemperDamage from FinalDamage to get the difference, TemperDamage cannot be converted since it is 'a nil value'.

In other words, you never stored a value in that MUSHclient variable, since the GetVariable() call returned nil.

Thus, are you sure you are setting the variable properly beforehand? I am going to do a bit of conjecture now, but I believe you are misunderstanding the wait.regexp() function in how it works and how it should be used. (Disclaimer: I have never used the wait library, as it was written way after I started coding and I never really got the hang of switching to using/learning it.)

Basically, the wait.regexp() will MAKE a new trigger behind the scenes, and from that, call back to your code so it can be run once more. That trigger will quite likely prevent your OTHER trigger from being run. To boot, you are doing your own matching in a loop to see if the word Speed is in the trigger somewhere, where it should not be needed anymore. And eventually, due to the wait the wait library works, you think you have done the entire waiting gig, but end up doing the calculations immediately.

So, once your wait.regexp() matches, you get your values deposited in the line and wildcards variables. Thus, you could simply fill the appropriate variables at that point. So, I'd arrive at something like this for you to put in your Send box...

require "wait"

wait.make (function ()
      
      -- Send the command.
      local TemperWeapon = GetVariable("weapon_number")
      Send ("wp " .. TemperWeapon)
      
      -- Wait for the line. (Your old trigger is not needed.)
      local line, wildcards = 
      wait.regexp ("^\\s*Damage:\\s+(\\d+)\\s+Precision:\\s+(\\d+)\\s+Speed:\\s+(\\d+)\\s*$")
      
      -- Assign the values according to the captures.
      -- These are local to this 'scope' only, so you can't use them elsewhere
      -- in your script. If you do want to use them elsewhere, remove the
      -- 'local' bits, and they will become available to your entire script,
      -- no matter which trigger, alias or timer it would be.
      local TemperDamage = wildcards[1]
      local TemperPrecision = wildcards[2]
      local TemperSpeed = wildcards[3]
      
      -- Do our logic stuff. (I took some liberties here since you had so many
      -- variables, some of which you never assigned, so it likely doesn't do
      -- exactly what you want. Still, hopefully you can understand how this
      -- works now.
      local FinalDamage = TemperDamage
      local DamageDifference = FinalDamage - TemperDamage
      
end)


Also, on another note... your wait.regexp() call is called with a string containing the regular expression to trigger on, but you should keep in mind that Lua will do some magic with backslashes (the \ character) itself. (Think of when you want to put a literal newline into a string, one would use a \n, thus the actual text '\n' would need to be written as '\\n' in your code. If you want to send a literal \ to the regexp function, you'll need to double it (and yes, you want that here). Thus, that would become...

wait.regexp ("^\\s*Damage:\\s+(\\d+)\\s+Precision:\\s+(\\d+)\\s+Speed:\\s+(\\d+)\\s*$")


(I already put that 'fix' in the above example.)

Edit: Nick, why the hell is the forum eating my backslashes outside the edit screen once forum codes are activated? Gonna double them up to insane levels now, I suppose. Bear with me Lilija while I fix the post.

Edit: Post should be fixed. Nick, if you fix the forum (I assume it is a bug as no other forum I know does it), please fix this post back? On the other hand, that could explain why Lilija's wait.regexp() missed half its backslashes, so I might be able to remove that part of my post. xD
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #4 on Tue 27 Jul 2010 09:09 PM (UTC)
Message
Worstje said:


Edit: Nick, why the hell is the forum eating my backslashes outside the edit screen once forum codes are activated? Gonna double them up to insane levels now, I suppose. Bear with me Lilija while I fix the post.



Once forum codes are activated, since they use backslashes to escape square brackets, you must double backslashes themselves.

What I (almost) always do, when posting code examples, is to use the utility built into MUSHclient itself: Edit Menu -> Convert Clipboard Forum Codes (Shift+Ctrl+Alt+Q). So I:


  • Copy an example:
  • In an open MUSHclient world or notepad window: Shift+Ctrl+Alt+Q
  • Post into forum message between: [code] ... [/code]


Your problem is that in Send-to-script, MUSHclient also processes backslashes, so each backslash that you actually want there has to be doubled again. And then inside a Lua string if you want backslashes you need to double them yet again.

So, if you want a single backslash in a regexp, inside "send to script", you need:


  • For Lua strings: "\\d+"
  • Because it is send-to-script: "\\\\d+"
  • To post on the forum with forum codes: "\\\\\\\\d+"


You can reduce the backslashes by using a script file, not send-to-script, especially if you are planning to use backslashes a lot, like in PCRE regexps.

Note that Lua regexps use % instead, which simplifies things, however %1 has a meaning inside send-to-script as well, so the % needs to be doubled also. Sigh.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Worstje   Netherlands  (899 posts)  Bio
Date Reply #5 on Wed 28 Jul 2010 03:27 AM (UTC)
Message
Yeah, I am quite familiar with the phenomenon and the reasons, and am not saying it is unreasonable for it to happen in strings, in send to script and so forth. I am only argueing it is strongly counter-intuitive to have another layer in the forums. An example of the trouble it can cause is someone pasting a trigger using send-to-script and the appropriate code tags.

To be fair, you did already document the way to do it at http://www.gammon.com.au/forum/?id=4776, but I doubt anyone will read the entire thing - at most they'll want to use it to figure out where the 'Copy Trigger' button is.

Every kid on the internet has posted on a forum and has experience with forum codes. Expecting them to think they don't know how to post a snippet in a code tag... well, that doesn't happen.

But I guess I'm derailing this topic even after going out of my way to create a seperate topic elsewhere. Sorry about that, Lilija.
Top

Posted by Lilija   (9 posts)  Bio
Date Reply #6 on Wed 28 Jul 2010 03:48 AM (UTC)
Message
No worries! Going to crack away at this now, so thank you VERY much for the help!
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #7 on Wed 28 Jul 2010 05:34 AM (UTC)
Message
Lilija said:

I'm currently writing a script and am trying to capture some output from the game, then perform some math with it. Obviously the script keeps


You may be trying something more complex than it has to be.

To react to output from the game, simply make a trigger that detects that output, and then do arithmetic when it happens. You don't need all this wait stuff for something simple like that.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Lilija   (9 posts)  Bio
Date Reply #8 on Wed 28 Jul 2010 05:44 AM (UTC)
Message
I've looked around a few places on the forums as well as the site, and haven't been successful in locating the information I'm looking for. I'd like to modularize my script into a few different files. When I try to import them in (via require, as in: require "myfile") it's unable to find them. Is there something specific I need to set to do this? Or do I need to locate the files in a specific folder?

I feel like an idiot not being able to figure it out. So thanks for bearing with me.
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #9 on Wed 28 Jul 2010 06:01 AM (UTC)
Message
Can you post the message? Require normally lists a whole heap of places it looks if it fails. Is your file in one of those?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Lilija   (9 posts)  Bio
Date Reply #10 on Wed 28 Jul 2010 06:34 AM (UTC)

Amended on Wed 28 Jul 2010 06:35 AM (UTC) by Lilija

Message
I'm a moron. Realized what I was doing wrong, and I can just make the user stick it in the lua folder I suppose. Any way to tell it to look inside a folder inside the lua folder? Or will it do that automatically?
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #11 on Wed 28 Jul 2010 06:42 AM (UTC)
Message
require("subfolder.yourscript")


That will look for lua/subfolder/yourscript.lua (among other paths).

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #12 on Wed 28 Jul 2010 06:44 AM (UTC)
Message
See:

http://www.gammon.com.au/scripts/doc.php?lua=require

In particular:

http://www.gammon.com.au/scripts/doc.php?lua=package.path

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Lilija   (9 posts)  Bio
Date Reply #13 on Wed 28 Jul 2010 07:49 AM (UTC)
Message
And, since I still can't seem to grasp what seem like they should be basic things.

Is there some sort of tut on the forums that discusses what belongs in what file type? Ie I imagine most code/logic belongs in .lua files, whereas aliases/triggers/variables go in .xml files. If this is the case, if I define a function in a .lua file, am I then able to use it within an alias from a .xml file, and what's a general syntax to do so? I played with this for half an hour, and can't seem to figure it out.

My current file that I was using before I decided to make it a bit more modular was a .lua file that I loaded in using File, Import. I'd like to split the functionality of what I'm doing across multiple files to keep my code cleaner.

I apologize if this makes little since, since it's late where I am. If you need a better explanation, I'll provide one tomorrow.
Top

Posted by Worstje   Netherlands  (899 posts)  Bio
Date Reply #14 on Wed 28 Jul 2010 07:54 AM (UTC)
Message
Opinions tend to differ, and different approaches have been used over the years by various people. All in all, I'd say you do what is best for you given your situation.

While you are still learning the basics, I'd recommend not to stick to a single plugin, and doing your scripting in its script tags as opposed to Sending to Script. That way, you won't run into extra difficulty of loading other files, and be able to keep it quite contained, while at the same time getting more insight into how MUSHclient works on the inside.

For example, you can use the Plugin Wizard to create a really basic plugin if you want, and look at the file it generates, and from then on edit that file rather than work your way through the crappy MUSHclient interface for editing stuff. It takes a bit of getting used to, but once you get past the hurdle you won't want to do it any differently. :)

Additionally, you can look at the plugins supplied with MUSHclient, or ask other people on these forums for example plugins they have written.
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.


65,919 views.

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

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

Go to topic:           Search the forum


[Go to top] top

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