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 ➜ General ➜ Need help with a script please

Need help with a script please

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


Posted by Curious2   (47 posts)  Bio
Date Fri 06 Feb 2009 02:58 PM (UTC)
Message
I have an herb script that needs to check if I have at least two afflictions set to true before attempting a cure on certain types of afflictions.

Orginally I placed the cures in a table and then just used this...


for _, v in ipairs(table) do 
  if afflicted[v.name] then
    eat(v.cure)
    return
  end
end


However, on some things I don't want it to eat the herb UNLESS there is more than one affliction with that cure because I can also use a different ability to cure that affliction. If I cure with the other ability and end up eating it anyway, it strips one of my defenses. So it's okay to go ahead and eat and cure with the other ability if there are at least two afflictions that require that herb because the herb will cure one and the ability the other.

So if the cure is this herb, I don't want it to eat that herb unless there is that affliction and a second one that require that herb OR I am unable to use the other curing ability at that time. Otherwise I just do both cures at the same time and end up stripping a defense.

I changed the script to a very large set if if/elseif statements but the problem is checking for that second affliction. Do I need to make like 5 seperate functions with if/elseif checks and return true or false for each separate set? I'm not sure what the best way to do this is. I would much rather use the easy way with the table, but it doesn't work right in this case.
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #1 on Fri 06 Feb 2009 08:31 PM (UTC)

Amended on Fri 06 Feb 2009 08:32 PM (UTC) by Nick Gammon

Message
First, there have been some posts before about afflictions and cures:


http://www.gammon.com.au/forum/?id=5514

http://www.gammon.com.au/forum/?id=6457

http://www.gammon.com.au/forum/?id=6074

The third one in particular has a lengthy treatment of handling afflictions in Lua, prioritizing them and so on.

Quote:

I changed the script to a very large set if if/elseif statements but the problem is checking for that second affliction. Do I need to make like 5 seperate functions with if/elseif checks and return true or false for each separate set?


Anyway, when you find yourself with a lot of if/elseif statements you should be thinking of using a table or two.

Here is some sample code to show what I mean. I made up some afflictions and cures. Note that sleep has two cures (wildvine and yarrow) and that the cure wildvine cures two afflictions (sleep and dazed).

In other words, according to what you want, if you are afflicted by sleep it should cure with yarrow instead of wildvine, because wildvine also cures something else.

So to work all this out, I made two extra tables, cureslist and afflictionslist. One maps one cure to multiple afflictions, and one maps one affliction to multiple cures. We walk through the original table once to set up both these extra tables, like this:


-- table of herbs and cures

curesherbs = 

{
  { name = "stupidity", cure = "orphine" },
  { name = "paralysis", cure = "maidenhair" },
  { name = "sleep", cure = "wildvine" },
  { name = "dizziness", cure = "sparkleberry" },
  { name = "dizziness", cure = "wormwood" },
  { name = "dazed", cure = "wildvine" },
  { name = "sleep", cure = "yarrow" },


}

cureslist = {}
afflictionslist = {}

-- map one to many ...

for _, v in ipairs (curesherbs) do
  afflictionslist [v.name] =  afflictionslist [v.name] or {}  -- create entry if necessary for this affliction
  cureslist [v.cure] =  cureslist [v.cure] or {}  -- create entry if necessary for this cure

  table.insert (afflictionslist [v.name], v.cure)
  table.insert (cureslist [v.cure], v.name)

end -- for

-- show tables for debugging

require "tprint"

print ("Afflictions:")
tprint (afflictionslist)

print ""

print ("Cures:")
tprint (cureslist)



The debugging output is this:


Afflictions:
"sleep":
  1="wildvine"
  2="yarrow"
"dazed":
  1="wildvine"
"stupidity":
  1="orphine"
"dizziness":
  1="sparkleberry"
  2="wormwood"
"paralysis":
  1="maidenhair"

Cures:
"maidenhair":
  1="paralysis"
"orphine":
  1="stupidity"
"yarrow":
  1="sleep"
"sparkleberry":
  1="dizziness"
"wildvine":
  1="sleep"
  2="dazed"
"wormwood":
  1="dizziness"


You can see that if we key the afflictions table by "sleep" we get two entries, wildvine and yarrow.

You can also see that if we key into the cures table for wildvine we see two entries, but if we key into it for yarrow, we see one. This gives us what we need to know.

Now we can check each affliction:




-- test

afflicted = { sleep = true }  -- we are sleepy


-- check all afflictions
for aff in pairs (afflicted) do

  local cured = false

  -- look for single cure

  for _, cure in ipairs (afflictionslist [aff]) do
    if #cureslist [cure] == 1 then
      Send (cure)
      cured = true
      break
    end -- this cure only cures one affliction
  end -- for

  -- otherwise look for something that cures this and something else

  if not cured then
    for _, cure in ipairs (afflictionslist [aff]) do
      Send (cure)
      cured = true
      break
    end -- for
  end -- if

  
end -- for each affliction


This sends "yarrow" as it should, as it found yarrow under the for loop "look for single cure".

However if we change the affliction to:


afflicted = { dazed = true }  -- we are dazed


This sends "wildvine", as it couldn't find a single cure, it then found wildvine which cures more than one thing.

This script could be fine-tuned a bit, for example testing if a particular cure was available right now. Also if you were afflicted by two things, and there was a single cure that cured both of them, you would use that in preference to two individual cures that cured each one (I imagine).



- Nick Gammon

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

Posted by Curious2   (47 posts)  Bio
Date Reply #2 on Fri 06 Feb 2009 09:43 PM (UTC)

Amended on Fri 06 Feb 2009 10:00 PM (UTC) by Curious2

Message
Yes your third link is exactly how I set it up originally.

The problem is afflictions cured by goldenseal also can be cured by focus and I cure off the prompt so it sends both types of cures. If you eat goldenseal but focus cured it already then the goldenseal strips your insomnia defense.

I set up my curing like in that third link. I have an herbcure, salvecure, and so on. Each of those iterate through a table for those specific cures for each affliction type.

The only problem with what you have there is I don't understand how I could set up for each cure type as in focus and herbs. Everything works on balance. That would work fine if there were two different herbs that cured the same affliction. I guess I will have to figure out how to mix herb curing and focus curing together to use that script somehow...

These are the two tables for the focus and herb cures I use.


cures.focus.affs = {
  "stupidity",
  "recklessness",
  "anorexia",
  "weakness",
  "confusion",
  "epilepsy",
  "agoraphobia",
  "claustrophobia",
  "shyness",
  "dizziness",
  "loneliness",
  "masochism"
  }


For focus, the cure is always just focus.


cures.herbs.curelist = {
  { name = "scytherus"          , cure = "ginseng" },
  { name = "hypochondria"       , cure = "kelp" },
  { name = "paralysis"          , cure = "bloodroot" },
  { name = "impatience"         , cure = "goldenseal" },
  { name = "asthma"             , cure = "kelp" },
  { name = "recklessness"       , cure = "lobelia" },
  { name = "masochism"          , cure = "lobelia" },
  { name = "darkshade"          , cure = "ginseng" },
  { name = "sensitivity"        , cure = "kelp" },
  { name = "haemophilia"        , cure = "ginseng" },
  { name = "slickness"          , cure = "bloodroot" },
  { name = "epilepsy"           , cure = "goldenseal" },
  { name = "clumsiness"         , cure = "kelp" },
  { name = "confusion"          , cure = "ash" },
  { name = "hallucinations"     , cure = "ash" },
  { name = "stupidity"          , cure = "goldenseal" },
  { name = "hypersomnia"        , cure = "ash" },
  { name = "healthleech"        , cure = "kelp" },
  { name = "weakness"           , cure = "kelp" },
  { name = "lethargy"           , cure = "ginseng" },
  { name = "nausea"             , cure = "ginseng" },
  { name = "dissonance"         , cure = "goldenseal" },
  { name = "shyness"            , cure = "goldenseal" },
  { name = "dizziness"          , cure = "goldenseal" },
  { name = "loneliness"         , cure = "lobelia" },
  { name = "vertigo"            , cure = "lobelia" },
  { name = "agoraphobia"        , cure = "lobelia" },
  { name = "claustrophobia"     , cure = "lobelia" },
  { name = "addiction"          , cure = "ginseng" },
  { name = "dementia"           , cure = "ash" },
  { name = "paranoia"           , cure = "ash" },
  { name = "justice"            , cure = "bellwort" }
  }


The problem is these 5 only:

{ name = "epilepsy" , cure = "goldenseal" },
{ name = "stupidity" , cure = "goldenseal" },
{ name = "dissonance" , cure = "goldenseal" },
{ name = "shyness" , cure = "goldenseal" },
{ name = "dizziness" , cure = "goldenseal" },

If I only have one of those, I just want to cure with focus and not eat an herb. If I have two of them however, then I want to do my focuscure and herbcure both. I don't understand how to do that with what you posted.

These are the two functions.


function cure.herbs()
  -- check for ability to eat herb
  if not auto.herbs or
    not cures.herbs.bal or
    cures.herbs.try or 
    afflicted.anorexia or 
    afflicted.aeon or
    afflicted.sleep or
    afflicted.stunned or
    afflicted.impaled or
    afflicted.transfixed or
    cures.general.paused then
    return
  end -- can't do it yet
	--  eat function
	local function eat(herb)
		if outrifted[herb] then -- if herb outrifted then eat first
			SendImmediate("eat " .. herb)
			SendImmediate("outr " .. herb)
		else
			SendImmediate("outr " .. herb)
			SendImmediate("eat " .. herb)
			SendImmediate("outr " .. herb)
		end
		cures.herbs.eating = herb
		cures.herbs.try = true
		EnableTimer("herbTimer", true)
		end
	end -- function eat
  -- find affliction and cure  
  for _, v in ipairs(cures.herbs.curelist) do
    if afflicted[v.name] then
      eat(v.cure)
      return
    end
  end
  if defense.blindness == false then
    eat("bayberry")
  elseif not defense.deafness and not cures.herbs.hawate then
    eat("hawthorn")
    cures.herbs.hawate = true
  elseif not defense.kola then
    if outrifted[kola] then
			SendImmediate("eat kola")
			SendImmediate("outr kola")
		else
			SendImmediate("outr kola")
			SendImmediate("eat kola")
			SendImmediate("outr kola")
		end
  end
end -- function herb cure


function cure.focus()
  -- check if can focus
  local halfmana = mystats.maxmana * 0.5
  if mystats.mana <= halfmana or
    afflicted.sleep or
    afflicted.stunned or
    afflicted.aeon or
    not auto.focus or
    not cures.focus.bal or
    afflicted.impatience or
    cures.general.paused or
    cures.focus.try then
    return
  end -- can't focus
  -- do focus
  for _, v in ipairs(cures.focus.affs) do
    if afflicted[v] then
      SendImmediate("focus")
      cures.focus.try = true
      EnableTimer("focusTimer", true)
      ResetTimer ("focusTimer")
      return
    end
  end
end -- focus
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #3 on Fri 06 Feb 2009 09:59 PM (UTC)
Message
Well there is usually more than one way to skin a cat. ...

Another way of expressing your cures is this:


cures = 
{
  scytherus = "ginseng",
  justice = "bellwort",
  lethargy = "ginseng",
  hypersomnia = "ash",
  paranoia = "ash",
  masochism = "lobelia",
  dementia = "ash",
  addiction = "ginseng",
  claustrophobia = "lobelia",
  epilepsy = "goldenseal",
  agoraphobia = "lobelia",
  clumsiness = "kelp",
  darkshade = "ginseng",
  loneliness = "lobelia",
  vertigo = "lobelia",
  confusion = "ash",
  haemophilia = "ginseng",
  weakness = "kelp",
  shyness = "goldenseal",
  sensitivity = "kelp",
  stupidity = "goldenseal",
  dissonance = "goldenseal",
  hypochondria = "kelp",
  nausea = "ginseng",
  hallucinations = "ash",
  healthleech = "kelp",
  recklessness = "lobelia",
  impatience = "goldenseal",
  paralysis = "bloodroot",
  asthma = "kelp",
  dizziness = "goldenseal",
  slickness = "bloodroot",
  }


Now you can key into the table directly, rather than using a for loop.

eg.


print (cures.slickness)  --> bloodroot


One thing you could do is loop through all your afflictions, counting how many have the goldenseal cure.

eg.


local count = 0
for aff in pairs (afflictions) do
  if cures [aff] = "goldenseal" then
     count = count + 1
  end -- if
end -- for


Now you know if more than one has the goldenseal cure.

However I note that six afflictions require goldenseal, but you only mention five specials. Maybe this is a typo, maybe not.

Another approach again is to list the exceptions, like this:


exceptions = {
 epilepsy = true,
 stupidity = true, 
 dissonance = true,
 shyness = true,
 dizziness = true,
}


Now you simply say:


if exceptions [affliction] then   ...


With a single "if" you can test if the affliction needs special treatment.


- Nick Gammon

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

Posted by Curious2   (47 posts)  Bio
Date Reply #4 on Fri 06 Feb 2009 10:05 PM (UTC)
Message
Yeah only 5 because those are also in the focus affliction list. I posted the functions I use. The spacing is also screwed up from Notepad++. It looks right in the editor but on here it's like way off.
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #5 on Fri 06 Feb 2009 10:28 PM (UTC)
Message
Don't use tabs. I saw from your earlier posting that you mixed tabs and spaces. The web browser renders tabs in different places to what the editor does. Use the editor preferences to make "convert tabs to spaces" or whatever it is called.

- Nick Gammon

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

Posted by Curious2   (47 posts)  Bio
Date Reply #6 on Fri 06 Feb 2009 11:35 PM (UTC)
Message
Well I can't figure this out. If I use just the k=v table then it doesn't prioritize the curing. I guess I will stick with a ton of if/elseif checks.
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #7 on Sat 07 Feb 2009 01:17 AM (UTC)
Message
If you want help, you have to post your code.

- Nick Gammon

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

Posted by Curious2   (47 posts)  Bio
Date Reply #8 on Sat 07 Feb 2009 02:30 AM (UTC)

Amended on Sat 07 Feb 2009 03:32 AM (UTC) by Curious2

Message
I did :-)

Here is the other way. I'm using a combination of the counting method along with my old table and if/elseif now.


function cure.herbs()
  -- check for ability to eat herb
  if not auto.herbs or
    not cures.herbs.bal or
    cures.herbs.try or 
    afflicted.anorexia or 
    afflicted.aeon or
    afflicted.sleep or
    afflicted.stunned or
    afflicted.impaled or
    afflicted.transfixed or
    cures.general.paused then
    return
  end -- if can't do it yet
  -- declare eat function
  local function eat(herb)
    if outrifted[herb] then -- if herb outrifted then eat first
      SendImmediate("eat " .. herb)
      SendImmediate("outr " .. herb)
    else
      SendImmediate("outr " .. herb)
      SendImmediate("eat " .. herb)
      SendImmediate("outr " .. herb)
    end
    cures.herbs.eating = herb
    cures.herbs.try = true
    EnableTimer("herbTimer", true)
    ResetTimer ("herbTimer")
  end -- function eat
  -- checks for second afflictions on goldenseal
  local function unablerage()
    if not auto.rage or 
      mystats.mana < mystats.maxmana * 0.5 then
      return true
    else
      return false
    end
  end
  local function unablefocus()
    if not auto.focus or 
    mystats.mana < mystats.maxmana * 0.5 or
    not cures.focus.bal then
      return true
    else
      return false
    end
  end
  local gscount = 0
  for aff in pairs(afflicted) do
    for k, v in ipairs(cures.herbs.curelist) do
      if afflicted[aff] and 
        aff == v.name and
        v.cure == "goldenseal" then
        gscount = gscount + 1
      end -- if
    end
  end -- for
  -- do herb cures
  if afflicted.scytherus then eat("ginseng")
  elseif afflicted.hypochondria then eat("kelp")
  elseif afflicted.paralysis then eat("bloodroot")
  elseif afflicted.impatience then eat("goldenseal")
  elseif afflicted.asthma then eat("kelp")
  elseif afflicted.recklessness then eat("lobelia")
  elseif afflicted.masochism then eat("lobelia")
  elseif afflicted.darkshade then eat("ginseng")
  elseif afflicted.sensitivity then eat("kelp")
  elseif afflicted.haemophilia then eat("ginseng")
  elseif afflicted.slickness then eat("bloodroot")
  elseif afflicted.epilepsy and (gscount > 1 or  unablefocus()) then eat("goldenseal")
  elseif afflicted.clumsiness then eat("kelp")
  elseif afflicted.confusion then eat("ash")
  elseif afflicted.hallucinations then eat("ash")
  elseif afflicted.stupidity and (gscount > 1 or unablefocus() then eat("goldenseal")
  elseif afflicted.hypersomnia then eat("ash")
  elseif afflicted.healthleech then eat("kelp")
  elseif afflicted.weakness then eat("kelp")
  elseif afflicted.lethargy then eat("ginseng")
  elseif afflicted.nausea then eat("ginseng")
  elseif afflicted.dissonance then eat("goldenseal")
  elseif afflicted.shyness and (gscount > 1 or unablefocus() then eat("goldenseal")
  elseif afflicted.dizziness and (gscount > 1 or unablefocus()) then eat("goldenseal")
  elseif afflicted.loneliness then eat("lobelia")
  elseif afflicted.vertigo then eat("lobelia")
  elseif afflicted.agoraphobia then eat("lobelia")
  elseif afflicted.claustrophobia then eat("lobelia")
  elseif afflicted.addiction then eat("ginseng")
  elseif afflicted.dementia then eat("ash")
  elseif afflicted.paranoia then eat("ash")
  elseif afflicted.justice then eat("bellwort")
  elseif (afflicted.pacifism or afflicted.lovers or 
    afflicted.generosity) and unablerage() then eat("bellwort")
  elseif not defense.blindness then eat("bayberry")
  elseif not defense.deafness and not cures.herbs.hawate then
    eat("hawthorn")
    cures.herbs.hawate = true
  elseif not defense.kola then eat("kola")
  end
end -- function 


See the confusion of how to do that using a table? It's probably just me being confused I am sure. The goldenseal and bellwort cures have other abilities that can cure them, namely the focus and rage. Well I can cure all of them with the tree tattoo as well...sigh.
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.


22,896 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.