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

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Jun 22, 2012 2:36 am   

Cleaning up a variable-heavy script with data base variables.
 
I have recently decided to try cleaning up a rather variable intensive script with database variables,
and I'm having a little trouble figuring out where to go. I have a script currently that reads my affects
list, which looks like this:
Code:

You are affected by:
 1) Spell:                swiftness modifies hitroll         by  10 for 47 hours.
 2) Spell:                swiftness modifies ac              by -25 for 47 hours.
 3) Spell:           wall of thorns modifies none            by   0 for 47 hours.
 4) Spell:                   shield modifies ac              by -20 for 47 hours.
 5) Spell:           giant strength modifies strength        by   4 for 47 hours.
 6) Spell:                 barkskin modifies ac              by -20 for 22 hours.
 7) Spell:                    bless modifies saving-spell    by -12 for 47 hours.
 8) Spell:                    bless modifies hitroll         by  12 for 47 hours.
 9) Spell:                 divinity modifies saving-spell    by -16 for 101 hours.
10) Spell:                 divinity modifies hitroll         by  16 for 101 hours.
11) Spell:                    invis modifies none            by   0   permanently.
12) Spell:        enhanced strength modifies strength        by   4   permanently.
13) Spell:           mental barrier modifies ac              by -20   permanently.
14) Spell:           thought shield modifies ac              by -20   permanently.
15) Spell:              flesh armor modifies ac              by -20   permanently.
16) Spell:             detect bless modifies none            by   0   permanently.
17) Spell:        song of traveling modifies none            by   0   permanently.
18) Spell:            magic shelter modifies saving-spell    by -300   permanently.
19) Spell:              detect evil modifies none            by   0   permanently.
20) Spell:              detect good modifies none            by   0   permanently.
21) Spell:               stone skin modifies ac              by -40   permanently.
22) Spell:          heighten senses modifies none            by   0   permanently.
23) Spell:          heighten senses modifies none            by   0   permanently.
24) Spell:          heighten senses modifies none            by   0   permanently.
25) Spell:          heighten senses modifies none            by   0   permanently.
26) Spell:              biofeedback modifies none            by   0   permanently.
27) Spell:       energy containment modifies saving-spell    by -20   permanently.
28) Spell:              combat mind modifies hitroll         by  12   permanently.
29) Spell:              combat mind modifies ac              by -38   permanently.
30) Spell:               minstrelsy modifies hp              by 400   permanently.
31) Spell:               minstrelsy modifies mana            by 400   permanently.
32) Spell:             displacement modifies ac              by -46   permanently.
33) Spell:          story of safety modifies ac              by -20   permanently.


And creates a variable for each spell name, concatenating multiple words, and setting the value to 0, with
a default value of 1. The string "You are affected by~:" resets the class in which the script is contained,
setting all values to 1, and turns on a prompt trigger, which checks specific variables for non-zero values
and recasts the spells, in whatever manner I specify before turning itself off, like so:
Code:

 <trigger name="rsp" priority="290" enabled="false" id="425">
    <pattern>~<%n~/%n~(%n~%~)Llohr~(%n~%~)</pattern>
    <value>#if (@faeriefire) {} {biobreak Llohr 'faerie fire'}
#if (@pestilence) {} {biobreak Llohr pestilence}
#if (@egowhip) {} {biobreak Llohr ego}
#if (@curse) {} {biobreak Llohr curse}
#if (@blindness) {} {biobreak Llohr blind}
#if (@impairstrength) {} {biobreak Llohr impair}
#if (@aniseed) {} {biobreak Llohr aniseed}
#if (@poison) {} {biobreak Llohr poison}
#if (@banzai) {} {biobreak Llohr banzai}
#if (@biofeedback) {c biofeedback}
#if (@magicshelter) {c 'magic shelter'}
#if (@energycontainment) {c 'energy containment'}
#if (@flesharmor) {c 'flesh armor'}
#if (@thoughtshield) {c 'thought shield'}
#if (@mentalbarrier) {c 'mental barrier'}
#if (@combatmind) {c 'combat mind'}
#if (@displacement) {c displacement}
#if (@enhancedstrength) {c 'enhanced strength'}
#if (@adrenalinecontrol) {c 'adrenaline control'}
#if (@ectoplasmicform) {#if (@spiritform) {#if (@passdoor) {#if (@wraithform) {c 'ectoplasmic form'}}}}
#if (@inertialbarrier) {#if (@protection) {c 'inertial barrier'}}
#if (@intellectfortress) {c 'intellect fortress'}
#if (@neutralbarrier) {c neutral}
;#if (@unholybarrier) {remove cobra;wear cobra}
;#if (@fly) {remove figurine;wear figurine}
#if (@stoneskin) {remove neutron;wear neutron}
#if (@storyofsafety) {remove boots;wear boots}
;#if (@detectmagic) {wear light}
#if (@heightensenses) {heighten}
#if (@sneak) {~sneak}
#if (@shadowform) {sform}
#if (@haste) {#if (@flurry) {#if (@fervour) {#echo MARK}}}
#t- aff1
#t- aff2
#t- rsp
;#if (@auto) {wear ivory}</value>
  </trigger>


As you might imagine, this script creates scores of variables, and I thought it might all be a great deal neater if I used a database
variable. I've managed a trigger to set the values fairly easily, which looks like this:
Code:
<trigger priority="4360" id="436">
  <pattern>%n~) Spell~:%s([a-z ]) modifies</pattern>
  <value>#addkey AffectsList %1 1
;#show affects recording fired</value>
</trigger>

And I believe I've found a way to check specific keys and recast as necessary, like so:
Code:
<trigger name="ASC" priority="4390" enabled="false" id="439">
  <pattern>~<%n~/%n~(%n~%~)Llohr~(%n~%~)%n~/%n</pattern>
  <value>#if (@AffectsList."combat mind") {c combat} {#show Combat Mind is up~!}
#t- ASC</value>
</trigger>


But I haven't figured out how I can set all the value of every key in a database variable at the same time.
I could fairly easily set the specific keys to 1 manually, but that seems like a lot of wasted keystrokes
when a single command should be able to do it. If anybody has a solution to that, any suggestions to
streamline the script, or sees a problem with what I have so far, I'd be happy to hear them!
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Jun 22, 2012 7:04 am   
 
Well, with some experimentation, I've come up with a (very) sloppy way to do what I want:

Code:
<trigger priority="4370" id="437">
  <pattern>You are affected by~:</pattern>
  <value>$AffectsReset = %list(%expanddb(@AffectsList,",",","),",")
#forall $AffectsReset {#addkey AffectsList %i 1}
#t+ ASC
</trigger>


This does set all of the values in the variable AffectsList to 1, but it also creates new keys, 0 and 1, and gives
them a value of 1. Actually, it sets those 2 keys to 1 over and over, since there are a lot of 0s and 1s in the
string list.

This is because nothing I tried was quite able to strip everything out of the string list except the keys from the
variable referenced. I've searched for some command to return all of the keys from a database variable, or a
command to set all of the values in a database variable simultaneously (without having to specify each individual
key) but have not managed to come up with anything. Even the ability--or proper syntax?--to use a wildcard in
place of a key in addkey or some other database modifying variable would make this simpler and cleaner.

So, I welcome any insights that will improve this script. Also welcome is any assurance that I'm not bound for
scripter's hell for writing something so very ugly.

After messing with syntax here for a while, trying to come up with something that would work, my "AffectsList"
variable suddenly took on the value held by $affectcheck (i.e. all of the spell names, with a 0 or 1 between each
and a few extra at the beginning, displayed as a valueless string list but still called a database). I'm going to
lean toward package corruption, as it's been nearly 24 hours since I exported and imported this session.
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Jun 22, 2012 7:04 am   
 
Well, as long as I'm going on and on about this, I'd like to pose a related question.

I've created an alias:
Code:
<alias name="check" id="442">
  <value>#pr ./Affects/AffectsCheck.%-1 "What action would you like to take if this affect is missing?"</value>
</alias>


And changed the trigger on my prompt to:
Code:
#loopdb @AffectsList {%if(%iskey(@AffectsCheck,%key),%if(%val=1,@AffectsCheck.%key))}


Which checks each key in AffectsList to see if it is both non-zero and has a matching key in AffectsCheck. If
both of those conditions are met, it sends the value of that key in AffectsCheck.

So I can type in "Check heighten senses" and when the dialog box prompts me to enter a value, I enter in
"heighten". Then, if "heighten senses" doesn't appear in my affects list, "heighten" is sent, effectively recasting
the spell.

This works, the problem is, I'm getting a blank line for every value in "AffectsList." So I see this:
Code:
You are affected by:
 1) Spell: renewal of the gladiator modifies ac              by -50 for 20 hours.
 2) Spell: renewal of the gladiator modifies hitroll         by  15 for 20 hours.
 3) Spell: renewal of the gladiator modifies damroll         by  15 for 20 hours.
 4) Spell:     strength of superman modifies strength        by  25 for 20 hours.
 5) Spell:     strength of superman modifies damroll         by  50 for 20 hours.
 6) Spell:          song of freedom modifies none            by   0 for 20 hours.
 7) Spell: restoration of zandramas modifies none            by   0 for 20 hours.
 8) Spell:             arcane focus modifies focus           by 250 for 20 hours.
 9) Spell:              weed shield modifies ac              by -20 for 50 hours.
10) Spell:                  crusade modifies damroll         by   6 for 30 hours.
11) Spell:              combat mind modifies ac              by -38   permanently.
12) Spell:              combat mind modifies hitroll         by  12   permanently.
13) Spell:                    haste modifies none            by   0 for 15 hours.
14) Spell:                 barkskin modifies ac              by -20 for 75 hours.
15) Spell:                pass door modifies none            by   0 for 40 hours.
16) Spell:                    armor modifies ac              by -20 for 50 hours.
17) Spell:        immortal blessing modifies mana            by 1000 for 50 hours.
18) Spell:        immortal blessing modifies hp              by 1000 for 50 hours.
19) Spell:          heighten senses modifies none            by   0   permanently.
20) Spell:          heighten senses modifies none            by   0   permanently.
21) Spell:          heighten senses modifies none            by   0   permanently.
22) Spell:          heighten senses modifies none            by   0   permanently.
23) Spell:                      fly modifies none            by   0   permanently.
24) Spell:                    invis modifies none            by   0   permanently.
25) Spell:               star drain modifies mana            by 4959 for 214 hours.
26) Spell:               star drain modifies hp              by -1983 for 214 hours.
27) Spell:                swiftness modifies hitroll         by  10 for 8 hours.
28) Spell:                swiftness modifies ac              by -25 for 8 hours.
29) Spell:           wall of thorns modifies none            by   0 for 8 hours.
30) Spell:                 divinity modifies saving-spell    by -16 for 108 hours.
31) Spell:                 divinity modifies hitroll         by  16 for 108 hours.
32) Spell:                   shield modifies ac              by -20 for 8 hours.
33) Spell:           giant strength modifies strength        by   4 for 8 hours.
34) Spell:                    bless modifies saving-spell    by -12 for 8 hours.
35) Spell:                    bless modifies hitroll         by  12 for 8 hours.
36) Spell:        enhanced strength modifies strength        by   4   permanently.
37) Spell:           mental barrier modifies ac              by -20   permanently.
38) Spell:           thought shield modifies ac              by -20   permanently.
39) Spell:              flesh armor modifies ac              by -20   permanently.
40) Spell:             detect bless modifies none            by   0   permanently.
41) Spell:        song of traveling modifies none            by   0   permanently.
42) Spell:            magic shelter modifies saving-spell    by -300   permanently.
43) Spell:              detect evil modifies none            by   0   permanently.
44) Spell:              detect good modifies none            by   0   permanently.
45) Spell:               stone skin modifies ac              by -40   permanently.
46) Spell:              biofeedback modifies none            by   0   permanently.
47) Spell:       energy containment modifies saving-spell    by -20   permanently.
48) Spell:               minstrelsy modifies hp              by 400   permanently.
49) Spell:               minstrelsy modifies mana            by 400   permanently.
50) Spell:             displacement modifies ac              by -46   permanently.
51) Spell:          story of safety modifies ac              by -20   permanently.

<17832/17832(100%)Llohr(100%)24253/24253 DR/HR: 467/640 AC: -2543 Gold:433,336> 









































<17832/17832(100%)Llohr(100%)24253/24253 DR/HR: 467/640 AC: -2543 Gold:433,336>


I can remove the blank lines with gagspace, but what can I do to prevent the sending of blank lines
entirely? Also, if I want to remove and rewear a piece of equipment, I can set the value of the corresponding
key to "remove eq;wear eq" but I can't make it parse the semicolon, it sends that exactly, but I have
to hit enter for the second part, "wear eq", to actually take effect. Is there any way around that short
of making a separate trigger? Is there any way to make the value being sent to the mud in this manner
function as an alias, assuming such an alias exists?
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Fri Jun 22, 2012 1:01 pm   
 
[edited]On your first question, you were looking for the %dbkeys() function. You may also want to know the %dbvalues() function for the future. And the best way to do the loop is with #LOOPDB
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Fri Jun 22, 2012 1:11 pm   
 
The problem in your AffectsCheck script is that you are trying to execute %if() as a command. You can't start a command statement with a function or a variable (basically, anything that starts with % or @).

This code
Code:
#loopdb @AffectsList {%if(%iskey(@AffectsCheck,%key),%if(%val=1,@AffectsCheck.%key))}

should look more like
Code:
#loopdb @AffectsList {#IF (%iskey(@AffectsCheck,%key) AND %val=1) {#SOMECOMMAND @AffectsCheck.%key}}

What exactly do you want to do with the @AffectsCheck value?
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Jun 22, 2012 5:38 pm   
 
So using
Code:
$AffectsReset = %list(%dbkeys(@AffectsList))
#forall $AffectsReset {#addkey ./Affects/AffectsList %i 1}

is the most efficient way to reset all the keys in a variable to the same thing?

I guess I wasn't that far off then, which surprises me greatly, using %dbkeys
is certainly much cleaner than the code I'd mangled into place.

Or did you mean that I should use #loopdb to accomplish that somehow?
I really wanted to, but it seemed like most of the functions that deal with
db variables simply return keys or values, rather than changing them. I
assume that if I tried some form of #loopdb @AffectsList (%dbkeys/etc
I wouldn't get where I wanted to go.

I have not fully grasped the function vs command difference yet, as may be
obvious from my use of %if, I am quite surprised that it worked perfectly
considering that I'd done it wrong.

As to your question, I want to send the value of @AffectsCheck.%key to the mud,
it works as I had it, but I wondered if some other method would be more condign.

The @AffectsCheck variable contains all of the spells that I want to check my--
mud generated--affects list for, and the key of each value contains the action to
take if a particular spell or affect is missing from that list, the problem I am
having is that I haven't figured out a way to take multiple actions if necessary.

Say, instance, I have a key in AffectsCheck called "stone skin." The action I want
to take if that key in AffectsList = 1 is "remove neutron;wear neutron." I can set
the value of that key to "remove neutron;wear neutron," but it only executes the
first action, the mud requires another carriage return before the "wear neutron"
is processed. I can change the value if true to "#send @AffectsCheck.%key" but
that works exactly the same. I have on occasion wished for some way to get the
value of a variable to parse as an alias, but I haven't had any luck with that yet.
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Fri Jun 22, 2012 6:24 pm   
 
No...%dbkeys() already produces a stringlist so you don't even need %list. Instead of:
Code:

$AffectsReset = %list(%dbkeys(@AffectsList))
#forall $AffectsReset {#addkey ./Affects/AffectsList %i 1}

do this:
Code:
#forall %dbkeys(@AffectsList) {#addkey ./Affects/AffectsList %i 1}

Or, to do it with #LOOPDB:
Code:
#LOOPDB @AffectsList {#addkey ./Affects/AffectsList %key 1}


The reason your %if() worked is because it worked that way in Zmud, and Zugg mostly left that working just for backwards compatibility. But it does not always work, and it is not guaranteed to continue working in future releases of Cmud. A function is designed to return a value which can be used within some other command statement. Yes, the proper way to send the value of @AffectsCheck.%key to the mud is with the #SEND command. Simply putting the variable and expecting it to send a command to the mud may or may not work in every instance, and is a deprecated Zmud practice.

If the value of the key is "remove neutron;wear neutron", #SEND {@AffectsCheck.%key} should properly parse the key and send it to the mud as two commands.
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Jun 22, 2012 7:04 pm   
 
I'd have sworn I tried that #loopdb method exactly, without success, but I imagine I simply mangled the syntax.
The #SEND {@AffectsCheck.%key} is still sending the single line "remove neutron;wear neutron" which requires
a carriage return to complete. Also tried #send (AffectsCheck.%key) mostly out of curiosity, it behaved exactly
the same.

Script XML so far:
Code:
<class name="Affects" id="435">
  <trigger priority="4360" id="436">
    <pattern>%n~) Spell~:%s([a-z ]) modifies</pattern>
    <value>#addkey ./Affects/AffectsList %1 0
</value>
  </trigger>
  <trigger priority="4370" id="437">
    <pattern>You are affected by~:</pattern>
    <value>#forall %dbkeys(@AffectsList) {#addkey ./Affects/AffectsList %i 1}
#t+ afreset</value>
  </trigger>
  <trigger name="afreset" priority="4390" enabled="false" id="439">
    <pattern>~<%n~/%n~(%n~%~)Llohr~(%n~%~)%n~/%n</pattern>
    <value>#loopdb @AffectsList {#if (%iskey(AffectsCheck,%key) AND %val=1) {#SEND {@AffectsCheck.%key}}}
#t- afreset</value>
  </trigger>
  <alias name="check" id="442">
    <value>#pr ./Affects/AffectsCheck.%-1 "What action would you like to take if this affect is missing?"</value>
  </alias>
  <var name="AffectsList" type="Record" sorted="1" id="449">
    <value>arcane focus=1|armor=1|barkskin=0|biofeedback=0|bless=0|combat mind=0|crusade=1|detect bless=0|detect evil=0|detect good=0|displacement=0|divinity=0|energy containment=0|enhanced strength=0|flesh armor=0|fly=0|giant strength=0|haste=1|heighten senses=0|immortal blessing=1|invis=1|magic shelter=0|mental barrier=0|minstrelsy=0|pass door=1|renewal of the gladiator=1|restoration of zandramas=1|shadow form=0|shield=0|sneak=0|song of freedom=1|song of traveling=0|star drain=1|stone skin=1|story of safety=0|strength of superman=1|swiftness=0|thought shield=0|wall of thorns=0|weed shield=1</value>
    <json>{"arcane focus":1,"armor":1,"barkskin":0,"biofeedback":0,"bless":0,"combat mind":0,"crusade":1,"detect bless":0,"detect evil":0,"detect good":0,"displacement":0,"divinity":0,"energy containment":0,"enhanced strength":0,"flesh armor":0,"fly":0,"giant strength":0,"haste":1,"heighten senses":0,"immortal blessing":1,"invis":1,"magic shelter":0,"mental barrier":0,"minstrelsy":0,"pass door":1,"renewal of the gladiator":1,"restoration of zandramas":1,"shadow form":0,"shield":0,"sneak":0,"song of freedom":1,"song of traveling":0,"star drain":1,"stone skin":1,"story of safety":0,"strength of superman":1,"swiftness":0,"thought shield":0,"wall of thorns":0,"weed shield":1}</json>
  </var>
  <var name="AffectsCheck" type="Record" id="450">
    <value>combat mind=c combat|heighten senses=heighten|mental barrier=c mental|shadow form=sform|sneak=sneak|stone skin=remove neutron ; wear neutron</value>
    <json>{"stone skin":"remove neutron;wear neutron","mental barrier":"c mental","shadow form":"sform","sneak":"sneak","heighten senses":"heighten","combat mind":"c combat"}</json>
  </var>
</class>



I suppose I could just add
Code:
 #if (@AffectsList."stone skin") {remove neutron;wear neutron}
to my prompt trigger, but I'm attempting to put together a very user-friendly package that doesn't require manual trigger editing by people who don't know much about triggers.

I also forgot to mention that changing the incorrect %if to #if got rid of the extra blank lines being sent. Huge thanks for all the help!
Reply with quote
Daern
Sorcerer


Joined: 15 Apr 2011
Posts: 809

PostPosted: Fri Jun 22, 2012 7:39 pm   
 
#SEND just sends the text directly to the mud. If you want the semi-colons to be parsed you need to use #EXECUTE.
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Jun 22, 2012 8:37 pm   
 
Awesome, that works perfectly. Thank you both!
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD 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