Functions and GetLinesInBuffer ()

Posted by Shadoweave on Sat 01 Dec 2007 08:09 PM — 6 posts, 26,971 views.

#0
I was wondering if there is a way to call functions with a specific word in them, like parsing through a table and calling different functions depending on what the keys are.
Also, is there a way to for the GetLinesInBuffer () function to see a line that arrived from the mud, but was omitted? I need this for something like this:

if (GetLineInfo (GetLinesInBuffer () - 4, 1) == <string>) then
<dosomething>
end --if

but I don't want the line I am getting info about to be shown on my screen.
Australia Forum Administrator #1
Quote:

I was wondering if there is a way to call functions with a specific word in them, like parsing through a table and calling different functions depending on what the keys are.


I'm not totally certain what you mean, but you can put functions into a table, here is an example:


t = {}

t.a = function () print "This is function a" end

t.b = function () print "This is function b" end

t.c = function () print "This is function c" end


t.a ()  --> This is function a
t.b ()  --> This is function b
t.c ()  --> This is function c


Quote:

Also, is there a way to for the GetLinesInBuffer () function to see a line that arrived from the mud, but was omitted?


When would you call that? The simple place to check a line is in the trigger that omits it, after all the trigger has the line available.

Try reading this post about how MUSHclient processing incoming lines:

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

If you are writing a plugin you could make a function OnPluginLineReceived that will be given lines as they arrive, even if they are going to be omitted eventually.


#2
Quote:

I'm not totally certain what you mean, but you can put functions into a table, here is an example:

I mean something like this:

for k, v in pairs (table) do
nocure_..k ()
end --for

Quote:

When would you call that? The simple place to check a line is in the trigger that omits it, after all the trigger has the line available.

I will check that at the prompt, and if the third of forth line before him is a specific message then I will call a function.
#3
I assume you're using Lua as the scripting language.

I also assume that what you want to do is something like this:

-- First, our functions that we might call.
-- These all have the cure_ prefix so we can find them
-- in the global dictionary easily (that's Pythonspeak for
-- 'table-that-is-pretending-to-be-an-associative-array') 

function cure_disease()
-- do disease curing stuff here
end

function cure_poison()
-- do poison curing stuff here
end

function cure_bleeding()
-- do bleeding curing stuff here
end

-- Secondly, a function to call the various cure_*
-- functions based on a list of named ailments it is given.
-- This isn't strictly necessary (it can be inlined 
-- everywhere it's needed), but in the name of code reuse
-- it is here (it might be called from a timer or a trigger
-- depending on how you write the rest of the script).
function cureall(ailments)
  for ailment in ailments do
    _G['cure_' .. ailment]() -- I'm almost certain there is a better idiom to do this :(
    -- What we're doing here is turning a specific ailment
    -- into the function name for curing it by prepending
    -- 'cure_' to the entry in the ailments list we were 
    -- passed.
    -- We then take advantage of the fact that functions
    -- are first class objects and that 'function f()' is
    -- really creating a global variable 'f' and stuffing
    -- it with an otherwise anonymous function.
    -- _G is the global table (at least for lookups) so
    -- _G['function name'] or _G.functionname give us
    -- the function object we want to call.
    -- The trailing parentheses call that function object
    -- with an empty parameter list.
  end --for
end --function

-- Finally, a trigger callback to assemble the list of 
-- ailments passed to cureall()
function trigger_curestuff(name, line, wildcards)
  -- construct an actual list of ailments here
  ailments = {'bleeding', 'poison'}
  cureall(ailments)
end


In a more general sense you write a lookup table that maps arbitrary strings to function calls, like so:
cure_lookup = {
    ['disease'] = cure_disease,
    ['sickness'] = cure_disease,
    ['wounding'] = cure_bleeding,
    ['bleeding'] = cure_bleeding,
    ['poison'] = cure_poison,
    }

function cureall(ailments)
  for ailment in ailments do
    cure_lookup[ailment]()
  end --for
end --function


You can have your trigger that matches and omits the line also set a flag (or a timestamp) so you know the line has been received. Then when your prompt trigger fires you can check (and reset) the flag.
Amended on Sun 02 Dec 2007 10:13 PM by Isthiriel
Australia Forum Administrator #4
Quote:

_G['cure_' .. ailment]() -- I'm almost certain there is a better idiom to do this :(


Personally I would make a "cure" table and make the various things entries in that. Thus, instead of cure_disease it would be cure.disease. This is the same typing, but you are putting all the cure stuff into one place.
Amended on Mon 03 Dec 2007 06:10 AM by Nick Gammon
#5
Wow, you guys are great! Exactly what I was looking for. After I've let it sink in, I think I will rewrite most of my system.