New to MUSHclient

Posted by Gid on Sat 12 Nov 2005 11:55 PM — 65 posts, 239,340 views.

#0
Okay, here I go.

I am very new to MUSHclient. I am learning like mad but I still need some help.

Here's the problem. I play the Iron Realms game "Achaea". The game is based ona balance system so that you cannot complete actions unless you have the specific "balance" that is related to the action. For instance, I eat an herb to cure a sickness. If I have another sickness, I have to wait a good 2 seconds be for I get my herb "balance" back so that I can eat another herb to cure the second sickness. I then receive the message "You may eat another herb". What I want to do is related to these sicknesses. When ever I get a sickness, it gives sends me the line "You are now sick with B" or "You are now sick with C" What I want to be able to do is to make it so that when I receive a messages saying that I am sick, I want it to remember that and be able to cure the sickness by eating the herb when I get my herb "balance" back.


More problems with this: There will be multiple sicknesses given to me while I don't have herb balance, so the system will have to be able to remember all of them and be able to eat a specific herb for each of them each time I receive herb balance back. Also, if I am able to, I want to be able to cure these sicknesses in a certain order, so when I get both the messages "You are now sick with B" and "You are now sick with C" while I don't have herb balance, I can eat the cure for C when I get herb balance back the first time, then eat the cure for B when I get my herb balance back the second time.


I know my question is complicated and I just hope you are able to figure out what I am trying to say.

Thanks
Australia Forum Administrator #1
Somehow I thought that question sounded familiar. :)

Try searching the forum, here is one post at least about their herbs:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=3302
#2
Thanks, that was helpful, just a few questions.

I don't understand what this is doing:

Sub herbhealing (a, b, c)
Dim value, spell, anorexia, scytherus
anorexia = world.getvariable ("affliction_anorexia")
scytherus = world.getvariable ("affliction_scytherus")

Also, is this actually part of the script? If so, what exactly is it doing?

For Each v In world.GetVariableList
value = world.GetVariable (v)
If Left (v, 11) = "affliction_" Then
spell = Mid (v, 12)
If value = "on" Then
Select Case spell
Case "stupidity" world.sendpush "eat goldenseal"
Case "slickness" world.sendpush "eat bloodroot"
Case "paralysis" world.sendpush "eat bloodroot
etc.



Also: It seems as if every time I get herb balance back I acutally eat the herbs for all of the afflictions I have. Is there any way I can make it so I will only eat 1 herb (I want to be able to specify which afffliction to heal in an order that I somehow put into the script.)

Amended on Sun 13 Nov 2005 02:11 AM by Gid
Australia Forum Administrator #3
You would put the script into your script file. The word "herbhealing" is the name of the script function in this case and would go into the "script" part of the trigger.

See:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=6030

That discusses how you interface scripts with triggers and suchlike.

For your 2nd question, this part of the script is important:


Select Case spell 
  Case "stupidity" world.sendpush "eat goldenseal"
  Case "slickness" world.sendpush "eat bloodroot"
  Case "paralysis" world.sendpush "eat bloodroot

etc.


The "select case" statement selects one from the list, depending on what the spell is. So, if the spell was "stupidity" it would send "eat goldenseal" (and nothing else).




#4
Okay, so I understand how to put all the different afflictions in variables and how to trigger them when I regain herb balance. That still leaves my question on how I can make it so that when I regain herb balance and two afflicts are set on the "on" position, I only eat the herb to cure one of them, and I wait till the next time I get herb balance back to eat the next one.
USA #5
Hmm I think the best way for this to work would be
something like the following, I dont really know the syntax in lua, but you should get the idea.

if anor == "off":
 if asleep == "off":
  if plantbal == "yes":
   if *AFFLICTION HERE* == "on":
    world.Send("outr this")
    world.Send("eat plant")
elif *AFFLICTION* == "on":
    world.Send("outr this")
    world.Send("eat plant")
   elif *AFFLICTION* == "on":
     

And so on adding afflictions with the most priority at the top. IE Aeon, stupidity etc.

**EDIT:Thought I was writing html with the code tags :P --Rakon**
Amended on Sun 13 Nov 2005 06:05 PM by Rakon
Australia Forum Administrator #6
OK, let's take a look at doing this in Lua, whose table handling makes keeping track of this sort of stuff quite easy.

I haven't played Achaea for a while, and am not familiar with their affliction system, but I gather from the other posts about this that it goes along these lines:

  • You can become afflicted by lots of things, where an affliction is indicated by one or more messages, like:


    An odd sensation descends upon you.
    You feel the urge to slash, cut, and bruise yourself.
    With the heel of your palm, you smack *
    You drive a clenched fist into your gut.
    You use your * foot to stomp on your * as hard as possible.

  • When you are cured of that affliction, either by time or the cure, you get another message, like:


    You no longer enjoy pain.

  • You can eat something to cure the affliction, eg.


    eat lobelia

  • Once eaten something you can't eat again until you see a message, like:


    You may eat another plant.

  • You can't eat while afflicted by the "food" affliction, or "anorexia", and other things.





The first thing we need is a table of what we are currently afflicted by, and a flag to show if we are currently eating a cure. I presume when you start a new game the afflictions are cleared, so the table can be a straight Lua table. If not, you could serialize the table into a variable on world disconnect, as described in other posts, and re-import it when you reconnect.


afflicted_by = {}  -- table of current afflictions
eating = false  -- are we currently eating a cure?


Next, we want a table of the various afflictions and their cures. I would rather have a table keyed by affliction name, but I gather that you would prefer to cure afflictions in a certain order (most urgent to least urgent) so we'll just have a table keyed in numeric order:


cures = {
    { name =  "stupidity"       , cure =  "goldenseal" },
    { name =  "slickness"       , cure =  "bloodroot" },
    { name =  "paralysis"       , cure =  "bloodroot" },
    { name =  "confusion"       , cure =  "ash" },
    { name =  "scytherus"       , cure =  "ginseng" },
    { name =  "epilepsy"        , cure =  "goldenseal" },
    { name =  "masochism"       , cure =  "lobelia" },
    { name =  "dizziness"       , cure =  "goldenseal" },
    { name =  "recklessness"    , cure =  "lobelia" },
    { name =  "heroism"         , cure =  "lobelia" },
    { name =  "justice"         , cure =  "bellwort" },
    { name =  "paranoia"        , cure =  "ash" },
    { name =  "shyness"         , cure =  "lobelia" },
    { name =  "hallucinations"  , cure =  "ash" },
    { name =  "generosity"      , cure =  "bellwort" },
    { name =  "loneliness"      , cure =  "lobelia" },
    { name =  "impatience"      , cure =  "goldenseal" },

-- and so on --

  } -- end of cures




Now we want a "cure me" routine, that can be called as soon as we become afflicted, and also when an affliction wears off, and we can eat another herb. For example, if the "food" affliction wears off, we can start curing other things.


-- find an affliction we have, and try to cure it
function do_cure ()

  -- can't eat more if just ate, or can't eat food

  if eating or 
    afflicted_by.food or 
    afflicted_by.anorexia then
    return
  end -- if can't do it yet

  -- find most urgent one to cure  

  for _, v in ipairs (cures) do
    if afflicted_by [v.name] then
      if v.cure ~= "" then  -- some afflictions might not have cures
        Send ("outb ", v.cure)  -- get out of bag
        Send ("eat ", v.cure)   -- eat it
        ColourNote ("black", "yellow", "Curing " .. v.name .. 
                    " with " .. v.cure)
        eating = true
        return  -- done 
      end -- of having a cure for it
    end -- found one
  end -- for

end -- function do_cure


What this does is first test for whether we can cure anything right now (eg. if we have just eaten we can't).

Then it goes through the cures table in sequence, and for each one, checks to see if we are afflicted by that thing. That way the most important things get cured first.

When it finds one, it pulls the herb out of the bag and eats it, and notes we are currently eating.




Next we need a series of triggers to indicate we have an affliction. Since multiple things may indicate the same affliction we call a function with "send to script" to indicate which affliction we now have:



<triggers>
  <trigger
   enabled="y"
   match="You drive a clenched fist into your gut."
   send_to="12"
   sequence="100"
  >
  <send>afflicted "masochism"</send>
  </trigger>
</triggers>


You would make a similar one for each affliction, where the "match" is what you see (it could be a regular expression), and the "send" text calls the "afflicted" function with the name of the affliction.


-- call this from a trigger to show we are afflicted by something

function afflicted (what)
  if afflicted_by [what] then
    ColourNote ("white", "red", "Already afflicted by " .. what)
  else
    afflicted_by [what] = true  -- note the affliction
    ColourNote ("white", "red", "Now afflicted by " .. what)
  end -- if
  do_cure ()  -- try a cure
end -- function afflicted 


This function calls "do_cure" to try to cure something straight away, which may be this affliction, or it may not if we are currently eating a herb.




Next we need to know when the affliction is cured.


<triggers>
  <trigger
   enabled="y"
   match="You no longer enjoy pain."
   send_to="12"
   sequence="100"
  >
  <send>cured "masochism"</send>
  </trigger>
</triggers>


This is similar to the above trigger, except it calls the "cured" function instead.


-- call this from a trigger to show we are cured

function cured (what)
  afflicted_by [what] = nil  -- note not afflicted
  ColourNote ("white", "green", "Now cured of " .. what)
  do_cure ()  -- try a cure for the next affliction if any
end -- function cured 


This also calls do_cure to try to cure something else. For example, if we are no longer afflicted by "food" we can start curing other things.




Next we need to know if we can eat another herb:


<triggers>
  <trigger
   enabled="y"
   match="You may eat another plant."
   script="can_eat"
   sequence="100"
  >
  </trigger>
</triggers>


This calls the can_eat function:


-- call this from a trigger when we have finished eating

function can_eat ()
  eating = false
  do_cure () -- now we can cure something else
end -- function can_eat



This also calls do_cure to try to cure something else if necessary.




The above techniques won't be perfect, for one thing it doesn't check if you actually have the herb in your inventory. You might maintain another table of the herbs you are carrying, which could be updated when you buy them, and when you use them. However it should be enough to give you some ideas.
Amended on Sun 13 Nov 2005 09:27 PM by Nick Gammon
#7
That is all great! It might take me a while to go through it all and try to make it work for me but this is good till then.

What I don't understand right now is where I set up the table and what exactly the the table's function is.


Thanks for all your help on this.
Australia Forum Administrator #8
All this stuff goes into your script file:



afflicted_by = {}  -- table of current afflictions
eating = false  -- are we currently eating a cure?

-- cures for afflictions, put in order you want them cured

cures = {
    { name =  "stupidity"       , cure =  "goldenseal" },
    { name =  "slickness"       , cure =  "bloodroot" },
    { name =  "paralysis"       , cure =  "bloodroot" },
    { name =  "confusion"       , cure =  "ash" },
    { name =  "scytherus"       , cure =  "ginseng" },
    { name =  "epilepsy"        , cure =  "goldenseal" },
    { name =  "masochism"       , cure =  "lobelia" },
    { name =  "dizziness"       , cure =  "goldenseal" },
    { name =  "recklessness"    , cure =  "lobelia" },
    { name =  "heroism"         , cure =  "lobelia" },
    { name =  "justice"         , cure =  "bellwort" },
    { name =  "paranoia"        , cure =  "ash" },
    { name =  "shyness"         , cure =  "lobelia" },
    { name =  "hallucinations"  , cure =  "ash" },
    { name =  "generosity"      , cure =  "bellwort" },
    { name =  "loneliness"      , cure =  "lobelia" },
    { name =  "impatience"      , cure =  "goldenseal" },

-- and so on --

  } -- end of cures

-- find an affliction we have, and try to cure it
function do_cure ()

  -- can't eat more if just ate, or can't eat food

  if eating or 
    afflicted_by.food or 
    afflicted_by.anorexia then
    return
  end -- if can't do it yet

  -- find most urgent one to cure  

  for _, v in ipairs (cures) do
    if afflicted_by [v.name] then
      if v.cure ~= "" then  -- some afflictions might not have cures
        Send ("outb ", v.cure)  -- get out of bag
        Send ("eat ", v.cure)   -- eat it
        ColourNote ("black", "yellow", "Curing " .. v.name .. 
                    " with " .. v.cure)
        eating = true
        return  -- done 
      end -- of having a cure for it
    end -- found one
  end -- for

end -- function do_cure

-- call this from a trigger to show we are afflicted by something

function afflicted (what)
  if afflicted_by [what] then
    ColourNote ("white", "red", "Already afflicted by " .. what)
  else
    afflicted_by [what] = true  -- note the affliction
    ColourNote ("white", "red", "Now afflicted by " .. what)
  end -- if
  do_cure ()  -- try a cure
end -- function afflicted 

-- call this from a trigger to show we are cured

function cured (what)
  afflicted_by [what] = nil  -- note not afflicted
  ColourNote ("white", "green", "Now cured of " .. what)
  do_cure ()  -- try a cure for the next affliction if any
end -- function cured 

-- call this from a trigger when we have finished eating

function can_eat ()
  eating = false
  do_cure () -- now we can cure something else
end -- function can_eat




The rest is a few triggers, which you can copy and paste (or write your own based on them).

The purpose of the big table above is to relate afflictions to cures. The purpose of the afflicted_by table is to keep track of each affliction. Each affliction you have will make a single entry in the table. eg.


afflicted_by.food = true
Amended on Mon 14 Nov 2005 03:09 AM by Nick Gammon
#9
Wonderful.....Now I don't understand this part.

for _, v in ipairs (cures) do
if afflicted_by [v.name] then
if v.cure ~= "" then -- some afflictions might not have cures

Do I actually write "for _, v in ipairs (cures)????
and will [v.name] acutually put in the name of the affiction that I get? Or do I need to type something in there?





do_cure () -- try a cure

Do I leave the space inside of the parantheses blank?
Amended on Mon 21 Nov 2005 04:07 AM by Gid
Australia Forum Administrator #10
Read this post, it talks about tables:


http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=6036


Quote:

Do I actually write "for _, v in ipairs (cures)????


Well, I would copy and paste it, but yes, that works as written.

"cures" is a table of affliction/cure pairs (actually a table of tables).

We are doing a linear scan of the table (which is why you put the most urgent one at the start).

The for loop extracts key/value pairs. The key is assigned to variable "_" which is usually used in Lua to indicate a temporary variable. The value is put into v.

In this case the value "v" is the inner table. The inner table has two entries for each one, "name" and "cure" (see the table definition).


So, this line:


if afflicted_by [v.name] then


... checks if we are afflicted by this particular affliction (v.name) and if so, we do the cure (v.cure).

Australia Forum Administrator #11
Quote:

Do I leave the space inside of the parantheses blank?


Yes. do_cure is a function, and to call it you must use parentheses. However as there are no arguments, the contents of the parentheses are empty.
#12
Another Question.

Is there anyway I can stop the script from working for a line or two? Heres what I would see:


John casts an illusion at you.
An odd sensation descends upon you.
You begin to puke.

I want to be able to ignore the two lines after "John casts an illusion at you."


Your help is greatly appreciated.
USA #13
couldn't you have john casts illusion on you trigger it to omit from output new lines till the prompt is reached and disable it?
USA #14
And I would like to use this for another of the Iron Realm games Lusternia. However they have a very weird... healing system. they have some herbs you eat, some your apply (one) and three you smoke. then they have Purgatives and Potions/Salves to cure the aliments, now I would like to use this system to do all of them, but I dont understand it enough to even start, so might you be willing to show me a little?
Australia Forum Administrator #15
I don't play Lusternia and it goes beyond the scope of what I can offer here to sit down and write a healing system from scratch for every user of MUSHclient.

I can show you the general idea, as I have done here, and if you have a specific query about why something isn't working you are welcome to post it, and I am sure someone will try to help.
#16
Correct me if I'm wrong, but just omitting it from the output would not keep it from setting off the trigger.

Just FYI, the Achaea healing system is almost exactly the same as the Lusternia one. The way I'm doing it is that I followed Nick's instructions exactly except that instead of setting up just one table and cure alias, I set up 4: One for eating, applying, smoking, and drinking. I'm pretty sure it will work, but I havn't actually put anything to use yet, as I am really busy from other stuff right now.
USA #17
I wasn't asking for you to do it, i meant because there are more then one way to heal an affliction drinking eatting applying and smoking, each having its own blance, how might I set that up using the tables and such?
USA #18
ok well I want to take what we've learned from this and use it to make a script to automaticly bind spirits. some of the spirits are like snake horse and monkey. once you bind you have to wait for blance to bind again... but I cant seem to figure it out...
#19
>>ok well I want to take what we've learned from this and use it to make a script to automaticly bind spirits. some of the spirits are like snake horse and monkey. once you bind you have to wait for blance to bind again... but I cant seem to figure it out...

For this you just need to create a trigger that responds to the balance regain and fire off then turns itself off. That's what I did for something similar. I have it turn itself off so it doesn't keep firing.
USA #20
in total i want to make an alias Def start a chain of defensing using the table i thought it would be the easiest way, since it uses two different blances and several different things like spiritbonding... gripping and breathing deep and stuff like that... so what I want is an alias to trigger a chain matching on when i have the blance to do another def, then have another alias tell me all defenses I have up (the game has one but it takes balance to check it... this way I can save me some time and balance...) and then be able to add more defenses if I need them...
USA #21
I thought I would need to use two tables... one of all the defense and one with none of them in it, and then find a way to compare the two tables and move the next one(do the command for the def) so it will be in the second table.
USA #22
Is it me... or does no one even read this thread anymore...
Australia Forum Administrator #23
Quote:

I thought I would need to use two tables...


This isn't really a question so it is hard to respond.

What you have said is all pretty general. If you posted some sample output from the MUD, and your aliases/triggers and associated scripts, and said what was happening, and what you expected to happen, that might be a question someone could answer.

Quote:

... find a way to compare the two tables ...


Give us a concrete example, to demonstrate you have tried to solve the problem, what you have tried, and in what way it doesn't work.

When you say "compare the two tables" do you mean:

  • What is in one table but not the other?
  • What is in both tables?
  • Are they the same?
  • Are we comparing keys or values?


USA #24
Well I've been thinking about it... and it would seem I'd need to use several different tables with each different thing so to say. I've got spiritbonding I want to put into a table

spiritbond sun - this beging the command

You call upon the spirit of sun and a warm ray of sunlight infuses you with confidence. - this being the output using the command gives

You have recovered equilibrium. - this would be the balance message.

Then I have things like this:

spiritbond night- command once more

It must be night to bond with mother night. - output

Meaning the defense isn't used then. And what I want to do is set up a table of defenses and compare it to another to check to see if I have the defense up or not, and if not to do it. But however then i'd need a herb table potion table, and a few more for the other different types of defenses I could use. And for those... they may not even use the same balance... Then I was thinking and though of coming up with an alias for different deffing up types, like default, arena, war, spirit, herb, salve, and such... Ya its alot to do... specially since I've not learned much about Lua... I haven't tried any scripts or aliases yet... expect the first one you gave to get it more to lusternia curing which I think I can do for the most part... but the rest of my ideas are a little out there... and was wondering if some of it was even possible?
Australia Forum Administrator #25
Quote:

I haven't tried any scripts or aliases yet ...


What? At all? Or to solve this problem?

Before you try something complex like a healing system you want to get the general hang of scripting. Start with something simpler, like counting how many times you see a particular mob, or make a table of the different things you fight. Although you may not particularly need such a thing, the practice you get in writing it will show you the general techniques for tackling something harder.
USA #26
well since the time of your post, I was trying to use the script you gave and play around with it.. but cause I dont know if what I want is even possible I dont know If i could know where to look at..
Australia Forum Administrator #27
Quote:

... and was wondering if some of it was even possible


Basically anything is possible in a script, some things are more work than others, that is all.

Again I suggest to start with a simple script, and work up from that. If you haven't done much scripting, a complex healing/balance script will seem hard, until you learn the basics.
Amended on Tue 06 Dec 2005 02:50 AM by Nick Gammon
USA #28
I have a quick question then, what is this doing

for _, v in ipairs (cures) do
if afflicted_by [v.name] then
if v.cure ~= "" then -- some afflictions might not have cures
Send ("outb ", v.cure) -- get out of bag
Send ("eat ", v.cure) -- eat it
ColourNote ("black", "yellow", "Curing " .. v.name ..
" with " .. v.cure)
eating = true
return -- done
end -- of having a cure for it
end -- found one
end -- for

I understand what its doing from the sends and down but the if checks and the for I dont
USA #29
I meant more along the lines of what is the in _, doing? and what is it?
Australia Forum Administrator #30
Lua tends to use the variable named _ as a temporary variable. Since variables can start with an underscore, a variable name of only an underscore is used to show an unimportant variable.

You could rewrite it as:


 for key, value in ipairs (cures) do

 -- blah blah

 end -- for loop


Both the "pairs" and "ipairs" functions iterate over a table, returning for each iteration the key and value from that entry.

In the case of a numeric table, the key will simply be the numbers 1, 2, 3 etc. so that was why I put it into the "_" variable.


Read my writeup on Lua tables here:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=6036
#31
I've just been able to start working on this script after a long time that I wasn't able to and I am having a problem. Whenever I try to send something to the script it always says "Send-to-script cannot execute because scripting is not enabled." even though the enable script button on config scripts is always checked. Any idea what my problem is?
Australia Forum Administrator #32
If there is an error in your script it is disabled (as it couldn't be processed) until you fix it and "reload script file".
#33
Here's what I have in my script file.

afflicted_by = {} -- table of current afflictions
applying = false -- are we currently applying a salve?

-- cures for afflictions, put in order you want them cured

salvecures: = {
{ name = "anorexia" , cure = "epidermal" },
{ name = "silerisdef" , cure = "sileris" },
{ name = "legrest1" , cure = "restoration" },
{ name = "legrest2" , cure = "restoration" },
{ name = "legmend2" , cure = "mending" },
{ name = "legmend2" , cure = "mending" },
{ name = "headrest" , cure = "restoration" },
{ name = "armrest1" , cure = "restoration" },
{ name = "armrest2" , cure = "restoration" },
{ name = "armmend1" , cure = "mending" },
{ name = "armmend2" , cure = "mending" },
{ name = "torsorest" , cure = "restoration" },
{ name = "burning" , cure = "mending" },
{ name = "shivering" , cure = "caloric" },
{ name = "caloricdef" , cure = "caloric" },
{ name = "massdef" , cure = "mass" },
} - end of salvecures

function do_cure ()

if applying or
afflicted_by.food or
afflicted_by.anorexia then
return
end -- if can't do it yet

-- find most urgent one to cure

for _, v in ipairs (salvecures) do
if afflicted_by [v.name] then
if v.cure ~= "" then -- some afflictions might not have cures
Send ("apply ", v.cure) -- apply it
applying = true
return -- done
end -- of having a cure for it
end -- found one
end -- for

end -- function do_cure


Note: When I copied it from my script file, the spacing messed up so it's all left alligned now.

Here's the error.


[string "Script file"]:6: <name> expected near `='


To the best of my knowledge (which I know in this subject is not very extensive), my script is pretty much exactly how you had it earlier, except with the changes specific to my file. Can you show me what I've done wrong?

Amended on Sun 08 Jan 2006 03:56 AM by Gid
Australia Forum Administrator #34
Well, line 6 (mentioned in the error message) is this, right?

Quote:

salvecures: = {


There is no colon. It should be:


salvecures = {


You can't just ignore errors and hope the script will work.
#35
I'm having trouble with the whole trigger sending afflicted thing so I tried something else.

Trigger goes of and makes masochism = true


for _, v in ipairs (cures) do
if [v.name] = true then
if v.cure ~= "" then -- some afflictions might not have cures
Send ("outb ", v.cure) -- get out of bag
Send ("eat ", v.cure) -- eat it
ColourNote ("black", "yellow", "Curing " .. v.name ..
" with " .. v.cure)
eating = true
return -- done
end -- of having a cure for it
end -- found one
end -- for

end -- function do_cure


The only problem is that "if [v.name] = true then" gives me an error that says unexpected symbol near ]. Is there a help file on If statements so that I can see what I've done wrong?
Australia Forum Administrator #36
The original line (which you had further up) was:


if afflicted_by [v.name] then


You have changed it to:


if [v.name] = true then


You have left out "afflicted_by", and also in an "if" test you should use "==" rather than "=".

The Lua manual, which is referenced in various places, describes the Lua syntax.
#37
With the triggers that I have, it doesn't quite work.

[string "Trigger: "]:1: attempt to call global `afflicted' (a nil value)
stack traceback:
[string "Trigger: "]:1: in main chunk

Australia Forum Administrator #38
What is "afflicted"? The variable I had was "afflicted_by".

Note the different spelling and the underscore.
#39
This is what you wrote on page 1.

<triggers>
<trigger
enabled="y"
match="You drive a clenched fist into your gut."
send_to="12"
sequence="100"
>
<send>afflicted "masochism"</send>
</trigger>
</triggers>


And I had wondered before if that was the problem so I changed it to what you afflicted_by just like you just said but it still gave me an error.

[string "Trigger: "]:1: attempt to call global `afflicted_by' (a table value)
stack traceback:
[string "Trigger: "]:1: in main chunk
Australia Forum Administrator #40
I am confused now as to what you have done to my original. In that I had this function:


-- call this from a trigger to show we are afflicted by something

function afflicted (what)
  if afflicted_by [what] then
    ColourNote ("white", "red", "Already afflicted by " .. what)
  else
    afflicted_by [what] = true  -- note the affliction
    ColourNote ("white", "red", "Now afflicted by " .. what)
  end -- if
  do_cure ()  -- try a cure
end -- function afflicted 


That is what the trigger is calling, the function "afflicted". In the syntax error you had you needed to use:


if afflicted_by [v.name] then


in your relevant piece of script.
#41
Thanks! I pretty much have it all working except for one problem now. Part of my script has Send ("apply ", v.cure)
in it. That is fine, except that for 2 of my cures I have to "apply mending to legs" or "apply restoration to head". Do you have any idea how I could do that?
Australia Forum Administrator #42
Can't you just make the cure "mending to legs"?
#43
Okay, so that works just fine now.

Just as a question beforehand, is there anyway I can have whatever my Send command sends to the world show in the output? I wanted to know this because now my triggers work, it gives me the messages that I am afflicted, that I am curing, but I don't think it send the right thing to to world because the world sends back the same messages as if I had just typed in "flkasdfgh" (meaning whatever my script is telling the world to do is just jibberish.
Send ("apply", v.cure) <-- this is from my script so I know that just just fine.


Another problem: People in the game can cast illusions to make me believe that my leg is broken, when it really is not. Also, one importan thing is that there are two different ways your arms can break, each requiring a different cure.

Here's what I would see:

Your arm breaks.
apply mending to arms <-- Called by the script, triggers won't respond to it I understand.
You take out some salve and quickly rub it on your arms.
You messily spread the salve over your body, to no effect.

Your arm breaks badly.
apply restoration to arms <--same as above
You take out some salve and quickly rub it on your arms.
You messily spread the salve over your body, to no effect.
Australia Forum Administrator #44
Quote:

... is there anyway I can have whatever my Send command sends to the world show in the output?


It does. If you do: Send ("hello") it is echoed in the output window.

Quote:

... but I don't think it send the right thing to to world ...

Send ("apply", v.cure)


Assuming v.cure contains a word like "salve" it will send:


applysalve


You need a space after "apply", it won't put one in for you.

Quote:

Your arm breaks.

...

Your arm breaks badly.


What's the problem here? You make 2 triggers that match the different ways your arm can break.
#45
The problem is that when I see this, my arms aren't really breaking, it is just an illusion. When I apply a salve and I don't have the affliction that I applied the salve for it gives me this message:

You messily spread the salve over your body, to no effect.

But I can't tell which salve I put on my body from that line. I want to be able to have the script recognize that this affliction is cured, but that line doesn't show me which salve I used so I can't tell it which affliction to say is cured.

I hope that made sense....
Australia Forum Administrator #46
You would have to save that, when you apply a salve, in a variable as something like last_salve_applied.
#47
I got it to log as a variable but I was wondering if this would work, and what the right syntax would be if it did.

function wasted_salve ()
if last_salve_applied = v.cure then
salvecured v.name
end -- function wasted_salve
Australia Forum Administrator #48
Quote:


if last_salve_applied = v.cure then
salvecured v.name



That's 3 problems in 2 lines:

You really need to look closely at the syntax.

  • To compare you use == not =
  • To assign you use =
  • You need "end" to end the if statement


So it should read:


if last_salve_applied == v.cure then
  salvecured = v.name
end -- if


That's assuming I read your intentions correctly. :)
#49
Having some trouble....


<triggers>
<trigger
enabled="y"
group="Multi Line"
lines_to_match="2"
keep_evaluating="y"
match="You take out some salve and quickly rub it on your arms\.\nYou messily spread the salve over your body\, to no effect\.\Z"
multi_line="y"
regexp="y"
send_to="12"
sequence="100"
>
<send>wasted_salve</send>
</trigger>
</triggers>


function wasted_salve ()
if last_salve_applied == v.cure then
salvecured = v.name
end -- if
end -- function wasted_salve


[string "Trigger: "]:1: `=' expected near `<eof>'
Amended on Tue 17 Jan 2006 01:22 AM by Gid
Australia Forum Administrator #50
Read this page:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=6030

You are combining two methods here. Either put wasted_salve into the "script" box of the trigger, and put your function into your script file, or have the command in the "send to script" without the function around it.
#51
function wasted_salve ()
Note ("working")
if last_salve_applied == "v.cure" then
salveafflicted_by [what] = nil -- note not afflicted
ColourNote ("white", "green", "Now cured of " .. what)
do_salvecure () -- try a cure for the next affliction if any
end -- if
end -- function wasted_salve


function wasted_salve ()
Note ("working")
if last_salve_applied == "v.cure" then
salvecured "mending"
end -- if
end -- function wasted_salve

I've tried both of these. Neither bring back errors now but neither seem to work. When the trigger calls the function, the Note shows on the output but the If thing doesn't work. Just fyi the ColourNote also doesn't work on the first function. Do you see something that I don't?
Australia Forum Administrator #52
Quote:

if last_salve_applied == "v.cure" then


You really need to think carefully about the difference between variables and literals.

Here you are saying "if the last salve was called 'v.cure' then do something".

I presume no salve is called 'v.cure'.

You want something like this:


if last_salve_applied == v.cure then

Canada #53
Greets all,

This is a bit of a thread resurrection, sorry about that.

I'm trying to teach myself lua scripting (I'm a sociology grad student by trade, so this isn't my area of expertise). As I was trying implement the bit of scripting Nick provided into my system for the IRE game I play, I ran into a little tidbit that I just couldn't wrap my mind around.

-- find an affliction we have, and try to cure it
function do_cure ()

  -- can't eat more if just ate, or can't eat food

  if eating or 
    afflicted_by.food or 
    afflicted_by.anorexia then
    return
  end -- if can't do it yet

  -- find most urgent one to cure  

  etc. etc.

end -- function do_cure


The part in bold is throwing me off a bit. As I understand it, the "or" operator returns the first argument if it is not false and the second argument if the first is false. This is all fine and all, but I don't understand how it's behaving with the "if . . . then" control.

As I understand it, if . . . then statements operate off of a logical condition. If the condition is met, then the "then" action is carried out. If it is not met, then the "then" part won't be carried out. When I look at that bolded chunk, it seems to me that something is missing, shouldn't we be giving it some sort of logical condition like:

if eating = true then X
elseif afflicted_by.food then X
etc. (I come from a vbscript backgroud)

Why does simply returning the value of one of those three arguments (eating, afflicted_by.food, afflicted_by.anorexia) lead to the proper conditions for the "then" statement to be carried out.

(Looking back, that was a very verbose post, let me know if anything is unclear.)
Australia Forum Administrator #54
"Or" is a boolean operator, which returns true if either of its arguments are true. In Lua, true is really any value other than nil or false.

Thus you could write:


if a or b or c or d or e then
  -- do something
end


This would do the something inside the if statement, if any of those was true. Also in Lua (like other languages) the "or" is a short-circuit evaluation, thus it doesn't even bother to evaluate b (or c, d, or e) if a is true.

What it is really doing is evaluating "a or b" and then applying the result of that to c, and the result of that to d, ie. ((a or b) or c) or d.

The converse operation is "and" where you might write:


if a and b and c and d and e then
  -- do something
end


Now the condition is only true if all of them are true.
Vanuatu #55
Thread Necro is Good for the soul. That said, I had a question (rather than making a new thread, I'll be using examples from the first portion of this thread so I figured this is the place.)

This is to check for illusions since I haven't really found anything decent on "illusion" stuff about Achaea (some wait / pause things but not what I was looking for). In Achaea, the skill 'lifevision' can be used to detect illusions and gives a "** Illusion **" type msg if it detects one. As I am sure you know, this can come over the "illusion" or under it. What I wanted as a check to afflictions was this....:

I want to make the afflictions received enter a temporary table (basically a queue). Once I hit the new prompt, evaluate, see if it has tripped lifevision, if not, add it to the "afflicted_by" table as used in the beginning of this thread. If it has tripped lifevision, just wipe it out.

I was wondering if this idea pans out.

1. Make a "temp_afflicted" function similar to your "afflicted" function but assigns afflictions to the temp_table obviously.

2. Have another function to run on the prompt and see if lifevision was tripped or not and take the appropriate action (ie wiping temp_afflictions or adding it to "Afflicted_by" depending on the lifevision variable)

3. Once it adds it, it would have to reset the lifevision variable and the tem_afflicted table.

Would a function like this work for what I am trying to do?


lifevision = GetVariable("lifevision")
function temp_toreal ()

  -- see if it picked up lifevision
  
   if lifevision == 1 then
    temp_afflicted [k] = nil
   end -- if lifevision picked up

  -- if lifevision didn't pick it up

    for k in pairs (temp_afflicted) do
     afflicted "[v.name]"
    end -- for
end -- function


Just curious as this is my very first experience with MUSH, Lua, actual non-Zmud code, etc...So far I love it, but I am still unfamiliar with tables and what not thus far. Any help is appreciated and.. thanks ahead of time.
Australia Forum Administrator #56
You need to be cautious with variable types here. The GetVariable function always returns a string (or nil if that variable doesn't exist).

Thus, comparing to 1 will always fail. For example:


a = "1"

print (a == 1)  --> false


Assuming you are using "1" in lifevision to indicate "true", then you need this test:


if lifevision == "1" then  ... blah blah


Also, I am a bit worried about this:


if lifevision == 1 then
    temp_afflicted [k] = nil
   end -- if lifevision picked up

  -- if lifevision didn't pick it up


You are falling through here, is that intended? Perhaps you mean:



if lifevision == "1" then
    temp_afflicted [k] = nil
    return   -- exit if found
   end -- if lifevision picked up

  -- if lifevision didn't pick it up


Although even then, I am unsure about your intentions. You are using "k" here, but "k" isn't defined yet.
Vanuatu #57

 if lifevision == "1" then
    temp_aff[k] = nil
    return   -- exit if found

    for k in pairs (temp_aff) do
     afflicted "[v.name]"
    end -- for
 end -- if


I have a table "temp_aff" to store what I MIGHT be afflicted with.

I have a table "afflicted_by" to store what I DO HAVE.

I want it so that if I see **Illusion** (@illusion) it just gets rid of the values in the temp_aff table until the next hit of afflictions.

If it doesn't say ** Illusion **, I want it to add whatever is currently in the 'temp_aff' table over to the 'afflicted_by' table.

From my limited understanding of tables, the first IF up there would say 'if it is in fact an illusion, and not really afflicting you, delete it from the temp_aff table'.

The second one, (again, to my understanding) says 'if it isn't an illusion, take all the keys stored in temp_aff (just names of afflictions so.... 'slickness', 'asthma', etc) and using the previous "afflicted" function, add that key to the actual "afflicted_by" table.

I am sure I am doing it wrong but, I am still new and a bit slow on the uptake. I hope I gave you enough info that time. I appreciate your help greatly, since I really like your product.
USA #58
Since I don't think Nick has much personal experience with Achaea, I believe I know what you're trying to do. Fixing your code, it would look something like:

Quote:

function temp_toreal ()
lifevision = GetVariable("lifevision")
-- see if it picked up lifevision

if (lifevision == '1') then
temp_afflicted = nil
return
end -- if lifevision picked up

-- if lifevision didn't pick it up

for k in pairs (temp_afflicted) do
afflicted(k)
end -- for
end -- function


this assumes that afflictions are stored in the index of temp_afflicted (temp_afflicted['asthma'] = true) not the value, and that there exists some function called afflicted, which takes as an argument a string of the affliction.
Australia Forum Administrator #59
Quote:

for k in pairs (temp_afflicted) do


If you set temp_afflicted to nil, then the next time you call this function the "pairs" will fail because it is being passed a nil argument.
USA #60
The assumption is that temp_afflicted is created somewhere else in the script, and that this is appropriately checked. You could equally set it equal to {} instead of nil.
Vanuatu #61
So would this work since it depends on the IF?

function temp_toreal ()
lifevision = GetVariable("lifevision")
-- see if it picked up lifevision

 if (lifevision == true) then
  temp_aff = {}
  return
 end -- if

 elseif (lifevision == false)
  for k in pairs (temp_aff) do
   afflicted(k)
  end -- for
 end -- if
end -- function


temp_aff is the table. temp_afflicted would be a function similar to the previous 'afflicted' one to assign the afflictions to the temp_aff table. If lifevision is true, I want all afflictions (would be 2 or 3 tops) cleared out of the temp_aff table.
USA #62
The idea is right, but there are a couple syntax problems.


if (lifevision == true) then
  temp_aff = {}
  return
 end


the 'end' right there closes the if statement. This means that you can't continue it with the elseif. Because of the return statement, you can eliminate the elseif altogether. If the script execution gets to that point, it is guarenteed lifevision is false; if not, it would have returned from the function.
Australia Forum Administrator #63
Quote:

lifevision = GetVariable("lifevision")
-- see if it picked up lifevision

if (lifevision == true) then


You haven't addressed here my concerns expressed earlier about variable types. You are using "true" here which is a boolean type, but GetVariable returns a string type. These are two different data types, and thus the expression " (lifevision == true)" will always be false. That is, it will never execute the code inside that 'if".

I suggest you play around with Lua a bit to get a feel for the syntax, perhaps a simple program in the Immediate window to print a list of numbers and multiply them by 2, something like that. Then you will feel more comfortable tackling more complex problems.

Quote:

The assumption is that temp_afflicted is created somewhere else in the script, and that this is appropriately checked.


It is my experience that it is usually assumptions that bring programs undone.

The code below should be syntactically correct, whether it works or not depends on what the variables are used for elsewhere:



function temp_toreal ()

-- see if it picked up lifevision

 if GetVariable ("lifevision") == "1" then
  temp_aff = {}
  return
 end -- if

  for k in pairs (temp_aff) do
   afflicted (k)
  end -- for

end -- function
Vanuatu #64
I got it to work. Thanks for the help.

I use tempafflicted to work the same as your 'afflicted' table function from before... then the other function is like this...


function tempafflicted (what)
  temp_aff 
Template:what
Please help us by showing:
  • A copy of the trigger, alias or timer you were using (see Copying XML)
  • The error message, if any, that you got
= true -- note the affliction end -- function afflicted function temp_toreal () -- see if it picked up lifevision if GetVariable ("lifevision") == "1" then temp_aff = {} return end -- if for k in pairs (temp_aff) do afflicted (k) end -- for temp_aff = {} SetVariable ("lifevision", 0) end -- function


Anytime it picks up '** Illusion **' it just clears any afflictions so the '** Illusion **' could have come before or after the msgs (but before the prompt as it always does).

Thanks again.

Edit : I got the idea here -
http://www.gammon.com.au/forum/bbshowpost.php?id=6670
but I think this is way easier (at least for me) when combined with the info at the beginning of this thread. I was able to set up a healing setup that goes off all the seperate balances (tree/focus/herb/salve/smoke (no balance on smoking though but for aeon it would be helpful)) and doesn't trip up so long as the person has lifevision. Now I just need to further illusion-proof for times when lifevision doesn't pick up the Illusion. THANKS A TON!