SetVariable and accessing variable

Posted by Reyth on Tue 06 Jul 2010 06:38 PM — 10 posts, 41,310 views.

#0
I'm making a basic sipper for Achaea, and I've got a trigger that looks like this:

SetVariable("currenthealth", "%1")
SetVariable("currentmana", "%2")
SetVariable("currentstate", "%3")
if @currenthealth < @siphealth and @sipbalance==1 then
   if @sm==1 and @currentmana < @sipmana then
      Send("sip mana")
      SetVariable("sipbalance", "2")
      Note(@sipbalance)
   else
      Send("sip health")
      SetVariable("sipbalance", "2")
      Note(@sipbalance)
   end
end
if @currentmana < @sipmana and @sipbalance==1 then
   Send("sip mana")
   SetVariable("sipbalance", "2")
end


For some reason, when it triggers and sends "sip health" then sets sipbalance to 2, it still notes sipbalance as 1. It seems that whenever I SetVariable then access the same variable inside a trigger, the variable hasn't actually changed yet. Is this normal, or am I missing a checkbox somewhere?

Thanks, this is my first post, but everyone on here has already helped me a lot indirectly :).
USA #1
First off, in Lua, numbers and strings cannot be directly compared. So when you use SetVariable("sipbalance", "2"), you're setting it to the string "2", but you later compare it to a number, so that won't work.

But to answer your main question:
Quote:
It seems that whenever I SetVariable then access the same variable inside a trigger, the variable hasn't actually changed yet.

If I remember correctly, variable expansion occurs when the trigger is "entered" by MUSHclient. So the string @sipbalance is expanded only once. If you want to get the always up-to-date version, you need to use the GetVariable function.
#2
Thanks, I'll try that right away. For some reason, it works even though I'm comparing it to a number. I'll let you know how GetVariable works out in a moment.
#3
GetVariable seems to fix it, but I think I need to make sure my flow is correct. I did get the number/string disagreement error you mentioned now, so I simply put tonumber before every GetVariable. Will this cause me problems later?
USA #4
It shouldn't cause you trouble, as long as you are consistent. The MUSHclient variable system only allows strings, so you have to convert numbers to strings going in (using tostring) and strings to numbers going out (using tonumber). Now, you might not actually need numbers, in which case you could just use strings everywhere. (I'm not sure if you're using it as a counter, or as a state indicator.)
USA #5
David Haley said:
convert numbers to strings going in (using tostring)

Lua coerces numbers to strings on the fly when circumstances allow it, so you don't need to use tostring in this case.


@Reyth - If you're using the variable more than once, I'd use tonumber() just once and assign it to a local variable:

-- totally arbitrary example
local myvariable = tonumber(GetVariable("foo"))
if myvariable > 1 then
  SetVariable("foo", myvariable + 1)
end


I can see you probably wanting to do this with the sipbalance variable.
USA #6
Quote:
Lua coerces numbers to strings on the fly when circumstances allow it

Well, if we're getting technical about it ;) no. For example, strings are not coerced for equality testing (which is a problem that was run into in this thread).

Also, in this instance, it is more likely the C API binding for SetVariable that does the conversion explicitly with lua_isstring and lua_getstring (both of which accept numbers and convert to strings).

The manual section:
http://www.lua.org/manual/5.1/manual.html#2.8
explains in detail when coercion takes place during arithmetic operations.


The above said: I mentioned explicit conversion for the sake of, well, explicitness, so that consistency is not only implied but also visual. So yes, I told a little white lie. :-)
Australia Forum Administrator #7
This has a subtle flaw:


SetVariable("currentmana", "%2")

...

if @currentmana < @sipmana and @sipbalance==1 then


MUSHclient expands out things like @currentmana *before* executing the script. Thus the change to currentmana (from wildcard 2) is too late.

What would work in this particular case is this:


if %2 < @sipmana and @sipbalance==1 then


In this case the %2 is expanded at the start, but that is OK, as it doesn't change during the script.

There is something to be said for sticking to Lua variables, eg.


currentmana = %2
sipmana = tonumber (GetVariable ("sipmana"))

...

if currentmana < sipmana then


Now you don't need to worry as we aren't chopping and changing between MUSHclient variables and Lua variables. Of course the remarks about comparing numbers to strings still apply. If you know %2 is a number and not a string, you don't need to quote it.
USA #8
David Haley said:
Quote:
Lua coerces numbers to strings on the fly when circumstances allow it

Well, if we're getting technical about it ;) no. For example, strings are not coerced for equality testing (which is a problem that was run into in this thread).

Which wasn't the specific scenario that I was alluding to. I also specifically said "when circumstances allow it".

David Haley said:
Also, in this instance, it is more likely the C API binding for SetVariable that does the conversion explicitly with lua_isstring and lua_getstring (both of which accept numbers and convert to strings).

Well, yes. If you use lua_getstring on a number, it automatically converts it to a string for you. I'm not sure how that invalidates my point.


David Haley said:
The above said: I mentioned explicit conversion for the sake of, well, explicitness, so that consistency is not only implied but also visual. So yes, I told a little white lie. :-)

For the sake of completeness, I thought I'd mention the implicit coercion as well. I wasn't arguing against you, I was supplementing your insight. ;)
USA #9
I wasn't trying to "invalidate" your point. I was making explicit (hehe) the somewhat vague condition of "when circumstances allow it" (why addition and not equality, after all?) or scenarios that are "alluded to" rather than given specifically. I think it's ok to be slightly hand-wavy when speaking in broad terms (or when one gives a condition that is stronger than necessary, such as always explicitly converting strings to integers), but if you get down to the buckets and bolts it's important to be as exact as possible.