Stat Roller

Posted by Agent_702 on Sun 11 Nov 2001 04:26 PM — 27 posts, 110,156 views.

#0
Hello. I have been trying to go about makeing a stat roller with mushclient to be used on the mud i play. BUt i can't even think about how to go start doing so. I guess that coding a stat roller would require me to know a scripting language? well i'm in luck because i'm not exactly an expert in VB but i'm definetly an advanced VB programmer. Any idea's how to start? How the whole thing should look? If you need more info just let me know and i'll give you everything that you need.

Thanks

Chris
USA #1
Emm.. What do you mean a "Stat Roller"

Is this something so you can just roll up stats? .. Because on a MUD usually the server itself rolls your stats.. And if they have a reroll system like mine does.. It usually just rerolls it for you..

In otherwords.. Why make a reroller.. When you won't be able to use it at all.. Erm.. Correct me if I'm wrong of course..

If you are a coder for the MUD and are trying to make a reroll system for the server itself.. Remember that there are ones already made for people like you and me who have little experience with actual coding.. In my case C++ .. That way you can add the reroll only by following instructions.. If the stat roller is only for your amusement.. Then I would say go for it.. But I have no idea where to get started..
Australia Forum Administrator #2

I presume you want to react automatically to the stats offered when you create a new character? To do this I would make a trigger that matches on the appropriate line (post an example from your mud, to make it easier to describe it exactly).

The trigger would call a script routine that (using wildcards for each stat) would decide whether or not to accept the roll and reply accordingly (using the script routine world.send).

Here is an example to get you started ...

Taking the character generation from the Dawn Of Time server as an example:


Rerolling please wait.
-====================== CHARACTER ATTRIBUTES SELECTION ======================-
            Strength (ST): 30( 77)   Constitution   (CO): 33( 53)
            Quickness(QU): 40( 40)   Agility        (AG): 52( 52)
            Presence (PR): 24( 84)   Self-Discipline(SD): 29( 39)
            Empathy  (EM): 20( 68)   Memory         (ME): 40( 40)
            Intuition(IN): 26( 47)   Reasoning      (RE): 29( 39)
            green is starting value, (blue) is potential with training.
Are you happy with these attributes?

You could match on the above with 5 triggers (one for each attribute line), or make a more complex regular expression. Let's make a regular expression because it lets us skip spaces more easily:

  • Trigger (one long line):

    ^\s*(Strength|Quickness|Presence|Empathy|Intuition)\s*\((ST|QU|PR|EM|IN)\):\s*(\d+)\(\s*(\d+)\)\s*(Constitution|Agility|Self-Discipline|Memory|Reasoning)\s*\((CO|AG|SD|ME|RE)\):\s*(\d+)\(\s*(\d+)\)$

  • Enabled: checked
  • Regular expression: checked
  • Label: Stats
  • Script: OnStats

This regular expression might look a little daunting, so let's break it up to explain what each bit does ...

^ Start of line
\s* Zero or more spaces
(Strength|Quickness|Presence|Empathy|Intuition) One of those words (wildcard 1)
\s* Zero or more spaces
\( The "(" character literally
(ST|QU|PR|EM|IN) One of those words (wildcard 2)
\) The ")" character literally
:\s* A colon followed by zero or more spaces
(\d+) One or more digits (0 to 9) (wildcard 3)
\( The "(" character literally
(\d+) One or more digits (0 to 9) (wildcard 4)
\) The ")" character literally
\s* Zero or more spaces
(Constitution|Agility|Self-Discipline|Memory|Reasoning) One of those words (wildcard 5)
\s* Zero or more spaces
\( The "(" character literally
(CO|AG|SD|ME|RE) One of those words (wildcard 6)
\) The ")" character literally
:\s* A colon followed by zero or more spaces
(\d+) One or more digits (0 to 9) (wildcard 7)
\( The "(" character literally
(\d+) One or more digits (0 to 9) (wildcard 8)
\) The ")" character literally
$ End of line

Parts of the regular expression in round brackets are "output" as wildcards, thus the expression above sets up 8 widcards, which we can retrieve in the script.

We add to the script file (this example is in VBscript) the "OnStats" handler:



sub OnStats (strName, strLine, aryWildcards) 

dim stat, start, potential

  ' get first stat (wildcards 2, 3, 4)

  stat = aryWildcards (2)
  start = aryWildcards (3) 
  potential = aryWildcards (4) 

  world.setvariable "stat_" & stat & "_start", start
  world.setvariable "stat_" & stat & "_potential", potential

  ' get second stat (wildcards 6, 7, 8)

  stat = aryWildcards (6)
  start = aryWildcards (7) 
  potential = aryWildcards (8) 

  world.setvariable "stat_" & stat & "_start", start
  world.setvariable "stat_" & stat & "_potential", potential

end sub 

After setting up this wildcard and testing it we can look at the "variables" window in the configuration dialog, to see that various variables have been set up to "remember" the rolls for each attribute.


stat_ag_potential = 52
stat_ag_start = 52
stat_co_potential = 53
stat_co_start = 33
stat_em_potential = 68
stat_em_start = 20
stat_in_potential = 47
stat_in_start = 26
stat_me_potential = 40
stat_me_start = 40
stat_pr_potential = 84
stat_pr_start = 24
stat_qu_potential = 40
stat_qu_start = 40
stat_re_potential = 39
stat_re_start = 29
stat_sd_potential = 39
stat_sd_start = 29
stat_st_potential = 77
stat_st_start = 30

Now what we need to do is reply to the question "Are you happy with these attributes?". The logical thing to do here is make a trigger that matches that line, retrieve each of the stats we saved in the earlier trigger, and make a decision. I don't know your criteria, so I'll do a simple example that tests that each stat exceeds a minimum value. You may want to do something more complex.

  • Trigger: Are you happy with these attributes?
  • Enabled: checked
  • Label: AreYouHappy
  • Script: OnAreYouHappy

Now we make the script "OnAreYouHappy" that makes the decision:



sub OnAreYouHappy  (strName, strLine, aryWildcards) 

dim ST, CO, QU, AG, PR, SD, EMP, MEM, INT, RE

  ST = cint (world.getvariable ("stat_st_start"))
  CO = cint (world.getvariable ("stat_co_start"))
  QU = cint (world.getvariable ("stat_qu_start"))
  AG = cint (world.getvariable ("stat_ag_start"))
  PR = cint (world.getvariable ("stat_pr_start"))
  SD = cint (world.getvariable ("stat_sd_start"))
  EMP = cint (world.getvariable ("stat_em_start"))
  MEM = cint (world.getvariable ("stat_me_start"))
  INT = cint (world.getvariable ("stat_in_start"))
  RE = cint (world.getvariable ("stat_re_start"))

' see if we accept these stats

  if ST > 30 and _
     CO > 50 and _
     QU > 25 and _
     AG > 40 and _
     PR > 30 and _
     SD > 22 and _
     EMP > 33 and _
     MEM > 47 and _
     INT > 21 and _
     RE > 13 then
    world.send "yes"
  else
    world.send "no"
  end if

end sub

Notice that this script sends "yes" or "no" to the world depending on the decision about each stat.

I hope this helps.

Australia Forum Administrator #3
By the way, be careful that you don't set your sights too high with the stats reroller, or you may "spam" the MUD with thousands of requests for new stats in quick succession.

If that looks like it is happening you may have to go to the Connection menu and click on "Disconnect".
#4
HOLY CRAP THATS EXACTLY WHAT I NEEDED!!! lol and you know whats even funnier i play on BloodMoon and Darkening Sun which they both use the old DoT codebase. AHHH DoT, how i miss those days of mudding. lol. I'll try out what you suggest and thank you again.

Chris G
#5
OK i've just tried making the stat roller to what you suggested. but it only works for 1 stat. I set it to try and roll a character above 70 strength and 70 constitution but it didn't work. it just keeps saying no and passed by 3 perfectly good rolls. WHat i then did was made it so that everything would have to be above 10 except for strength which had to be above 70 and it worked. I wonder why it doesn't work when i put strength and constitution above 70? i basically took your code and nothing more it seemed perfectly sound so i made no modifications to it. ANY ideas are welcome and thanks again so much for your help.

chris g
Australia Forum Administrator #6
I tried myself using DOT and looking for ST > 70 and CO > 70 but it kicked me off before it got a match.

You realise the way I have written it it matches on the *starting* value, not the potential with training.

The highest starting strength I got was 60, and the highest constitution was 59. Also, when I got 59 for constitution the strength was only 50.

You may be aiming too high. If you want to match on the *potential* for an attribute you need to change the line:


ST = cint (world.getvariable ("stat_st_start"))


to


ST = cint (world.getvariable ("stat_st_potential"))

and the rest in a similar way.
#7
Hmmm anyone came out with e multiline stats roller?
Cos I have no exp in programming and i do not know what is for wat...
So someone who have please mail me at lunloon@hotmail.com
#8
Hello...I'm going to read the rest of the forums first...or I guess I'm not...hehe...If there is any possible way to include within the parameters of Alias and Trigger a way to setvariable like tintin uses...that would make scripting unncessary for 90% of MUSHclient users...or at least I feel I'm an average client user and that I can make anything work just using triggers aliases and variables but I need to have easy access to my variables...for example on this statrolling script wouldn't it have been easier to include in the trigger a setvariable command for each of those stat values and then have another alias which analysed them? I may just be too old fashioned but I think that would be easier for most users than having to learn all the scripting syntax to make use of variables
Australia Forum Administrator #9
You can retrieve variables by using the @variable syntax inside a trigger or alias, however having a trigger syntax set a variable I think is probably just as confusing as using a short script.

You can already use a trigger to set a single variable without scripting, and once you want to set more than one it is just as easy in a script, and I think more readable. eg.


sub myTrigger (line, output, wildcards)

  world.setvariable "var_a", wildcards (1)
  world.setvariable "var_b", wildcards (2)
 
end sub
#10
Hello...It's me Variable boy again...okay I was almost able to do what I wanted to do using triggers to set my variables with one problem...I can only have one trigger per variable...this is problematic...because It doesn't allow me to switch my variables back and forth...unless there is a way to change the value of a variable from an alias I think I'm going to have to break down and try to script...

I saw some posts about variables within a script being different from the world variables that the triggers can access?...is that correct?

Maybe you guys can help me figure out how to do what I want to do...once this first problem is taken care of my style of alias/trigger/variable usage all revolves around doing this so this one problem will solve all the rest of them...

Here is what I want from a trigger/alias/variable system for backstabbing...

My alias is...

b *

which should

1) backstab %1
2) SetVariable TARGET %1
3) Turn on backstab Triggers

My triggers trigger on...

"You flee northward!"...etc....

and should respond

s
backstab @TARGET

now I need to have two different flee commands

first flee is regular which allows me to come back in and backstab again

second flee turns off my backstabbing triggers before fleeing so I can escape...

My current system almost works by saying the targets name before I attack it to trigger capture the mob name for variable TARGET. I then can have two other sayings that would set four other variables that replace northward etc. in my triggers with some garbage like zyxyzxyzxyzxy so that it essentially turns off my flee triggers. My problem now is that I can only have one trigger per variable so I can't turn them back on, reset the variables to northward, eastward etc.
USA #11
Shouldn't this be a topic in one of the scripting sections, then, if you want help with scripting?
#12
Hehe...Neva...

My point is...the client should allow me to easily manipulate my variables...Thankyou for your help everyone...I have found another client...I'm not sure if it's as fast as MUSH client but in my new client I can change my variables from aliases like this

b dragon

$var TARGET %1
backstab %1

Quick and easy...the $var command works in triggers also...if I find this new client to be as fast as MUSH client I won't need to come back and learn how to script to make up for an incomplete mud client...I can see scripting for more complex things...but I won't learn to script to control variables...I'm a MUDder not a programmer Jim!
USA #13
Well Nosferat. Being able to do what you want is on the list and the next version 'may' include it. It is quite likely that mushclient will eventually include such, even if not in the very next version. Have some patients. ;)

Oh. And most clients that allow inline variable setting don't use syntax like $var TARGET %1. It also looks to me like an inline 'script', which means like it or not you are a scripter. ;) lol Clients that use such inlined stuff btw, are by definition slower, because they essentially process all aliases through scripting to look for commands, before actually sending any text to the mud.

It probably wouldn't hurt if aliases in mushclient accepted /{command} syntax and processed through the normal command interpreter (or at least the part that handles inline commands), but if it did, to avoid slowing the client, there would likely need to be an 'Process inline scripts' option for them that you could turn on as needed. Otherwise, the result of adding such a thing would slow down all aliased commands. Whether Nick thinks an option to enable such functionality is reasonable though... ;)
USA #14
watch this thread

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=2274&page=999999

and see what Nick replies.. :)
Australia Forum Administrator #15
Quote:

It probably wouldn't hurt if aliases in mushclient accepted /{command} syntax and processed through the normal command interpreter (or at least the part that handles inline commands)


I'm worried about indefinite loops when you do that. eg.

Alias: X
Script: DoX

sub DoX (line, output, wildcards)

world.Interpret "X"

end sub

In this case the player types X which calls a script, the script does the (currently non-existent) Interpret function to pass the command X to the command interpreter, this calls the script, which then does X again, and so on, until the stack runs out.
USA #16
Hmm.. Well that is a potential issue, but this is a programming language we are dealing with and last I checked it was up to the coder to avoid those things. It is no different than someone accidentally creating an infinite loop in a for next statement in a sub. Both will cause a problem. After all, these are all similar issues:

1. a regexp that you forget to escape [ and ] in.
2. loops in scripts that have invalid exit code.
3. Ctrl-Enter treating (at least in one case I know of) the seperate lines not as explicit data to go to the mud, but rather as though you used a command seperator.

Using a world.interpret command 'could' present a problem and I would tend to agree that it would be a bad thing. However, as something that is processed in the 'send' field of the actual alias and can be turned off, safeguards could also be set in place to prevent it calling itself. In theory..

You could even track such inline events so that each alias called got added to a list and if at any point the same alias name came up a dialog would appear to the effect that 'a recursive call was detected and processing of the alias {name here} was terminated.', along with an error window listing the names in the list and thus how the recursion happened. Since such internal calling would be disabled unless explicitly asked for, the overhead for normal aliases and triggers that didn't use the feature should be no more than the execution time of a single 'if then'.

Actually.. The same thing could be done through world.interpret, but unless it checked to see if each command was an alias before placing it in the list, you would have to track every command. However, since the point was to avoid having to duplicate the function of an alias by calling a scipt to handle the command, such a script side method is a bit silly.
Amended on Sun 16 Feb 2003 07:35 PM by Shadowfyr
Australia Forum Administrator #17
Hmmm - and if the thing being interpreted was something that called another script, even something like this?

world.Interpret "/world.note blah"

This would require another instance of the script engine to be created. I'm not saying it couldn't be done, but I think there would be places where you would get unexpected behaviour. Already MUSHclient defers things like executing scripts on an alias or trigger by queing them. I can imagine a case where if there was a world.Interpret function, a week later I would get forum posts showing how things were being executed out of sequence.
USA #18
Hmm. I wasn't aware that internal commands did that. But again, as I said having a command that did that 'in' scripting makes no sense anyway. The only practical use is to directly execute an alias inside another alias or a trigger. If you are coding scripting anyway, then it is quite silly to not just use the commands you need directly. It is much easier to do 'world.note blah' than 'world.interpret "/world.note blah"'. Imho anyone dumb enough to try such deserves bugs. ;) lol

The only case anyone is really worried about is like:

alias: at *
send: attack %1

alias: fl *
send: flag %1
/setvariable "Mob", %1
at %1

The idea being to avoid what would require using a script, but frankly shouldn't. Some people think it is a bit nuts to 'require' scripting or multiple aliases/triggers just to set more than one variable as and example, or just to set one in the first place. This is the only instance where it is an issue.

Though.. Didn't you add direct setting using variable names of some sort into the actual trigger text? I seem to remember that you did or where going to, but if so then it certainly isn't in the normal help file ;) and I don't remember seeing it anyplace else in examples. If it does exist it is definitely an undocumented feature. lol
Australia Forum Administrator #19
The ability to set variables directly from an alias is something that is planned for the next version, I think Demonsurfer is hanging out for that one. :)

I think I considered doing what you said, but gave up because of the complexity and possible bugs.

I am looking into setting variables directly from an alias in the next day or so.
USA #20
Quote:
I think Demonsurfer is hanging out for that one. :)

hehe yup :)

..oh, and a new field for variable name instead of using label so 2 triggers/aliases can send to the same variable without having to add a script for one of them. :)
Amended on Tue 18 Feb 2003 10:29 PM by Guest1
USA #21
just a thought.. I guess you'll need to make the label the default (for send to variable) if the new variable field is blank, to allow for existing people's scripts..
Australia Forum Administrator #22
I think the simple solution would be to have another option:

"send to variable" where you then specify the variable name, as backwards compatibility is important.
USA #23
that works too :)

how's it going?

--------

*sniff sniff* vers 3.33 far away?
Amended on Sun 02 Mar 2003 12:17 AM by Guest1
#24
Hi, I have something much more simpler but I don't fully understand everything above, or have something quite different:


Strength: 14 (Hardy)
Dexterity: 14 (Nimble)
Constitution: 12 (Average)
Intelligence: 14 (Smart)
Wisdom: 15 (Thoughtful)
Charisma: 13 (Pretty)
Luck: 14 (Lucky)

I am experiencing this error message:
============================
There was a problem in script file "G:\Vault\Documents\Misc\OnStats.vbs":
==========================

Here is what I have come up with:

Trigger:
===============================================
^\s*(Strength|Dexterity|Constitution|Intelligence|Wisdom|Charisma|Luck)\s*(\d+) * $
===============================================

===============================================
Keep? (Y/N)
===============================================

OnStats:
===============================================
sub OnStats (strName, strLine, aryWildcards)

dim stat, start

' get stat (wildcards 1, 2)

stat = aryWildcards (1)
start = aryWildcards (2)

world.setvariable "stat_" & stat, start

end sub
==============================================

Thanks.
Amended on Fri 06 Jun 2003 09:50 PM by Ntmsz
USA #25
I really really need a stat roller for realms of kaos, if anyone could possibly help me out I would appreciate it tons!!!! My email is just_a_chic@hotmail.com and I have msn. Thank you a lot.

(edited to remove all caps)
Amended on Sun 12 Dec 2004 09:52 PM by Nick Gammon
USA #26
Ahem. You're in the wrong place, RoK isn't even a MUD, it has nothing to do with MUSHclient.