Last Updated: 1/29/2010 (Release 463)
View the live web reference here.
The DM (Dream Maker) language uses a syntax similar to C/C++ to build networked multi-user worlds. This reference and the accompanying guide discuss the structure and function of DM.
Files specified in single quotes are loaded (at compile time) into the
world cache file (ending in .rsc
). These are referred to as
resource files. At runtime these files are downloaded by players into their
byond.rsc
file for future use. With the appropriate verbs or
through savefiles, players may also upload files into the world cache.
If a resource file is not used for a long time, it will be automatically removed from the cache file to save space. If a cache file gets too bulky, however, you may manually delete it and start from scratch.
To make compilation faster and to make it easier to distribute code, the
compiler will use an existing cache file if possible. That means you could
compile up a world, and send people the .dm
and
.rsc
files without any need to package all the individual
resource files. It is also possible to include additional supplementary
.rsc
files by using the #include
statement.
Comments may be used to explain code. They can also be used to turn off a line or block of code. All text inside a comment is ignored by the compiler.
The single line comment begins with //
and runs to the end of
the line.
The multi-line comment begins with /*
and runs until
*/
.
Multi-line comments may be nested.
At runtime, data objects are garbage collected. That means data which is no longer in use gets automatically deleted to free up system memory. This applies to text strings, lists, savefiles, datum objects, and so on.
The garbage collector works by using an efficient reference counting system. Once an item is no longer referenced by any variable, it gets deleted. For the most part, that frees you from having to think about memory allocation, which is wonderful, especially in the case of text strings, which tend to be allocated on the fly all over the place.
There are a couple provisos that you should note. One is that circular
references will never be deleted by the garbage collector. By circular
reference, I mean a pair of objects with variables that point to each
other, or even an object with a variable that points to itself. In rare
cases, you may even depend on this behavior. When you are done with such
objects, you should either null out the circular reference, or you should
forcibly destroy each object with the del
instruction.
An object with running or sleeping procs is referenced by the
src
variable of those procs and will therefore not be thrown out.
Another note is that the world.contents
list does not count as
a reference. Otherwise, /mob and /obj objects would never be deleted, which
is not the case. Note that objects which are contained by another object or
which contain objects themselves are referenced and will not be
deleted. That means an object must be at loc=null
with no
contents and, of course, no other references anywhere in order to get deleted
by the garbage collector.
Mobs with a non-empty key and all objects with non-empty tags are also immortal.
Turfs and areas do not currently get garbage collected.
When the world shuts down, all objects are destroyed, whether they are referenced or not. You don't have to worry about system memory getting consumed by persistent objects. That doesn't happen.
In general, people who do not like reference counting garbage collection
should be happy that DM provides a del
instruction, allowing you
to take charge and delete things whether they are referenced or not. Another
nicety is that this automatically nulls out any existing references to the
object, so you don't end up with dangling references to a deleted object,
which can otherwise be a great source of instability and mysterious bugs.
An icon file may be referenced by putting single quotes around the
filename. The file extension determines the type of icon. Currently
supported icon types are .dmi
, .bmp
, .png
,
.jpg
, and .gif
. To create dmi icons, use the Dream
Maker icon editor. This allows you to make animations, 4 or 8 directional icons,
and icons with different states (such as "live" and "dead").
You can also load icons into memory at run-time and manipulate the graphical data to produce new icons dynamically. This is done by creating an /icon object.
NOTE: the following "arithmetical" methods of icon manipulation are being phased out in favor of the new /icon object, which can be directly manipulated and which provides a wider variety of operations.
There are several ways in which icons can be manipulated at runtime. They can be rotated, added together, and the colors components may be altered.
One purpose for such operations is to make players look different. Other interesting uses (and abuses) will undoubtedly follow.
The result of adding two icons is an arithmetic combination of the color components of each individual pixel. At positions where either icon is transparent, the result is also transparent. Subtraction, instead of increasing the intensity, decreases it by the amount in each pixel of the icon being subtracted.
Suppose you wanted to add together different bodies and heads. You could do that by making a few of each type with black backgrounds. When these add together, the black contributes nothing but prevents pixels in the other icon from getting clipped.
If you need to add the same color to every pixel, you can do so using a color value. Color values have the same format as in HTML: "#RRGGBB" with two hexadecimal digits for each color component. That gives you a range in color from 0 to FF (which is 255 in decimal).
You can also specify a color value as "#RGB". The single digit is automatically repeated, so "#F00" is the same as "#FF0000", which is bright red. For certain pre-defined color values, you can also specify a name, such as "red". See HTML colors for a list of color names.
If you prefer base 10, you can create color values with the rgb(R,G,B) instruction. Each parameter is in the range 0 to 255.
To increase (or decrease) the intensity of an icon multiplicatively, you
can use the '*
' operator.
Various mouse actions may be handled by defining procedures either on the client object or on the atomic object being manipulated. Any of the following procedures may be defined:
In general, define only the procedures you need, because extra communication overhead may be avoided when the compiler detects that you do not care about certain events.
The arguments used in mouse procs generally follow one of two forms:
The location argument varies with the type of control. For the map, it will be the turf where the mouse action happened. For info controls (statpanels), it will be the name of the statpanel where the action happened. For grid controls, it will be the cell where the action happened. For others controls it may vary, but most will leave this blank.
The control argument is the ID of the skin control where the action happened, such as "mappane.map" or "mainwindow.banner".
The params argument is text, and can be converted to a list using params2list(). It may contain any of the following properties, which will only be set if they are used:
The mouse pointer may be customized as well. The following variables all deal with the appearance of the pointer. They do not control what actions may be taken by the user, but they provide hints to the user about what actions may work.
When selecting a mouse pointer, you may provide your own custom icon or use one of the built-in pointers.
Note: Older games compiled prior to BYOND 4.0 had a different format for the MouseDown() and MouseUp() procs. These used icon_x and icon_y as arguments, but control and params have replaced them.
The following mouse pointers are built-in and may be assigned to any of the mouse pointer variables. Of course, you can also define your own custom mouse pointers using an icon file.
Variables that are not initialized have the value null. This value is
distinct from 0 and "". If you compare it to these, using the ==
operator, it is not equal. However, in a numeric context (like a mathematical
operation), null evaluates to 0 and in a text context (like insertion into a
text expression), null evaluates to "". In a logical expression, null, 0, and
"" evaluate to false and all other values are true.
In an embedded text expression, null behaves like "". That means, if you are expecting a variable to display a 0, you should explicitly initialize it to 0 rather than leaving it as null.
The preprocessor performs various transformations on source code as the DM compiler reads the file. It may be used to define macros--that is words which are replaced by other fragments of code. It is also possible to insert other source code files and to conditionally compile or not compile sections of code.
Preprocessor commands are called directives. They are placed on a line by
themselves and always begin with a hash symbol #
. The
preprocessor directives recognized by DM are the same as standard C compilers:
#define
#if
#elif
#ifdef
#ifndef
#else
#endif
#include
#error
This macro indicates the version of the compiler. This could be useful when distributing code that uses new language features that would not compile in older compilers.
The __FILE__ macro expands to a string containing the name of the current source file. This may be useful when generating debugging error messages.
The __LINE__ macro is replaced by the line number in the current source file. This may be useful when generating debugging error messages.
The __MAIN__ macro is defined in the main .dme
file being
compiled. In all other files included by this file, __MAIN__ is not defined.
The purpose of this is for library writers to package a small demo of their
library directly in the library source code. When users compile the library
directly, the library's own .dme
is the main file and can include
extra files that are not normally part of the library.
If the demo requires a lot of extra resources, it is probably better to
package the demo as a separate project. Small demos, however, are nice and
convenient using this "auto-demo" technique--especially since Dream Seeker
automatically launches Dream Maker after installing a library containing a
.dme
file.
The #define statement creates a macro that is substituted for Name.
Substitution only applies to whole words. Text inside of double or single
quotes is not processed for substitution, so "This is BIG."
would
not be modified even if a macro named BIG were defined. That is different
from "This is [BIG]."
, where BIG is an embedded expression, which
does get processed for macro substitution.
Note that it's usually important to use parentheses around any arguments you use in a macro. Otherwise strange results may occur if you use an expression such as 2+3. In the SQR(X) example, if there were no parentheses around each X then the expansion of the macro would be (2+3*2+3). Since the * operator has a higher precedence than + the result is 11, not 25 as expected. It's equally important to put parentheses around the entire macro for the same reason.
If DEBUG
is defined, source file and line number information
will be stored in the compiled .dmb
file. If a proc crashes
during execution and DEBUG
information is present, the current
source file name and line number will be indicated in the error output.
This option increases the size of the .dmb
, typically by about
10%. Execution of the code may also be a tiny bit slower.
If you are distributing the .dmb
to players and you do not
want them to have debug access at runtime, you should not compile in
debug mode.
If you want to use the run-time profiler (see the debugging options in Dream Seeker), you must compile in debug mode. Then you can get a report of CPU usage by your various procs.
This macro defines a search path to be used in evaluating resource files
(icons and sounds). First the current directory is searched, then the first
FILE_DIR
path, then the next, etc.
This searches for the file at the paths "./clown.dmi"
,
"./icons/clown.dmi"
, and "./icons/sounds/clown.dmi"
,
where "."
is the directory of the current source file.
The #error directive halts compilation and displays the specified message.
The #if
statement is used to conditionally compile code. If
Val is true (non-zero), the code following the #if
statement
will be compiled. Otherwise, compilation skips to the next
#elif
, #else
, or #endif
statement.
The function defined()
can be used in the conditional
expression. It is true if its argument is a defined macro (with
#define
) and false otherwise.
The #ifdef
statement is used to conditionally compile code. It
is equivalent to #if defined(Name)
.
The #ifndef
statement is used to conditionally compile code.
It is equivalent to #if !defined(Name)
.
The #include
statement causes the compiler to process another
file before continuing in the current source file.
If a file is included multiple times, only the first occurrence will be processed. That is a convenient addition to the standard C preprocessor, which DM otherwise emulates quite closely.
The file <stddef.dm>
is automatically included before
all other source code.
The BYOND lib directory is called "lib"
and is located in the
BYOND system directory (typically "\Program Files\Byond\lib"
).
If the file is not found there, it also looks in the user lib directory, which
would typically be "...\Byond\user\login-name\lib"
.
Note that the compiler interface allows you to include files graphically by
simply clicking the checkbox next to the file. This creates an include
statement for you in the .dme
project environment file. The only
time you would still want to manually include files is when you need to ensure
a certain order of processing. For example, if file "MyCode.dm"
overrides procedure definitions of an object defined in
"LibCode.dm"
, you should include "LibCode.dm"
at the
top of "MyCode.dm"
. Most other DM code is independent of order,
but overriding procedure definitions is not. The compiler will warn you in
such cases if you forget.
Another case in which you should manually include files is if you are
writing a library to be used by other programmers. Since the
.dme
file is not distributed with a library, all necessary
inclusions must be made in the .dm
files.
The #undef
statement removes a macro definition.
A sound stored in a file may be referenced by putting single quotes around the filename. The file extension determines the type of sound. Currently supported music types include MIDI (.mid or .midi), and module formats .mod, .it, .s3m, .xm, and .oxm. Supported sound effect formats include .wav, .ogg, .raw, .wma, and .aiff.*
This example plays the specified midi file to all players.
*The MP3 format is not presently supported by BYOND due to licensing issues. Ogg-Vorbis, however, is a good alternative. For music the module formats are also a good choice, and tend to be smaller.
Text consists of a string of characters enclosed in double quotes. To
place a quote inside a string, escape it with \
.
This example sends some text to the usr: He said, "Hi."
To insert a variable expression into a string, enclose it in brackets
[]
. These are referred to as embedded text expressions. An
object expression will display the object's name preceded by the text macro
\the
or \The
if no other article has been
specified. Capitalization of the article is inferred from context.
If this example is called by a mob named "Bill" with the text "hi everybody!", it will display "Bill: hi everybody!".
On the other hand, if it is called by a mob named "cat", it would display "The cat: hi everybody!".
For lengthy text strings, DM provides a special text document
syntax. This begins with {"
and ends with "}
. It
may include multiple lines and even un-escaped double quotes.
Special characters may be inserted into text using HTML syntax. Such
characters are known as entities. They start with an ampersand and end with a
semicolon. The main reason for doing this is to insert characters that
otherwise have a special meaning. The most common entities have names. The
rest must be referred to by their ASCII number (e.g. & is the same as
&). The common ones are listed in the following table. Note that the
same effect may be achieved by simply escaping the special character (like
\<
). The full entity syntax is included for generality.
& | & |
< | < |
> | > |
" | " |
© | © |
Text macros start with '\' (a backslash) and end with a space or other punctuation.
The \icon macro is used to treat the following embedded expression (in []'s) as an icon rather than as text. An object, for example, would be replaced by its icon rather than by its name.
The \icon
macro expands internally to the <IMG> tag. The
above example, could be rewritten like this:
Note that the current icon state of the object is automatically used.
Also note that the image belongs to a class called icon
. That
allows you to configure the way icons are displayed by using a style sheet.
The following default style rule causes icons to be shrunk to 16 by 16
pixels so they fit in better with surrounding text:
You could override this setting globally in your own style sheet. You could even define rules to allow individual icons to be formatted differently from the rest.
With those rules in place, you could output a full sized icon by using the <BIG> tag:
The one time that one might want to use the <IMG> tag directly is to specify the ALT text to be displayed on clients which don't support graphical icons.
Specific states, directions, and frames of an icon can be displayed in lieu of the default through use of the following tags:
Note that the \icon macro does not work in the mini-browser; it is only for text output. To make icons appear in an HTML document, use browse_rsc() to send an icon to the client before using browse() to display it.
The \ref
text macro inserts a unique identification number
or text string for the following embedded object (inside []'s). If the
object has a tag, that will be used. Otherwise, an internal id number is
used. In either case, the embedded reference is surrounded by [] brackets.
The reason the tag is preferred is that it stands a better chance of still being valid if the object is deleted and recreated (like in a world reboot). The internal id number, on the other hand, is transient and should only be expected to remain the same for the duration of the object's existence. If you want a more permanent reference, you must assign and save the object's tag variable.
The primary use for object references embedded in text is in topic links. This allows you to encode a reference to an object in the href value of a hyperlink. (Just make sure the object does not get deleted before the user executes the link. See garbage collection.)
Topic links that contain a parameter "src" assigned to an object reference are treated somewhat specially. Unless you override client.Topic() to do otherwise, the default behavior is to call the referenced object's own Topic() procedure.
The above example uses an embedded reference to the player's own mob to
create a link to a topic handled by that mob's Topic() proc. The
href_list
parameter is simply the result of
params2list(href)
.
In that example, the embedded reference was automatically converted back into an object (dereferenced) for you. If you embed references to additional objects in the href data, you would have to dereference those yourself using the locate() instruction.
HTML tags, such as <FONT>
may be used to directly format
output text. Another approach, however, is to use HTML tags to specify
purely structural information and use a style sheet to define how various
elements within that structure should be treated. DM uses a subset of the
Cascading Style Sheet (CSS) language, which was introduced for this purpose
in HTML documents.
This section discusses the syntax of style sheets as an independent element. For information on how to include the style sheets in your DM code, see the section on client.script.
As an example of a style sheet, one might want combat and conversational
messages to appear differently--perhaps using different colors. Instead of
using the <FONT>
tag to color the text, you could use
<SPAN>
to mark the beginning and ending of the text and
to specify what kind of message it is. The result might be text such as the
following:
The CLASS
attribute may be used with any tag, but
SPAN
and DIV
are often convenient because they
have no other side-effect but defining the style class. SPAN
is for text within a single paragraph and DIV
is for whole
paragraphs. The way text belonging to a particular class is formatted may be
controlled in a style sheet such as the following:
This says that text in the 'combat' class should be colored red and text in the 'chat' class should be colored green. These classes are not pre-defined; you can create whatever new style classes you need.
The advantage of using style sheets instead of direct formatting tags is that you can cleanly separate structural information (such as combat and conversational messages) from formatting information (such as red and green text). By separating the two, you or the player can easily plug in different formatting schemes without changing any of the actual content.
A style sheet is composed of a list of rules, such as the two rules in the preceding example. Each rule contains one or more selectors followed by a body of attribute assignments (in braces). The selector specifies the context of the rule and the body specifies the format.
A selector may specify a container tag (such as SPAN
,
BODY
, or P
) and a class. The above example could
have been written with a selector of SPAN.chat
. However, by
leaving out the tag, it applies to any tag with CLASS=chat
. It
is also possible to only specify the tag and not the class. In that case,
the selector applies to any matching tag, regardless of class.
To specify a nested context, several simple selectors may be listed one after the other. For example, emphasized text within a combat message could be enlarged with the following rule:
It is also possible to list several selectors separated by commas in order to make them all apply to the same body. For example, this next rule is equivalent to the two following ones:
The style rule body contains a list of attribute assignments, delimited by semicolons. Each assignment takes the form of an attribute name, followed by a colon, followed by the value of the attribute. The following table summarizes the recognized attributes and their possible values.
color | #F00, #FF000, red, rgb(255,0,0), rgb(100%,0%,0%) |
background | |
font-size | 10pt, 1.5em, 150% |
font-style | normal or italic |
font-weight | normal, bold, lighter, darker, or 100 to 900 |
font-family | monospace, sans-serif, serif, cursive, ... |
font | style weight size family |
text-decoration | none or underline |
text-align | right, left, or center |
text-indent | 0.25in, 3em, 20pt |
margin-left | |
margin-right | |
width | 16px, 32px, auto |
height |
The font
attribute is a special short-hand for assigning
font-size
, font-style
, font-weight
,
and font-family
in one statement. Any properties that are not
specified in the font
statement are assigned to their default
values.
The font family may be a specific font name or a more general category such as monospace or sans-serif. Since not all users necessarily have the same fonts installed, it is a good idea to list alternate fonts. The desired font is placed first, followed by other possible fall-backs, each separated by a comma. Usually a general family such as monospace is listed last of all. Any font names containing a space should have quotes around them.
The following example sets the font for the <BODY>
tag. Even if you don't explicitly use <BODY>
in output
text, it is applied implicitly.
This sets the font to 12 point and selects Times New Roman
if
it is available and otherwise falls back on a system-determined sans-serif
font. This command also implicitly specifies not to use italics and to use a
normal font weight (not bold).
Font sizes may be specified in points (1pt = 1/72 of an inch), picas (1pc = 12pt), pixels (px), inches (in), centimeters (cm), and millimeters (mm). There are also various levels corresponding to the traditional 1 to 7 HTML scale. These are xx-small, x-small, small, medium, large, x-large, and xx-large. In addition to these absolute font sizes, it is possible to use a relative size, such as 150% or equivalently 1.5em. This scales the font relative to the currently active font setting.
In addition to regular classes, there are special pseudo-classes for
handling embedded hyperlinks. These are specified in the selector with the
class starting with a colon rather than a dot. They are :link
,
:visited
, and :active
. These only apply to the
<A>
tag. The :link
class applies to
hyperlinks in their normal state. Once a link has been clicked, it belongs
instead to the :visited
class. When the user holds the mouse
over a link, it temporarily belongs to the :active
class. The
only attribute that may change in an active or visited link is the text
color.
Paragraphs can be given different margins according to your preferences.
The margin-left
attribute controls the left margin, and
margin-right
is the right margin. You can use specific sizes
like inches or points, or a relative size unit like em or ex. (A percentage
is interpreted so that 100% is 1em, not the width of the window.) Using the
text-indent
attribute will indent the first line of a paragraph
from the left margin. It is possible to create a hanging indent by using a
negative value for text-indent
, like so:
The background attribute is only relevant to the BODY context. It causes the entire terminal background to change color. When doing this, it is usually necessary to change the foreground colors of text or it may become unreadable. The various standard classes of output generated by DreamSeeker are in the following table.