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, 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.
 Entire forum ➜ MUSHclient ➜ Lua ➜ Accessing MUSHclient variables via a table

Accessing MUSHclient variables via a table

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


Posted by Nick Gammon   Australia  (23,057 posts)  Bio   Forum Administrator
Date Wed 24 Nov 2004 03:15 AM (UTC)
Message
Lua starts to come into its own with its powerful support for what it calls "metatables".

By using these, we can greatly simplify the things you do a lot of in MUSHclient - accessing variables.

How many times have you written something like this in VBscript? ...



dim coins
  
  coins = CInt (GetVariable ("coins"))
  coins = coins + CInt (wildcards (2))
  SetVariable "coins", coins


Here we have to muck around using GetVariable and SetVariable, as well as use CInt to convert strings into numbers.

Wouldn't it be nice to be able to write:


  coins = coins + wildcards (2)


... and have that saved as a MUSHclient variable? Well, with Lua you can (almost).

To do this we need to create a dummy table, like this:


var = {}	-- variables table


We will use that as our gateway to access MUSHclient variables. Now to make that work we need to make a "metatable" which implements two functions:


  • __index - which is called when we attempt to get data from it

  • __newindex - which is called when we attempt to add to it


These functions will call GetVariable and SetVariable to interface with MUSHclient variables.

Here is how it could look:


var = {}	-- variables table

setmetatable (var, 
 { 
 -- called to access an entry
 __index = 
 function (t, name) 
  return GetVariable (name) 
 end;
 
 -- called to change or delete an entry
 __newindex = 
 function (t, name, val) 
 local result
   if val == nil then	-- nil deletes it
     result = DeleteVariable (name)
   else
     result = SetVariable (name, tostring (val)) 
   end 
   -- warn if they are using bad variable names
   if result == error_code.eInvalidObjectLabel then
     error ("Bad variable name '" .. name .. "'")
   end
 end;
 })




You could put that into your script file to be run when the world file opens. Now with that in place, we simply do this:


  var.coins = var.coins + wildcards [2]


The "trick" here is the use of the "var" table - when we get data from that, or add to it, we go through the metamethod, which calls GetVariable and SetVariable, as shown above.


- Nick Gammon

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

Posted by Larkin   (278 posts)  Bio
Date Reply #1 on Fri 09 Mar 2007 03:22 PM (UTC)
Message
I use a lot of numbers in my Lua coding, and I didn't want to always have to convert the MUSHclient string variables to numbers for comparison. I modified this module a tiny bit to do the conversion for me after a simple check for a "numbers only" string. You could easily do the same for true/false, if you wanted. My var index function now looks like this:


function (t, name)
  local v = GetVariable(name)
  if (v == tostring(tonumber(v))) then
    return tonumber(v)
  end
  return v
end
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #2 on Fri 09 Mar 2007 04:14 PM (UTC)
Message
Alternatively, you could check the return value of tonumber against nil:

function (t, name)
  local v = GetVariable(name)
  local n = tonumber(v)
  if n ~= nil then
    return n
  end
  return v
end


The ~= nil part is optional, since any number (including 0) is considered to be true.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #3 on Fri 09 Mar 2007 04:37 PM (UTC)
Message
You could actually make it even simpler:


function (t, name)
 local v = GetVariable(name)
 return tonumber(v) or v
end
Top

Posted by Larkin   (278 posts)  Bio
Date Reply #4 on Fri 09 Mar 2007 06:01 PM (UTC)
Message
Good points, guys. Thanks for the tips. Sometimes I just don't think of the shortest, or even the easiest, way to code something. My purpose was more to suggest that Nick add something like this to his version of var.lua for future MUSHclient distributions. :)
Top

Posted by Nick Gammon   Australia  (23,057 posts)  Bio   Forum Administrator
Date Reply #5 on Sat 10 Mar 2007 12:48 AM (UTC)

Amended on Sat 10 Mar 2007 12:51 AM (UTC) by Nick Gammon

Message
I think it would be better for individual coders to make the suggested change, if they want to. Changing from a string to a number can't necessarily be reversed. For example:


a = tonumber ("1234e343")
print (a)  --> 1.#INF
a = tonumber ("143123412431243124124312431234132")
print (a)  --> 1.4312341243124e+032


It might happen that someone is using variables to store things like that and simply accessing the variable, and re-storing it, should not change it.

You could conceivably make the function do this:


function (t, name)
 local v = GetVariable(name)  -- fetch variable
 local n = tonumber (v)       -- try to make number
 if n and tostring (n) == v then    -- reversible?
   return n                   -- ok, return number
 else
   return v                   -- better return string
 end -- if
end -- function


This is now doing a tonumber and maybe a tostring on every access - perhaps you don't want the speed decrease.

Even that suggestion would not be foolproof, for example a string containing "-01" once converted to a number and back again is "-1". I suppose it depends on whether you are certain you are dealing with numbers or not.

- Nick Gammon

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

Posted by Nick Gammon   Australia  (23,057 posts)  Bio   Forum Administrator
Date Reply #6 on Sat 29 Mar 2008 08:29 PM (UTC)

Amended on Sat 29 Mar 2008 08:34 PM (UTC) by Nick Gammon

Message
This "var" code now ships as part of MUSHclient (from version 3.80 onwards), in a separate module file called var.lua.

If you have things installed in their default locations, all you have to do is "require" it like this:


require "var"

var.coins = var.coins + wildcards [2]


The "require" line pulls in all of the code described above, all you have to do is go ahead and use it.

In an example like the above one, you need to be cautious that the variable exists (as a MUSHclient variable). Otherwise you are doing arithmetic on a nil value, which will fail. This approach can solve that:


require "var"

var.coins = (var.coins or 0) + wildcards [2]


The "or 0" part says, in effect: if var.coins is nil, use 0 instead (as a default)

A more long winded way of achieving the same thing is:



require "var"

if var.coins == nil then
  var.coins = 0
end -- if variable does not exist

var.coins = var.coins + wildcards [2]

- Nick Gammon

www.gammon.com.au, www.mushclient.com
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.


32,864 views.

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.