Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » zMUD General Discussion
rJames
Newbie


Joined: 18 Mar 2005
Posts: 2

PostPosted: Fri Mar 18, 2005 10:42 pm   

Need help with a spellbot script...
 
I'm trying to do something a bit unusual with my script. Instead of the spellbot sending all the spells it wants to cast to the MUD at once, I want it to keep a queue of the spells it wants to cast and the targets for those spells, and then cast one sell after the other when the previous one succeeds. Among other things, this allows the bot to recast a spell immediately if it fails, and also allows it to interrupt casting spells instantly without having to reconnect to the MUD, and even pick up where he left off after the interrupt is finished.

To give an example, one of the lists of spells would be "levelup." If the character Bob wants spells from that list and is on the list of approved characters, he says "levelup." The end result I want is for six spells to be cast on him: slink, elven, trollish, ogre, 'dragon wit', and sagacity. My idea was to have the trigger for levelup construct two lists, one of which would read "slink|elven|trollish|ogre|'dragon wit'|sagacity", and the other "Bob|Bob|Bob|Bob|Bob|Bob".

There would then be a separate, two-state trigger. The first state triggers on just about anything, because I want it to trigger ASAP after levelup is called (the levelup trigger will change the state of this trigger to the first state when it is activated). This trigger looks to see if there is anything in the spell list and target list, and if there is it casts the spell on the target. It also enters a numeric value into a variable called spellNumber that corresponds to the spell (if I explain this correctly, it will make sense later).

When this trigger finishes, it moves on to the second state. The second state is a duration trigger, so that if nothing happens for a while it will return to the first state. It triggers on the messages "You failed." (Meaning that you cast the spell successfully but the target already has the spell on him), "They aren't here" (the target isn't here), or @successList.@spellNumber. successList is a list of all the messages you get when a spell succeeds, and spellNumber is a number corresponding to the actual spell you're trying to cast. Since slink has the first message in successList, its spellNumber is 1, so after the first trigger fires, the second trigger is looking for the first string in successList. When the second trigger fires, it pops the first item of spellList and targetList out (moving the second spell and target to the front of their lines) and sets the state of the trigger equal to 0, which hopefully makes the first trigger restart and cast the second spell on the second target. I did this manual state reset because it appears that duration triggers will keep firing until their time runs out, which isn't what I want.

Finally, there is a third trigger looking for messages that indicate that the spell casting failed; when this triger fires, it sets the state of the other trigger equal to 0 without popping anything out of spellList and targetList, which hopefully makes the bot attempt to recast the spell.

Anyway, the script somewhat works, but not particularly well. It gets stuck in the middle of spellcasting sometimes, it repeat casts sometimes without getting a failure message, etc. Could someone take a look at this script and point out what I've done wrong, or suggest a different tactic for accomplishing the same aims that might give me better results?

The script:

#CLASS {Mage}

#VAR successList {@targetList.1 suddenly appears more agile...|@targetList.1's ears grow pointed and his voice takes on a musical aspect.|@targetList.1's face contorts with a bestial vigor.|@targetList.1's muscles ripple as they are infused with the might of an ogre.|@targetList.1's eyes glimmer with the wit of the dragon.|@targetList.1 grows serious as wisdom takes root within him.} {@targetList.1 suddenly appears more agile...|@targetList.1's ears grow pointed and his voice takes on a musical aspect.|@targetList.1's face contorts with a bestial vigor.|@targetList.1's muscles ripple as they are infused with the might of an ogre.|@targetList.1's eyes glimmer with the wit of the dragon.|@targetList.1 grows serious as wisdom takes root within him.}

#VAR spellNumber {0} {0}

#VAR meanMage {blind|curse|razor|sword|winter|blaze|weaken|sleep} {blind|curse|razor|sword|winter|blaze|weaken|sleep}

#VAR buffer {}

#TRIGGER "CastTrig" {(%w)} {#if (@spellList.1 <> "") {#show @spellList;#show @targetList;c @spellList.1 @targetList.1;#if (@spellList.1="slink") {spellNumber=1};#if (@spellList.1="elven") {spellNumber=2};#if (@spellList.1="trollish") {spellNumber=3};#if (@spellList.1="ogre") {spellNumber=4};#if (@spellList.1="(%w)dragon(%w)") {spellNumber=5};#if (@spellList.1="(%w)agacit(%w)") {spellNumber=6}}}
#COND {{%item(@successList,@spellNumber)|You failed.|They aren't here.}} {buffer = %pop( spellList);buffer = %pop( targetList);trance;#State CastTrig 0} {dur|param=20000}

#TRIGGER {^(%w) says 'levelup test'} {target = %1;#if {%ismember( @target, @goodList)>0} {#T- CastTrig;#var spellList %additem( "slink", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "elven", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "trollish", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "ogre", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "'dragon wit'", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "sagacity", @spellList);#var targetList %additem( @target, @targetList);#State CastTrig 0} {shake @target}}

#TRIGGER {{Something distracts you, and you lose your concentration.|You lost your concentration.|You get a mental block mid-way through the casting.|A tickle in your nose prevents you from keeping your concentration.|An itch on your leg keeps you from properly casting your spell.}} {#State CastTrig 0}


#CLASS {All}

#ALIAS newgood {#var goodList %additem( %1, @goodList);#var goodList %dups( @goodList)}

#ALIAS purge {spellList="";targetList=""}

#VAR spellList {}

#VAR targetList {} {}

#VAR spell {}

#VAR target {nobody} {nobody}

#VAR goodList {Bob|Joe|George|John}
Reply with quote
Maelstrom
Apprentice


Joined: 10 Feb 2005
Posts: 158

PostPosted: Fri Mar 18, 2005 11:40 pm   
 
I think I can optimize this some... if I have some time I will look at it closer at a later date.

First trigger replace:
#if (@spellList.1="slink") {spellNumber=1};#if (@spellList.1="elven") {spellNumber=2};#if (@spellList.1="trollish") {spellNumber=3};#if (@spellList.1="ogre") {spellNumber=4};#if (@spellList.1="(%w)dragon(%w)") {spellNumber=5};#if (@spellList.1="(%w)agacit(%w)") {spellNumber=6}

With:
#VAR spellNumber {%ismember("slink|elven|trollish|ogre|(%w)dragon(%w)|(%w)agacit(%w)"}

Actually the last two might not work... should be functionally equal but testing would be in order.

Second trigger replace:
#var spellList %additem( "slink", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "elven", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "trollish", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "ogre", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "'dragon wit'", @spellList);#var targetList %additem( @target, @targetList);#var spellList %additem( "sagacity", @spellList);#var targetList %additem( @target, @targetList)

With:
#FOR {slink|elven|trollish|ogre|dragon wit|sagacity} {#VAR spellList %additem(%i,@spellList)}
#FOR {%leftback(%repeat(@target|,6),1} {#VAR targetList %additem(%i,@targetList)}

In the very least its more readable Wink
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Sat Mar 19, 2005 6:51 am   
 
Example text from the mud would be helpful here. In any case I will write you up something that sort of resembles what you started with.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Sat Mar 19, 2005 9:09 am   
 
This should do everything you want and then some. Replace the "!!!prompt!!!" with something that will match your prompt. You should enable the preference "Wildcards in {} triggers" under the "Script Parser" section to properly match the prompt.

I did not provide a specific means to pause it, but that can easily be added to the CastSpell alias. I turned your Duration condition into a pattern condition and use a seperate alarm for the time out. This allows a another state to determine which way thing went more readily.

Next the multiple mass of lists was reduced to a few record variables. The SpellSets list allows you to add multiple spellup sets. Each set should have the success text as keys and anything for values, those values are not actually used but provide references. Next the set should contain a key of "SpellsQueue" that has a value of a list of all the spells in that set. Look at the structure used with the LevelUpSpells variable for reference.

Finally some little informational messages were added. The accuracy of the estimated time message could be made much tighter by also expanding out the spell queue for the different sets and using a smaller multiplier. Did I make it more readable?..I doubt it, but I did test it out some and it should work right.

Also it only issues "trance" when spellup is done and at error points. If this is a problem you should move the trance command.

#CLASS {Mage}
#ALIAS newgood {#ADDITEM goodList {%1}}
#ALIAS NextCast {#IF ((@Spell="")&(@Target="")) {#IF (@SpellTargets) {Target=%word(%expanddb(@SpellTargets," "," "),1);SpellSuccess=@{%item(%db(@SpellTargets,@Target),1)Spells};SpellsQueue=%db(@SpellSuccess,"SpellsQueue");Spell=%pop(SpellsQueue)} {#ECHO Error in spells system, no spell requests pending;trance}} {#IF (@SpellsQueue) {Spell=%pop(SpellsQueue)} {Spell=%db(@SpellTargets,@Target);#IF (%numitems(@Spell)>1) {#DELNITEM Spell 1;#ADDKEY SpellTargets {@Target} {@Spell};SpellSuccess=@{%item(@Spell,1)Spells};SpellsQueue=%db(@SpellSuccess,"SpellsQueue");Spell=%pop(SpellsQueue)} {#DELKEY SpellTargets {@Target};#IF (@SpellTargets) {Target=%word(%expanddb(@SpellTargets," "," "),1);SpellSuccess=@{%item(%db(@SpellTargets,@Target),1)Spells};SpellsQueue=%db(@SpellSuccess,"SpellsQueue");Spell=%pop(SpellsQueue)} {Spell="";Target="";#T- CastFailTrig;#T- CastTrig;trance}}}};#IF ((@Spell)&(@Target)) {CastSpell}}
#ALIAS AddSpellSet {#IF (%iskey(@SpellTargets,"%1")) {#ADDITEM SpellTargets.%1 {%2}} {#ADDKEY SpellTargets {%1} {%2}};tell %1 estimated time till your turn %eval((%ismember("%1",%expanddb(@SpellTargets,"|","|"))-%iskey(@SpellTargets,"%1"))*30) seconds.;#IF ((@Spell="")&(@Target="")) {NextCast}}
#ALIAS CastSpell {#IF (@InCast=0) {c '@Spell' @Target;InCast=1;#T+ CastTrig;#T+ CastFailTrig} {#ECHO Error in spells system, attempting to cast while cast pending}}
#ALIAS purge {#RESET Mage;#T- CastSecond;#T- CastTrig;#T- CastFailTrig;trance}
#VAR SpellSuccess {} {}
#VAR meanMage {blind|curse|razor|sword|winter|blaze|weaken|sleep}
#VAR SpellTargets {} {}
#VAR Spell {} {}
#VAR Target {} {}
#VAR goodList {Bob|Joe|George|John}
#VAR SpellFails {Something distracts you, and you lose your concentration.|You lost your concentration.|You get a mental block mid-way through the casting.|A tickle in your nose prevents you from keeping your concentration.|An itch on your leg keeps you from properly casting your spell.}
#ADDKEY LevelUpSpells { suddenly appears more agile...=slink|'s ears grow pointed and his voice takes on a musical aspect.=elven|'s face contorts with a bestial vigor.=trollish|'s muscles ripple as they are infused with the might of an ogre.=ogre|'s eyes glimmer with the wit of the dragon.=dragon wit| grows serious as wisdom takes root within him.=sagacity|(SpellsQueue=slink|elven|trollish|ogre|dragon wit|sagacity)}
#VAR InCast {0} {0}
#VAR SpellSets {levelup}
#VAR SpellsQueue {} {}
#TRIGGER "CastTrig" {^{@Target}{@SpellSuccess}$} {InCast=-1;#T- CastFailTrig;#T+ CastSecond} "" {disable}
#COND {^({!!!prompt!!!|You failed.|They aren't here.})} {InCast=0;#T- CastSecond;#IF ("%1"="They aren't here.") {#DELKEY SpellTargets {@Target};Spell="";Target=""}} {prompt|disable}
#COND {} {#IF (@InCast=-1) {#ECHO Error in spells system, did not detect prompt or secondary cast message after successful cast.;trance} {#T- CastTrig;NextCast}} {wait|param=1|disable}
#ALARM "CastSecond" {20} {#STATE CastTrig 2;#T- CastSecond} "" {disable}
#TRIGGER {^(%w) says '({@SpellSets}) test'$} {#IF (%iskey(@SpellTargets,"%1")) {#IF (%ismember("%2",%db(@SpellTargets,"%1"))=0) {AddSpellSet %1 %2} {say %1, I heard your request.}} {#if {%ismember( "%1", @goodList)=0} {shake "%1"} {AddSpellSet %1 %2}}}
#TRIGGER "CastFailTrig" {^{@SpellFails}$} {InCast=0;CastSpell} "" {disable}
#CLASS 0
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
rJames
Newbie


Joined: 18 Mar 2005
Posts: 2

PostPosted: Sat Mar 19, 2005 8:33 pm   
 
Thanks to both of you for your help! I did manage to get something working, but vijilante's script looks more sophisticated and I'd like to implement it if possible. Unfortunately, it doesn't appear to work for me, probably due to MUD text differences. I don't really follow he script well enough to be able to debug it myself. It casts the first spell in the list, but afterwards does nothing. No error messages are given; it just appears to be suspended.

The MUD text itself is nothing special: when you cast a spell you either get one of the success messages or one of the failure messages, which may be displayed either on a new line or after your prompt. If there's anything specific you need as a sample, please let me know. Also, could you provide a very general overview of what exactly the script is doing?

Also, if it helps, here is the working version of the script I wrote; I used some of Maelstrom's suggestions to clean it up.

#CLASS {Mage}
#VAR friendlyMage {slink|elven|trollish|ogre|dragon wit|sagacity|inner|shield|iceshield|shockshield|fireshield|invis|valiance} {slink|elven|trollish|ogre|dragon wit|sagacity|inner|shield|iceshield|shockshield|fireshield|invis|valiance}

#VAR A {10} {10}

#VAR successList {@targetList.1 suddenly appears more agile...|@targetList.1's ears grow pointed and his voice takes on a musical aspect.|@targetList.1's face contorts with a bestial vigor.|@targetList.1's muscles ripple as they are infused with the might of an ogre.|@targetList.1's eyes glimmer with the wit of the dragon.|@targetList.1 grows serious as wisdom takes root within him.|A mysterious warmth radiates from @targetList.1|A force shield of shimmering blue surrounds @targetList.1|A glistening hail of ice encompasses @targetList.1|Torrents of cascading energy form around @targetList.1|Mystical flames rise to enshroud @targetList.1|@targetList.1 fades out of existence.|@targetList.1 is surrounded by an aura which protects him from paralysis.|Tracing a ring before you, the graceful flow of a mystical spring emerges.} {@targetList.1 suddenly appears more agile...|@targetList.1's ears grow pointed and his voice takes on a musical aspect.|@targetList.1's face contorts with a bestial vigor.|@targetList.1's muscles ripple as they are infused with the might of an ogre.|@targetList.1's eyes glimmer with the wit of the dragon.|@targetList.1 grows serious as wisdom takes root within him.|A mysterious warmth radiates from @targetList.1|A force shield of shimmering blue surrounds @targetList.1|A glistening hail of ice encompasses @targetList.1|Torrents of cascading energy form around @targetList.1|Mystical flames rise to enshroud @targetList.1|@targetList.1 fades out of existence.|@targetList.1 is surrounded by an aura which protects him from paralysis.|Tracing a ring before you, the graceful flow of a mystical spring emerges.}

#VAR spellNumber {0} {0}

#VAR meanMage {blind|curse|razor|sword|winter|blaze|weaken|sleep} {blind|curse|razor|sword|winter|blaze|weaken|sleep}

#VAR buffer {}

#VAR levelTest {slink|elven|trollish|ogre|dragon wit|sagacity} {slink|elven|trollish|ogre|dragon wit|sagacity}

#TRIGGER {^You come out of your trance.} {trance} "" {disable}

#TRIGGER {^(%w) says '(%w) test'} {target = %1;spell = %2;#if {%ismember( @spell, @friendlyMage)>0} {#if {%ismember( @target, @goodList)>0} {#var targetList %additem( @target, @targetList);#var spellList %additem( @spell, @spellList);#state CastTrig 0;#set CastTrig 0 true} {shake @target}}}

#TRIGGER "CastTrig" {You enter a peaceful trance, collecting mana from the cosmos.} {#if (@spellList.1 <> "" & @casting = 0 & @interrupt = 0) {#if (@spellList.1 <> "dragon wit" & @spellList.1 <> "create spring") {c @spellList.1 @targetList.1};#if (@spellList.1 = "dragon wit") {c 'dragon wit' @targetList.1};#if (@spellList.1 = "create spring") {c 'create spring'};#var spellNumber {%ismember( @spellList.1, @friendlyMage)};#if (@spellList.1 = "dragon wit") {spellNumber = 5};#if (@spellList.1 = "create spring") {spellNumber=14};casting=1}}

#COND {{%item(@successList,@spellNumber)|You failed.|They aren't here.}} {buffer = %pop( spellList);buffer = %pop( targetList);trance;spellNumber=0;casting=0;#State CastTrig 0} {dur|param=20000}

#TRIGGER {^(%w) says 'levelup test'} {target = %1;#if {%ismember( @target, @goodList)>0} {#for {slink|elven|trollish|ogre|'dragon wit'|sagacity} {#VAR spellList %additem( %i, @spellList)};#loop 6,1 {#VAR targetList %additem( @target, @targetList)};#State CastTrig 0;#set CastTrig 0 true} {shake @target}}

#TRIGGER {{Something distracts you, and you lose your concentration.|You lost your concentration.|You get a mental block mid-way through the casting.|A tickle in your nose prevents you from keeping your concentration.|An itch on your leg keeps you from properly casting your spell.}} {casting=0;#State CastTrig 0;#set CastTrig 0 true}

#TRIGGER {^(%w) says 'interrupt test'} {target = %1;#if {%ismember( @target, @goodList)>0} {interrupt = 1} {shake @target}}

#TRIGGER {^(%w) says 'resume test'} {target = %1;#if {%ismember( @target, @goodList)>0} {interrupt = 0;#state CastTrig 0;#set CastTrig 0 true} {shake @target}}

#TRIGGER {^(%w) says 'purge test'} {target = %1;#if {%ismember( @target, @goodList)>0} {purgeall} {shake @target}}

#TRIGGER {^(%w) says 'dragon wit test'} {target = %1;#if {%ismember( @target, @goodList)>0} {#var targetList %additem( @target, @targetList);#var spellList %additem( "dragon wit", @spellList);#state CastTrig 0;#set CastTrig 0 true} {shake @target}}

#TRIGGER {^(%w) says 'create spring test'} {target = %1;#if {%ismember( @target, @goodList)>0} {#var targetList %additem( @target, @targetList);#var spellList %additem( "create spring", @spellList);#state CastTrig 0;#set CastTrig 0 true} {shake @target}}

#CLASS {All}

#ALIAS showspell {#show @spellList;#show @targetList}

#ALIAS newgood {#var goodList %additem( %1, @goodList);#var goodList %dups( @goodList)}

#ALIAS purgeall {spellList="";targetList=""}

#VAR spellList {}

#VAR targetList {} {}

#VAR speaker {nobody} {nobody}

#VAR spell {invis}

#VAR target {nobody} {nobody}

#VAR goodList {Bob|Joe|George|John}

#VAR casting {0} {0}

#VAR interrupt {0} {0}
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Tue Mar 22, 2005 10:19 am   
 
I will tweak around with what I wrote some more and see if I can integrate some of the things you added to yours. I think the problem is in how I interpretted your original statement about the mud output. If you really want me to get what I wrote working right then you should post a copy of mud output with your existing script running through a few spells. Including some examples of the the various failures.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » zMUD General Discussion All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net