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
➜ help with nil results and metatables
help with nil results and metatables
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Posted by
| Hoplo
(16 posts) Bio
|
Date
| Tue 31 Jul 2012 08:55 AM (UTC) |
Message
| I have seen an example of how this is supposed to work (i think), but I seem to be doing something wrong.
the goal is have a trigger that decreases the number of spells memorized as i cast them.
This is what I have so far:
<triggers>
<trigger
enabled="y"
expand_variables="y"
group="spellcounter"
match="^You utter the words\, \'([a-zA-Z ]+)\'$"
regexp="y"
send_to="12"
sequence="100"
>
<send>
spell_cast = "%1"
memc = 0;
memt [spell_cast] = memt [spell_cast] or {}
mt = { __index =
function (tbl, key)
tbl [key] = {} -- add sub table
return tbl [key] -- return as missing value
end }
setmetatable (memt, mt)
memt [spell_cast].mem = memt [spell_cast].mem - 1
memc = memt [spell_cast].mem
Note (" *** ".. memc .." of " .. spell_cast .." left ***")
end</send>
</trigger>
</triggers>
Everything works as long as the spell is in the table. If the spell is not then I get a Nil error. The memt table is already set and populated through another trigger based on information from the mud; however, sometimes a character is able to cast a spell even if it is not memorized.
I tried to use a metatable as shown in another thread, but I do not seem to have it working right because I still get the error.
| Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #1 on Tue 31 Jul 2012 10:42 PM (UTC) |
Message
| What other thread?
 |
To make your code more readable please use [code] tags as described here.
|
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Fiendish
USA (2,534 posts) Bio
Global Moderator |
Date
| Reply #2 on Tue 31 Jul 2012 11:34 PM (UTC) Amended on Tue 31 Jul 2012 11:35 PM (UTC) by Fiendish
|
Message
|
Quote: If the spell is not then I get a Nil error.
Of course you do. If memt[spell_cast] doesn't exist it gets set to {}. {}.mem results in nil. You then try to subtract 1 from nil.
In the future post your actual error message. We all know that MUSHclient gave you something far more specific and useful than just "a Nil error". So please next time actually tell us what it is. |
https://github.com/fiendish/aardwolfclientpackage | Top |
|
Posted by
| Hoplo
(16 posts) Bio
|
Date
| Reply #3 on Thu 02 Aug 2012 01:32 AM (UTC) |
Message
| Sorry for the late response, was working on other things. I updated the script a bit and made it into a function.
function docasted(name, line, wildcards)
spell_cast = wildcards [1]
setmetatable (memt, { __index = function () return {} end } )
memc = 0;
if spell_cast == "heal" then
healc = tonumber (GetVariable("healcount")) - 1
Note (" *** ".. healc .." of Heal left ***")
if healc <= 3 then
if healc == 1 then
Send("gt *** ".. healc .." HEAL REMAINING ***")
else
Send("gt *** ".. healc .." HEALS REMAINING ***")
end
end
else
memt [spell_cast].mem = memt [spell_cast].mem - 1
memc = memt [spell_cast].mem
Note (" *** ".. memc .." of " .. spell_cast .." left ***")
end -- if
end -- function
the error i get is :
You utter the words, 'ewd exe'
Run-time error
World: BaseArctic
Function/Sub: docasted called by trigger
Reason: processing trigger ""
[string "Script file"]:42: attempt to perform arithmetic on field 'mem' (a nil value)
stack traceback:
[string "Script file"]:42: in function <[string "Script file"]:26>
Error context in script:
38 : Send("gt *** ".. healc .." HEALS REMAINING ***")
39 : end
40 : end
41 : else
42*: memt [spell_cast].mem = memt [spell_cast].mem - 1
43 : memc = memt [spell_cast].mem
44 : Note (" *** ".. memc .." of " .. spell_cast .." left ***")
45 : end -- if
46 : end -- function
You've never heard of such a spell.
I tried to add in a meta table as shown in here.
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=9085
| Top |
|
Posted by
| Fiendish
USA (2,534 posts) Bio
Global Moderator |
Date
| Reply #4 on Thu 02 Aug 2012 04:28 AM (UTC) |
Message
| I already told you what the problem is. |
https://github.com/fiendish/aardwolfclientpackage | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #5 on Thu 02 Aug 2012 05:53 AM (UTC) |
Message
|
memt [spell_cast].mem = memt [spell_cast].mem - 1
If there is doubt if mem exists, you can do this:
memt [spell_cast].mem = (memt [spell_cast].mem or 0) - 1
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Hoplo
(16 posts) Bio
|
Date
| Reply #6 on Thu 02 Aug 2012 05:59 PM (UTC) |
Message
| Thank you Nick, I am sure I will need this once the first step is fixed. The problem, as Fiendish has noted, is that the error starts when a spell not in the table is attempted. The table is formed automatically from a list of memorized spells provided from the mud.
What I would ultimately like to do is make it so if a spell is attempted that is not in the list then there is not an error.
One way to do this would be to simply have the script do something like a ipair search through the table to see if the spell is there and then cast it, or exit the script. This can cause a problem because there are unique situations where spells can be cast even if they are not memorized ( as seen by my hackish "heal" check). But, I am not really sure how to do this... I will give it a try.
Another way that sounded promising was to use a metatable to make the entry as needed. Again, I am not really sure how to do this either. I had attemted something like this in the original code post, but I have done something obviously wrong.
| Top |
|
Posted by
| Fiendish
USA (2,534 posts) Bio
Global Moderator |
Date
| Reply #7 on Thu 02 Aug 2012 08:09 PM (UTC) Amended on Sat 04 Aug 2012 04:38 PM (UTC) by Fiendish
|
Message
|
Hoplo said:
Thank you Nick, I am sure I will need this once the first step is fixed.
There is no first step. Nick understands the problem I am talking about.
Quote: The problem, as Fiendish has noted, is that the error starts when a spell not in the table is attempted.
No. The problem happens because, while you construct a member table for memt[spell_cast], you neglect to give it any meaningful members. The problem is your arithmetic, not your table. That is, you have no ".mem" from which to subtract 1.
Quote: ...stuff...I had attemted something like this in the original code post, but I have done something obviously wrong.
IMO, the thing you did wrong was trying to write a solution before understanding the problem. Checking the existence of something before using it is trivial and does not become easier with metatables. |
https://github.com/fiendish/aardwolfclientpackage | Top |
|
Posted by
| Hoplo
(16 posts) Bio
|
Date
| Reply #8 on Thu 02 Aug 2012 09:24 PM (UTC) Amended on Fri 03 Aug 2012 03:28 AM (UTC) by Hoplo
|
Message
| "construct a member table for memt[spell_cast], you neglect to give it any meaningful members. The problem is your arithmetic, not your table. That is, you have no ".mem" from which to subtract 1."
I will freely admit I have little idea of what I am doing, as I tried to state above. I am aware the issue is an arithmetic problem because there is not a number in certain ".mem"s to subtract from.
However, the memt table is populated by "meaningful members" that work just fine. The problem I posted is when a spell is cast that is not in the table. Then, I believe, the issue is not simple ensuring there is a .mem to subract, but the whole parent subtable of the spell name the .mem is applied to exists.
I did try Nick's suggestion, with the same error being returned.
If it may help, the when I use tprint (memt) I get something like :
"blindness":
"mem"="4"
"silence":
"mem"="2"
"the thing you did wrong was trying to write a solution before understanding the problem."
I tried what I thought might work. I certainly would not be surprised if I was wrong. | Top |
|
Posted by
| Fiendish
USA (2,534 posts) Bio
Global Moderator |
Date
| Reply #9 on Thu 02 Aug 2012 10:05 PM (UTC) Amended on Thu 02 Aug 2012 10:09 PM (UTC) by Fiendish
|
Message
|
Hoplo said: However, the memt table is populated by "meaningful members" that work just fine. No it is not. Not when the spell isn't already in the table.
Quote: Then, I believe, the issue is not simple ensuring there is a .mem to subract, but the whole parent subtable of the spell name the .mem is applied to exists.
The error message you posted does not support your belief.
Here's the thing. Your metatable trick worked. It's a silly thing to do because it clearly solves only half of your original problem (you tried to access a member of nil), and does so in a way you don't understand, but it did work. memt[spell_cast] will no longer return nil.
Much more sane would have been to check if memt[spell_cast] is null and create a new table on that condition with the appropriate mem value. Or better yet, not a table at all. Tables containing a single member are silly. You might as well just make memt[spell_cast] store the value mem directly.
But now you have just punted your nil problem down the field. memt[spell_cast] no longer returns nil, it returns an empty table. Your problem now is that empty tables are empty. They do not contain mem. So trying to access .mem returns nil. This is only a problem when you try to subtract 1.
Quote: I did try Nick's suggestion, with the same error being returned. I doubt that. What Nick posted would solve the error you showed given the code you showed. Please post your new code and new error message. |
https://github.com/fiendish/aardwolfclientpackage | Top |
|
Posted by
| Hoplo
(16 posts) Bio
|
Date
| Reply #10 on Fri 03 Aug 2012 04:07 AM (UTC) |
Message
|
function docasted(name, line, wildcards)
spell_cast = wildcards [1]
memc = 0;
if spell_cast == "heal" then
healc = tonumber (GetVariable("healcount")) - 1
Note (" *** ".. healc .." of Heal left ***")
if healc <= 3 then
if healc == 1 then
Send("gt *** ".. healc .." HEAL REMAINING ***")
else
Send("gt *** ".. healc .." HEALS REMAINING ***")
end
end
else
for s,m in pairs(memt) do
if s == spell_cast then
memt [spell_cast].mem = (memt [spell_cast].mem or 0) - 1
memc = memt [spell_cast].mem
Note (" *** ".. memc .." of " .. spell_cast .." left ***")
end -- if
end -- for
end -- if
end -- function
This fixed my problem. Thanks for the help. | Top |
|
Posted by
| Fiendish
USA (2,534 posts) Bio
Global Moderator |
Date
| Reply #11 on Fri 03 Aug 2012 12:23 PM (UTC) |
Message
| for s,m in pairs(memt) do
if s == spell_cast then
...
end
Can be done much more simply with just
if memt[spell_cast] then
...
end
|
https://github.com/fiendish/aardwolfclientpackage | Top |
|
Posted by
| Fiendish
USA (2,534 posts) Bio
Global Moderator |
Date
| Reply #12 on Fri 03 Aug 2012 04:03 PM (UTC) |
Message
| Though, now that you are sanely checking for the spell's existence in memt, perhaps you no longer need Nick's patch because you should have already set up .mem elsewhere? |
https://github.com/fiendish/aardwolfclientpackage | 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.
29,951 views.
It is now over 60 days since the last post. This thread is closed.
Refresh page
top