______________________________________________________________________
FURCADIA VARIABLE DOCUMENTATION - Variables - Their nature and purpose
______________________________________________________________________
TABLE OF CONTENTS
2.1. What are they?
2.2. Why use variables?
2.3. Variables in DragonSpeak.
2.3.1. Use of variables in DragonSpeak.
2.3.2. Related DragonSpeak lines.
2.4. Using variables.
2.4.1. Dynamic sound player (Using variables to play specific sounds).
2.4.2. Dream activity time (Countup timers).
2.4.3. Dream statistics (Player counter and peak).
2.4.4. Dynamic object/floor creation (Using variables to set an object/floor).
2.4.5. Code-based dreamlock (Variables and the entry code).
2.1 WHAT ARE THEY?
Variables were first introduced into DragonSpeak sometime in 2003 to further enhance it with new
features and more dynamics, allowing Furcadia players to make their dreams more interactive
than they were so far. Variables add a wide range of possibilities that were previously
unavailable to the community or required an enormously large amount of DragonSpeak lines to
achieve: the ability to create objects/floors of your choice, for instance - without variables
you would need over 3 DS lines for each object you would like to create! With variables, however,
you can create any available object and put it underneath you by specifying its number - all
that with no more than 5 DragonSpeak lines! Variables also allow timekeeping, dream statistics,
DS execution according to chance (random encounters) and many other things you simply can't do
in any other way.
So what are variables anyway? Those of you that never did any kind of programming are probably
not familiar with the term "variable". Variables are basically containers - they store numbers
inside them and allow the program (or in our case DragonSpeak) to utilize them by either storing
numbers in them upon command, changing them, performing mathematical functions with these numbers
or simply using them with other DragonSpeak lines as arguments instead of static numbers. A
typical example for this would be storing a number you said into a variable and creating an object
represented by that number, placing it under your feet.
2.2 WHY USE VARIABLES?
As it was mentioned earlier, variables are there to extend your dream to be more interactive and
help you make new features or make the old ones smaller, more dynamic and powerful. Obviously,
the more interactive your dream seems, the more interest it will attract from visitors as well as
give you more control and abilities in your dream.
Let's take the chance DragonSpeak lines for instance - 5:312 and 5:313. These will store a random
number into a variable which you can then use with DS lines 1:200 to 1:209 to make a chance-based
random encounter - something that happens randomly as you do something - walk for instance. This way
you can create a game with enemies popping up randomly as you walk the forest. Furthermore, you can
extend all that into a chance-based fighting system to defeat them! Randomization is a very important
thing in cases like these and will make things interesting not only to the unsuspecting visitor, but
even the dream creator, considering the fact that the features of his dreams are not as predictable
anymore. Of course this is only one example out of countless others that you can do with variables
and other DragonSpeak lines - it's all up to one's imagination...
2.3 VARIABLES IN DRAGONSPEAK
So far we've discussed what variables are and how can they be used. Now it's the time to see just
how are we going to use them in DragonSpeak to make use of them.
2.3.1 USE OF VARIABLES IN DRAGONSPEAK
Variables in DragonSpeak are prefixed by the '%' character (i.e. %var) to let the DS processor in
Furcadia know that we're dealing with a variable and not just a regular word. After that delimiter
(another word for the % character) follows the name of the variable. You can call it anything as
long as the name meets all the following conditions:
# The name has to be one word - a space and everything after it will no longer be considered a part
of the name.
# Avoid creating variables with numeric names - they work somewhat differently while using the same
memory space as the other variables. You might encounter unexpected behavior if you use them
without knowing how do they actually work.
# Avoid creating variables with non-alphanumeric characters for your own safety. They may cause
unexpected results in the way DS is interpreted. The following characters are considered safe:
- (dash/minus)
_ (underscore)
The following example code shows how to assign a variable a specific number (1337):
--------------------------------------------------------------------------------------------------------
(0:0) When everything is starting up,
(5:300) set variable %variable to the value 1337.
(0:31) When a furre says {@show},
(5:200) emit message {The variable is currently: %variable} to whoever set off the trigger.
--------------------------------------------------------------------------------------------------------
In this example, the first pair of lines set the variable with name "variable" to the number 1337
just as the dream starts working. The second pair of lines would emit a piece of text to whoever uses
the command "@show", telling what does the variable %variable currently contain (which is 1337). This
should explain the basic use of variables - how to "initialize" them and how to display them in emits
with DragonSpeak. More code examples of variables will be included later on.
That's pretty much it. Variables can be used in this form in nearly any DragonSpeak line instead of
just a number. Want to put an object stored in a variable %obj upon command? No problem:
-------------------------------------------------------------------------------------------------------
(0:32) When a furre says something with {@put} in it,
(5:314) set variable %obj to the number the triggering furre just said.
(3:7) where the triggering furre is currently at,
(5:4) place object type %obj.
-------------------------------------------------------------------------------------------------------
Instead of putting a number such as 8 in line (5:4), I've used the variable %obj which can be changed
upon command. This will let me use these four lines to put any object I want just because %obj can be
set from within the dream. If there would be no variables, to let me put 10 objects like this, I would
need to waste 30 DS lines instead of these 4 that allow me to do a lot more than that. Should you want
to test it in your dream, just paste this code into it and say "@put #" where # is the object number
you want underneath you. Nice, isn't it?
Variables have their limitations that you must remember in order to prevent mistakes within the code
just because you think something should work the way it doesn't:
# Remember the limits on naming a variable described above - incorrect naming may produce unwanted
results!
# In emits, avoid placing text or HTML tags right after a variable name - the tag will be counted as
part of the variable name if there is no space in between the variable and the tag!
# A variable is always initialized to zero, so if you use a variable without setting anything to it
first, the value should be assumed as 0.
# Officially, variables can store numbers from -32768 to 32767 (to those who know these terms: it's
a signed 16bit integer). Using anything beyond these limits (-32769 or 32768 for instance) may
produce unexpected results, so if you're not feeling adventurous about it, stay within the bounds.
# The number capturing line (5:314) can only capture positive numbers! It is not aware of the minus
sign you may want to use.
# [HIGHLY TECHNICAL] It is possible to capture negative numbers by the laws of signed binary numbers.
Meaning a negative number is an 8-bit inverted version of the 7-bit positive number: if we take a
number 1337 (00000101 00111001) and invert it to (11111010 11000110), we get the number
64198 which is an unsigned version of the otherwise signed number -1338. Subtract it by 1 (or add
1 to the unsigned number) to make it right... Basically, the trick is to go out of bounds:
32768 == -32768, 32769 == -32767, 32770 == -32766, etc. It can go all the way till -1 like this!
# Officially, you can only have 250 different variable names in your code and expect them to work
the way they're supposed to! If you are using arrays, consider each element a separate variable
name (arrays are explained later on).
# It is possible to use a lot more than 250 array elements, but there is a limit to how many can
the server synchronize with the client. Should you assign too many elements to an array, you
risk having the ones assigned last not to work properly with DS.
2.3.2 RELATED DRAGONSPEAK LINES
Variables can be used in most DragonSpeak lines, but the following ones were designed especially
for variables and their manipulation:
-------------------------------------------------------------------------------------------------------
== CAUSES ==
(1:200) and variable # is equal to #,
(1:201) and variable # is greater than #,
(1:202) and variable # is less than #,
(1:203) and variable # is equal to variable #,
(1:204) and variable # is greater than variable #,
(1:205) and variable # is less than variable #,
(1:206) and variable # is not equal to #,
(1:207) and variable # is not equal to variable #,
(1:208) and the X,Y position in variable # is the same as the position in variable #,
(1:209) and the X,Y position in variable # is not the same as the position in variable #,
== EFFECTS ==
(5:300) set variable # to the value #.
(5:301) copy the value of variable # into variable #.
(5:302) take variable # and add # to it.
(5:303) take variable # and add variable # to it.
(5:304) take variable # and subtract # from it.
(5:305) take variable # and subtract variable # from it.
(5:306) multiply variable # by #.
(5:307) multiply variable # by variable #.
(5:308) divide variable # by # and put the remainder in variable #.
(5:309) divide variable # by variable # and put the remainder in variable #.
(5:310) use variable # as an array, and copy element # of it into variable #.
(5:311) use variable # as an array, and set element # of it to #.
(5:312) set variable # to the total of rolling # dice with # sides plus #.
(5:313) set variable # to the total of rolling # dice with # sides minus #.
(5:314) set variable # to the number the triggering furre just said.
(5:350) set variable # to the X,Y position the triggering furre (moved from/is standing at).
(5:351) set variable # to the X,Y position the triggering furre moved to.
(5:352) move the position in variable # northeast (up and right) # step(s).
(5:353) move the position in variable # southeast (down and right) # step(s).
(5:354) move the position in variable # southwest (down and left) # step(s).
(5:355) move the position in variable # northwest (up and left) # step(s).
(5:380) set variable # to the floor type at (#, #).
(5:381) set variable # to the object type at (#, #).
(5:399) clear all variables to zero.
(5:500) set variable # to the X,Y position of a random spot within the rectangle (#,#) - (#,#),
(5:501) set variable # to the X,Y position of a random spot that is onscreen for the triggering furre,
(5:502) set variable # to the X,Y position of a random spot somewhere in the dream,
(5:510) set variable # to the X,Y position of a random spot where the floor is type # within the rectangle (#,#) - (#,#),
(5:511) set variable # to the X,Y position of a random spot where the floor is type # that is onscreen for the triggering furre,
(5:512) set variable # to the X,Y position of a random spot where the floor is type # somewhere in the dream,
(5:520) set variable # to the X,Y position of a random spot where the floor is not type # within the rectangle (#,#) - (#,#),
(5:521) set variable # to the X,Y position of a random spot where the floor is not type # that is onscreen for the triggering furre,
(5:522) set variable # to the X,Y position of a random spot where the floor is not type # somewhere in the dream,
(5:530) set variable # to the X,Y position of a random spot where the object is type # within the rectangle (#,#) - (#,#),
(5:531) set variable # to the X,Y position of a random spot where the object is type # that is onscreen for the triggering furre,
(5:532) set variable # to the X,Y position of a random spot where the object is type # somewhere in the dream,
(5:540) set variable # to the X,Y position of a random spot where the object is not type # within the rectangle (#,#) - (#,#),
(5:541) set variable # to the X,Y position of a random spot where the object is not type # that is onscreen for the triggering furre,
(5:542) set variable # to the X,Y position of a random spot where the object is not type # somewhere in the dream,
-------------------------------------------------------------------------------------------------------
2.4 USING VARIABLES
So far we have discussed what variables are, what are they for and how are they used in DragonSpeak.
What is left for us here is to see a few examples for their usage in DragonSpeak you can learn from and
perhaps enhance. The code here was formed by me (Artex), so all the smartasses who plan on telling that
I steal or miscredit - don't bother. Until there is a patent law on DragonSpeak code, I don't see a
reason to credit people who might've created such code before me...
2.4.1 DYNAMIC SOUND PLAYER
The following example will use a simple DragonSpeak code to form a sort of sound/music player on
Furcadia. All it does is play a specific sound/music number from the custom (or default) patch.
-------------------------------------------------------------------------------------------------------
* This is the sound player bit - %ID stores the sound number said.
(0:32) When a furre says something with {@sound} in it,
(5:314) set variable %ID to the number the triggering furre just said.
(5:8) play sound %ID to whoever set off the trigger.
* This is the music player bit - same story with %ID, just a different
* set of lines and the command.
(0:32) When a furre says something with {@music} in it,
(5:314) set variable %ID to the number the triggering furre just said.
(5:30) play midi %ID to whoever set off the trigger.
-------------------------------------------------------------------------------------------------------
In order to test each triplet of lines, type "@sound #" or "@music #" in the dream where # equals an
ID number of the sound/music. There should be number 1 in each, so you can use it to make sure things
actually work for you. Needless to say, you should not type the commands out with quotes - they are
only there to separate commands from the rest of the text...
2.4.2 DREAM ACTIVITY TIME
This bunch of code will keep track of how long has the dream been active. The information can then
be retrieved with the command @uptime.
-------------------------------------------------------------------------------------------------------
* Assigning & initializing hours/minutes variables (seconds are pointless IMO)
(0:0) When everything is starting up,
(5:300) set variable %uptime_hours to the value 0.
(5:300) set variable %uptime_minutes to the value 0.
* Advance the minute counter every minute.
(0:100) When 60 seconds have passed, offset by 0,
(5:302) take variable %uptime_minutes and add 1 to it.
* If the minute counter reaches over 59, reset it and increase the hour counter.
(0:100) When 60 seconds have passed, offset by 0,
(1:201) and variable %uptime_minutes is greater than 59,
(5:300) set variable %uptime_minutes to the value 0.
(5:302) take variable %uptime_hours and add 1 to it.
* Uptime response upon command.
(0:31) When a furre says {@uptime},
(5:200) emit message {Dream uptime: %uptime_hours hr %uptime_minutes min} to whoever set off the trigger.
-------------------------------------------------------------------------------------------------------
Note that I didn't put the tag right after the variable name because it would be considered a
part of the name! Also note that when your dream is completely empty (no people inside), the counters
will stop and the entire dream will freeze, so this uptime is only counted when there's at least one
person inside. To avoid this, you will have to deal with the clock and make a lot more complex DS for
this.
2.4.3 DREAM STATISTICS
The following code will count the amount of players currently in the dream and the maximal number
ever been to the dream at once - sort of a simple peak counter using variables.
-------------------------------------------------------------------------------------------------------
* Forming and initializing variables.
(0:0) When everything is starting up,
(5:300) set variable %stat_current to the value 0.
(5:300) set variable %stat_max to the value 0.
* When someone joins, increase the current counter.
(0:9) When a furre arrives in the dream,
(5:302) take variable %stat_current and add 1 to it.
* If the current count exceeds the maximum count, update the other one.
* Note: You can use 1:201 for this, too - same result, different method.
(0:9) When a furre arrives in the dream,
(1:204) and variable %stat_current is greater than variable %stat_max,
(5:300) set variable %stat_max to the value %stat_current.
* When someone leaves, decrease the current count.
* Note: Someone can trigger a leave before they have entered! We fix that
* by checking if they're at 0,0 - if they are, they have still not arrived.
(0:10) When a furre leaves the dream,
(1:119) and they (didn't move from/aren't standing at) position (0,0),
(5:304) take variable %stat_current and subtract 1 from it.
* Reporting statistics.
(0:31) When a furre says {@stats},
(5:200) emit message {Dream statistics:} to whoever set off the trigger.
(5:200) emit message {- Current players: %stat_current } to whoever set off the trigger.
(5:200) emit message {- Max players: %stat_max } to whoever set off the trigger.
-------------------------------------------------------------------------------------------------------
Each step done here should be self-explandatory by the comments. This can further be extended by adding
a "per hour" and "per day" counter, but that's up to you to make.
2.4.4 DYNAMIC OBJECT/FLOOR CREATION
In this example we will make a kind of code that populates most dynamic dreams out there and that's
dynamic object/floor creation. Previously I've discussed (and might've already given an example to)
this method opposing to the one without variables, but I will post it here anyway.
-------------------------------------------------------------------------------------------------------
* Syntax: "@mkobject #" where # is the object number in your Dream Editor.
(0:32) When a furre says something with {@mkobject} in it,
(5:314) set variable %mkobj to the number the triggering furre just said.
(3:7) where the triggering furre is currently at,
(5:4) place object type %mkobj.
* Syntax: "@mkfloor #" ditto floors.
(0:32) When a furre says something with {@mkfloor} in it,
(5:314) set variable %mkfloor to the number the triggering furre just said.
(3:7) where the triggering furre is currently at,
(5:1) set the floor to type %mkfloor.
-------------------------------------------------------------------------------------------------------
Not hard, as you can see. You can also add a line there to trigger these commands only when a dream
owner or a shared member uses it to prevent abuse, but that's already up to you to play with it.
2.4.5 CODE-BASED DREAM LOCK
In this sample we'll be using a rather new (for this time) feature - DreamURLs and the Entry Codes
in order to lock our dream against unauthorized personnel. Only those who will know the code, shared
people and the dream owner will be able to access the dream and not be auto-ejected out of it.
-------------------------------------------------------------------------------------------------------
* Setting this to 0 will disable locking.
(0:0) When everything is starting up,
(5:300) set variable %lock_code to the value 0.
* Any auto-share code must be BEFORE this one or auto-sharing will not work
* in time to immunize the person entering without a code.
(0:9) When a furre arrives in the dream,
(1:110) and the triggering furre is not the dream owner,
(1:111) and the triggering furre hasn't got shared control (and is not the dream owner),
(1:201) and variable %lock_code is greater than 0,
(1:190) and their entry code is not %lock_code,
(5:200) emit message {Sorry, this dream is currently locked.} to whoever set off the trigger.
(5:78) eject the triggering furre.
* Setting the lock code (restricted to dream owner).
* WARNING: Don't exceed 32767 or locking will not occur!
(0:32) When a furre says something with {@setcode} in it,
(1:10) and the triggering furre is the dream owner,
(5:314) set variable %lock_code to the number the triggering furre just said.
(5:200) emit message {Dream lock code is now: %lock_code } to whoever set off the trigger.
-------------------------------------------------------------------------------------------------------
This locking method is rather strict and it requires the use of DreamURLs to access your dream, making
summons and dream portals ineffective when in locked state (wouldn't this be what you want, though?).
The code can be set by typing "@setcode #" where # is the lock code one must specify. In order to use
the access code in my dream (no name), one will have to type "`fdl furc://Artex/1337", provided that
my lock code at that moment is 1337. If my dream name is "Test Dream", the URL would instead be
furc://Artex:TestDream/1337.
That pretty much does it. Hope that this text will get the point across and will give you enough
information about variables in Furcadia. The other sections deal with other sorts of variables Furcadia
supports up to the technical explanations on how things are done in relation to them. You are welcome
to go through them should you not feel tired from this yet. ;)
______________________________________________________________________