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


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  General
. . -> [Subject]  Passing wildcards to script procedure as arguments

Passing wildcards to script procedure as arguments

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


Pages: 1 2  3  

Posted by Cadari   (25 posts)  [Biography] bio
Date Sun 26 Aug 2007 04:27 PM (UTC)

Amended on Sun 26 Aug 2007 05:24 PM (UTC) by Cadari

Message
Greetings again. I'll continue bothering you with simple questions, if you don't mind.

Say, I need to make a trigger firing on the line:

You attack a (ghost|ghast|spectre).

and sending the matching wildcard to the script procedure, like this:

def on_attack(target):
    world.Note('You attack a %s!' % target)

So you'll see 'You attack a ghost!'. The trigger:

  <trigger
   enabled="y"
   match="^You attack a (ghost|ghast|spectre)\.$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>on_attack(%1)</send>
  </trigger>

won't work, as it passes ghost as a variable name, not as a string:

Traceback (most recent call last):
  File "<Script Block 64>", line 1, in <module>
    on_attack(ghost)
NameError: name 'ghost' is not defined

Anything I'm missing?

EDIT: Forgot to add: Send to: World and working with world.GetTriggerWildcard isn't it. It must send to Script.
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #1 on Sun 26 Aug 2007 06:24 PM (UTC)
Message
  <trigger
   enabled="y"
   match="^You attack a (ghost|ghast|spectre)\.$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>on_attack("%1")</send>
  </trigger>

The %1 isn't a string, it's a literal replacement of the wildcard. So for your example, you were calling on_attack( ghost ) instead of on_attack( "ghost" )

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

Posted by Cadari   (25 posts)  [Biography] bio
Date Reply #2 on Sun 26 Aug 2007 08:16 PM (UTC)
Message
You can't imagine how many hours of futile attempts to make it work you just saved me. Thanks!
[Go to top] top

Posted by Isthiriel   (113 posts)  [Biography] bio
Date Reply #3 on Mon 27 Aug 2007 04:27 AM (UTC)

Amended on Mon 27 Aug 2007 04:28 AM (UTC) by Isthiriel

Message
There's some kind of a memory leak somewhere in the bowels of the connection between MUSHclient and Python's Active Scripting implementation that is triggered by "Send to Script" (probably the code object isn't free'ed but that's not something I know how to test).

If you are writing a script function anyway you might as well use the script call feature:
<triggers>
  <trigger
   enabled="y"
   match="^You attack a (ghost|ghast|spectre)\.$"
   regexp="y"
   script="on_attack"
   sequence="100"
  >
  </trigger>
</triggers>


Which means your function must look like:
def on_attack(name, line, wildcards):
    world.Note("You attack a %s!" % wildcards[0])


HTH. HAND.
[Go to top] top

Posted by Cadari   (25 posts)  [Biography] bio
Date Reply #4 on Mon 27 Aug 2007 07:33 AM (UTC)
Message
Thank you, Isthiriel, but unfortunately, I have to use Send to: Script. My example above is just an example, not the real routine.
[Go to top] top

Posted by Isthiriel   (113 posts)  [Biography] bio
Date Reply #5 on Mon 27 Aug 2007 03:57 PM (UTC)
Message
Out of curiousity, why?
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #6 on Mon 27 Aug 2007 04:12 PM (UTC)
Message
Only thing I can think of to have Send to Script necessary would be if you needed to dynamically change what the trigger does. In Lua, this can be done fairly easily with a loadstring() call, and I'm sure Python has a way to do it. Usually calling a script has much more versatility than the send field, and I can't really seem to think of a way to require the use of the send field.

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

Posted by Isthiriel   (113 posts)  [Biography] bio
Date Reply #7 on Mon 27 Aug 2007 04:32 PM (UTC)

Amended on Mon 27 Aug 2007 04:33 PM (UTC) by Isthiriel

Message
Python has at least two.

The eval() function which evaluates a string expression, and the exec statement which executes a string.

That is:
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print eval("4 + 5")
9
>>> exec "print 'Hello world!'"
Hello world!
>>>


I think you can also compose functions on the fly (like LISP macros), though that is trickier.
[Go to top] top

Posted by Cadari   (25 posts)  [Biography] bio
Date Reply #8 on Mon 27 Aug 2007 08:40 PM (UTC)
Message
Maybe it's just my ignorance of certain MUSHclient/Python features, but I use Send to: Script most of time.

I play IRE MUD. There are numerous afflictions (blindness, deafness, limb breaks, curses and on and on). I could setup a script procedure for each one of them, like

def on_blindness():
    global afflictions    
    afflictions['blindness'] = True    
    world.Note('Blindness!')

Then add an equal number of corresponding triggers and use Send to: World. But as I said, there are lots of possible afflictions, so obviously it's better to have something like:

def on_affliction(affliction):
    global afflictions    
    afflictions[affliction] = True    
    world.Note(affliction)

And Send to: Script on_affliction('blindness').

This whole topic was about the following thing (some examples):

<triggers>
  <trigger
   enabled="y"
   group="knighthood_afflictions"
   match="\w+ (strikes|cuts|slashes) the tendon above your (left|right) heel\, and you scream in agony as it\'s completely severed\.$"
   name="severed_tendon"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>
    afflicted('severed_%s_tendon' % '%2')
  </send>
  </trigger>

  <trigger
   enabled="y"
   group="knighthood_afflictions"
   match="Your (left|right) leg is completely slashed through\, which immediately plops to the ground\, leaving only a bloody stump\.$"
   name="amputated_leg"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>
    afflicted('amutated_%s_leg' % '%1')
    afflicted('stun')
  </send>
  </trigger>
</triggers>

If there's any way to do this without Send to: Script, that would mean I'm just dumb :) And also I would be very grateful, as Send to: Script looks ugly when you look through the XML file with triggers :)
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Mon 27 Aug 2007 10:18 PM (UTC)

Amended on Mon 27 Aug 2007 10:19 PM (UTC) by Nick Gammon

Message
Quote:

But as I said, there are lots of possible afflictions, so obviously it's better to have something like:



def on_affliction(affliction):
    global afflictions    
    afflictions[affliction] = True    
    world.Note(affliction)


And Send to: Script on_affliction('blindness').


You could put the affliction into the trigger name (label), and then the script could simply use that. Something like this:


def on_affliction(name, line, wildcards):
    global afflictions    
    afflictions[name] = True    
    world.Note(name)


Now each (appropriate) trigger can simply call on_affliction, without having to use send-to-script. You may have a problem if you have an "on" affliction and an "off" affliction, but the name could convey that, eg.

Turned on: on_blindness
Turned off: off_blindness

The script strips off the first part (on or off) and uses that to decide whether the affliction is going on or off. The rest of the word is which affliction.

Here is another way of achieving that. In the trigger use "send to variable", This lets you send a nice long string to a single variable, without the overhead of invoking the script engine parser. For example:


<triggers>
  <trigger
   custom_colour="2"
   enabled="y"
   match="You are going mad."
   script="on_affliction"
   send_to="9"
   sequence="100"
   variable="affliction"
  >
  <send>madness</send>
  </trigger>
</triggers>


This puts the word "madness" into the MUSHclient variable "affliction" and then calls the script "on_affliction". That can then pull "madness" out of the variable and set the appropriate script language variables. This is what it might look like in Lua:


function on_affliction (name, line, wildcards)
  afflictions [GetVariable ("affliction")] = true
end -- function


- Nick Gammon

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

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #10 on Mon 27 Aug 2007 10:56 PM (UTC)

Amended on Mon 27 Aug 2007 10:58 PM (UTC) by Shaun Biggs

Message
Another possibly way to do this is to have the script act differently with a bunch of if statements or a case switch. My Python skills are horrid, so I'll show an example in Lua, which is easy enough to read.


<triggers>
  <trigger
   enabled="y"
   group="knighthood_afflictions"
   match="\w+ (?:strikes|cuts|slashes) the tendon above your (left|right) heel\, and you scream in agony as it\'s completely severed\.$"
   name="severed_tendon"
   script="affliction"
   regexp="y"
   send_to="1"
   sequence="100"
  >
  </trigger>

  <trigger
   enabled="y"
   group="knighthood_afflictions"
   match="Your (left|right) leg is completely slashed through\, which immediately plops to the ground\, leaving only a bloody stump\.$"
   name="amputated_leg"
   script="affliction"
   regexp="y"
   send_to="1"
   sequence="100"
  >
  </trigger>
</triggers>

function affliction( sTrig, sLine, wildcards[] )
  if sTrig == "severed_tendon" then
    afflicted( 'severed_%s_tendon'..wildcards[1] ) -- Lua starts arrays off at 1, not 0
  elseif sTrig == "amputated_leg" then
    afflicted('amutated_%s_leg'..wildcards[1])
    afflicted('stun')
  end
end -- affliction

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

Posted by Cadari   (25 posts)  [Biography] bio
Date Reply #11 on Tue 28 Aug 2007 07:49 AM (UTC)
Message
Nick, Shaun, many thanks for explaining the things for me, though some questions arise.

In fact, my first version was identical to Shaun's one, but I thought it would work slower with all the if-elif statements, so I switched to what I posted above.

Now the question. Given the fact you're dealing with more than hundred possible afflictions, what route is the best? Execution speed issue is very important, as I have about two hundred triggers for now, and the numbers are growing.

P.S. As promised, I admit I'm dumb :)
[Go to top] top

Posted by Shaun Biggs   USA  (644 posts)  [Biography] bio
Date Reply #12 on Tue 28 Aug 2007 08:25 AM (UTC)
Message
Just keeping it out of 'send to script' will help execution speed immensely. MUSHclient's trigger matching is very fast, and I have had a few hundred triggers on a P120 with no choppiness. A simple case statement should take care of the actual grunt work, and Python's script engine is pretty fast on it's own. It will be a long list, but manageable.

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

Posted by Cadari   (25 posts)  [Biography] bio
Date Reply #13 on Wed 29 Aug 2007 09:50 AM (UTC)
Message
Understood. Thank you.
[Go to top] top

Posted by Curious2   (47 posts)  [Biography] bio
Date Reply #14 on Thu 22 Jan 2009 02:08 AM (UTC)
Message
You know I just downloaded MUSHClient and like the guy above it confuses me to no end. The main problem is just simply communicating with my LUA scripts.

Why is it so complicated to do afflict("illness")?

Using the label to send the affliction works, but the only problem is you also have a trigger that cures the same affliction...

How do I do this without having to creating a bunch of extra code for no reason?

I have all the afflictions in a table.

All I want to do is send the affliction name to:

-- Afflict function
function afflict(affliction)
if afflicted[affliction] == false then
afflicted[affliction] = true
ColourNote("red", "black", "Afflicted: ", "khaki", "black", affliction)
end
end -- afflict

-- Unafflict function
function unafflict(affliction)
if afflicted[affliction] then
afflicted[affliction] = false
ColourNote("lime", "black", "Cured: ", "khaki", "black", affliction)
end
end -- unafflict

There are no wildcards on most of the triggers.

I am just not understandstanding the interface of Mushclient. Why would I want to have to create other variables when I am already using the LUA table? sigh
[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.


73,790 views.

This is page 1, subject is 3 pages long: 1 2  3  [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]