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: Sat Jun 02, 2012 8:27 am   

Variable type difficulties
 
I have been attempting to write a very basic script to keep track of experience gained, xp per hour, and that sort of thing, and coming up against the perennial problem of variable types. I've had a lot of difficulty with this over the years, and usually found a way around it, but this time it just doesn't seem to be happening.

I receive xp gained messages like this: "You receive 5,863 of 11,727 experience points."
I created a trigger to track the experience with this pattern:
You recieve (%n)~,(%n) of (%n)~,(%n) experience points.
And a value of:
#add kills 1
#add pxp %1%2
#add gxp %3%4

Before putting that trigger into service, I created a reset alias in order to create the necessary variables and place them firmly in the desired class.
The value of that alias was essentially this:
#tz
#var pxp {0} {0} {classname}
//personal experience
#var gxp {0} {0} {classname}
//group experience
#var kills {0} {0} {classname}
#var minutes {0} {0} {classname}

Note: I use the full variable syntax rather than varname = value because every other syntax has a habit of sticking copies of my variables in other classes, for the same reason, I also tend to use #math instead of #add or var = @var + x because it allows for the specification of a class name.

Anyhow, execution of that alias created the desired variables and reset the tick timer, but set all variables to "string, expanded" rather than the usual "autotype." I switched types manually to "integer," retested the alias, and found that it reverted them to "string, expanded," repeated that experiment after setting them to autotype with the same result, and then changed the value of the rest alias to:
#tx
#res classname

Upon finding that that method kept the variable types as I set them (most of the time), I turned on the xp message trigger, which worked fine for one kill, then on the second kill it changed one xp variable to autotype, the other to expanded string, and set their values to a concatenation of the xp received from the first kill and that of the second, rather than adding them together.

After that, I decided to try out local variables, and changed the value of the xp trig to:
#add kills 1
$pxpt = %1%2
#add pxp $pxpt
$gxpt = %3%4
#add gxp $gxpt

This had the same effect, simply concatenating the values instead of adding them mathematically.
I tried a few other variations, like:
pxp = @pxp + %1%2
,and
$pxpt = %1%2;pxp = @pxp + $pxpt
,and then I tried taking out the spaces of those formats, before moving on to:
#math pxp {@pxp+%1%2} {classname} and #math pxp {@pxp+$pxpt} {classname}
which, rather than concatenating, literally changed the value of the variable to things like "0+11437+11667," again, no matter what type I set the variable to.

I also tried some other alternatives, like $pxpt = %concat{%1,%2} which didn't parse at all, making me wonder what the point of %concat even is, considering that the example given in the help file can be reproduced without using the command at all. I.e., "#show %concat{00,@var}" shows the same thing as "#show 00@var." But, whatever.


So, further experimentation with #add, #math, and var = syntaxes led me to believe that it wasn't possible without adding extra lines of code. I then started throwing in #call %vartype {varname,1} after every variable was set, and immediately before any #math or #add procedure. This continued the trend of concatenating values and adding in plus signs while switching all variables back to expanded strings, until I finally changed the local variables into normal variables, immediately using %vartype to set them to integers, and then used the "var = @var1 + @var2" syntax. No other combination came anywhere near working.


So I suppose my first question is, "what am I doing wrong?" This script should be ridiculously simple, but my xp trigger ended up looking like this:
#add kills 1
#var pxpc {%1%2} {0} {xpcounter}
#call %vartype(pxpc,1)
#var gxpc {%3%4} {0} {xpcounter}
#call %vartype(gxpc,1)
#call %vartype(pxp,1)
#call %vartype(gxp,1)
pxp = @pxp + @pxpc
gxp = @gxp + @gxpc

While the reset alias looks like this:
#var minutes {0} {0} {xpcounter}
#var pxp {0} {0} {xpcounter}
#call %vartype(pxp,1)
#var gxp {0} {0} {xpcounter}
#call %vartype(gxp,1)
#var kills {0} {0} {xpcounter}
#tz

Note, adding 1 at a time for kills and minutes works just fine. This script should have taken me 3 minutes to write, and it took nearly 2 hours to figure out exactly what syntax would work instead.


My second and third questions are, "Why can't we specify class names with all variable creating or modifying operations?" And, "Why can't we specify a variable type upon creation, or even modification, and expect it not to be changed arbitrarily?" I've been told that my variables "shouldn't" get duplicated into other classes, and that it's likely the result of corruption, or sloppy coding, but I am not sure how I can input "#add varname 1" any less sloppily than that. Some of it seems to be caused by creating classes using the #class classname syntax, which sets them as default, but shouldn't the code check for existing copies of a variable before creating a new one with the #add or = commands? As for corruption issues, I have many times exported and imported character files, and always do so as a first step when I start having issues like the one outlined here. I have also uninstalled, re-downloaded, and reinstalled cmud on a number of occasions to no effect.
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Sat Jun 02, 2012 4:47 pm   
 
First thing: rather than saying "my code was essentially this", give us the actual code (preferably the XML code), enclosed within [code] ... [/code] tags, so that we can see what is actually happening. To see the XML code, click the XML tab at the bottom of the viewer in the Package Editor.

Now, to your problems. The code
Code:
#add pxp %1%2
is going to form a string, not a number. When you concatenate %1 and %2 that way, you are making a string. So that is why your variable keeps turning into a string type, and why the values are concatenated as strings. Similarly, %concat() is a string concatenation, so any result will be a string.

I would avoid both the #MATH and #ADD commands. They are retained for backwards compatibility with Zmud, but there are better ways of doing it in Cmud.

If you are having problems with duplicate variables being created, that is a separate problem; it should not be happening. You may want to have a separate thread about that problem. If you set a default class with the #CLASS command, it will not check for the existence of other variables because it assumes you want them here. Fortunately, we don't have to solve that to fix your other problems. Also, your problems are not corruption, but simply the fact that you are assignign string values to your variables.

Solution 1. I believe that the %n value in a trigger pattern will actually match numbers with commas like "5,863", so you don't need your concatenation at all. Have you tried that?

Solution 2. If that doesn't work, then you need to create your values as numbers rather than strings. This code is one way of doing it (note that this does not use #MATH or #ADD, or the var = value syntax):
Code:

#VAR kills (@kills + 1)
#VAR pxp (@pxp + (%1 * 1000) + %2)
#VAR gxp (@gxp + (%3 * 1000) + %4)
Reply with quote
Daern
Sorcerer


Joined: 15 Apr 2011
Posts: 809

PostPosted: Sat Jun 02, 2012 5:53 pm   
 
Ok, a few things here. First, Rahab is correct, %n matches numbers with commas (also with a plus or minus sign before it, and decimals). Changing your pattern to "^You recieve (%n) of (%n) experience points.$" will match "You receive 5,863 of 11,727 experience points." and %1 and %2 will contain 5863 and 11727 respectively (no commas).

Second, $pxpt = %concat{%1,%2} didn't parse at all because you need parentheses, not braces - the correct syntax would be $pxpt = %concat(%1,%2).

Third, you actually can specify class names with all variable creating or modifying operations. Just use the full path of the variable: //module/class/subclass/variable. There are also a few special characters you can use for relative paths. A single dot represents the current class (i.e. ./varname will find a variable with that name in the current class). Two dots represents the parent class, or the class that the current class is in. These can even be chained - if you want to go two levels up, you could use ../../varname. Finally, a slash represents the root level, the current window or module. If you wanted to reference a variable at the top level in the current module (not in any classes), you could use /varname. If you're familiar with how file paths work in Windows or Linux, this will be common sense.

Keep in mind that if you specify a full path in any of these ways, CMUD will NOT look anywhere else for the variable. If you try to reference a variable that is not found in the specified class but is found somewhere else, the other variable will not be used.
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Sat Jun 02, 2012 6:41 pm   
 
I actually avoided using %n to match numbers with commas because I always found that it made variables into the "string" type with which no math functions can be accomplished. However, I went ahead and attempted that solution, and again it created them as "string, expanded."

Attempting to ignore that, I used the suggested "#var pxp {@pxp + %1}" sytnax, gave me the old "5,192 + 3,139 + 7,103" value for my variable after a few attempted additions. Furthermore, when matching a number with a comma, attempting to force it to be an integer value with "#call %vartype(var,1)" sets the value of the variable to zero, because apparently cmud is incapable of recognizing a number with any number of commas as actually being a number. So much for that.

Also, I am delighted to hear that I can specify a path for variable, how would that look exactly? Do I specify the path wherever I name the variable? As in "#add //module/class/variable 1"? Could I even do:
"//module/class/subclass/variable = @var + @var2"?
or even " //module/class/sub/var = //module/class/sub/var + //module/class/sub/var2"?

The reason I'm asking is because, as far as I know, putting // anywhere in a code block is going to comment out whatever comes after it.
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Sat Jun 02, 2012 7:56 pm   
 
Don't worry about vartype, it's all but meaningless (Zscript is a typeless language). Variables in CMud are stored as string values, with the vartype you see in the variable editor dependant on how you're encapsulating the data being assigned:

"_____" <-- this is a literal string
{_____} <-- this is an expanded string
(_____) <-- this is an evaluated string (yes, a string)
____ <-- this is a raw string (numbers and non-numeric "words", whitespace is not allowed here and reserved keywords can activate)

When you pass the variable to a command or function, the value is also recast to suit the needs of that routine. You can pass the literal string value of "12" to #MATH and it will use it as a number, for example. Similarly, if you pass an integer value of 12 to a routine expecting a string argument, it's going to treat that 12 as a string rather than as a number.

Quote:

Also, I am delighted to hear that I can specify a path for variable, how would that look exactly?


The full version would be //module/class/.../class/varname and can be used anywhere you would use varname (using the same rules, too, so include or exclude the @ as appropriate.) There are some things you can do with @varname that you cannot do with the longer reference yet, mostly revolving around dot-notation.
_________________
EDIT: I didn't like my old signature
Reply with quote
Daern
Sorcerer


Joined: 15 Apr 2011
Posts: 809

PostPosted: Sat Jun 02, 2012 8:05 pm   
 
That's really strange. I'm not sure why you're getting commas there, because %n strips them for me. This is the trigger that I tested it with:
Code:
#trigger (^test (%n)$} {#print %1}

I fired it with "#show test 5,192" (the number in your example) and it printed 5192, with no comma. Can you try the same test? Also, you should be using parentheses for your #var command, instead of braces. Parentheses tell CMUD to evaluate the contents mathematically, braces will use string concatenation.

As for the paths, your first two examples are correct. The last one should be "//module/class/sub/var = @//module/class/sub/var + @//module/class/sub/var2" - you still need the @ symbols for variable references.
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Sun Jun 03, 2012 4:38 pm   
 
You are correct, it did strip the commas, I messed that up.

However, all of that may well be meaningless now, because I had never realized that using parentheses in #var was even possible, let alone necessary to evaluate the contents. It turns out there's a help file associated with "#variable," and one with "#var." The #var help file explains the differences between brackets and parentheses, but the #variable one does not. I suppose I looked at the wrong one :)

It does appear, based on my tests, that the "variable = x" syntax will evaluate mathematically, but only if the variables are type integer. Might that be an exception to the typelessness of CMud? I base this assumption on the syntax that finally worked for me, wherein I only managed to make it work by manually setting the variables to integers and using the equals sign syntax.

Also, I see why I couldn't get the //module/class/subclass/variable syntax to work. I had unchecked that special character because it's used as the recall character in my primary mud. I still had to quote it whenever I used it in a trigger though, so checking that box won't cause any problems.

Thank you all for the help! The different uses of brackets/parentheses in #var will make things a great deal easier for me.
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Mon Jun 04, 2012 3:31 am   
 
Quote:

Might that be an exception to the typelessness of CMud?


It's not. I am betting that your problems resulted from doing something like Var = Var + 1 rather than Var = (Var + 1). I use the latter ALL the time, and unless I'm dealing with a database key as one of the terms it REALLY doesn't matter what datatype the variable is set to.

Keep in mind that there are differences in parsing between @//module/class.../class/var.key and @var.key in various situations that could affect the result of your operation. For example, @//module/class.../class/var.key inside a parenthetic operation (ie, a function, the condition of #IF, mathematical evaluation, etc) results in a syntax error but @var.key or $var.key does not. Similarly, assignment of an explicitly-pathed datarecord key to another variable results in an assignment of string concatenation consisting of the entire value of the datarecord variable plus the .key reference you tried to make while @var.key and local variables don't have that problem. Another good example is the assignment of a stringlist value to a datarecord key field. You can easily do the assignment with no problems, but you can't actually reference the key value as a stringlist.
_________________
EDIT: I didn't like my old signature
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