Fun With Variables

Contents:

Learning how to use variables properly can be a really effective way to get your mobs to do almost anything that you want them to do. With variables, I have been able to create insanely detailed mobprogs, such as mobs that play blackjack and roulette. Variables are the key to mob intelligence, and this section of the tutorial is designed to show you how to use them.

Setting the Variable

The mobprog command mpsetvar creates variables and stores values into them. The mpsetvar command can set integers, strings, and expanded character variables like var-actor as the values of a variable. The variable name can be anything you want, but should probably be ten characters or less for simplicity’s sake. The target of mpsetvar is normally the mob using it, but it can be used to set the variable for another mob. Here are a few examples of variables being set:

mpsetvar me myvictim var-actor

(Variable myvictim is given the value held in var-actor, or \$n)

mpsetvar me myfriendguardthree

(Variable myfriend is given the value guardthree)

mpsetvar me counter 1

(Variable counter is given the value 1)

mpsetvar me counter \$(+(var-counter,1))

(Variable counter is given the value of the previous value of counter + 1)

mpsetvar me dice number(1,6)

(Variable dice is given a random value from 1 to 6)

mpsetvar me goldcount goldamt(\$n)

(Variable goldcount is given the value of the gold on hand of \$n)

mpsetvar me questobj var-object

(Variable questobj is given the value held in var-object or \$o)

mpsetvar me myweapon “axe”

(Variable myweapon is given the value axe)

mpsetvar me average \$(/(+(var-diceone,var-dicetwo),2))

(Variable average is given the value of (diceone + dicetwo) / 2)

mpsetvar me fincount var-average

(Variable fincount is given the value of variable average)

mpsetvar xxxgoblinonexxx hunting var-actor

(Variable hunting of mob xxxgoblinonexxx is set to actor)

mpsetvar xxxgoblintwoxxx value 1

(Variable value of mob xxxgoblintwoxxx is set to 1)

mpsetvar xxxgoblinonexxx  greenvar var-bluevar

(Variable greenvar of mob xxxgoblinonexxx is set to value of variable bluevar)

mpsetvar xxxgoblintwoxxx guarding “orc

(Variable guarding of mob xxxgoblintwoxxx is set to “orc”)

Note that different kinds of values set by the mpsetvar command have different ways of being set. Here are the general rules of mpsetvar values:

Integer            mpsetvar [target] variable integer

- Ex: mpsetvar me varone 1

String              mpsetvar [target] variable “string”

- Ex: mpsetvar me varone “cow”

Character       mpsetvar [target] variable var-character

- Ex: mpsetvar me varone var-actor

Variable         mpsetvar [target] variable var-variable

- Ex: mpsetvar me varone var-counter

mpsetvar [target] variable \$[variable]

- Ex: mpsetvar me varone \$[vartwo]

Arithmetical    mpsetvar [target] variable \$(functions)

- Ex: mpsetvar me varone \$(-(var-varone,1))

Function         mpsetvar [target] variable function

- Ex: mpsetvar me varone number(1,3)

There is another way to set variables, and that is using the := command. Under most circumstances the := command works just as easily as mpsetvar. The target for the variable setting when using := is always the mob setting the variable. The := syntax is a useful shortcut, but more advanced variable setting will may require mpsetvar. Also, it is usually necessary currently to use the mpsetvar syntax when dealing with character variables (such as \$n, var-actor, variables set to character variable values, etc.). Here are the syntaxes for using := to set variables:

Integer            \$[variable] := integer

- Ex: \$[varone] := 1

String              \$[variable] := “string”

- Ex: \$[varone] := “cow”

Variable         \$[variable] := var-variable

- Ex: \$[varone] := var-counter

\$[variable] := \$[variable]

- Ex: \$[varone] := \$[var-two]

Arithmetical    \$[variable] := \$(functions)

- Ex: \$[varone] := \$(-(var-varone,1))

Function         \$[variable] := function

- Ex: \$[varone] := number(1,3)

You can also have a mob set a variable from the variable of another mob, but only if it is an integer. To do this you make use of the var function. The syntax for doing this is:  mpsetvar variable \$(var(variable”,\$n))  This assuming that \$n is a mob that has triggered the current mob. For instance you could have a mob poke another mob, triggering the second mob to use the first mobs variable. This unfortunately only works on integers, so its use is somewhat limited. Luckily, there are better ways to do this.

The mpsetvar command can be used to set the variables of a different mob than the one using the command. The mob having variables set on it must be in the same room as the mob doing it, or affected using the mpat command. Setting the variables of another mob is pretty much the same as having a mob set its own variables. Using this ability can create truly interesting mobprogs, but what if you want to set the variables of several mobs?

Shared Variables

Using shared variables is a way to create variables that can be accessed by mobs in the same zone, or even by mobs of the same vnum. The syntax for creating shared variables is simple enough, using the @ and : characters:

\$[@SharedWithMobsInSameZone] := 1

This will create or set a variable equal to a value or string that will be shared by all mobs in the zone – so all mobs within the vnum range of the zone the mob is in (for instance zone 99). This means any mob in the zone can access the variable as if it was their own, using it for checks and comparisons, or setting it again with a new value.

\$[:SharedWithSameMobVnum] := 1

This will create or set a variable equal to a value or string that will be shared by all mobs with the same vnum. So if this variable is first set by a mob with a vnum of 9901, all mobs with that vnum will be able to access the variable as if it was their own variable.

Shared variables have a wide variety of uses, and help mobs communicate information with each other. You could use shared variables to set up zone-wide events and quests, or let large numbers of mobs know who to go after. The possibilities are quite impressive.

Stored Variables

Stored variables can make for some interesting opportunities for zone builders. Stored variables are retained from uptime to uptime, so they are never erased by crashes or reboots. These variables are continuous. The syntax for creating and accessing stored variables is to use the ^ character like so:

\$[^StoredVariable] := 1

This will create or set a stored variable that will be saved for… well, forever theoretically. Of course, the variable could be modified in the future by the same mob or another one if you’d like. In fact you can combine stored variables to also be shared variables:

\$[@^SharedAndStoredVariable] := “I am a variable both saved AND shared by mobs in the same zone”

\$[:^SharedAndStoredVariable] := “I am a variable both saved AND shared by mobs of the same vnum

Stored variables open up a lot of options for a zone builder. You can create a ‘high score’ sort of system and keep track of things, create a zone that retains all of its information from reboot to reboot, and more.

Comparing Variables

Comparing variables is fairly straight forward. You can use any of the operators listed in the Mobprog Functions section of this tutorial. For variables that store a numeric value, you would use the numeric operators (==, =, !=, >, <, >=, <=). See the following examples:

if >(var-counter,3)   - OR -   if >(\$[counter],3)

(Is variable counter greater than three?)

if <=(var-plrtotal,var-dlrtotal)   - OR -   if <=(\$[plrtotal],\$[dlrtotal])

(Is variable plrtotal less than or equal to variable dlrtotal?)

if =(var-randcheck,1)   - OR -   if =(\$[randcheck],1)

(Is variable randcheck equal to 1?)

if != (var-monkey,(+(var-banana,1)))   - OR -   if !=(\$[monkey],+(\$[banana],1))

(Is variable monkey not equal to variable banana + 1?)

if <(goldamt(\$n),var-infocost))   - OR -   if <(goldamt(\$n),\$[infocost])

(Is the amount of gold \$n has on hand less than variable infocost?)

if >=(var-strtest,stat(\$n,”str”))   - OR -   if >=(\$[strtest],stat(\$n,”str”))

(Is variable strtest greater than or equal to \$n’s strength stat?)

Note again the use of var- in our expansion of variables values, as well is the use of the \$[ ] syntax. As you can see, this sort of variable comparison is not very difficult. The key is only getting the syntax down correctly. For string and character variable comparisons of variables, you can use the string operators found in the Mobprog Functions section of this tutorial (==, =, !=, /, !/). You cannot use the \$[ ] syntax when dealing with character variables, similar to setting variables of type character variable. See the following examples:

if =(var-talkingto,var-actor)

(Is variable talkingto the same person as the actor triggering me?)

if !=(var-myvictim,var-myfriend)

(Is variable myvictim not the same as variable myfriend?)

if  =(var-myweapon,”axe”)   - OR – if =(\$[myweapon],”axe”)

(Is variable myweapon the same as the string axe?)

if /(var-barnyard,”cow”)

(Is the string cow contained in whole or part in variable barnyard?)

if !/(var-1337list,var-tempplayer)

(Is the string contained in the variable tempplayer NOT in the string contained in the variable 1337list?)

One thing to keep in mind. You cannot compare different types of variable values, so for example, you cannot compare a variable that has been stored with var-actor or any other character variable to a string. So you could not store var-actor in a variable called myvictim, and then later have an if check to see if myvictim was the same as “guard.” They are different – myvictim is a character/mobile and “guard” is a string. Thus the only time you can compare a string to a variable is if the variable has been set with a string itself. You can, however, do some things to make variables the same so they can be compared:

mpsetvar me temp var-actor

mpsetvar me tempplayer “\$n”

if /(var-liststring,var-tempplayer)

mpecho Hurray!

else

mpecho Boo!

endif

The above will take the character variable var-actor stored in the variable temp, and set a variable tempplayer equal to the string of what is contained in temp. For instance, if var-actor was equal to the player Bobzilla, then in the end the variable temp would be set to a string “Bobzilla” and then can be compared to other strings. In this way you can sort of take a character variable and turn it into a string. You can use the “ “ marks in the same way to change an integer into a string, and you can use the atoi function (detailed in the Mobprog Functions page) to turn a string into an integer if applicable:

mpsetvar me tempnumber 777

mpsetvar me tempstring “temp”

mpsetvar me miscstring “12345”

mpsetvar me miscnumber atoi(var-temp)

mpsetvar me killthischaracter var-actor

mpsetvar me killthisstring “\$n”

The above would produce the following variable values:

\$[ tempnumber] = 777, type integer

\$[ tempstring] = "777", type string

\$[ miscstring] = "12345", type string
\$[ miscnumber] = 12345, type integer

\$[ killthischaracter] = Bobzilla, type character

\$[ killthisstring] = “Bobzilla”, type string

Deleting Variables

You can completely delete a variable if you need to do so. This is something good to keep in mind if you are going to be storing a lot of variables and want to eliminate some of them should the amount become too cumbersome and you no longer need them. To do this, simply exercise the –delete option on the mpsetvar command. Here are some examples:

mpsetvar me –delete myvictim

mpsetvar me –delete @^thekiller

mpsetvar xxxdogxxx –delete bone

mpsetvar xxxcatxxx –delete \$[var_mouse]

Variables and Mobprog Functions

You can use variables in mobprog functions aside from comparison with operators as well. However, in order to do this, the type of value stored in the variable must be the same as the kind used in the function. For example, the ispc function works with characters, and nothing else. So you could store a character variable like var-actor or var-me into a variable talkingto, and then do a if ispc(var-talkingto). See the usage of each mobprog function to see which ones will work with what type of variable value. Here are a few examples:

if ispc(var-talkingto)

(Is variable talkingto (character var) a player character?)

if =(inroom(var-myvictim),inroom(\$i))

(Is variable myvictim (character var) in the same room is me?)

if >((isaffected(var-myfriend,11)),0)

(Is variable myfriend (character var) affected by poison?)

if =(name(var-talkingto),”guard”)

(Is the name of variable (character var) talking to guard?)

if !=(objtype(var-myweapon),5)

(Is variable myweapon (object var) a weapon?)

if rand(var-check)

(Is the random chance between 1 and 100 less than variable check (integer var)?)

if vinroom(var-mobvnum)

(Is a mob ov vnum variable mobvnum (integer var) in the room?)

if or(=(class(var-myvictim),3),=(premulticlass(var-myvictim),3))

(Is variable myvictim (character var) a thief either pre or post multiclass?)

Creating Dynamic Variable Names

This is an advanced option to use, so you should be familiar with the concepts already presented here before trying this. It is sometimes necessary to be able to have a variable name itself contain a variable. A good example of this would be to name a variable after a player or their unique ID number so you can keep track of that players progress on a quest, or their high score in a game you have set up in your zone. To do this requires a little tinkering. See the example below:

mpsetvar me tempplrid \$(idnum(\$n))

mpsetvar me tempplayer "\$[tempplrid]"

\$[tempvarone] := strcat("@^myvar_",\$[tempplayer])

\$[tempvartwo] := strcat(strcat("\$[@^",strcat("myvar_",\$[tempplayer])),"]")

mpsetvar me tempvarthree \$[tempvartwo]

mpsetvar me \$[tempvarone] strcat("\$[tempvarthree]","A")

This is a little complex so let’s break down what this does. It first creates a variable named tempplrid that stores the unique ID number of the actor. Then, it sets a variable tempplayer equal to the string version of tempplrid (which starts as a number). It then creates a variable tempvarone and uses the strcat function to bind together “@^myvar_” with the unique ID number string held in tempplayer, resulting in, for example, if the player ID was 999, a variable storing the string “@^myvar_999” in it. Then, a variable named tempvartwo is set to hold a strcat string containing “\$[@^” then “myvar_” then the string version of the unique player ID. Now tempvarthree is set to the value contained in tempvartwo – which happens to be the string “\$[@^myvar_999” in our example.  The final command is the critical one. What this does is set whatever is contained in the variable tempvarone (in this case @^myvar_999) to a string contained in whatever is contained in tempvarthree (in this case also @^myvar_999) and binds the string “A” to it. What’s that mean? It’s taking the variable [@^myvar_999], and setting its contents to whatever was stored before in it, and then adding “A.” Now the variable, whenever it is checked, will show it contains the string “A.” What does A signify? Whatever you want. Perhaps A means the player has completed a quest. Perhaps it means they are free to access a part of your zone limited to individuals have done something special. Whenever the player with ID 999 needs to be referenced, a variable exists for them and contains “A.” So how do we check this?

mpsetvar me tempplrid \$(idnum(\$n))

mpsetvar me tempplayer "\$[tempplrid]"

\$[tempvartwo] := strcat(strcat("\$[@^",strcat("myvar_",\$[tempplayer])),"]")

mpsetvar me tempvar \$[tempvartwo]

if /(\$[tempvar],"A")

mpadd mpecho \$I says, ‘\$n has the string A in \$s variable!'

break

else

endif

endif

This is similar to the above, but instead creates a temporary variable with the same name as the variable that needs to be referenced, then compares that variable with its identical counterpart. In this manner, you can check the contents of the player’s personal variable and take appropriate action from there.

As noted above, this is some complex stuff, so don’t feel too bad if it seems over your head. You can always just copy these examples and alter them to your needs.

Using and Displaying Variables

The next thing you need to know is how to use variables once you have them. Often you will be doing a lot of comparisons with variables, particularly integer variables. You can do other things though as well. You can display variables for players to see, have the mob act upon variables, etc. The way to do this is using \$[   ]. Here are a few examples:

mpadd mpecho \$I says, ‘You know, I’m looking for someone named \$[myfriend].’

mpadd mpecho \$I says, ‘The total is \$[counter].’

Expressing variables in this way works for all types of variables, although obviously your mob will find it hard to backstab an integer or wield an actor. Now you have all the knowledge you need to create truly intelligent mobs.

Putting It All Together

Okay. So now we know how to use variables. Now let’s make a set of progs that use variables well. We are going to make a set of mobprogs that allows a mob to pursue its victim and do random nasty stuff to them. First of all, we’ll need to set the variable. Let’s do this in a greet_prog:

>greet_prog 100~
if isqueued(\$i)

break

else

endif

endif

if isnpc(\$n)

break

else

endif

endif

mpsetvar me myvictim var-actor

mpadd mpecho \$I says, ‘You should not have come here, \$n. Now you will die.’

~

Next, let’s have out mob pursue our fleeing victim:

>act_prog p panics, and attempts to flee.~
if =(var-myvictim,var-actor)

else

endif

endif

~

We will want to make sure that our mob has the hunt skill if we want to do this. We could also add some checks in here. Perhaps only sometimes the mob hunts the pc, and sometimes it summons:

>act_prog p panics, and attempts to flee.~
if !=(var-myvictim,var-actor)

break

else

endif

endif

if rand(50)

else

endif

~

As you can see, having a mob have this option is much more interesting than simply giving the mob the zonehunt bit in the mob file. We can make the mob much more intelligent or varying about the way it handles things. We could also add perhaps a check on the mobs hit points… if the mob is hurt badly, it won’t pursue the fleeing player, but instead will go and hide. At any rate, we will now need to have the mob do something when it does hunt after its victim:

>entry_prog 100~

if =(inroom(var-myvictim),inroom(\$i))

else

endif

endif

~

Or, if we wanted to spice it up a little:

>entry_prog 100~

if !=(inroom(var-myvictim),inroom(\$i))

break

else

endif

endif

mpsetvar me check number(1,5)

if or(=(var-check,1),=(var-check,2))

break

else

endif

endif

if =(var-check,3)

break

else

endif

endif

if =(var-check,4)

break

else

endif

endif

if =(var-check,5)

break

else

endif

endif

~

What we have done here is now made it so when the mob enters the room with its victim, it does one of four things, with the probability of it backstabbing the victim a little higher than the rest.

Now let’s try setting the variable of another mob. A good example of how this can be useful is to make a ‘scout’ mob that sees a character coming, and have another mob that goes after the character. One mob would thus have the following prog:

>greet_prog 100~

if isqueued(\$n)

break

else

endif

endif

if ispc(\$n)

mpsetvar xxxhuntergolemxxx myvictim var-actor

mpadd mpat xxxhuntergolemxxx mpechoat xxxhuntergolemxxx START HUNTING

else

endif

endif

~

This mob basically sets the second mob, xxxhuntergolemxxx, to have a variable myvictim filled with the value of the first mob’s var-actor (the one who set off the greet_prog). The mob then gives a trigger line to the hunter golem, and goes to a private room and purges itself. Now the second mob:

>act_prog p START HUNTING~

~

>entry_prog 100~

if =(inroom(var-myvictim),inroom(\$i))

else

endif

~

>act_prog p panics, and attempts to flee.~
if !=(var-myvictim,var-actor)

break

else

endif

endif

~

The hunting golem will now pursue the poor character stored in myvictim, without ever even having encountered the unsuspecting character previously! Pretty snazzy, eh? Now let’s say you wanted ten hunter golem mobs to start chasing a character. Easily done:

>greet_prog 100~

if isqueued(\$n)

break

else

endif

endif

if ispc(\$n)

mpsetvar me @myvictim var-actor

else

endif

endif

~

Now every hunter golem mob in the zone will have access to the shared variable myvictim and see the START HUNTING message to go after the poor character who stumbled into this mess. Very soon they will all converge on him and give him a thorough beating.

That about does it for variables. They can be fun to use, and will allow you to create incredibly detailed and intelligent mobs if you so choose.