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


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  General
. . -> [Subject]  Having trouble printing a table

Having trouble printing a table

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


Pages: 1 2  

Posted by Shinth   (10 posts)  [Biography] bio
Date Fri 10 Aug 2007 06:57 AM (UTC)

Amended on Fri 10 Aug 2007 06:58 AM (UTC) by Shinth

Message
Could someone tell me what is wrong with this function?

function change_priority(name,line,wildcards)
if (wildcards [1] == "health") then 
   healpriority = {}	
   healpriority = {health = "drink health", mana = "drink mana", ego = "drink bromide"}
end
if (wildcards [1] == "mana") then
   healpriority = {}
   Note ("mana")
   healpriority = {mana = "drink mana", health = "drink health", ego = "drink bromide"}
   for k, v in ipairs (healpriority) do 
   Tell (tostring(k),"=")
   Note (v)
   end -- for
end
if (wildcards [1] == "ego") then
   healpriority = {}
   healpriority = {ego = "drink bromide", health = "drink health", mana = "drink mana"}
end
ColourTell ("aqua","","Healing priority: ") ColourNote ("lime","", string.upper(wildcards [1]))
tprint (healpriority)
end

If I call the function with the wildcard "mana" (from an alias) and don't have tprint, the "for k,v in ipairs (healpriority)" loop doesn't do a thing, but it enters the if statement (that's why I put "Note" there, to check).
If I use tprint, no matter what wildcard I use, either health, mana or ego, it prints the same table

ego=drink bromide
mana=drink mana
health=drink health

I've been trying to see what is wrong with it for a couple of hours now, any suggestions?
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Fri 10 Aug 2007 07:04 AM (UTC)
Message
ipairs is designed to only iterate over numeric keys. You want pairs, not ipairs.

Your keys are the strings "mana", "health" and "ego", which are not numbers.

- Nick Gammon

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

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Fri 10 Aug 2007 07:07 AM (UTC)
Message
Quote:

healpriority = {}
healpriority = {health = "drink health", mana = "drink mana", ego = "drink bromide"}


The first line there is redundant. You are recreating the table in the second line, and thus you create an empty table that has to be garbage-collected eventually. It is like writing this:


a = 2
a = 3


Not much point in the first line.

- Nick Gammon

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

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #3 on Fri 10 Aug 2007 07:17 AM (UTC)

Amended on Fri 10 Aug 2007 07:20 AM (UTC) by Shaun Biggs

Message
I'm not really entirely sure what the end result of this script would be, but here's how I would do what you have so far:

healqueues = { health = { "drink health", "drink mana", "drink bromide" },
               mana   = { "drink mana", "drink bromide", "drink health" },
	       ego    = { "drink bromide", "drink health", "drink mana" } }
function change_priority(name,line,wildcards)
  healpriority = healqueues[ wildcards[1] ]
  ColourNote ("aqua","","Healing priority: ",
              "lime","", string.upper(wildcards [1]) )
  for k,v in ipairs( healpriority ) do
    Note( k.."="..v )
  end
end

This will let you access the highest priority with healpriority[1], just like a normal list. Some sanity checking will need to be done for making sure that healqueues[wildcards[1]] exists and isn't nil unless you're absolutely positive that sane values will be sent into the script.

oh, and here's the output of a quick test:

Healing priority: MANA
1=drink mana
2=drink bromide
3=drink health
Healing priority: HEALTH
1=drink health
2=drink mana
3=drink bromide

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #4 on Fri 10 Aug 2007 08:18 AM (UTC)
Message
Odd thought on sanity checking... no change to the healpriorty variable if there isn't a bad value is passed. This is assuming that you declared healpriority somewhere globally...

healqueues = { health = { "drink health", "drink mana", "drink bromide" },
               mana   = { "drink mana", "drink bromide", "drink health" },
	       ego    = { "drink bromide", "drink health", "drink mana" } }
healpriority = healqueues.health --make health the default

function change_priority(name,line,wildcards)
  healpriority = healqueues[ wildcards[1] ] or healpriority
  ColourNote ("aqua","","Healing priority: ",
              "lime","", string.upper(wildcards [1]) )
  for k,v in ipairs( healpriority ) do
    Note( k.."="..v )
  end
end

and the test data:

Healing priority: MANA
1=drink mana
2=drink bromide
3=drink health
Healing priority: WAFFLES
1=drink mana
2=drink bromide
3=drink health

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shinth   (10 posts)  [Biography] bio
Date Reply #5 on Fri 10 Aug 2007 10:20 AM (UTC)

Amended on Fri 10 Aug 2007 09:18 PM (UTC) by Nick Gammon

Message
Thank you all for the help, I have decided to use an array instead of a table because I need it compared to the key of another table, but in a specific order. Another question, I've declared a table like this:

drinkqueue = {health=0;mana=0;ego=0}

So when I check the conditions to drink health:

drinkqueue.health="drink health"

I want to check if a key is 0, but for some reason v != 0 gives me the error:

Compile error
World: Lusternia
Immediate execution
[string "Script file"]:86: ')' expected near '!'
Error context in script:
  82 : tprint(drinkqueue)
  83 : if (todrink == 1) then
  84 : for i=1,3 do
  85 :   for k,v in pairs (drinkqueue) do
  86*:     if (healpriority[i] == k) and (v != 0) then

Any ideas what is wrong with it? And also, a break in the second for loop will stop the first loop too?
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #6 on Fri 10 Aug 2007 10:43 AM (UTC)

Amended on Fri 10 Aug 2007 10:44 AM (UTC) by Shaun Biggs

Message
Quote:
I have decided to use an array instead of a table because I need it compared to the key of another table, but in a specific order.
In Lua, there is no difference between an array and a table. An "array" is merely a table with a sequential set of keys. Being a table, there is no practical difference at all between {health = "drink health", mana = "drink mana", ego = "drink bromide"} and {mana = "drink mana", health = "drink health", ego = "drink bromide"}. They both have the same keys and the same values, and order does not matter terribly much, since there isn't a numerical set dictating any order.

Quote:
I want to check if a key is 0, but for some reason v != 0 gives me the error:

!= doesn't mean anything to a Lua interpreter. A nonequivalency is declared as ~= for this language.

If you would like to get a bit more familiar with Lua, this site is where I learned from: http://lua-users.org/wiki/TutorialDirectory I still use it quite frequently for reference.

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #7 on Fri 10 Aug 2007 11:05 AM (UTC)
Message
Would you mind posting the whole function? I'm getting confused with how the line drinkqueue.health="drink health" relates to drinkqueue = {health=0;mana=0;ego=0}

Break will just break the most recent block of code, so it won't exit all of your loops, just the last one. Keep in mind that the counter in a for loop is destroyed once the for loop is finished, so if you plan on keeping the value, use a while loop instead.

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shinth   (10 posts)  [Biography] bio
Date Reply #8 on Fri 10 Aug 2007 11:37 AM (UTC)

Amended on Fri 10 Aug 2007 09:18 PM (UTC) by Nick Gammon

Message
Thank you for the link, I will try the tutorials there as soon as I have time, they seem interesting.
And here is the function:

function system_drink ()
todrink=0
if (tonumber(GetVariable("health"))<math.floor(tonumber(GetVariable("MaxHealth"))*2/3)) then 
  drinkqueue.health="drink health"
  todrink=1
end -- if
if (tonumber(GetVariable("mana"))<math.floor(tonumber(GetVariable("MaxMana"))*1/4)) then 
  drinkqueue.mana="drink mana"
  todrink=1
end -- if
if (tonumber(GetVariable("ego"))<math.floor(tonumber(GetVariable("MaxEgo"))*1/3)) then 
  drinkqueue.ego="drink bromide"
  todrink=1
end -- if
i = 1
while (todrink == 1) and (i <= 3) do
  for k,v in pairs (drinkqueue) do
    if (healpriority[i] == k) and (v ~= 0) then
      Send (drinkqueue.v)
      SetVariable("elixbal","0.5")
      drinkqueue = {health = 0, mana = 0, ego = 0}
      todrink=0
      break
    end -- if
  end -- for
  i = i+1
end -- while
end -- function

What I am trying to do is a priority based autosipper, when both my mana and health are low, for example, what will drink first will be set by my healpriority table. Basically it checks if the first item, then the next, and so on, in the healpriority table is below a certain level by checking if there is a value, not equal to 0, assigned to that attribute in the drink queue. If so, it drinks, sets my balance flag to 0.5, that means that I am waiting to actually drink from a vial and exits. It also resets the drinkqueue, just to be sure it will always cure based on my priorities. There might be some flaws here, I haven't test it yet.
Edit: it keeps spelling italic, I don't know why.
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #9 on Fri 10 Aug 2007 12:41 PM (UTC)

Amended on Fri 10 Aug 2007 09:26 PM (UTC) by Nick Gammon

Message

i = 1
while (todrink == 1) and (i <= 3) do
  for k,v in pairs (drinkqueue) do
    if (healpriority == k) and (v ~= 0) then
      Send (drinkqueue.v)
      SetVariable("elixbal","0.5")
      drinkqueue = {health = 0, mana = 0, ego = 0}
      todrink=0
      break
    end -- if
  end -- for
  i = i+1
end -- while

II'm not quite sure I understand the outer loop in this part. i is never used within the loop, so it will either do the loop once if you send a drink, or it will repeat three times if you don't send a drink (which is impossible due to you needing a drink in the first place.

I'm also still not clear on some of those variables. If the heal priority is the same as the function I posted above, then you should go through that array using ipairs to ensure the proper order, and match drinkqueue up with that.

The following block of code is how I would do the whole thing (both functions and supporting tables). Obviously, it's not the only way to do it, but this way you just have one loop to deal with testing and sending data. This will require changing the max health/mana/ego variables to lowercase, but if that would complicate things too much for other scripts, just change the keys/values for the various tables here. I tested this out with some dummy data, and it seemed to work. I've also taken advantage of quite a few scripting tricks to make the loop easier to deal with, such as concatenating the "max"..healpriority[i] have only one loop take care of all the data comparisons.

healstart = { health = 2/3, mana = 0.25, ego = 1/3 }
healaction = { health = "drink health", mana = "drink mana", ego = "drink bromide" }
healqueues = { health = { "health", "mana", "ego" },
               mana   = { "mana", "ego", "health" },
	       ego    = { "ego", "health", "mana" } }
healpriority = healqueues.health --make health the default

function change_priority(name,line,wildcards)
  healpriority = healqueues[ wildcards[1] ] or healpriority
  ColourNote ("aqua","","Healing priority: ",
              "lime","", string.upper(wildcards [1]) )
  for k,v in ipairs( healpriority ) do
    Note( k.."="..v.."  action = "..healaction[v] )
  end
end

function system_drink()
  i = 1
  repeat
    if tonumber( GetVariable( healpriority[i] ) ) <
      tonumber( GetVariable( "max"..healpriority[i] ) ) * healstart[healpriority[i]] then
      Send( healaction[healpriority[i]] )
      SetVariable( "elixbal", "0.5")
      i = 3
    end
    i = i + 1
  until i > 3
end

edit: Once again foiled by the forum eating my table brackets.

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #10 on Fri 10 Aug 2007 12:55 PM (UTC)

Amended on Fri 10 Aug 2007 01:00 PM (UTC) by Shaun Biggs

Message
if (tonumber(GetVariable("health"))<math.floor(tonumber(GetVariable("MaxHealth"))*2/3)) then

Two quick notes about these lines. First, you don't need to put the tonumber(GetVariable...) in parenthesis. Lua will recognize that fine as it is. Second, and the actual important one, is that there isn't really a point to using math.floor here unless you can somehow get 12.7 health or something like that. The test for 25 <= 25 is just the same as 25 < 25.12 and 26 <= 25 is just the same as 26 < 25.12.

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shinth   (10 posts)  [Biography] bio
Date Reply #11 on Fri 10 Aug 2007 02:19 PM (UTC)

Amended on Fri 10 Aug 2007 03:25 PM (UTC) by Shinth

Message
Very nice scripting, it's faster and you can also configure when to drink (like at 3/4*health, instead of 2/3). One thing though, this will run every prompt line, and could slow me down. The todrink variable was to do into the loop only if you needed to drink. But the again, when you needed to heal, you execute more lines, so I guess I will use yours, it looks better. And thanks for the advice about math.floor too!

Edit: It works great. Thank you!
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #12 on Fri 10 Aug 2007 04:01 PM (UTC)
Message
Quote:
One thing though, this will run every prompt line, and could slow me down. The todrink variable was to do into the loop only if you needed to drink.

The way you originally had it set up worked the same way as mine. You had todrink set with 3 if statements, where I have it set with a loop of one if statement up to three times. I figured you would have the "elixbal" variable checked to see if you drank a potion already, surrounding the whole thing with an if GetVariable( "elixbal" ) ~= "0.5" bit. Or you could turn off the trigger with EnableTrigger( "triggername", false ) and turn it back on with the trigger that catches you drinking the potion. The latter option is what I tend to do, but I go crazy and solve things by turning triggers on and off like strobe lights. For simple things that's fine, but it can get complicated very quickly.

It is much easier to fight for one's ideals than to live up to them.
[Go to top] top

Posted by Shinth   (10 posts)  [Biography] bio
Date Reply #13 on Fri 10 Aug 2007 04:59 PM (UTC)
Message
I check to see if I have balance in the prompt trigger. And at the drink message I check to see if I had actually sent the drink command by seeing if the elixbal is 0.5. If it is, then I enable a failsafe timer in case I cannot sip because of an affliction. Then when the actual effect message of the potion is sent I check to see if I drank, then make my balance 0. When the message that I can drink another potion is sent, I check to see if I was off balance and assign elixbal=1. Complicated, but it is a good protection against illusion.
Quote:

Or you could turn off the trigger with EnableTrigger( "triggername", false ) and turn it back on with the trigger that catches you drinking the potion. The latter option is what I tend to do, but I go crazy and solve things by turning triggers on and off like strobe lights.

I don't like having too much triggers active too, it slows you down and makes you vulnerable to illusions. Disabling the prompt trigger where I have set this function is a bad idea, because when my system will be finished I will have to check for about 10 types of balances and other afflictions, and turning it off and on isn't going to work.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #14 on Fri 10 Aug 2007 09:21 PM (UTC)

Amended on Fri 10 Aug 2007 11:04 PM (UTC) by Nick Gammon

Message
Quote:

Edit: it keeps spelling italic, I don't know why.


You are using [i] which means "make the text italic" to the forum. If you are posting text with square brackets, or backslashes in it, you should "escape" them by putting a backslash in front of them, like this: \[i\]

There is a function in MUSHclient to do that for you, which I always use when posting code here. This is what I do:


  • Copy the code I want to paste (Ctrl+C)

  • Select Edit menu -> Convert Clipboard Forum Codes (Shift+Ctrl+Alt+Q) - a small dialog box pops up showing how many were converted

  • Switch to the forum and paste (Ctrl+V)


This reliably fixes this problem with only a small amount of effort.

I am fixing up your current posts for you.

- Nick Gammon

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


37,722 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] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

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

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

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

[Best viewed with any browser - 2K]    [Hosted at HostDash]