Prompt trigger question

by Simimi

Back to Mechanic's Corner.

Simimi2007-05-17 20:19:54
So I do not need to have things like var.anorexia = true/false then? How would I noy set a state variable for having/not having an affliction? I do not thing I grok your point...
Unknown2007-05-17 20:21:23
The var table stuff should be in a var.lua file under C:\\Program Files\\MUSHclient\\lua\\, and then in your script you just put a require "lua" at the top and that's it! (The var.lua file should already be included if you have a recent version of MUSHclient installed.)

Here's an example of how I use my salve_affs table, and I hope you can tell by the names of the helper functions and variables what's going on in this function:

CODE
function salve_curing()
    if not AbleApply() then
        return
    end

    if affs.aeon or affs.sap then
        return
    end

    if not HaveBalance("salve") then
        return
    end

    for aff,cure in salve_affs:pairs() do
        if affs then
            -- Don't try to stack regeneration cures, but other salves are fine
            if (not string.find(cure, "regeneration") or not flags.regenerating) then
                Execute(cure)
                break
            end
        end
    end
end


I use affs for tracking afflictions, flags for tracking miscellaneous status things, and the salve_affs table I use (as I said above) is actually a phpTable() created table, as opposed to the {} table initialization I posted. That script just ensures that the items in the table stay in the order I add them, guaranteeing priority order when I go through the table in this loop to cure stuff.

This can go in phptable.lua with the other MUSHclient Lua modules and then you just use require "phptable" as with the var module.
CODE
function phpTable(...)
    local newTable,keys,values={},{},{}
    newTable.pairs=function(self) -- pairs iterator
        local count=0
        return function()
            count=count+1
            return keys,values]
        end
    end
    setmetatable(newTable,{
        __newindex=function(self,key,value)
            if not self then table.insert(keys,key)
            elseif value==nil then -- Handle item delete
                local count=1
                while keys~=key do count = count + 1 end
                table.remove(keys,count)
            end
            values=value -- replace/create
        end,
        __index=function(self,key) return values end
    })
    return newTable
end

return phpTable


Coincidentally, another way I use my salve_affs table is to check whether or not I even need to execute the salve_curing function when I'm afflicted. If I'm hit with something and it's not in that table, I don't cure with salves.

(Disclaimer: this is from pieces of a partially finished system I wrote myself, never used in practice, and it has been watered down a little for illustration purposes. Make your own modifications and do your own testing as fits what you're building.)
Simimi2007-05-17 20:26:00
Wow, thank you so much for the examples, I may try to try the phptable() idea rather than my current afflictions table if it is indeed more effecient.

I do think I see what is going on with your function script as well, I think I will work on improving mine a bit then, since things work now, now I just have to decide how I want things to get done.

EDIT: ok I removed the entire part of Nick's var script and I just added
CODE
require "var"
and
CODE
require "phptable"


Simimi2007-05-18 06:09:19
Ok so I have been working on this for a bit, and I want to make sure I understand what it is I should be doing before I travel the basin looking for trigger lines and such.

QUOTE(Demetrios)
This is the part where I've gone back and forth on the best way to do things, and I don't think there's a lot of difference since MUSHClient can read thousands of table lines in milliseconds, but the two main ways to do this are:

1) Use flag variables to say yea or nay if you have an affliction.
2) Use a table to store current afflictions.

I think I want to use the table to store current afflictions, and not use things like var.anorexia = true/false. I have no logical reasoning to why, but that way just seems like more fun. I have the phptable.lua module in the modules folder, and I have require "phptable" at the very top of my script.

I read some things fromthe Mush forums (I have about 5 threads open next to this one in tabs so I can jump around trying to figure things out) and I think I am slowly understanding.

Here is what I am thinking. I am not sure how to make a phptable... I thought Lua tables were like this
CODE
afflictions_herbs = {
{name = "anorexia", cure = coltspipe, state = false },
{name = "slickness", cure = "calamus", state = false },
{name = "hypochondria", cure = "wormwood", state = false },
{name = "impatient", cure = coltsfootpipe, state = false },
{name = "stupidity", cure = "pennyroyal", state = false }
}

So would a phptable be like...
CODE
afflictions_herbs {}
afflictions_herbs = "coltspipe"


I assume the different look of those two tables makes a difference as to what they are and do...

anyway, so for an empty set, or for current afflictions...maybe like:
CODE
current_afflictions = {}

And then, for a trigger like...
CODE
^You are so bloody stupid it hurts!\\.$

I could have that send to script to add stupidity to my current affs table with like...
CODE
table.insert (current_afflictions, afflictions_herbs )

Then use a for loop to run through the current affs for me? Like"
CODE
for k, v in current_afflictions do
       if var.herbbalance == 1 then
            Send ("outr ", v.cure)
            Send ("eat ", v.cure)
     elseif return
     end
end


I hope I am at least heading in the right direction here...
Unknown2007-05-18 11:25:21
1. You don't need a phpTable to keep track of afflictions or defenses. The phpTable is used for lookup tables, like salve_affs, herb_affs, etc, that need to stay sorted in the order they're created. For afflictions tracking, you can just use a regular Lua table.

CODE
herb_affs = phpTable()
herb_affs = "smoke coltsfoot"
herb_affs = "apply arnica to head"
herb_affs = "eat myrtle"


2. To start afflictions tracking (or to reset it after a spar or something), create it as an empty table. No need to initialize every affliction to false because you can just check for their presence or absence instead. You seem to have gotten this far already.

CODE
affs = {}


3. For an affliction trigger, I recommend using a function that tracks the affliction rather than adding it directly to the table. This gives you more flexibility in how you handle adding and curing the afflictions because you can modify that function to handle any special cases or other fun things like counting how many afflictions you have currently.

CODE
function OnAff(aff, val)
  -- If it's not a valid affliction name, leave the
  -- function early to avoid crashing
  if not aff then
    return
  end

  -- This will default "val" to true if it's omitted from
  -- the arguments passed in
  val = val or true

  -- You can pass in a table of afflictions to save calls,
  -- or you can omit this as it's really just extra fun
  if type(aff) == "table" then
    for _,v in pairs(aff) do
      OnAff(v, val)
    end
    return
  end

  -- The actual setting of the affliction in the table
  affs = val

  -- This is where I set flags on which healing
  -- queues to check on the next prompt, but
  -- you do your curing however you like...
end


4. If you do what I did and put all the herb cures in a single lookup table, you need to be sure you execute them based on their type: eat, apply, or smoke.

CODE
function herb_curing()
  if not HaveBalance("herb") then
    return
  end

  if affs.aeon or affs.sap then
    return
  end

  for aff,cure in herb_affs:pairs() do
    if affs then
      if (string.find(cure, "eat") and AbleEat()) or
         (string.find(cure, "apply") and AbleApply()) or
         (string.find(cure, "smoke") and AbleSmoke()) then
        Execute(cure)
        break
      end
    end
  end
end


(Footnote: I have "eat" and "apply" aliases that override the game commands only for the herbs, so they can outr first and then eat/apply. You may want to add the outr command to these functions somewhere. It's up to you.)
Simimi2007-05-18 12:11:35
Wow I think I am getting it, so I made a phpTable() for the current herb_affs and salve_affs that I know, I do not yet have any like purgative_affs or anything that does not have an herb or salve cure. I do have a few more questions though... (big surprise right?)

CODE
function addaff(aff, val)
  -- If it's not a valid affliction name, leave the
  -- function early to avoid crashing
  if not aff then
    return
  end

  -- This will default "val" to true if it's omitted from
  -- the arguments passed in
  val = val or true

  -- You can pass in a table of afflictions to save calls,
  -- or you can omit this as it's really just extra fun
  if type(aff) == "table" then
    for _,v in pairs(aff) do
      addaff(v, val)
    end
    return
  end

  -- The actual setting of the affliction in the table
  affs = val

  -- This is where I set flags on which healing
  -- queues to check on the next prompt, but
  -- you do your curing however you like...
end


Does this need to be in any special place in the script itself? How does that known to put them in
CODE
currentaffs = {}

Is it because of this line?
CODE
if type(aff) == "table" then


The part that is starting to worry me is that, I know A works, and I know if I modify A with more things it continues to work, but I do not know why A works, as opposed to B. A nice really oversimplified example, yay!


I also noticed, Zarquan, that you have balance functions... I'm gonna try and guess at how that would work...
CODE
HaveBalance("herb")

Might be like...
CODE
function HaveBalance("herb")
     if var.herbbalance = 1 then
    return
end

Maybe? OR some similiar idea at least?


I want to do my curing in whatever way is best to learn, I would like to learn a nice, effecient way of doing things from the get go, the sad part is that I am really enjoying working on this system, but I will not be able to over the weekend as I am going to the beach.
Unknown2007-05-18 13:45:07
QUOTE(Simimi @ May 18 2007, 07:11 AM) 409464
I also noticed, Zarquan, that you have balance functions... I'm gonna try and guess at how that would work...
CODE
HaveBalance("herb")

Might be like...
CODE
function HaveBalance("herb")
     if var.herbbalance = 1 then
    return
end

Maybe? OR some similiar idea at least?


Close!

I don't know exactly how Zarquan's function looks, but it's probably more like this:

CODE
function HaveBalance(balance)
  if GetVariable(balance .. "balance") = 1 then
    return true
  else
    return false
  end
end


And you would use it like:

CODE
if HaveBalance("herb") then


or

CODE
if HaveBalance("salve") then


Code will vary, of course, based on how you name your variables, but the key idea is:

1) You can pass in any balance to the function to check it.
2) You return either true or false.

QUOTE
I want to do my curing in whatever way is best to learn, I would like to learn a nice, effecient way of doing things from the get go, the sad part is that I am really enjoying working on this system, but I will not be able to over the weekend as I am going to the beach.


Going to the beach is far better!
Unknown2007-05-18 19:04:26
QUOTE(Simimi @ May 18 2007, 08:11 AM) 409464
Does this need to be in any special place in the script itself? How does that known to put them in
CODE
currentaffs = {}

Is it because of this line?
CODE
if type(aff) == "table" then


It's the line right after the comment that says "This is the actual setting of the affliction in the table." wink.gif

The line you quoted is used so I can add a list of afflictions in a single call to the function. For example addaff({"paralysis", "stupidity", "dizziness"}). Note the curly brackets around the list, which passes these in as a table. The if type(aff) == "table" then is the trick I added to make this multiple afflictions add possible. It just grabs the items from the table and calls the function again (recursively).


Demetrios already clarified fairly well on the HaveBalance function. My implementation is a bit different, but the idea is still the same. smile.gif