# DM Reference

View the live web reference here.

## DM language details

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.

This reference is arranged in sections:

- The DM language: The majority of the reference; items in this section can have top-level entries.
- Special notes: Articles describing advanced features or concepts in more depth.
- User interface skins: Anything related to creating custom UIs for your world.
- Appendix: Additional reference informtation that might apply to multiple topics, e.g. regarding colors or HTML.

You can filter the reference content by subject, which helps narrow down anything you might be looking for.

In various articles you may see notes or sidebar content:

⚠️Important note
🔒️Security concerns
🏃️Performance tip
👍️Rule of thumb
🏛️Compatibility
💡️Did you know?
🔧️Under the hood
🦕️Deprecated feature
🎳️Play area

## cache

See also:
  FILE_DIR definition
  cache_lifespan var (world)
  fcopy_rsc proc
  file proc
  icons
  sounds

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.

## comment

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.

### Example:

      // single line comment
      /*
         multi-line comment
      */

## garbage collection

See also:
  del proc
  world
  refcount proc

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 `tag` 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.

## icons

See also:
  FILE_DIR definition
  cache
  flick proc
  icon
  icon var (atom)
  icon_state var (atom)
  image objects

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").

### Example:

      mob
        icon = 'monster.dmi'

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.

## icon arithmetic

See also:
  icon proc
  icon_states proc
  icons
  rgb proc
  turn proc (applied to an icon)
  icon object

Note: The following "arithmetical" methods of icon manipulation are being phased out in favor of the /icon object, which can be directly manipulated and which provides a wider variety of operations. Many of those in turn have been obviated by the color and transform vars.

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.

### Addition and Subtraction

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.

### Example:

    mob/verb
       addicon(I as icon)
          icon += I
       subicon(I as icon)
          icon -= I

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.

### Multiplication

To increase (or decrease) the intensity of an icon multiplicatively, you can use the '`*`' operator.

### Example:

    mob/verb/multicon(factor as num)
       icon *= factor

## mouse handling

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:

- MouseDown()
- MouseUp()
- MouseDrag()
- MouseDrop()
- MouseEntered()
- MouseExited()
- MouseMove
- MouseWheel
- Click()
- DblClick()

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 these forms:

For Click(), DblClick(), MouseDown(), MouseUp(), MouseEntered(), MouseExited(), and MouseMove():
  client/Click(object, location, control, params)
  atom/Click(location, control, params)
For MouseDrag() and MouseDrop():
  client/MouseDrag(src_object, over_object, src_location, over_location, src_control, over_control, params)
  atom/MouseDrag(over_object, src_location, over_location, src_control, over_control, params)
For MouseWheel():
  client/MouseWheel(object, delta_x, delta_y, location, control, params)
  atom/MouseWheel(delta_x, delta_y, location, control, params)

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:

- icon-x, icon-y: Pixel coordinates within the icon, in the icon's coordinate space
- screen-loc: Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]")
- left, middle, right: Mouse buttons pressed, held, or released in this action (see compatibility note below)
- button: Mouse button pressed or released in this action (see compatibility note below)
- ctrl, shift, alt: Keys held down during the mouse action
- drag-cell, drop-cell: Cells involved if using a Grid control
- drag: The button used for dragging (only sent for unrelated mouse up/down messages during a drag)
- link: If the mouse is over a link in maptext, or this event is related to clicking such a link
- vis-x, vis-y: Pixel coordinates relative to the icon's position on screen

The icon-x/y coordinates are integers, and try to point to the actual pixel in the icon before any atom transforms are done; i.e. if the icon were scaled up to 3 times its size using the transform var, then a 3×3 region of pixels would all have the same icon-x/y values. The lower left pixel of the icon is 1,1. The vis-x/y parameters are screen-based, and their origin (1,1) is wherever the lower left corner of the icon is rendered.

Note: vis-x/y will not be included in the parameters if they are the same as icon-x/y.

If the mouse is over an overlay, icon-x/y and vis-x/y are relative to the parent object, not the overlay icon itself, so it's possible to have value outside of the normal range of 1,1 to [width],[height].

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.

- mouse_pointer_icon
- mouse_over_pointer
- mouse_drag_pointer
- mouse_drop_pointer
- mouse_drop_zone
- mouse_opacity

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.

Note: Games compiled before version 514 did not have the `button` parameter, so they handled the `left`, `middle`, and `right` parameters differently. In old versions, only the button used in the action (left, middle, right) was included as a parameter; now all buttons being held or changed are included, and `button` is the mouse button that changed.

## mouse pointers

See also:
  mouse handling
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  mouse_pointer_icon var (client)

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.

MOUSE_INACTIVE_POINTER (0)
MOUSE_ACTIVE_POINTER (1)
MOUSE_DRAG_POINTER
  Same as mouse_drag_pointer = MOUSE_ACTIVE_POINTER.
MOUSE_DROP_POINTER
  Same as mouse_drop_pointer = MOUSE_ACTIVE_POINTER.
MOUSE_ARROW_POINTER
  Same as mouse_over_pointer = MOUSE_INACTIVE_POINTER.
MOUSE_CROSSHAIRS_POINTER
  Same as mouse_over_pointer = MOUSE_ACTIVE_POINTER.
MOUSE_HAND_POINTER

## null

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.

## preprocessor

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
    #pragma
    #error
    #warn

## DM_BUILD macro

See also:
  byond_build var (world)
  byond_build var (client)
  DM_VERSION macro
  preprocessor

This macro indicates the minor version of the compiler, which is useful during BYOND beta testing. More often, you will want to use the `DM_VERSION` macro instead, which is the major version.

## DM_VERSION macro

See also:
  byond_version var (world)
  byond_version var (client)
  DM_BUILD macro
  preprocessor
  #pragma compatibility directive

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.

### Example:

    #if DM_VERSION < 230
    #error This compiler is too far out of date!
    #endif

If you use `#pragma compatibility`, it will alter the value of this macro (but never higher than the actual version being compiled). In this way you can alter your code's behavior based on the pragma.

## __FILE__ macro

See also:
  ASSERT proc
  DEBUG definition
  __LINE__ macro
  __MAIN__ macro
  __PROC__ macro
  __TYPE__ macro
  __IMPLIED_TYPE__ macro

The __FILE__ macro expands to a string containing the name of the current source file. This may be useful when generating debugging error messages.

## __IMPLIED_TYPE__ macro

See also:
  __FILE__ macro
  __LINE__ macro
  __PROC__ macro
  __TYPE__ macro
  new proc
  locate proc
  istype proc
  astype proc

The `__IMPLIED_TYPE__` macro is replaced by a reference to the type path implied at the current point in compilation. For instance, when using the `new` proc and assigning to a var, the type path for `new()` is implied by the var's type. Implied types are also automatically used in locate(), and are used by default for the second argument in istype() and astype().

### Example:

    proc/Factory(new_type)
        world.log << "Creating new [new_type]"
        return new new_type()

    proc/CreateThing()
        // pass /thing to Factory
        var/thing/T = Factory(__IMPLIED_TYPE__)

`__IMPLIED_TYPE__` is valid in the following situations:

- In an expression on the right-hand side of an assignment operator (this includes operators like `+=`), where the left-hand side is a var that has a defined type path.
- Within the second argument of istype(). The implied type is the first argument's var type.
- Within the second argument of astype(). If the astype() call is on the right-hand side of an assignment, this is the type of the var being assigned to; otherwise it's the type of the first argument.

This is actually a pseudo-macro; the preprocessor doesn't handle it directly.

## __LINE__ macro

See also:
  ASSERT proc
  DEBUG definition
  __FILE__ macro
  __PROC__ macro
  __TYPE__ macro
  __IMPLIED_TYPE__ macro

The __LINE__ macro is replaced by the line number in the current source file. This may be useful when generating debugging error messages.

## __MAIN__ macro

See also:
  preprocessor

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.

### Example:

    #ifdef __MAIN__
    #include "demo.dm"
    #include "demo.dmm"
    #endif

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.

## __PROC__ macro

See also:
  __FILE__ macro
  __LINE__ macro
  __TYPE__ macro
  __IMPLIED_TYPE__ macro

The `__PROC__` macro is replaced by a reference to the current proc being compiled. This may be useful when generating debugging error messages, especially when wrapped in `nameof`, e.g. `nameof(__PROC__)`.

This is actually a pseudo-macro; the preprocessor doesn't handle it directly.

## __TYPE__ macro

See also:
  __FILE__ macro
  __LINE__ macro
  __PROC__ macro
  __IMPLIED_TYPE__ macro

The `__TYPE__` macro is replaced by a reference to the type path currently being compiled. This may be useful when generating debugging error messages. If used in a global proc, the value will be null.

This is actually a pseudo-macro; the preprocessor doesn't handle it directly.

## #define directive

See also:
  preprocessor

Format:
  #define Name Value
  #define Name(Parameters) Value

Args:
  Name: A macro definition.
  Value: The value to substitute for Name.
  Parameters: Arguments to pass into the macro.

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.

### Example:

    #define DAY   0
    #define NIGHT 1
    var/daytime = NIGHT  //daytime = 1

### Example:

    #define SQR(X) ((X)*(X))
    var/x = SQR(2)       //x = ((2)*(2)) = 4

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.

### Variadic macros

The last parameter of a macro can end in `...` which means that it and all other arguments following it count as a single argument. This is called a variadic macro because it lets you use a variable number of arguments. The last parameter will also become optional.

### Example:

    #define DEFAULT_LIST(n, items...) if(!n) n = list(items)

### `#var` to string

In a macro's body, if you precede a parameter by `#`, the replacement value will be turned into a string. For instance, 2 would become "2".

### Example:

    #define DEBUG_VAR(v) world.log << "[#v] = [v]"
    DEBUG_VAR(usr.x)    // world.log << "usr.x = [usr.x]"

### `##var` concatenation

A parameter preceded by `##` in the macro body is substituted directly, without any spaces. If you use this with the last argument in a variadic macro, any preceding spaces and a comma (if found) will be removed if the replacement is empty.

### Example:

    #define MACROVAR(k) var/macro_state_##k
    // MACROVAR(right) becomes var/macro_state_right

    #define PREFIX_LIST(x, y...) list(x, src, ##y)
    // PREFIX_LIST(1, 2, 3) becomes list(1, src, 2, 3)
    // PREFIX_LIST(4) becomes list(4, src)

### `n###var` repeat

Using `###` in the macro body, preceded by a number, will repeat the replacement a certain number of times.

### Example:

    #define SAYTWICE(t) 2###t
    #define TOTEXT(t) #t
    world << "[TOTEXT(SAYTWICE(hi))]"   // world << "hihi"

## DEBUG definition

See also:
  #define directive

Format:
  #define DEBUG

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.

## FILE_DIR definition

See also:
  cache
  icons

Format:
  #define FILE_DIR Path

Args:
  Path: A search path on the current filesystem.

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.

### Example:

    #define FILE_DIR icons
    #define FILE_DIR icons/mobs

    mob/clown
      icon = 'clown.dmi'

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.

## #elif directive

See:
  #if directive

## #else directive

See:
  #if directive

## #endif directive

See:
  #if directive

## #error directive

See also:
  preprocessor
  #warn directive

Format:
  #error Text

Args:
  Text: an error message to display

The #error directive halts compilation and displays the specified message.

### Example:

    #if DM_VERSION < 4
    #error This compiler is too far out of date!
    #endif

## #if directive

See also:
  #define directive
  #ifdef directive

Format:
  #if Val
  ...
  #elif Val2
  ...
  #else
  ...
  #endif

Args:
  Val: A logical expression.

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.

### Example:

    #if defined(DEBUG)
    // This code will be compiled if DEBUG is
    // defined
    #else
    // This code will be compiled if DEBUG is
    // not defined
    #endif

You can also use `fexists()` in a conditional to check if a file exists.

## #ifdef directive

See also:
  #define directive
  #if directive
  #ifndef directive

Format:
  #ifdef Name

Args:
  Name: A macro definition.

The `#ifdef` statement is used to conditionally compile code. It is equivalent to `#if defined(Name)`.

## #ifndef directive

See also:
  #define directive
  #if directive
  #ifdef directive
  preprocessor

Format:
  #ifndef Name

Args:
  Name: A macro definition.

The `#ifndef` statement is used to conditionally compile code. It is equivalent to `#if !defined(Name)`.

## #include directive

See also:
  #define directive
  #pragma directive
  preprocessor

Format:
  #include "Filename"
  #include <Filename>

Args:
  "Filename": The path to the filename to include, from the current directory.
  <Filename>: The path inside the BYOND lib directory.

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. If you want the file to be included more than once, put the line `#pragma multiple` somewhere in the file.

The file `<stddef.dm>` is automatically included before all other source code. You can view the contents of that file by creating a file with that name in Dream Maker.

### Example:

    #include "test.dm" // checks ./test.dm
    #include <test.dm> // checks lib-path/test.dm

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.

## #pragma directive

See also:
  #define directive
  #include directive
  preprocessor

The `#pragma` directive alters the compiler's behavior in various ways.

#pragma multiple
  Include this file more than once.
#pragma ignore Warning
#pragma warn Warning
#pragma error Warning
  Changes how the compiler handles certain warnings.
#pragma push
  Save the current pragma state.
#pragma pop
  Restore a previously saved warning state.
#pragma syntax
  Switch to a different syntax for parsing certain procs.
#pragma compatibility
  Hint that the compiler should avoid using features higher than a given version.
#pragma math
  Choose faster (old) or more accurate (new default) trigonometry.

Pragmas will not be inherited by libraries included in your project.

## #pragma compatibility directive

See also:
  #pragma directive
  warn/ignore/error directive
  DM_VERSION macro

Format:
  #pragma compatibility <version>

Hints that the compiler should avoid using features past a certain major BYOND version. If it encounters a situation where you explicitly or implicitly use a newer feature than requested, it will generate a warning.

### Example:

    #pragma compatibility 515

This directive also alters the DM_VERSION macro.

A value of 0 or anything negative will reset the compatibility version to the default.

## #pragma math directive

See also:
  #pragma directive
  sin proc
  cos proc
  tan proc

Format:
  #pragma math <fast|accurate>

Chooses old-style fast math procs, or newer more accurate ones that sacrifice a small amount of speed. This appplies to sin(), cos(), and tan().

The reason this is necessary is because BYOND uses degrees for its angles, but converting to radians (for the underlying math libraries) can't be done with precision for many angles such as 90°, which is π/2 in radians. When the result of the trig function is small, the angle being slightly off from what the user intended will produce a small error in the result as well.

The more-accurate procs use trigonometric identities to reduce the angle to a more manageable range of 0 to 45° (π/4 radians).

### Example:

    var/angle = 90
    #pragma math fast
    usr << cos(angle)   // 6.12323e-17
    #pragma math accurate
    usr << cos(angle)   // 0

Using #pragma compatibility 515 will also force the fast math version.

Note: For consistency, built-in compiler math for constant values uses the same calculations that would be used for non-constant values runtime, so `cos(90)` compiles as 6.12323e-17 with fast math and as 0 for accurate math.

## #pragma multiple directive

See also:
  #pragma directive
  #include directive

Allows this file to be included more than once. Ordinarily the `#include` directive only allows a file to be included once.

## #pragma push/pop directive

See also:
  #pragma directive
  #pragma warn/ignore/error directive

`#pragma push` saves the current state any pragma flags, so for instance a warning's level can be temporarily changed to ignore, warn, or error.

`#pragma pop` restores a previously saved pragma state.

### Example:

    // temporarily ignore the unused_var warning
    #pragma push
    #pragma ignore unused_var

    proc/GNDN()
        var/nothing // var defined but not used

    #pragma pop

## #pragma syntax directive

See also:
  #pragma directive
  for loop proc
  switch proc

Format:
  #pragma syntax <C|DM> [for|switch]

Changes the syntax used to parse certain statements. This can be more natural for users who prefer non-DM style, and can sometimes do things that regular DM syntax can't do.

Changing the `for()` loop syntax to C will use semicolons to separate the Init, Test, Inc sections instead of commas. That means commas can be used to chain multiple statements together instead.

In switch(), C syntax changes the if/else statements to use C's `case` and/or `default` keywords, followed by a colon, and the `break` statement is required to skip to the end of the switch unless you want to fall through to the next case. Fall-through behavior isn't possible in the default DM syntax.

### Example:

    #pragma push
    #pragma syntax C switch

    switch(thing)
        case 1:
            usr << "This is case 1!"
            break
        case 2, 3:
            usr << "This is case 2 or 3."
            // no break, fall through
        case 4 to 6:
            usr << "This is case 4 through 6 (or maybe 2 or 3)."
            break
        default:
            usr << "This is a different case.

    #pragma pop

## #pragma warn/ignore/error directive

See also:
  #pragma directive
  #warn directive
  #error directive

Format:
  #pragma <warn|ignore|error> WarningName

Changes the way the compiler responds to warnings (except those caused by the `#warn` directive). The warning name appears in the compiler output when the warning is generated.

Multiple warning names can be used in the same pragma, separated by commas.

### Example:

    // temporarily ignore the unused_var warning
    #pragma push
    #pragma ignore unused_var

    proc/GNDN()
        var/nothing // var defined but not used

    #pragma pop

Here is a list of warnings that are disabled by default, but can be turned on for linting purposes:

Name | Description
--- | ---
init_proc | A var in a very commonly used type, like `/turf` or `/atom` or `/datum`, is being initialized with an init proc. An example is `var/stuff[]` or `var/list/stuff = list(1,2,3)` which creates a list in a special internal proc because calling New(). Best practice is to not initialize the list until it's needed.
frequent_call | A very commonly called proc such as New() or Del() has been overridden on a type that gets created or destroyed frequently, such as `/turf`, `/atom`, or `/datum`.

## #undef directive

See also:
  #define directive
  preprocessor

Format:
  #undef Name

Args:
  Name: A macro definition.

The `#undef` statement removes a macro definition.

## #warn directive

See also:
  preprocessor
  #error directive

Format:
  #warn Text

Args:
  Text: a warning message to display

The #warn directive displays the specified message as a warning, but does not prevent the project from compiling.

### Example:

    #ifdef USE_LIGHTING
    #warn The lighting feature in MyLibrary is experimental.
    #endif

## sounds

See also:
  FILE_DIR definition
  cache
  sound proc
  /sound datum
  load_resource proc

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, .mp3, .raw, .wma, and .aiff.

### Example:

    world << sound('fugue.midi')

This example plays the specified midi file to all players.

## text

See also:
  << output operator
  entities (text)
  macros (text)
  tags (text)
  text proc
  Unicode

Text consists of a string of characters enclosed in double quotes. To place a quote inside a string, escape it with a backslash `\` character. You will also need to escape a backslash if you want to use one on purpose.

### Example:

    usr << "He said, \"Hi.\""

This example sends some text to the usr: `He said, "Hi."`

Backslashes are also used for special macros and to escape other characters that would normally be hard to include in a string. A backslash at the end of a line will ignore the line break, and continue the string on the next line after ignoring any leading spaces.

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.

### Example:

    mob/verb/shout(T as text)
      world << "[usr]: [T]"

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!".

Via operator overloading you can define an `operator""` proc for an object to return different text when it's embedded in a string.

### Document strings

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, but it still parses escape characters and embedded expressions.

### Example:

    mob/verb/end()
      usr << {"
    This is the way the world ends
    This is the way the world ends
    This is the way the world ends
    Not with a bang but a whimper.

    --T.S. Eliot "Hollow Men"
    "}
      del world  //the end!

### Raw strings

DM also has a format for raw strings, which do not allow escape characters or embedded expressions. This can be useful for many situations, especially regular expressions which tend to use characters that need escaping. There are three ways to specify a raw string. All of them begin with the `@` character.

Simple raw strings follow `@` with a single-character delimiter, usually `"` but it can be almost anything, and end when that delimiter is seen again. Line breaks are not allowed in simple raw strings.

### Examples:

    world << @"I can say \ or [] without escaping anything!"
    world << @#Here I can use "quotes" but not the pound sign.#

    var/regex/R = new(@/(\d+)/)

    // without raw strings
    world << "I can say \\ or \[] without escaping anything!"   // lying
    world << "I have to escape \"quotes\" to use them."

    var/regex/R = new("(\\d+)")

Complex raw strings use more complicated delimiters, but they let you include line breaks. There are two ways to do this: One starts with `@{"` and ends with `"}`, so it looks like the familiar document string format. The other way starts with `@(XYZ)`, where `XYZ` is any arbitrary text you want it to be, and ends when that same text is encountered.

With a complex raw string, a single leading and/or trailing line break will be ignored.

### Examples:

    world << @{"
    Now I have absolute freedom to use "quotes"
    or [brackets] or line breaks, as long as I
    don't follow a quote with a closing brace.
    "}

    world << @(~~~)
    Until three tilde (~) characters are seen, this is a valid string.
    ~~~     // end of string

    world << @(!!)You don't need a line break if you don't want one.!!

## entities (text)

See also:
  macros (text)
  tags (text)
  text

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 Unicode character number (e.g. `&#38;` is the same as `&amp;`). 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.

Entity | Character
--- | ---
&amp; | &
&lt; | <
&gt; | >
&quot; | "
&copy; | ©

When using numbered entities, you can put an `x` in front of the number to use hexadecimal. For instance `&#x26;`, `&#38;`, and `&amp;` are all equivalent.

## macros (text)

See also:
  icon text macro
  text
  text proc

Text macros start with '\' (a backslash) and end with a space or other punctuation.

    \the, \The // insert 'the' (if needed)
    \a, \an,   // insert 'a(n)' or 'some' (if needed)
    \A, \An

    \he, \He   // insert 'he/she/they/it'
    \she, \She // same
    \his, \His // insert 'his/her/their/its'
    \him       // insert 'him/her/them/it'
    \himself   // insert 'himself/herself/themself/itself'
    \herself   // same
    \hers      // insert 'his/hers/theirs/its'

    \proper    // used in an object name to force proper-noun behavior
    \improper  // used in an object name to force improper-noun behavior

    \th        // insert 1st, 2nd, 5th etc.
    \s         // insert 's' if [] was plural
    \icon      // insert icon of following []
    \ref       // insert a unique id for following []
    \roman     // insert following [] as a lower-case roman numeral
    \Roman     // insert following [] as an upper-case roman numeral
    \...       // suppress final new line
    \t         // insert tab
    \n         // insert new line
    \"         // insert double quote
    \\         // insert backslash
    \<         // insert &amp;lt; (less than)
    \>         // insert &amp;gt; (greater than)
    \(space)   // skip a space
    \(newline) // skip a newline (and following space)

    \xNN       // insert a character by its ASCII/Unicode value
    \uNNNN     // "
    \UNNNNNN   // "

### Example:

    mob/verb/steal(M as mob,obj/O as obj in M)
      O.loc = usr
      view() << "[usr] finds \himself \an [O]."

### Example:

    var/DayCount
    proc/NewDay()
      DayCount++
      world << "The [DayCount]\th day dawns."

### Example:

    obj/CPU
      name = "\improper CPU"  //prevent capitalization from causing proper-noun behavior

## icon text macro

See also:
  icon_state var (atom)
  macros (text)
  style sheets
  tags (text)

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.

### Example:

    usr << "You look like this: \icon[usr]!"

The `\icon` macro expands internally to the <IMG> tag. The above example, could be rewritten like this:

    usr << "You look like this: \
      <IMG CLASS=icon SRC=\ref[usr.icon] ICONSTATE='[usr.icon_state]'>!"

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:

    IMG.icon {width: 16px; height: 16px}

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.

### Example:

    BIG IMG.icon {width: 32px; height: 32px}
    SMALL IMG.icon {width: 16px; height: 16px}

With those rules in place, you could output a full sized icon by using the <BIG> tag:

    usr << "You look like this: <BIG>\icon[usr]</BIG>!"

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:

- ICONSTATE='[state]'
- ICONDIR=[dir], where dir is one of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST
- ICONFRAME=[frame], where frame is the animation frame, starting with 1

### Example:

    usr << "You look like this: \
      <IMG CLASS=icon SRC=\ref[usr.icon] ICONSTATE='glowing' ICONDIR=NORTH ICONFRAME=2>!"

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.

## ref text macro

See also:
  Topic proc (client)
  icon text macro
  locate proc
  macros (text)
  tag var (datum)

The `\ref` text macro inserts a unique identification number or text string for the following embedded object (inside []'s).

In older versions of BYOND, if an object had a tag, that was used instead. However this has often proved to be problematic, so anything compiled from version 512 onward should expect to output a reference number. If you want to use the tag, which stands a better chance of still being valid if the object is deleted and recreated (like in a world reboot), you can output the object's tag explicitly.

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.

### Example:

    mob/verb/test()
       usr << "Click <a href=?src=\ref[src];action=start>here</a>!"
    mob/Topic(href,href_list[])
       switch(href_list["action"])
          if("start")
             usr << "Starting the game..."
          else
             return ..()

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.

### Browser images

In output for browser controls, you can use `\ref[object]` as the src parameter for an <img> tag. The object can be an appearance, an icon, or an atom or image.

If the ref string is for an icon, you can add an HTML query string after the icon reference.

### Example:

    player << browse({"
        <html><body>
        <img src="\ref[icon]?state=hungry&dir=[EAST]">
        </body></html>"})

The query string can include any of the following (separated by & characters):

sheet
  Display all matching frames as a sprite sheet; otherwise the first matching frame is used
state=ICON_STATE
  Use a specific icon state; be sure to url_encode it)
moving=M
  Specify whether to choose only moving (M=1) or non-moving (M=0) states
dir=DIR
  Choose only frames with a specific direction (this should be a number, not text, so for instance `dir=[NORTH]`)
frame=N
  Choose the Nth animation frame in an animated icon

## style sheets

See also:
  CSS attributes
  entities (text)
  macros (text)
  script var (client)
  tags (text)
  text

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:

    "[usr] <span class=combat>spanks</span> [targ]!"
    "[usr] says, '<span class=chat>[msg]</span>'"

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:

    .combat {color: red}
    .chat {color: green}

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 color names are predefined however. You can find a list of them in HTML colors.

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:

    .combat em {font-size: larger}

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:

    .combat em, .chat em {font-size: larger}
    .combat em {font-size: larger}
    .chat em {font-size: larger}

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, #FF0000, 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, underline
text-align | right, left, or center
vertical-align | top, middle, bottom
text-indent | 0.25in, 3em, 20pt
margin-left
margin-right
width | 16px, 32px, auto
height
line-height | 1.2

### fonts

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.

    body {font: 12pt 'Times New Roman', sans-serif}

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 old 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 (1em = 100% of the current font size). 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.

### margins and indents

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:

    body {text-indent: -0.5in; margin-left: 0.5in}

### background colors

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.

### system colors

system notice | general notices from the client
system command echo | command echoing
system command expansion | command-line expansion list
system pager | pager messages
system irc | IRC command prefix

The value of the CLASS attribute may contain a list of classes separated by spaces. This permits client output to be in the 'system' class as well as more specific ones. That allows you to change all of these colors in one shot if you are too lazy to change them each individually. For example, if you define a style sheet that changes the background color, you might need to redefine the various foreground colors like this:

    body {background: aqua; color: black}
    .system {color: red; font-weight: bold}
    .command {color: green}

In this example, the background color of the terminal will be aqua, normal text from the server will be black, and all output from the client will be bold and red, except echoed commands and expansion lists, which will be bold and green. The more specific .command rule is placed after the general .system rule so that its color takes precedence. This is how style sheets are composed—you write general rules first followed by any exceptions.

### style rule precedence

The order in which rules are specified is one of the factors that determines precedence of style sheet commands. The language is known as Cascading Style Sheets because of its ability to handle several layers of stylistic rules, intermingling the configurations of the user and the designer in an ordered fashion.

Rules are selected by first finding all matching candidates for a given attribute in the current HTML tag being processed. If there is more than one, rules from a higher level style sheet take precedence over lower level ones. That means the basic user configurable settings in DreamSeeker are the lowest priority, followed by a style sheet in the user's `.dms` script file, followed by a style sheet from the designer's `client.script` setting, because that is the order in which these are read by the style sheet manager.

Rules from the same style sheet are ordered by specificity. The selector `span.chat` is more specific than `.chat` and `.chat em` is more specific than `em`. In general, the more classes referenced by a selector, the more specific it is. When that results in a tie, the selector with the greater number of tags takes precedence.

If two rules about the same attribute come from the same sheet and have the same specificity, the final one to be defined takes precedence.

In the rare event that a rule needs to break out of the normal order of precedence, it can be flagged as important. In this case it will take precedence over all other "unimportant" rules. However, if more than one rule is important, the normal rules of precedence will be used to resolve the conflict.

The important flag is applied after the attribute assignment like this:

    body {background: white ! important; font: serif}

In the above example, only the background color is important, not the font specification.

### `style` attribute

Style commands may also be inserted directly in an html tag to control its appearance. This does not have the advantages of style sheets, which separate content from presentation, but it does allow you to use the style sheet syntax when formatting text.

The following example uses the style attribute to color some text:

    usr << "That <span style='color: red'>HURT</span>!"

As you can see, the `style` attribute of any tag can be assigned to a text string containing a list of attribute assignments. Just the body of the style rule is given, since no selector is needed to match the current context.

### Maptext options

The atom.maptext var supports some additional CSS attributes.

vertical-align | top, middle, bottom
text-shadow | x-offset y-offset blur color
-dm-text-outline | width color style

Additionally, you can use the `:hover` pseudo-class to change the color of a link. As with other link pseudo-classes, only the text color can currently be changed.

## tags (text)

See also:
  entities (text)
  macros (text)
  style sheets
  text

Text tags (also known as elements by snooty HTML purists) control how the text is formatted. HTML syntax is used, so all tags start with `<` and end with `>`. The tags which are currently supported by Dream Seeker, are listed below:

    <A></A>              // anchor (hyperlink)
    <ACRONYM></ACRONYM>  // acronym or abbreviation
    <B></B>              // bold text
    <BIG></BIG>          // one size bigger text
    <BODY></BODY>        // body of html document
    <BR>                 // line break
    <CITE></CITE>        // citation reference
    <CODE></CODE>        // program source code
    <DFN></DFN>          // definition
    <DIV></DIV>          // used in conjunction with style sheets
    <EM></EM>            // emphasized text
    <FONT></FONT>        // font face, color, and size
    <H1></H1>            // heading level
    <H2></H2>
    <H3></H3>
    <H4></H4>
    <H5></H5>
    <H6></H6>
    <HEAD></HEAD>        // document head section
    <HTML></HTML>        // html document
    <I></I>              // italic text
    <IMG></IMG>          // display icons
    <KBD></KBD>          // keyboard input
    <P></P>              // paragraph
    <PRE></PRE>          // pre-formatted text
    <S></S>              // overstrike text
    <SAMP></SAMP>        // sample output
    <SMALL></SMALL>      // one size smaller text
    <SPAN></SPAN>        // used in conjunction with style sheets
    <STRONG></STRONG>    // strongly emphasized text
    <STYLE></STYLE>      // contains a style sheet
    <TITLE></TITLE>      // document title
    <TT></TT>            // typewriter style
    <U></U>              // underline
    <VAR></VAR>          // variable name
    <XMP></XMP>          // preformatted (tags ignored)

In addition to these, the `<BEEP>` tag, which is not standard HTML, may be used to beep the terminal.

Some tags take additional parameters, known as attributes. The most common ones are `<FONT>` and `<A>`. The syntax for these is illustrated by the following two examples:

    "How about <FONT FACE=Arial COLOR=red SIZE=+1>this</FONT>!"
    "Click <A HREF=byond.com TITLE=BYOND!>here</A>!"

As many attributes may be specified as desired. The attribute value may have quotes around it, but this is only necessary if the value contains spaces. It is usually more convenient to use single quotes so you don't have to escape the double quotes, but you can also embed the HTML in a text document to avoid the need for escaping quotes.

When applying color to text, you can use hexadecimal RGB or you can use one of the named HTML colors.

Text sizes range from 1 to 7, 1 being the smallest and 7 being the largest. In addition to absolute sizes, relative sizes may be specified (like +1 for one size bigger or -1 for one size smaller).

## vars list var (global)

See also:
  vars list var (datum)

This is a list of all global variables. The items in the list are the variable names. If the variable name is used as an index into the list, the value of that variable is accessed.

### Example:

    mob/verb/dumpglobal()
       for(var/V in global.vars)
          usr << "[V] = [global.vars[V]]"

This example displays all global variables. The `global` keyword is used here to distinguish it from `src.vars`, which in this example would be the mob's vars.

## area

See also:
  atom
  procs (area)
  rooms
  vars (area)

Areas are derived from `/area`, which derives from `/atom`. Regions on the map may be assigned to an area by painting it onto the map. Areas off the map serve as rooms that objects may enter and exit.

For each area type defined, one area object is created at runtime. So for areas on the map, all squares with the same area type belong to the same instance of the area.

Additional instances of rooms may be created from the same type by explicitly creating them with null as the initial location. That is, the first argument to `new()` should either be `null` or left unspecified.

The following example defines the area prototype `/area/outside`. It also defines an action to be taken when somebody enters an area, namely to display its description.

### Example:

    area
      Entered(O)
        if(desc) O << desc
        return ..()

      outside
        desc = "Ah!  A breath of fresh air!"

## procs (area)

Built-in area procs:

area/proc
  Click
  Cross proc
  Crossed proc
  DblClick
  Del
  Enter
  Entered
  Exit
  Exited
  MouseDown
  MouseDrag
  MouseDrop
  MouseEntered
  MouseExited
  MouseMove
  MouseUp
  MouseWheel
  New
  Read
  Stat
  Topic
  Uncross proc
  Uncrossed proc
  Write

## rooms

Areas that are not located on the map are referred to as rooms. When a player enters one, the map goes away and you have something like a text MUD. By default, there would be no way for players to move from one room to another, so you have to handle movement yourself.

You can check the variable area.x to see if a given area is on the map or not.

The following example puts players in a room when they log in and provides a single exit.

### Example:

    mob/Login()
       if(!loc) Move(locate(/area/birthing_hut))
       return ..()

    area/birthing_hut
       Entered(O)
          O << "Waaaaah!  You land in a pile of straw."
          return ..()
       verb/exit()
          if(Move(locate(1,1,1))) //jump to the map or whatever
             usr << "You crawl into the open air..."
          else
             usr << "The hut door is blocked.  You cannot get out."

## vars (area)

Built-in area vars:

area/var
  alpha
  appearance
  appearance_flags
  blend_mode
  color
  contents
  density
  desc
  dir
  filters
  gender
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  underlays
  overlays
  layer
  luminosity
  maptext
  maptext_width
  maptext_height
  maptext_x
  maptext_y
  mouse_over_pointer
  mouse_drag_pointer
  mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  parent_type
  pixloc
  plane
  render_source
  render_target
  suffix
  tag
  text
  transform
  type
  vars
  verbs

## parent_type var (area)

See also:
  parent_type var

The default parent_type of /area is /atom.

## atom

See also:
  area
  datum
  mob
  movable atoms
  obj
  procs (atom)
  turf
  vars (atom)

The /atom object type is the ancestor of all mappable objects in the game. The types /area, /turf, /obj, and /mob are all derived from /atom. You should not create instances of /atom directly but should use /area, /turf, /obj, and /mob for actual objects. The /atom object type exists for the purpose of defining variables or procedures that are shared by all of the other "physical" objects. These are also the only objects for which verbs may be accessible to the user.

/atom is derived from /datum, so it inherits the basic properties that are shared by all DM objects.

## movable atoms

See also:
  atom
  mob
  obj
  procs (movable atoms)
  vars (movable atoms)

The /atom/movable object type is the ancestor of all mappable objects that are capable of motion. The types /obj and /mob are derived from /atom/movable. You should not create instances of /atom/movable but should use /obj and /mob for actual objects. This object definition exists solely to define variables and procedures related to motion.

## procs (movable atoms)

Built-in movement procs:

atom/movable/proc
  Bump
  Move

## Bump proc (movable atom)

See also:
  Move proc (movable atom)
  Pixel movement

Format:
  Bump(atom/Obstacle)

When:
  Called when a movement fails due to a dense blockage.

Args:
  Obstacle: The blocking object.

Default action:
  If the obstacle is a mob and src is in its group, swap their positions. This is only done if the mobs both move by full tiles and do not use pixel movement, to preserve the behavior of older games.

## Cross proc (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)
  group var (mob)
  movement_mode var (world)
  Pixel movement

Format:
  Cross(atom/movable/O)

Returns:
  1 to permit; 0 to deny.

When:
  Called when another object attempts to overlap this one.

Args:
  O: the object attempting to overlap.

Default action:
  Allow overlap unless both atoms are dense. If both atoms are mobs, the behavior depends partly on whether they are in the same group.

The following behavior only applies to LEGACY_MOVEMENT_MODE. In other movement modes, src.Cross(O) returns 0 by default if src and O are both mobs in the same group.

If src completely covers the turf it is standing on, Cross() is called as part of turf.Enter(). This is to preserve the behavior of older games, which expect turf.Enter() to care about its contents.

If src and O are both mobs, and O is in src's group, overlap is allowed unless neither of them use pixel movement. Older games that do not use pixel movement expect that Bump() will be called, and by default Bump() will swap the mobs' positions. Swapping obviously only works in situations where a mob takes up a whole tile and only moves by tiles; for all other situations, allowing an overlap makes more sense.

## Crossed proc (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)
  group var (mob)
  Pixel movement

Format:
  Crossed(atom/movable/O)

When:
  Called when an object has overlapped this one through Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Crossed() or any other movement side-effects. The same goes for creation or deletion of an object at a location.

Args:
  O: the object that moved and is now overlapping.

Default action:
  none

### Example:

    obj/landmine
       Crossed(O)
          O << "You stepped on a land mine!"
          Explode()

## Move proc (movable atom)

See also:
  Bump proc (movable atom)
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  loc var (atom)
  locs list var (movable atom)
  walk proc
  Gliding
  Pixel movement

Format:
  Move(NewLoc,Dir=0,step_x=0,step_y=0)

Returns:
  Success (jump): 1
  Success (slide): Number of pixels moved
  Failure: 0

When:
  Called to move the object. By default, client.Move() calls this proc when players use direction keys. The automated movement functions (like walk()) also call this proc. Directly setting the loc variable does not call this procedure.

Args:
  NewLoc: The new location.
  Dir: The direction of movement (or 0).
  step_x: The new step_x value, relative to NewLoc
  step_y: The new step_y value, relative to NewLoc

Any Move() is either a slide or a jump. Normal walking around is a slide; it can be stopped partway. A jump is pass/fail. See more information below.

This is what happens by default:

1. oldloc.Exit(src) is called for any turfs or areas being vacated, or the container if moving out of an obj or mob. neighbor.Uncross(src) is called for any atoms that will no longer be overlapping this object. If any of these return 0 (failure), movement fails.

2. newloc.Enter(src) is called for any turfs or areas that may be entered for the first time, or the container if moving into an obj or mob. neighbor.Cross(src) is called for any atoms that may be in collision with this object if the move fully succeeds. If any of these return 0 (failure), then a slide can be cut short but a jump will fail completely.

3. If any obstacles were encountered via Enter() or Cross() failing, then src.Bump(obstacle) will be called for each of them.

4. If movement did not fail completely, then loc and step_x/y, will be changed, and the following calls will be made: oldloc.Exited() for any turfs, areas, or other containers vacated; neighbor.Uncrossed() for any movable atoms no longer overlapping; newloc.Entered() for any turfs, areas, or other containers being entered for the first time; and neighbor.Crossed() for any movable atoms now overlapping the object.

A movement is considered a slide if src is moving from one turf to another on the same z level, and the total pixel distance is less than either src.step_size or a full tile size (whichever is largest). Any other movement is a jump. Movement to the same turf with no step_x/y change is also considered a jump.

## Uncross proc (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)
  group var (mob)
  Pixel movement

Format:
  Uncross(atom/movable/O)

Returns:
  1 to permit; 0 to deny.

When:
  Called when another object attempts to stop overlapping this one.

Args:
  O: the object attempting to get away.

Default action:
  Allow the object to get away (returning 1)

## Uncrossed proc (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Move proc (movable atom)
  group var (mob)
  Pixel movement

Format:
  Uncrossed(atom/movable/O)

When:
  Called when an object has stopped overlapping this one through a call to Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Uncrossed() or any other movement side-effects. The same goes for deletion of an object.

Args:
  O: the object that moved and is no longer overlapping.

Default action:
  none

### Example:

    obj/pressure_plate
       Uncrossed(O)
          // if no other mobs are standing on it...
          if(!(locate(/mob) in bounds()))
             // do something
             Release()

## vars (movable atoms)

Built-in movement vars:

atom/movable/var
  animate_movement
  bound_x
  bound_y
  bound_width
  bound_height
  locs
  screen_loc
  glide_size
  particles
  step_size
  step_x
  step_y

## animate_movement var (movable atoms)

See also:
  Move proc (movable atom)
  glide_size var (movable atoms)
  Gliding

Default value:
  FORWARD_STEPS (1)

Possible values:
  NO_STEPS (0)
  FORWARD_STEPS (1)
  SLIDE_STEPS (2)
  SYNC_STEPS (3)

Setting this to 0 causes movement between two adjacent positions to be displayed as a single discrete jump. Otherwise, objects will be made to glide from one position to another, using the movement animation defined in the icon file if one is defined.

By default, movement animation avoids cutting corners, since this can look very bad in some games. If you want objects to take the shortest (and smoothest) visual path when moving around, use `SLIDE_STEPS` instead of the default `FORWARD_STEPS`. This also allows the object to be facing in a different direction than it is moving, so make sure this is what you want.

`SYNC_STEPS` is intended for objects that move in unison as part of a larger "conglomerate" object. You should set the movement animation to `SYNC_STEPS` on all but a single "head" object, which will serve as the leader when choosing pixel step sizes. If you do not use `SYNC_STEPS`, there are cases where the pixel offsets of objects may get out of sync during motion, causing the object to visually break up. Because of the advent of features like big icons, this value is no longer of much use.

Note: This setting has no impact when used with pixel movement, except in special cases. See Gliding for more details.

## bound_x var (movable atom)

See also:
  icon_w var (atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)
  locs list var (movable atom)
  Pixel movement

Default value:
  0

Note: The bound_x/y vars aren't exactly deprecated, but it's preferable to use icon_w/z or pixel_w/z instead. Best practice is to avoid bound_x/y altogether, and use bound_width/height alone to define a bounding box. New behavior simply subtracts bound_x/y from pixel_w/z to mimic the old usage.

This var defines the left side of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

The left edge of the bounding box starts bound_x pixels inward from the left edge of the atom's icon (as affected by step_x). A bound_x value of 4 means the atom has 4 pixels of empty space to its left.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_x value of 8, since there are 8 pixels of empty space to the left.

## bound_y var (movable atom)

See also:
  icon_z var (atom)
  bound_x var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)
  locs list var (movable atom)
  Pixel movement

Default value:
  0

Note: The bound_x/y vars aren't exactly deprecated, but it's preferable to use icon_w/z or pixel_w/z instead. Best practice is to avoid bound_x/y altogether, and use bound_width/height alone to define a bounding box. New behavior simply subtracts bound_x/y from pixel_w/z to mimic the old usage.

This var defines the bottom side of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

The bottom edge of the bounding box starts bound_y pixels inward from the bottom edge of the atom's icon (as affected by step_y). A bound_y value of 4 means the atom has 4 pixels of empty space below it.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_y value of 8, since there are 8 pixels of empty space below.

## bound_width var (movable atom)

See also:
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_height var (movable atom)
  icon_w var (atom)
  icon_z var (atom)
  step_x var (movable atom)
  step_y var (movable atom)
  locs list var (movable atom)
  icon_size var (world)
  Pixel movement

Default value:
  32 (width of default icon; depends on world.icon_size)

This var defines the width of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_width value of 16.

## bound_height var (movable atom)

See also:
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  icon_w var (atom)
  icon_z var (atom)
  step_x var (movable atom)
  step_y var (movable atom)
  locs list var (movable atom)
  icon_size var (world)
  map_format var (world)
  Pixel movement

Default value:
  32 (depends on world.icon_size)

This var defines the height of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_height value of 16.

The default value depends on world.icon_size and world.map_format. In a topdown or tiled map_format, the icon height specified in world.icon_size is used. In other modes, height is irrelevant and tile "footprints" are square, so the icon width is used.

## glide_size var (movable atoms)

See also:
  animate_movement var (movable atoms)
  glide_size var (client)
  pixel_x var (atom)
  pixel_y var (atom)
  icon_size var (world)
  movement_mode var (world)
  fps var (client)
  Gliding

Default value:
  0

Note: The way this setting is used depends on world.movement_mode. See Gliding for more details.

This controls the number of pixels an object is moved in each footstep during animated movement. The default value of 0 chooses automated control over this value, which generally results in a minimum footstep of 4 pixels that is increased when necessary to keep up with motion on the turf grid.

Decimal values are allowed.

Be careful about using small glide sizes. Icons with high contrast pixel-level detail can look pretty ugly when displaced by short distances.

The glide size is measured in server ticks. If you use a different client tick rate by altering `client.fps` or `client.tick_lag`, the actual glide used will be scaled appropriately. E.g., if your `client.fps` is 4 times greater than `world.fps`, the actual glide amount each client tick will be `glide_size/4`.

This was renamed from `pixel_step_size`.

## locs list var (movable atom)

See also:
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)
  loc var (atom)
  contents list var (atom)

Default value:
  list(src.loc)

This read-only var tells which turfs are being physically covered by the atom's bounding box. The purpose of this is for cases where you set the atom's bounds to change its physical size so that it ends up covering more than one turf.

This is different from the loc var in that every atom still has only one "true" location. A movable atom may cover multiple turfs, but only one turf is its loc. The loc var can be thought of as an anchor point, while the actual physical footprint is in locs.

For every turf in locs, this atom will also be in that turf's contents list.

If loc is not a turf, it will be the only item in the locs list. If loc is null, locs will be empty.

## particles var (movable atom)

See also:
  Particle effects

Default value:
  null

A datum (not derived from /atom) containing information about a particle set attached to this atom. See Particle effects for more information.

Resetting this var to null after it has contained a particle set will cause any existing particles on this object to immiediately disappear.

## pixel_step_size var (movable atoms)

Renamed to glide_size.

## screen_loc var (movable atoms)

See also:
  HUD / screen objects
  layer var (atom)
  screen var (client)
  view var (client)
  map_format var (world)

This is a text string that controls where an object that is listed in client.screen will appear on the user's screen. The format is:

    "x,y"
    "x:px,y:py"
    "x1,y1 to x2,y2"

The bottom left corner of the map viewport (southwest) is `"1,1"`. If the view is 11x11, then the top-right corner (northeast) is `"11,11"`. (Changing world.map_format may change the range for screen_loc.)

A range of coordinates (the second format above) causes a square region to be filled with the object at each position. The southwest and northeast corners of the box are indicated in the screen_loc value.

If you use a `screen_loc` outside of the normal map view, extra tiles will be added to that side and the map will be clipped. For example, a value of `"0,1"` adds an extra column of tiles to the left, but that column will be blank except for any screen objects you show there. This is used if you want screen objects to provide a border around the map.

### Special keywords

The edges of the map may also be referenced by using directions, such as `"3,NORTH"`. For convenience, the order of coordinates is arbitrary when using directions, so one may specify y before x as in `"NORTH,WEST"`. In expressions such as the latter, you may also leave out the comma. Icon size is not taken into account, so a big icon with a screen_loc of `"SOUTHEAST"` will extend further to the right and may create a border (see "Outside the map" below).

The `CENTER` keyword can also be used. This can be used alone to completely center the object, or as either the x or y component. If the map covers an even number of tiles in either direction, pixel offsets will be applied automatically. Centering is relative to the regular map edges, and it does not take the icon's size into account.

The `LEFT`, `RIGHT`, `TOP`, and `BOTTOM` keywords (also `TOPLEFT`, `TOPRIGHT`, `BOTTOMLEFT`, `BOTTOMRIGHT`) can be used to anchor a screen object to the edge of the map control if the map is zoomed in so that some pixels are cut off. When you use these edge-alignment keywords, the icon size is taken into account, and the alignment of the icon changes to fit whichever edge you use. Because these keywords do not conform to the normal tile-based structure of the HUD, they can't be used for a range of tiles with the `"to"` format.

The equivalent to `CENTER` for the `LEFT`/`RIGHT`/`TOP`/`BOTTOM` keywords is `MIDDLE`. It acts the same as `LEFT+50%`, `BOTTOM+50%`, or both.

Note: Letterboxing, the blank space to either side of the map if it doesn't take up the whole map control, is not considered usable space. HUD objects aligned to the control edge appear inside any letterboxing, not on top of it.

`SCREEN_SOUTHWEST`, `SCREEN_EAST`, and other directions with `SCREEN_` in front will anchor a screen object relative to the extent of all other screen objects. That is, if you extend the screen beyond the map with another object that uses `0,0`, then `SCREEN_SOUTHWEST` will refer to `0,0` instead of the normal `1,1` that `SOUTHWEST` would do.

This is especially useful if you're using a render_source to copy a plane master. The object using `render_source` should be anchored at `SCREEN_SOUTHWEST`, which is the corner of the plane.

### Outside the map

In addition to objects inside of the map view, one may create border objects. Borders are automatically created when screen objects are placed at coordinates outside of the inner map view. For example, objects placed at y=0 fall on a border directly below the map and y=-1 is one tile below that. (The `CENTER` keyword is based on normal viewport bounds and not any extra borders.)

A big icon placed towards the northeast end of the map, if it spills over the edge, will create a border big enough for the whole icon to be shown. You can avoid this by using the `TILE_BOUND` appearance flag. Transforms on this atom are not taken into account when determining whether to add a border.

### Offsets

Offsets may be applied to screen_loc coordinates. For example, `"NORTH+1,WEST"` is in a border above the map. `"CENTER+2,CENTER-1"` will appear 2 units right, 1 unit down from the center of the map.

Non-integer offsets like 1.5 are allowed; the fractional part will be counted towards a pixel offset.

Offsets may be specified in percentages as well. These effectively always count as pixel offsets and will never be used to determine if a border should be added. `"WEST+100%"` and `"100%"` are basically identical to `"EAST"` in most respects, and `"WEST+50%"` is basically the same as `"CENTER"`. If you're using the edge keywords (`LEFT`, `TOP`, etc.), this percentage is relative to the control edge and also factors in the icon size, so `"LEFT+100%"` is equivalent to `"RIGHT"`.

It is also possible to specify a pixel offset. Screen objects do not use `pixel_x` and `pixel_y` for this purpose, because it is intended that an object could exist on the map and in the screen object list simultaneously, so positioning must be independent. Pixel offsets are specified after a colon like this: `"1:16,1:16"`. In this case the object is shifted to the northeast by 16 pixels.

### Layering

Screen objects on a plane will appear above non-screen objects on the same plane regardless of layer, except that `BACKGROUND_LAYER` or `EFFECTS_LAYER` may be used to move the objects forward or back.

### Secondary map controls

You can use HUD objects in any additional map controls that might appear in game's skin file. If you have a second map named `map2` for instance, then you can use `"map2:1,1"` or something similar as a `screen_loc`. If the map control is set to automatically scale to fit its contents, it will try to show every object you put there.

Note: For secondary-map HUD items, you should not use the full `window.control` ID, just the id of the control itself. Map controls should always have a unique `id`.

## step_size var (movable atom)

See also:
  step_x var (movable atom)
  step_y var (movable atom)
  Move proc (movable atom)
  locs list var (movable atom)
  fps var (world)
  icon_size var (world)
  Gliding
  Pixel movement

Default value:
  32 (width of default icon; depends on world.icon_size)

This var defines how fast, in pixels, an atom will move by default. If you use lower values of `step_size` for most items in your world, you may want to consider raising `world.fps` (at higher performance cost).

When `Move()` is called by a step or walk, or by the built-in client movement verbs, a change of `step_size` is applied to `step_x` and/or `step_y`. Any movement within the speed of `step_size`, or up to one tile in distance (whichever is greater), is considered a slide and may partially succeed if an obstacle is bumped before reaching the final position.

## step_x var (movable atom)

See also:
  step_y var (movable atom)
  step_size var (movable atom)
  bound_x var (movable atom)
  Move proc (movable atom)
  locs list var (movable atom)
  Pixel movement

Default value:
  0

This var defines the position of the atom (in pixels) relative to its tile, on the x axis. A step_x of 5 means the atom actually is shown 5 pixels east of the tile's western edge.

The atom's actual bounding box may not begin at step_x, but can be set even further in via bound_x.

Example: A 16×16 smiley face centered in a 32×32 icon should have the following bounds:

- bound_x = 8
- bound_y = 8
- bound_width = 16
- bound_height = 16

For the smiley to appear at the left edge of the tile it is standing on, it would need a step_x value of -8. A step_x value of 8 takes it all the way to the rightmost edge of the tile. Anything outside of the range -8 to 8 will have the atom straddling multiple turfs.

## step_y var (movable atom)

See also:
  step_x var (movable atom)
  step_size var (movable atom)
  bound_y var (movable atom)
  Move proc (movable atom)
  locs list var (movable atom)
  Pixel movement

Default value:
  0

This var defines the position of the atom (in pixels) relative to its tile, on the y axis. A step_y of 5 means the atom actually is shown 5 pixels north of the tile's southern edge.

The atom's actual bounding box may not begin at step_y, but can be set even further in via bound_y.

Example: A 16×16 smiley face centered in a 32×32 icon should have the following bounds:

- bound_x = 8
- bound_y = 8
- bound_width = 16
- bound_height = 16

For the smiley to appear at the bottom edge of the tile it is standing on, it would need a step_y value of -8. A step_y value of 8 takes it all the way to the top edge of the tile. Anything outside of the range -8 to 8 will have the atom straddling multiple turfs.

## procs (atom)

Built-in atom procs:

atom/proc
  Click
  Cross proc
  Crossed proc
  DblClick
  Del
  Enter
  Entered
  Exit
  Exited
  MouseDown
  MouseDrag
  MouseDrop
  MouseEntered
  MouseExited
  MouseMove
  MouseUp
  MouseWheel
  New
  Read
  Stat
  Topic
  Uncross proc
  Uncrossed proc
  Write

## Click proc (atom)

See also:
  Click proc (client)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  show_popup_menus var (client)

Format:
  Click(location,control,params)

When:
  Called when the object is clicked.

Args:
  location: the turf, stat panel, grid cell, etc. in which the object was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This proc is called by the default client.Click() procedure.

The following example allows the player to walk to a position by clicking it.

### Example:

    turf/Click()
      walk_to(usr,src)

## DblClick proc (atom)

See also:
  Click proc (atom)
  DblClick proc (client)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  show_popup_menus var (client)

Format:
  DblClick(location,control,params)

When:
  Called when the object is double-clicked.

Args:
  location: the turf, stat panel, grid cell, etc. in which the object was double-clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This proc is called by the default client.DblClick() procedure.

This example allows the player to teleport to a position by double clicking it.

### Example:

    turf/DblClick()
      usr.Move(src)

## Enter proc (atom)

See also:
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)
  movement_mode var (world)
  Pixel movement

Format:
  Enter(atom/movable/O, atom/oldloc)

Returns:
  1 to permit; 0 to deny.

When:
  Called when an object attempts to enter the contents list.

Args:
  O: the object attempting to enter.
  oldloc: the old (current) loc of the object attempting to enter.

Default action:
  Explained below.

Areas, objs, and mobs will always permit anything to enter by default.

The following behavior only applies to LEGACY_MOVEMENT_MODE. In all other movement modes, the turf's contents are not taken into account. Only the result of turf.Cross() matters.

Turfs will return 1 (permit) or 0 (deny) based on density. In simple terms, if the atom that is entering is dense, then the turf will deny entry if the turf itself or its contents (any that take up the full tile) are dense.

What actually happens in turf.Enter() is more detailed: Cross() is called for the turf, and if it succeeds (movement is permitted), then Cross() is called for any atoms in turf.contents that cover the entire tile. If any Cross() call fails, Enter() fails too and will return 0.

If a mob is standing on a turf but its bounding box does not cover the whole tile, it is ignored by Enter(). Instead, its Cross() proc is called if there is a danger of the object overlapping it.

## Entered proc (atom)

See also:
  Enter proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)

Format:
  Entered(atom/movable/Obj,atom/OldLoc)

When:
  Called when an object has entered the contents list through Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Entered() or any other movement side-effects. The same goes for creation or deletion of an object at a location.

Args:
  Obj: the object that entered (a mob or obj).
  OldLoc: the previous location of the object.

Default action:
  None for most atoms, but turfs will call Crossed().

### Example:

    turf/pit
       Entered(O)
          O << "OUCH.  You fell in a pit!"

The mob's Entered() and Exited() procs can be used to control what happens when objects are added or removed from the mob's inventory. Of course that could all be done within get() and drop() verbs, but the following code separates user interface from lower-level functions.

### Example:

    obj
       var
          weight = 10
       verb
          get()
             set src in oview(1)
             if(Move(usr))
                usr << "You pick up \a [src]."
             else
                usr << "You cannot pick up [src]."
          drop()
             set src in usr
             if(Move(usr.loc))
                usr << "You drop \a [src]."
    mob
       var
          weight
          max_weight = 50

       Entered(obj/O)
          weight += O.weight
       Exited(obj/O)
          weight -= O.weight
       Enter(obj/O)
          //only allow entrance if weight is within the limit
          if(O.weight + weight <= max_weight)
             return ..()

To see the advantages of this arrangement, imagine that there are certain situations in which an object may be created directly within the mob's inventory without the mob picking it up. You can still run it through your normal movement rules without calling get().

### Example:

    mob/verb/wish()
       var/obj/O = new() //create it with loc=null
       if(O.Move(usr))   //and then move it into inventory
          usr << "Your wish has been granted!"
       else
          usr << "You are too greedy!"
          del O

## Exit proc (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exited proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)
  movement_mode var (world)

Format:
  Exit(atom/movable/O, atom/newloc)

Returns:
  1 to permit; 0 to deny.

When:
  Called when an object attempts to exit the contents list.

Args:
  O: the object attempting to exit.
  newloc: the object's new location.

Default action:
  Turfs will call Uncross() and return that value (1 by default). All others allow the object to exit (returning 1).

By default, every atom returns 1 to allow exit, except for turfs which call Uncross() to handle it for them.

The following behavior only applies to LEGACY_MOVEMENT_MODE. In all other movement modes, the turf's contents are not taken into account. Only the result of turf.Uncross() matters.

In the default Exit handler for turfs, Uncross() is called for the turf itself and then Uncross() will also be called for any atoms in turf.contents that cover the entire tile. If any Uncross() call fails, Exit() fails too and will return 0. In games using pixel movement, Uncross() is usually called separately, but this allows projects using tile-based movement instead to benefit from Cross() and Uncross().

## Exited proc (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  Move proc (movable atom)

Format:
  Exited(atom/movable/Obj, atom/newloc)

When:
  Called when an object has exited from the contents list through a call to Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Exited() or any other movement side-effects. The same goes for deletion of an object.

Args:
  Obj: the object that exited (a mob or obj).
  newloc: the object's new location.

Default action:
  None for most atoms, but turfs will call Uncrossed().

## MouseDown proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (client)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseDown(location,control,params)

Args:
  location: the turf, stat panel, grid cell, etc. in which the object was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when a mouse button is pressed while pointing to this object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through `Click()`, `DblClick()`, and `MouseDrop()`. The other procedures are simply available for completeness.

Note: In BYOND 3.5 this procedure took three different arguments: `location`, `icon_x`, and `icon_y`. Since `icon_x` and `icon_y` have been replaced, old code will need to be modified. Games compiled before this change will still work normally.

## MouseDrag proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (client)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseDrag(over_object,src_location,over_location,src_control,over_control,params)

Args:
  over_object: the object under the mouse pointer
  src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
  over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
  src_control: The id of the skin control the object was dragged from
  over_control: The id of the skin control the object was dragged over
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called while dragging this object by pressing and holding the left mouse button over the object and moving the mouse. The over_object may be null if dragging over a stat panel or over other empty space.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through `Click()`, `DblClick()`, and `MouseDrop()`. The other procedures are simply available for completeness.

## MouseDrop proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (client)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseDrop(over_object,src_location,over_location,src_control,over_control,params)

Args:
  over_object: the object under the mouse pointer
  src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
  over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
  src_control: The id of the skin control the object was dragged from
  over_control: The id of the skin control the object was dropped onto
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the a mouse button is released after dragging this object. The over_object may be null if dropping over a stat panel or over other empty space.

## MouseEntered proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (client)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseEntered(location,control,params)

Args:
  location: the turf, stat panel, grid cell, etc. containing the object
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse moves onto the object with no buttons pressed.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

## MouseExited proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (client)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseExited(location,control,params)

Args:
  location: the turf, stat panel, grid cell, etc. containing the object
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse moves off of an object with no buttons pressed.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

## MouseMove proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (client)
  MouseUp proc (atom)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseMove(location,control,params)

Args:
  location: the turf, stat panel, grid cell, etc. containing the object
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse moves over the object with no buttons pressed. When the mouse moves over for the first time, MouseEntered() is called instead.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

## MouseUp proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (client)
  MouseWheel proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  MouseUp(location,control,params)

Args:
  location: the turf, stat panel, grid cell, etc. in which the object was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when a mouse button is released while pointing to this object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through `Click()`, `DblClick()`, and `MouseDrop()`. The other procedures are simply available for completeness.

Note: In BYOND 3.5 this procedure took three different arguments: `location`, `icon_x`, and `icon_y`. Since `icon_x` and `icon_y` have been replaced, old code will need to be modified. Games compiled before this change will still work normally.

## MouseWheel proc (atom)

See also:
  Click proc (atom)
  DblClick proc (atom)
  MouseDown proc (atom)
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  MouseUp proc (atom)
  MouseWheel proc (client)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)

Format:
  MouseWheel(delta_x,delta_y,location,control,params)

Args:
  delta_x,delta_y: amount of wheel movement
  location: the turf, stat panel, grid cell, etc. containing the object
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse wheel is moved while over an object.

Positive values of delta_x and delta_y refer to scrolling right or up, respectively. Negative values are left and down, respectively.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

## New proc (atom)

See also:
  New proc (datum)
  new proc

Format:
  New(loc)
  (supports named arguments)

When:
  Called when the object is created.

Args:
  loc: The initial location.

Default action:
  None.

By the time New() is called, the object has already been created at the specified location and all of its variables have been initialized. You can perform additional initialization by overriding this procedure.

Since the initial location parameter passed to `new()` is applied before New() is even called, there is some special handling of the loc variable when using named arguments in a call. Normally, if a procedure is overridden, named arguments in a call are matched against those in the the overridden definition. In this case, however, the loc parameter name is hard-coded. Regardless of what you call the first argument in your definition of New(), the initial location will be taken from the first positional argument, or from the argument named loc if there are no positional arguments.

The following example does some extra initialization that is not possible in the variable definition section, because it requires a runtime evaluation. This is a common reason to use New().

### Example:

    mob
       var
          birthdate //time stamp
       New()
          birthdate = world.realtime
          return ..()
       verb/look()
          set src in view()
          usr << "[src] was born on [time2text(birthdate,"DD-MMM-YYYY")]."

## Stat proc (atom)

See also:
  Stat proc (client)
  stat proc
  Info control (skin)

Format:
  Stat()

When:
  Called periodically by the client to update the stat window.

Default action:
  none.

The following code could be used to display a player's current status.

### Example:

    mob/var
       health = 100
    mob/Stat()
       stat("health",health)
       statpanel("Inventory",contents)

## vars (atom)

Built-in atom vars:

atom/var
  alpha
  appearance
  appearance_flags
  blend_mode
  color
  contents
  density
  desc
  dir
  filters
  gender
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  infra_luminosity
  loc
  layer
  luminosity
  maptext
  maptext_width
  maptext_height
  maptext_x
  maptext_y
  mouse_over_pointer
  mouse_drag_pointer
  mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  overlays
  override (images only)
  parent_type
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  plane
  render_source
  render_target
  suffix
  tag
  text
  transform
  type
  underlays
  vars
  verbs
  x
  y
  z

## alpha var (atom)

See also:
  vars (atom)
  appearance_flags var (atom)
  blend_mode var (atom)
  color var (atom)

Default value:
  255 (opaque)

Possible values:
  0 (transparent) through 255 (opaque)

Controls the opacity of the icon displayed on players' screens. A value of 128 means the atom is half-transparent, so it will have a ghostly appearance. This can be used to fade an atom in and out, especially when combined with animation. Alpha is also applied to maptext.

Overlays and images will also be affected by alpha, unless they use the RESET_ALPHA value in appearance_flags.

## appearance var (atom)

See also:
  vars (atom)
  mutable appearance
  Understanding the renderer

Every atom or image has an appearance, which controls all of the values relating to how it appears on the map. (The overlays and underlays lists are lists of appearances.) When read, this var provides a copy of the current appearance.

This value can also be used to change an atom's appearance, altering multiple values at once. Setting atom.appearance to another appearance will change all of the following values to match:

  alpha
  appearance_flags
  blend_mode
  color
  desc
  gender
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  infra_luminosity
  filters
  layer
  luminosity
  maptext
  maptext_width, maptext_height, maptext_x, maptext_y
  mouse_over_pointer, mouse_drag_pointer, mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  overlays
  override (images only)
  pixel_x, pixel_y, pixel_w, pixel_z
  plane
  render_source, render_target
  suffix
  text
  transform
  underlays
  vis_flags

Other vars that are technically part of the appearance, but don't make any sense to change when cloning, are not changed. These include `density`, `dir`, `screen_loc`, and `verbs`. However, those vars ARE copied when you assign a `/mutable_appearance`.

If you set `atom.appearance` to another atom, the other atom's appearance will be copied.

## appearance_flags var (atom)

See also:
  vars (atom)
  alpha var (atom)
  color var (atom)
  transform var (atom)
  color var (client)
  Gliding
  movement_mode var (world)
  Understanding the renderer

Default value:
  0

Possible values:
  Any combination of:
  LONG_GLIDE: Diagonal glides take as long as cardinal ones
  RESET_COLOR: If this is an overlay/image/etc., ignore the parent's color
  RESET_ALPHA: If this is an overlay/image/etc., ignore the parent's alpha value
  RESET_TRANSFORM: If this is an overlay/image/etc., ignore the parent's transform
  NO_CLIENT_COLOR: Ignore client.color
  KEEP_TOGETHER: Draw this icon along with its overlays and underlays, as one unit
  KEEP_APART: Detach from a parent icon that uses `KEEP_TOGETHER`
  PLANE_MASTER: Groups all other icons in the same plane
  TILE_BOUND: Avoids more accurate visibility calculations
  PIXEL_SCALE: Use point sampling when transforming this icon
  PASS_MOUSE: If this icon has a `render_source`, pass any mouse hits to the render source
  TILE_MOVER: This atom is always locked to the grid

The appearance_flags value controls miscellaneous behavior of an atom or appearance that doesn't make sense to handle in any other var.

These values are bitflags, and can be combined with the `+` or `|` operator.

### LONG_GLIDE

Gliding is normally done by Euclidean (straight-line) distance, so diagonal gliding across a square tile takes about 41% longer, since the distance is multiplied by sqrt(2). With `LONG_GLIDE`, the dominant X or Y direction of the glide is used to adjust the glide size so it takes just as long as if the object were gliding in a cardinal direction.

### RESET_COLOR, RESET_ALPHA, RESET_TRANSFORM

These flags cause this overlay not to inherit aspects of its parent object. Ordinarily, transforms on a parent get applied to overlays too, as does color.

All of these flags are ignored if `KEEP_TOGETHER` is used on the parent (and this object does not override with `KEEP_APART`), since then the parent icon along with all of its overlays get drawn to a single surface and color, transform, etc. are applied afterward.

### NO_CLIENT_COLOR

The value of client.color is normally applied to all icons. This flag says that the icon is an exception. Generally `client.color` has been superseded by the use of plane masters anyway.

The `NO_CLIENT_COLOR` flag is inherited by overlays and images automatically unless they have the `RESET_COLOR` flag. It is also basically meaningless when used on an overlay that's inside of a `KEEP_TOGETHER` group, since the client's color is applied to the entire group.

### KEEP_TOGETHER

This flag is used to force the overlays and underlays of this icon (its "children") to be drawn with it all at once, not each icon individually. One reason you might want to do this is if your player's icon uses overlays for hair and equipment, and you want to change the alpha value to make them fade out. With regular drawing, changing the parent icon's alpha means that each individual icon becomes translucent; with `KEEP_TOGETHER`, the whole combination fades as one unit. Because this incurs some small overhead, it should be avoided for atoms that do not need it.

Any child appearances underneath `KEEP_TOGETHER` use `NO_CLIENT_COLOR` automatically, and `RESET_COLOR`, `RESET_ALPHA`, and `RESET_TRANSFORM` become meaningless. Use `KEEP_APART` with them if you want to use those flags.

Icons that are in a different plane from the parent icon will automatically have `KEEP_APART` set and therefore won't be included.

### KEEP_APART

If this appearance is a child of something that uses `KEEP_TOGETHER`, it will be separated out from the main icon and drawn separately. This may be useful for things such as health meters, for instance.

This flag is automatically applied to icons that are on a different plane from their parents.

### PLANE_MASTER

Use this flag to group all icons in the same plane and draw them on a temporary surface the size of the whole screen, and then that image is drawn over the existing scene. This is useful for post-processing effects, like lighting. The plane master's icon is not drawn, but its color, transform, and blend_mode are all taken into account when drawing.

### Example

    obj/lighting_plane
        screen_loc = "1,1"
        plane = 2
        blend_mode = BLEND_MULTIPLY
        appearance_flags = PLANE_MASTER | NO_CLIENT_COLOR
        // use 20% ambient lighting; be sure to add full alpha
        color = list(null,null,null,null,"#333f")
        mouse_opacity = 0    // nothing on this plane is mouse-visible

    image/spotlight
        plane = 2
        blend_mode = BLEND_ADD
        icon = 'spotlight.dmi'  // a 96x96 white circle
        pixel_x = -32
        pixel_y = -32

    mob/Login()
        ..()
        client.screen += new/obj/lighting_plane
        overlays += /image/spotlight

In the example, all objects in plane 2 are lights. They're added together, and then the whole image is put through the color matrix, then multiplied over the rest of the scene below. This will darken everything that doesn't have a spotlight overlay, but anywhere a spotlight exists will have a circle of light.

The example also makes a point of adding full alpha to the plane, because a plane is fully transparent by default. However, it's usually a better idea not to mess with the alpha color, and instead use another icon, scaled to the appropriate size, as a backdrop.

The mouse_opacity set by the plane master will determine how the mouse interacts with objects on the plane. A value of 0 will mean everything in the plane is invisible to the mouse; 1 means the plane is mouse-invisible but the objects in it use their own `mouse_opacity`. 2 is the same except the plane itself is mouse-visible.

### TILE_BOUND

There are many ways an object may be shifted out of the normal bounds of the tile it's on: a large icon, pixel offsets, step offsets, and transform. Ordinarily it's desirable to be able to see the object if it touches any visible turf. However, in some cases it's more desirable to only show the object if its actual loc is in view. The `TILE_BOUND` flag will accomplish that. This flag is inherited by images and overlays.

### PIXEL_SCALE

Normally if an icon is transformed via atom.transform, it uses bilinear texture sampling which produces a nice smooth effect. If you want a granular pixel-art effect instead, `PIXEL_SCALE` will do that for you by using nearest-neighbor sampling.

### PASS_MOUSE

If this object has a `render_source` it will take on the rendered appearance of another object (source). This is just a visual copy, so the mouse still interacts with this object, not the source. The `PASS_MOUSE` flag causes any mouse interaction to happen with the source instead of this object.

### TILE_MOVER

This flag indicates this atom is locked to the tile grid as it would be in TILE_MOVEMENT_MODE, regardless of the setting of `world.movement_mode`. In this way, pixel movers and tile movers can coexist.

## blend_mode var (atom)

See also:
  vars (atom)
  alpha var (atom)
  color var (atom)
  appearance_flags var (atom)

Default value:
  0 (none/overlay)

Possible values:
  BLEND_DEFAULT (0)
  BLEND_OVERLAY
  BLEND_ADD
  BLEND_SUBTRACT*
  BLEND_MULTIPLY*†
  BLEND_INSET_OVERLAY*†

[* This blend type appears only when using graphics hardware mode. It is also not visible in the map editor.]
[† Since the alpha of the icon underneath is used for alpha masking, mouse hits take it into account.]

Controls the way the atom's icon is blended onto the icons behind it. The blend mode used by an atom is inherited by any attached overlays, unless they override it. `BLEND_DEFAULT` will use the main atom's blend mode; for the atom itself, it's the same as `BLEND_OVERLAY`.

`BLEND_OVERLAY` will draw an icon the normal way.

`BLEND_ADD` will do additive blending, so that the colors in the icon are added to whatever is behind it. Light effects like explosions will tend to look better in this mode.

`BLEND_SUBTRACT` is for subtractive blending. This may be useful for special effects.

`BLEND_MULTIPLY` will multiply the icon's colors by whatever is behind it. This is typically only useful for applying a colored light effect; for simply darkening, using a translucent black icon with normal overlay blending is a better option.

`BLEND_INSET_OVERLAY` overlays the icon, but masks it by the image being drawn on. This is pretty much not at all useful directly on the map, but can be very useful for an overlay for an atom that uses `KEEP_TOGETHER` (see appearance_flags), or for the layering filter.

## color var (atom)

See also:
  vars (atom)
  alpha var (atom)
  appearance_flags var (atom)
  blend_mode var (atom)
  color var (client)
  rgb proc
  MapColors proc (icon)

Default value:
  null (white)

Possible values:
  null (white)
  any color generated by `rgb()` (e.g., `"#00ff00"` for green)
  a color matrix (in list form)

Controls the color of the icon displayed on players' screens. This color is multiplied by the icon, so that a white icon will become this color. The color multiplier is also applied to `maptext`.

If you include an alpha component in the color, the atom's alpha var will be set at the same time.

Overlays and images will also be multiplied by this color, unless they use the `RESET_COLOR` value in `appearance_flags`.

The color value can be set to a color matrix, which is a list of values. This allows for more complex transformations such as adding or subtracting color, inverting the color, turning to grayscale, shifting hue, etc. Using an RGB-only color matrix will include the existing alpha value in the matrix.

When reading the `color` var, if it is a matrix it will be read out as a list with 20 items (full RGBA format). That list is a copy, so if you save it and make changes to that list later it will not impact the actual color of the atom. This also means you can't use `color[9] = 0.5`; you would have to grab the value of `color` first, make sure it's a list, change it, and then assign the changed list back to the `color` var.

## contents list var (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)
  locs list var (movable atom)
  Pixel movement
  list
  loc var (atom)

Default value:
  List of contained objects.

Except in the case of areas, this list is always restricted to objs and mobs (ie movable objects). Only direct contents are listed. Items inside of a bag object, for example, would not show up in the mob's contents list.

The contents of areas are a little different. The turfs contained in the area are in the list along with any objs or mobs directly contained by those turfs.

If a movable atom uses the bound vars to change its physical size, or `step_x` or `step_y` to change its position, it may cover more than one turf. In that case, those turfs' contents won't just contain anything directly in them, but also any atoms overhanging them. I.e., if a turf is in a mob's `locs` list, then the mob is in that turf's contents list. (See locs for more information.)

Note: Looping through all of the atoms, or even just turfs, in a particular area actually loops through every turf in the world. E.g., `for(var/turf/T in area)`. The engine will check each turf to see if it belongs to that area, and then includes the turf and/or its contents in the results depending on what the loop is looking for. This also applies to any situation where you might grab area.contents as a list, e.g. `area.contents.Copy()`. Therefore in a large world, it's advisable not to loop through area contents at all.

## density var (atom)

See also:
  Enter proc (atom)
  Entered proc (atom)
  Exit proc (atom)
  Exited proc (atom)

Default value:
  0 (1 for mobs)

This turns the object's density on or off (1 or 0). Two dense objects may not occupy the same space in the standard movement system.

## desc var (atom)

Default value:
  null

This is the description of the object.

### Example:

    mob/verb/look(atom/O in view())
       if(O.desc) usr << O.desc
       else usr << "It's just \an [O]."

## dir var (atom)

See also:
  Move proc (movable atom)
  icon var (atom)
  turn proc
  stddef.dm file

Default value:
  SOUTH

Possible values:
  NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST

This is the direction that the object is facing. This has little effect unless the object's icon is directional. In the case of a directional icon, this selects the corresponding orientation from the icon file.

An icon file with only four (cardinal) directions makes the choice of orientation ambiguous when the true direction is a diagonal. In that case, of the two possibilities, the one closest to the previous orientation is displayed. Sounds complicated, but it's what one would naturally expect.

## filters var (atom)

See also:
  appearance_flags var (atom)
  filter proc
  animate proc
  Filter effects

Default value:
  empty list

This var is a list of graphical filters to use for post-processing effects, applied in order. You can assign this value a list, an individual filter, or null to empty it.

### Example:

    obj/blurry
        filters = filter(type="blur", size=1)

Atoms with the `KEEP_TOGETHER` flag will apply their filters after the composite image has been drawn. Filters will also apply to any maptext the atom has.

See the filters section for more information on individual filters.

### Named Filters

Filters can be created with a `name` argument. That name can be used to access the filter in the list (e.g. `filters["drunk_blur"]` instead of using a numeric index, which is helpful for managing animations and updating multiple filters on an object.

Adding a new filter with the same name as an existing filter will remove the old one, since only one of a given filter name can be used on an appearance at a time.

You can also remove a named filter from the list simply by subtracting the name instead of the filter itself. That is, `filters -= filters["foo"]` and `filters -= "foo"` do the same thing.

## gender var (atom)

See also:
  macros (text)
  name var (atom)

Default value:
  "neuter"

This sets the object's gender. This influences text macros like `\he`, which may expand to "it", "he", "she", or "they". Valid values are:

    "neuter"
    "male"
    "female"
    "plural"

These are also defined as constants, which may help prevent typos, since the compiler will complain if it doesn't recognize what you type:

    NEUTER
    MALE
    FEMALE
    PLURAL

## icon var (atom)

See also:
  icon proc
  icon_state var (atom)
  icons
  overlays var (atom)
  underlays var (atom)
  load_resource proc
  icon_w var (atom)
  icon_z var (atom)

Default value:
  null

This is the icon file that will be used to represent the object on graphical clients.

### Example:

    turf/wall
       icon = 'wall.dmi'

You can also assign this to an external file at run-time with an expression such as file("wall.dmi"), but you would only want to do that when the other method is not possible, because it requires addition of the file to the resource cache, which can take a little time.

When this variable is set to any dynamically created icon object, that object gets dumped into the world's resource cache (the `.rsc` file), and a reference to that cached file is assigned to atom.icon. In other words, don't expect comparisons such as `usr.icon == MyDynamicallyCreatedIcon` to work unless you have used fcopy_rsc() to get a cache reference to your dynamically created icon first. This is almost never an issue, so don't worry about it if none of that made any sense to you!

## icon_state var (atom)

See also:
  flick proc
  icon var (atom)
  icon_states proc

Default value:
  null

Icons may appear differently depending on the icon state. For example, turf door icons could have "open" and "closed" states. If a state is specified that does not exist in the icon file, the default null state will be displayed if it exists.

### Example:

    turf/door
       icon_state = "closed"
       density = 1
       verb
          open()
             set src in view(1)
             icon_state = "open"
             density = 0
          close()
             set src in view(1)
             icon_state = "closed"
             density = 1

## icon_w var (atom)

See also:
  icon_z var (atom)
  pixel_w var (atom)
  icon var (atom)

Default value:
  0

Defines the anchor point for this icon, from the bottom left. Higher values of icon_w will offset this icon to the left; lower values offset it to the right. It acts like a negative pixel_w except it's not inherited by any overlays, images, or visual contents. It applies ONLY to this icon.

This var is meant to replace the `bound_x` var, which was applied very inconsistently in old versions.

## icon_z var (atom)

See also:
  icon_w var (atom)
  pixel_z var (atom)
  icon var (atom)

Default value:
  0

Defines the anchor point for this icon, from the bottom left. Higher values of icon_w will offset this icon downward; lower values offset it upward. It acts like a negative pixel_z except it's not inherited by any overlays, images, or visual contents. It applies ONLY to this icon.

This var is meant to replace the `bound_y` var, which was applied very inconsistently in old versions.

## infra_luminosity var (atom)

See also:
  luminosity var (atom)
  see_infrared var (mob)
  sight var (mob)
  view proc

Default value:
  0

This causes the object to be visible in the dark to mobs that can see infrared light. Nothing but the object itself is lit up by the infrared emission. The scale is identical to luminosity: 1 makes it visible only from the same location; 2 makes it visible from a neighboring position; and so on.

## invisibility var (atom)

See also:
  invisibility setting (verb)
  opacity var (atom)
  see_invisible var (mob)
  sight var (mob)
  view proc

Default value:
  0

Possible values:
  0 to 101

This determines the object's level of invisibility. The corresponding mob variable `see_invisible` controls the maximum level of invisibility that the mob may see.

A value of 101 is absolutely invisible, no matter what, and it is filtered from all lists of possible values for verb arguments. This is intended for objects that exist purely for some internal purpose, such as "verb containers".

## layer var (atom)

See also:
  overlays var (atom)
  plane var (atom)
  z var (atom)
  map_format var (world)
  BACKGROUND_LAYER
  EFFECTS_LAYER
  TOPDOWN_LAYER
  Understanding the renderer

Default value:
  1 (AREA_LAYER)
  2 (TURF_LAYER)
  3 (OBJ_LAYER)
  4 (MOB_LAYER)

This numerical value determines the layer in which the object is drawn on the map. By default, the order is area, turf, obj, mob, followed by missiles and images (in FLY_LAYER, which is 5).

### Example:

    turf
       archway
          layer = MOB_LAYER+1  //overhead

When making objects to be used as graphical overlays, you should also be aware of the special `FLOAT_LAYER` value. This causes the overlay (or underlay) to be in the same drawing layer as the base object, no matter how that layer changes after the addition of the overlay. Otherwise, the overlay object's own drawing layer is used.

The actual drawing order of icons may change depending on world.map_format. An isometric map for instance has to display tiles that are "closer" to the viewer in front of tiles that are in the back, so the layer var takes a backseat to the needs of the map. If you use the `TOPDOWN_MAP` or `TILED_ICON_MAP` map formats, the layer is more important.

If you are using a `world.map_format` that does not display topdown, such as `ISOMETRIC_MAP` or `SIDE_MAP`, then you can use a special layer for showing certain portions of the map in topdown mode. For those parts of the map, you can add `TOPDOWN_LAYER` to every atom's layer to make the atom appear in topdown mode. This is for special cases, like for instance a battle map in an RPG, where a regular topdown view is preferable to the special mapping used by the rest of the game. It is recommended that you use `TOPDOWN_LAYER` with every atom in that portion of the map, since topdown and isometric maps for instance don't mix. If you use `TOPDOWN_LAYER`, it is best to use a square size in `world.icon_size` if any of these atoms will be moving around.

Another special layer, `EFFECTS_LAYER`, is also available. Icons that use this layer will display above icons that don't. `TOPDOWN_LAYER` will then display above that. This layer is useful for situations such as using a floating name or health meter overlay on a mob in isometric mode. When using `EFFECTS_LAYER`, other icons on the regular map won't cover the overlay. (It is preferable to use atom.plane for this, when possible.)

Finally there is BACKGROUND_LAYER. Adding this to an atom's layer will make it appear below any atoms that do not use BACKGROUND_LAYER. (It is preferable to use atom.plane when possible.)

The `atom.plane` var takes priority over layer. This is the preferred method of handling background and effects.

## loc var (atom)

See also:
  contents list var (atom)
  x var (atom)
  y var (atom)
  z var (atom)

Default value:
  The location of the object or null if there is none.

The container is always an atom (or null). For areas, this value is always null, since an area may not be contained by any other object.

## luminosity var (atom)

Default value:
  0
  1 (areas)

This sets the object's luminosity (how far it casts light). It must be an integer in the range 0 to 6.

Areas are a little different. Any non-zero value in an area results in all objects within the area being bathed in light.

## maptext var (atom)

See also:
  maptext_width var (atom)
  maptext_height var (atom)
  maptext_x var (atom)
  maptext_y var (atom)
  overlays var (atom)
  image objects
  pixel_x var (atom)
  pixel_y var (atom)
  pixel_w var (atom)
  pixel_z var (atom)

Default value:
  null

This is optional text that will be displayed in the same position as the atom. If an atom has both an icon and maptext, the text will be displayed in front of the icon. Usually however, this is something that would be added to an overlay or image object, which can then be positioned with pixel offsets.

Map text is constrained to the bounds set by maptext_width and maptext_height, which default to a single icon in size. It can be offset by maptext_x and maptext_y.

Text can use HTML and CSS, mostly the same limited subset supported by regular text output, and different styles can be used in the same block of text. In addition, alpha colors can also be used, by specifying a color as #rrggbbaa instead of just #rrggbb. (Alpha transparency will be ignored when the map is drawn without hardware rendering, so anything below 50% opacity is not displayed in those cases.)

Maptext supports links with the `<a>` tag. Left-clicking on a link will follow the link, but also generate other events such as `MouseDown` or `Click`.

## maptext_width var (atom)

See also:
  maptext var (atom)
  maptext_x var (atom)
  maptext_y var (atom)
  maptext_height var (atom)
  icon_size var (world)

Default value:
  32 (depends on world.icon_size)

This is the width of the text shown in the maptext var. By default, it uses the icon width provided in world.icon_size.

## maptext_height var (atom)

See also:
  maptext var (atom)
  maptext_width var (atom)
  maptext_x var (atom)
  maptext_y var (atom)
  icon_size var (world)
  map_format var (world)

Default value:
  32 (depends on world.icon_size)

This is the height of the text shown in the maptext var. The default value depends on world.icon_size and world.map_format. In a topdown (default) or tiled map_format, the icon height is used. In other map views, tile "footprints" are square and height is irrelevant, so the default will be the icon width instead.)

## maptext_x var (atom)

See also:
  maptext var (atom)
  maptext_width var (atom)
  maptext_height var (atom)
  maptext_y var (atom)
  icon_size var (world)

Default value:
  0

Maptext, if used, is offset by this many pixels to the right.

## maptext_y var (atom)

See also:
  maptext var (atom)
  maptext_width var (atom)
  maptext_height var (atom)
  maptext_x var (atom)
  icon_size var (world)

Default value:
  0

Maptext, if used, is offset by this many pixels upward.

## mouse_drag_pointer var (atom)

See also:
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_over_pointer var (atom)
  mouse_pointer_icon var (client)

Default value:
  MOUSE_INACTIVE_POINTER (0)

This defines how the mouse looks when dragging this object. Assigning this to MOUSE_ACTIVE_POINTER (1) enables the default dragging indicator.

This variable may also be set to any of the other built-in mouse pointers, or a custom icon or icon state. If an icon state is specified, this is applied against the object's main icon to find a custom pointer.

Note that all mouse pointers are purely visual indicators. They do not effect what objects may actually be manipulated with the mouse. You control all of the real behavior in the associated procedures.

## mouse_drop_pointer var (atom)

See also:
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  mouse_pointer_icon var (client)

Default value:
  MOUSE_ACTIVE_POINTER (1)

This defines how the mouse looks when dragging this object over another object that has mouse_drop_zone set. The default value enables the addition of a standard "droppable" indicator to whatever mouse_drag_pointer is (unless mouse_drag_pointer is turned off).

This variable may also be set to any of the other built-in mouse pointers, or a custom icon or icon state. If an icon state is specified, this is applied against the object's main icon to find a custom pointer.

Note that all mouse pointers are purely visual indicators. They do not effect what objects may actually be manipulated with the mouse. You control all of the real behavior in the associated procedures.

## mouse_drop_zone var (atom)

See also:
  MouseDrag proc (atom)
  MouseDrop proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  mouse_pointer_icon var (client)

Default value:
  0

Setting this to 1 indicates that this object is a valid site on which to drop other objects. While dragging, mouse_drop_cursor of the object being dragged will become active in this case. Note that this is a purely visual effect. It does not control what the user may do with the mouse. You control the real behavior with the associated procedures.

## mouse_opacity var (atom)

See also:
  mouse handling
  overlays var (atom)
  underlays var (atom)
  vis_contents var (atom)
  render_source var (atom)

Default value:
  1

Possible values:
  0 // transparent to mouse
  1 // mouse-opaque where icon is also opaque
  2 // completely mouse-opaque

This may be used to control how mouse operations on an object are interpreted. A click or mouse movement over an object's icon normally applies to that object only if it is the topmost object that is not transparent at the position of the mouse. Setting `mouse_opacity` to 0 would cause the object to be ignored completely, and setting it to 2 causes it to always be chosen over any lower-level objects, regardless of the transparency of its icon.

Note that overlays and underlays are not distinct objects, so their `mouse_opacity` is completely ignored in favor of the object they're attached to. The same applies to image objects, which act like special overlays as well. Visual contents, on the other hand, are separate objects that can act like overlays in some ways, but because they're separate their `mouse_opacity` is taken into account.

When this is applied to a `PLANE_MASTER` object (see appearance_flags), a value of 0 means everything on the plane is mouse-transparent. 1 means everything on the plane is mouse-visible (using the objects' normal mouse_opacity), but the plane master itself is not. 2 means everything on the plane is mouse-visible, and so is the plane master.

## mouse_over_pointer var (atom)

See also:
  Click proc (atom)
  MouseEntered proc (atom)
  MouseExited proc (atom)
  MouseMove proc (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)

Default value:
  MOUSE_INACTIVE_POINTER (0)

This defines how the mouse looks when no buttons are pressed and it is held over this object. Assigning this to MOUSE_ACTIVE_POINTER (1) enables the default indicator that there is something special under the mouse (crosshairs).

This variable may also be set to any of the other built-in mouse pointers, or a custom icon or icon state. If an icon state is specified, this is applied against the object's main icon to find a custom pointer.

Note that all mouse pointers are purely visual indicators. They do not effect what objects may actually be manipulated with the mouse. You control all of the real behavior in the associated procedures.

## name var (atom)

See also:
  gender var (atom)

Default value:
  The name of the object type with underscores converted to spaces.

## opacity var (atom)

Default value:
  0

This turns the object's opacity on or off (1 or 0). Opaque objects block light.

## overlays var (atom)

See also:
  underlays var (atom)
  icon var (atom)
  layer var (atom)
  list
  image objects
  vis_contents var (atom)
  Understanding the renderer

Default value:
  empty list

This is a list of simple icons which are displayed on top of the object's main icon.

The individual items in the list may not be directly accessed, since they are stored in a special internal format. However, the list operators `+=`, `-=`, and the procedures `Add`, `Remove`, and `Cut` work normally.

### Example:

    turf/verb/AddOverlay(I as icon)
       overlays += I
    turf/verb/RemoveOverlay(I as icon)
       overlays -= I

The data types that may be used as overlays are icons, icon states (text strings), objects, and object types. When an icon state is used, the corresponding image in the object's icon is displayed. When another object is used as an overlay, a static "snapshot" of the object is taken at the time when the overlay is created. Future changes to the object will not change the appearance of the overlay, except that in some cases the overlay may inherit things from the base object like its icon (if left empty), direction, and moving state.

Overlays have their own independent drawing layer. It is normally the special value FLOAT_LAYER, which makes them float above the base object. If the overlay is a snapshot of another object, the drawing layer of that object is used (and in that case, the overlay can appear beneath the object if its layer is lower). The important advantage of using FLOAT_LAYER is that if the layer of the base object changes, the overlays will move with it into the new layer.

Any negative number may be used in place of FLOAT_LAYER (which happens to be -1). They all cause the same "floating" behavior. However, the overlays are ordered amongst themselves according to their own relative layer values (-2 below -1 and so on). This may be useful if you have several classes of overlays that should always appear in a certain order, because you would not have to worry about the order in which you add them to the list.

### Example:

    var/const
       ARMOR_LAYER = FLOAT_LAYER-1
       CLOTHES_LAYER = FLOAT_LAYER-2
    obj/overlay
       armor
          icon = 'armor.dmi'
          layer = ARMOR_LAYER
       clothes
          icon = 'clothes.dmi'
          layer = CLOTHES_LAYER
    mob/verb
       wear_clothes()
          overlays += /obj/overlay/clothes
       wear_armor()
          overlays += /obj/overlay/armor
       remove_clothes()
          overlays -= /obj/overlay/clothes
       remove_armor()
          overlays -= /obj/overlay/armor

That example used object types, but you can use instances of objects as well. Rather than using different "float" layers, you can also just make your own list of overlays with the order you want and assign that to the actual overlays list.

### Example:

    mob/var
       boots
       clothes
    	armor
    mob/proc
       ShowOverlays()
          var/L[0]
          if(boots)   L += boots
          if(clothes) L += clothes
          if(armor)   L += armor
          overlays = L

## override var (atom)

Default value:
  0

Currently this only applies to images.

If you attach an image to an atom, normally it is seen only in addition to the atom's regular icon. If the image's override var is 1, it will be seen in place of the original atom (and its overlays). It will inherit the atom's color, alpha, transform, and appearance_flags, unless its own appearance_flags say otherwise.

If the image has a specific name and/or suffix value, those will override the parent atom too. Leaving them blank will let the original atom take precedence.

## pixel_x var (atom)

See also:
  animate_movement var (movable atoms)
  glide_size var (movable atoms)
  pixel_y var (atom)
  pixel_w var (atom)
  pixel_z var (atom)
  icon_size var (world)
  map_format var (world)
  Pixel movement

Default value:
  0

This displaces the object's icon on the x-axis by the specified number of pixels. In a project with a standard 32x32 tile size, this can range from -32 to +32. (You can get away with larger displacements, but they are not guaranteed to work for objects off the edge of the map.)

Since overlays and images can each have their own additional displacements, this makes it possible to create visual effects that extend beyond the object's own cell in the turf grid, but which automatically move around with the object.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.

## pixel_y var (atom)

See also:
  animate_movement var (movable atoms)
  glide_size var (movable atoms)
  pixel_x var (atom)
  pixel_w var (atom)
  pixel_z var (atom)
  icon_size var (world)
  map_format var (world)
  Pixel movement

Default value:
  0

This displaces the object's icon on the y-axis by the specified number of pixels. In a project with a standard 32x32 tile size, this can range from -32 to +32. (You can get away with larger displacements, but they are not guaranteed to work for objects off the edge of the map.)

Since overlays and images can each have their own additional displacements, this makes it possible to create visual effects that extend beyond the object's own cell in the turf grid, but which automatically move around with the object.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.

## pixel_w var (atom)

See also:
  animate_movement var (movable atoms)
  glide_size var (movable atoms)
  pixel_x var (atom)
  pixel_y var (atom)
  pixel_z var (atom)
  icon_size var (world)
  map_format var (world)

Default value:
  0

This displaces the object's icon horizontally by the specified number of pixels. This is meant to be used in situations where world.map_format is used to display something other than a top-down form, for instance in an isometric or side-view display. In a top-down mode pixel_w behaves the same as pixel_x, except that it does not rotate with changes to client.dir.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.

## pixel_z var (atom)

See also:
  animate_movement var (movable atoms)
  glide_size var (movable atoms)
  pixel_x var (atom)
  pixel_y var (atom)
  pixel_w var (atom)
  icon_size var (world)
  map_format var (world)

Default value:
  0

This displaces the object's icon vertically by the specified number of pixels. This is meant to be used in situations where world.map_format is used to display something other than a top-down form, for instance in an isometric or side-view display. In a top-down mode pixel_z behaves the same as pixel_y, except that it does not rotate with changes to client.dir.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.

## pixloc var (atom)

See also:
  pixloc
  loc var (atom)
  step_x var (movable atoms)
  step_y var (movable atoms)
  pixloc proc
  bound_pixloc proc
  Pixel movement

Returns a pixloc representing this atom's physical position. The position is based on its `loc`, `step_x`, `step_y`, `bound_x`, and `bound_y`. This var is read-only for areas and turfs, but writable for movable atoms. When changed, it will alter the related vars. A movable's pixloc is null if it isn't located on a turf.

A pixloc can be used for calculating distances, or passed to various procs such as get_dir() and Move().

This pixloc is equivalent to bound_pixloc(src,SOUTHWEST). You can use the `bound_pixloc()` proc to get the pixloc of an atom's other corners or center of bounds.

The returned pixloc is not tied to this atom, so changing its vars will not alter the atom's pixloc. The only exception is when using operators such as `+=`, since `a += b` is just a shortcut for `a = a + b`.

    // does not alter obj's position
    var/pixloc/p = obj.pixloc
    p.step_x += 12

    // does alter obj's position, since a += b is just a = a + b
    obj.pixloc += vector(12,0)

## plane var (atom)

See also:
  layer var (atom)
  appearance_flags var (atom)
  vis_contents var (atom)
  map_format var (world)
  Understanding the renderer

Default value:
  `FLOAT_PLANE`

Possible values:
  -10000 to 10000 (integers only), `FLOAT_PLANE+p`

The value of plane overrides layer, and is mainly used for non-topdown map formats like isometric. Positive values are drawn on top, and negative values are drawn below. This mostly deprecates `EFFECTS_LAYER` and `BACKGROUND_LAYER`, but they can still be useful when using `PLANE_MASTER` for effects (see appearance_flags).

The special value `FLOAT_PLANE` can be used for images and overlays, to take on the plane of the parent atom. Whenever an icon or icon_state is used directly as an overlay, this is its plane. If there is no parent atom, the plane is 0.

You can also use `FLOAT_PLANE` as a relative value, so `FLOAT_PLANE+1` adds 1 to the parent atom's plane. This may be useful for some applications where an object is included in visual contents. The added value should still be kept in the range of -10000 to 10000, or preferably much smaller.

## render_source var (atom)

See also:
  render_target var (atom)
  appearance_flags var (atom)

Default value:
  null

Possible values:
  Any non-empty text string

If any icon uses `render_source`, the renderer will look for another icon with a matching `render_target` value on the visible map, and draw that in place of the `icon`/`icon_state`/`dir` that it normally would. The same render target might be used as a source multiple times, and for a complex image this can save some rendering time. This is also usable for special effects such as filters that might require copies of an image.

Note: The corresponding `render_target` must be visible to the player for a render source to be used.

The replacement icon from the `render_source` will be anchored to the bottom left of the icon it replaces.

Other vars that would normally affect the appearance of this icon, such as `color`, `transform`, `filters`, `appearance_flags`, etc. are all applied. Additionally, if this object has overlays, underlays, or visual contents, those will still be drawn as well.

Note: Any mouse hits on this object belong to the object itself, not to the object used in the `render_source` or its children. If you want mouse clicks and other behavior to go to the source, use the `PASS_MOUSE` appearance flag.

## render_target var (atom)

See also:
  render_source var (atom)
  appearance_flags var (atom)
  color var (atom)
  filters var (atom)
  transform var (atom)

Default value:
  null

Possible values:
  Any non-empty text string

If any icon uses `render_target`, and another icon in the scene has a matching `render_source`, this icon will be drawn to a temporary image called a "slate", which can be reused mutiple times for faster drawing and for special effects.

If the `render_target` value starts with an asterisk (`"*"`), it will not be drawn on the map, but will still be drawn to a slate for reuse.

Other vars that would normally affect the appearance of this icon, such as `color`, `transform`, `filters`, `appearance_flags`, etc. are all applied when drawing to the slate. Additionally, if this object has overlays, underlays, or visual contents and uses the `KEEP_TOGETHER` flag to group all of the icons together, those will also be included in the slate.

If the render target is a `PLANE_MASTER`, vars like `pixel_x/y/w/z` will not apply when it is re-drawn as a `render_source`.

To use a `render_target`, the object it belongs to must be within the visible part of the map, or in the HUD, etc., so that it would be visible to the user under normal circumstances. If not, it will not be included in the render process and therefore it can't be reused as a `render_source`.

Additionally, if you use multiple map controls, a given render target can only be used as a source on the same map control where it appears. This is because each map is rendered separately.

## suffix var (atom)

Default value:
  null

This is an optional text string that follows the object's name in the stat panels. For example, items in an inventory list are displayed as an icon, a name, and a suffix.

## text var (atom)

Default value:
  The first letter of the object's name.

This is the character used to represent the object on text clients.

Entering several characters produces a text movie (the state of the art!). In that case, each character is displayed for a 10th of a second.

HTML tags in the text can be used to modify the colors of the text characters. As a convenience, the <font> tag may include a `bgcolor` attribute, so you don't have to do a CSS style setting to accomplish the same thing.

### Example:

    world
       maxx = 10
       maxy = 10
    area
       text = "<font bgcolor=blue> "
    turf
       text = "<font color=#F00>....<font color=#C00>.."

The example above produces a map with a blue background (from the area) and turfs (depicted by ".") that flash from bright red to a shorter span of light red.

Note that in order to see text icons, the user must switch to the text map in Dream Seeker. If your DM code never does anything with the icon variable, then this is the default configuration. Such applications are known as advanced iconic text games:)

## transform var (atom)

See also:
  vars (atom)
  matrix

An atom can be made to appear rotated, scaled, and/or translated (moved) by using affine transforms. This takes a matrix and multiplies the x and y positions of the icon's corners like so:

              a d 0
    x y 1  *  b e 0  =  x' y' 1
              c f 1

This is equivalent to:

    x' = a*x + b*y + c
    y' = d*x + e*y + f

You do not need to understand matrix math to use transforms, because you can use the matrix datum to do this for you.

Transformations are relative to the center of the icon. They do not apply to maptext.

### Examples:

    // Rotate the atom by 45° clockwise
    src.transform = turn(src.transform, 45)

    // OR
    var/matrix/M = matrix()
    M.Turn(45)
    src.transform = M

    // Scale the atom by 2x2
    src.transform *= 2

    // OR
    var/matrix/M = matrix()
    M.Scale(2,2)
    src.transform = M

Whenever you read the atom.transform var, you will get a copy of the atom's current transformation. Whenever you assign a value to the var, you will update the transformation.

Assigning null to atom.transform will revert the atom to using no transformation at all. It is also legal to assign a list with six values, which is equivalent to using a matrix.

## underlays var (atom)

See also:
  icon var (atom)
  list
  overlays var (atom)
  Understanding the renderer

Default value:
  empty list

This is a list of icons which are displayed underneath the object's main icon. Since these are basically the same as overlays, see overlays for more detailed information.

The only real differences between items in the underlays list vs. the overlays list is that they're processed first, and if they use `FLOAT_LAYER` (or any other negative layer value) they'll appear below the object instead of above it. For this reason, the underlays list isn't used nearly as much as overlays since it's easier to throw most things into the overlays list.

When multiple turfs are stacked on top of one another in the map editor, there is actually only one turf (the topmost) and the rest are all underlays.

## verbs list var (atom)

See also:
  list
  typesof proc

Default value:
  The list of verbs defined for the object's prototype.

This is a list of the object's verbs. Initially, it contains all of the verbs defined in the prototype. It may be used to add and remove verbs at runtime.

Note that this variable is not automatically saved when the object is written to a savefile. That behavior may change in the future. In the mean time, you must save any necessary changes yourself or they will not be preserved when the object is loaded.

### Example:

    mob/proc/kazaam()
       usr << "Kazaam!"

    mob/verb/add_kazaam()
       verbs += /mob/proc/kazaam
    mob/verb/remove_kazaam()
       verbs -= /mob/proc/kazaam

## vis_contents var (atom)

See also:
  vis_locs var (atom)
  vis_flags var (atom)
  image objects
  HUD / screen objects

Default value:
  Empty list.

Turfs, movable atoms, and images can be given a list of atoms (limited to turfs and movable atoms) that are attached to them visually, like an overlay or image object, but act independently and have their own identity. These are visual contents. The purpose of visual contents is to provide an alternative system to overlays and images, with a little more flexibility for various special effects.

For example, a mob with an obj in its visual contents will show the obj as if it's following the mob around like an overlay, but clicking on the obj will not—unlike an overlay or an image object—count as a click on the mob. Likewise, the obj will retain its own separate `mouse_opacity` setting, which is not true of regular overlays.

An atom that appears on the map normally can still be in the visual contents of another atom. However it will not apply gliding and step offsets here. Also, considerations like visibility will not apply.

If a turf is in an atom's visual contents, the turf and all of that turf's contents will be displayed. (In the case of big atoms, or movable atoms with step offsets, only atoms that actually have that turf as their loc will appear. "Overhangers" will not.) Gliding and step offsets will be applied to that turf's contents normally; but again visibility, opacity, etc. will not be considered. (If you have one or more turfs in visual contents, an object gliding to a new turf outside of that list will not be shown because it's already technically on the new turf.)

If multiple turfs are present in visual contents, they will be offset as needed (relative to the southwest-most turf) to appear in the correct positions. That is, `pixel_x` and `pixel_y` offsets will be applied automatically, so if you add an entire block to visual contents (be aware this will impact performance), you don't have to do anything else to make the block appear normal.

You can alter some aspects of how an object behaves when in visual contents by changing its vis_flags var. In particular this is useful if you want an object to behave more like an overlay, inheriting aspects of its parent object or even acting like a part of that object instead of an independent one. Also this can make an object act like an underlay instead of an overlay when using a floating layer.

Visual contents do not impact the results of `view()` or `range()`, or verb availability, in any way. This is strictly a visual effect.

Being in a visual contents list counts as a reference for anything in the list, the same way that being on the map or inside of a movable counts as a reference.

## vis_flags var (atom)

See also:
  vis_contents var (atom)
  vis_locs var (atom)

Default value:
  0

Possible values:
  Any combination of:
  VIS_INHERIT_ICON: Use the parent object's icon.
  VIS_INHERIT_ICON_STATE: Use the parent object's icon_state.
  VIS_INHERIT_DIR: Use the parent object's dir.
  VIS_INHERIT_LAYER: Use the parent object's layer.
  VIS_INHERIT_PLANE: Use the parent object's plane.
  VIS_INHERIT_ID: Use the parent object's identity, so it acts like part of the same object.
  VIS_UNDERLAY: Act as if this is at the bottom of the parent's underlays list instead of overlays (only relevant if using `VIS_INHERIT_LAYER` or a FLOAT_LAYER).
  VIS_HIDE: Do not show this object in visual contents at all.

This is a set of flags that determine how this object will behave when it is in another object's visual contents.

Because only turfs, objs, and mobs can be in visual contents, this var belongs only to those types.

The `VIS_INHERIT_ID` flag effectively makes this object act like an ordinary overlay when in visual contents. This means its mouse_opacity will be meaningless, for example.

Sometimes it's desirable for an object not to show up in visual contents, so `VIS_HIDE` will prevent that. The flag applies even if this object appears indirectly, like if it's in the contents of a turf that is in the visual contents of something else.

Note: Using any of the the flags `VIS_INHERIT_ICON`, `VIS_INHERIT_ICON_STATE`, `VIS_INHERIT_DIR`, or `VIS_INHERIT_ID` will cause movable atoms to inherit the "moving" flag of their container that appears during gliding. E.g., if your mob is walking, anything in its visual contents that uses these flags will use a moving icon state instead of a non-moving icon state, when available.

## vis_locs var (atom)

See also:
  vis_contents var (atom)
  vis_flags var (atom)
  image objects
  HUD / screen objects

Default value:
  Empty list.

This list is the opposite of the `vis_contents` list. If this atom is in any other atoms' visual contents, those parent atoms will appear in this list.

Because only turfs, objs, and mobs can be in visual contents, this var belongs only to those types.

Being in a visual locs list does not count as a reference, the same way that being a movable's loc does not count as a reference. If an object in this list otherwise runs out of references, it will be garbage collected and therefore removed from this list.

## x var (atom)

See also:
  loc var (atom)

Default value:
  The x coordinate of the object on the map.

You may assign the coordinates of movable objects (mobs and objs), but this is not advisable. It is better to compute the new location (with `locate()`) and move them to that. Then you can use the normal `Move()` procedure, which enables all the normal movement behavior.

For areas that are on the map, this is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area.

## y var (atom)

See also:
  loc var (atom)

Default value:
  The y coordinate of the object on the map.

You may assign the coordinates of movable objects (mobs and objs), but this is not advisable. It is better to compute the new location (with `locate()`) and move them to that. Then you can use the normal `Move()` procedure, which enables all the normal movement behavior.

For areas that are on the map, this is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area.

## z var (atom)

See also:
  layer var (atom)
  loc var (atom)

Default value:
  The z coordinate of the object on the map.

The z coordinate is how objects move between maps. When you include several maps in a project, they are placed on different z levels so that the full map is a single 3-dimensional space. It is also possible for a single map file to contain multiple z levels.

Do not confuse this with drawing layer. The z coordinate moves an object between different maps. The layer variable determines the order in which an object is drawn graphically relative to other objects at the same position on the map.

You may assign the coordinates of movable objects (mobs and objs), but this is not advisable. It is better to compute the new location (with `locate()`) and move them to that. Then you can use the normal `Move()` procedure, which enables all the normal movement behavior.

For areas that are on the map, this is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area.

## callee

See also:
  proc
  vars (proc)
  callee var (proc)
  caller var (proc)
  Error proc (world)
  try and catch statements

A primitive type representing a running or sleeping proc. This gives access to the proc's information, and can be used to output a stack trace in situations such as writing your own custom `world.Error()` handler.

You can get a `/callee` for the current running proc with its callee var, or its caller with the caller var. You can follow callers up the call chain.

### Example:

    world/Error(err)
        world.log << "Error [err]:"
        for(var/callee/p = caller, p, p = p.caller)
            world.log << "  [p.proc.type] (src=[p.src], usr=[p.usr])"
            if(p.file) world.log << "    at [p.file]:[p.line]"

Built-in callee vars (read-only):

  args
  caller
  category*
  desc*
  file
  name*
  line
  proc
  src
  type
  usr

* These vars are quick aliases for `proc.varname`. `proc.type` is excluded since `/callee` has its own type var.

The `file` and `line` vars are available if debugging information was turned on when the world was compiled. The other vars are all aliases for info about the running/sleeping proc or its prototype.

Even though the `args` var itself is read-only, the list it returns is mutable. Making changes to the list will affect the proc it belongs to.

## client

See also:
  client var (mob)
  key var (mob)
  procs (client)
  vars (client)

Each connected player has a corresponding client object. It has variables and procedures which control aspects of player input/output. This object is also responsible for linking the player up to a mob.

The client can be reassigned from its original mob M to a new mob N by setting N.client = M.client. This process disconnects the player from M (calling M.Logout()) and connects the player to N (calling N.Login()). Setting the mob's key has the same effect.

Additional vars, procs, and verbs may be added to the client in order to give the player properties that are independent of the mob.

## procs (client)

Built-in client procs:

client/proc
  AllowUpload
  Center
  CheckPassport
  Click
  Command
  DblClick
  Del
  East
  Export
  GetAPI proc
  Import
  IsByondMember
  MeasureText
  MouseDown
  MouseDrag
  MouseDrop
  MouseEntered
  MouseExited
  MouseMove
  MouseUp
  MouseWheel
  Move
  New
  North
  Northeast
  Northwest
  RenderIcon
  SendPage
  SetAPI proc
  SoundQuery
  South
  Southeast
  Southwest
  Stat
  Topic
  West

## AllowUpload proc (client)

See also:
  input proc

Format:
  AllowUpload(filename, filelength)

When:
  Called when the player attempts to upload a file to the server, through input() or a command.

Default action:
  Allows the upload by returning 1.

The client who owns this proc (src) is the one trying to upload the file. If this proc returns a true value, the upload will be allowed. Otherwise, it will be rejected.

### Example:

    client
       AllowUpload(filename, filelength)
          if(filelength >= 524288)  // 512K (0.5M)
             src << "[filename] is too big to upload!"
             return 0
          return 1

## Center proc (client)

See also:
  walk proc

Format:
  Center()

When:
  Called when the player presses the "center" key or cursor.

Default action:
  Cancels any automated movement by calling walk(usr,0).

## CheckPassport proc (client)

See also:
  IsSubscribed proc (world)
  IsByondMember proc (client)
  GetAPI proc (client)
  SetAPI proc (client)

Format:
  CheckPassport(passport_identifier)

Args:
  passport_identifier: a text string assigned to you by the BYOND hub (or an ID/token for a different API; see below).

This built-in procedure checks to see if the user is subscribed to a particular BYOND hub entry. If the user is subscribed, the result is the number of days left (rounded up) on their subscription, or -1 for lifetime subscribers.

### Example:

    world
       hub = "My.Hub"  //change this to your own hub entry

    mob/var
       full_access

    mob/Login()
       if(client.CheckPassport("0123456789abcdef"))
          full_access = 1
       else
          src << "For full access, <a href=\
                  'http://www.byond.com/hub/[world.hub]' >subscribe</a>!"
       return ..()

Note that in general the value of world.hub has nothing to do with the passport you happen to check. This example assumes the passport number belongs to world.hub just for the purpose of forwarding the user to the appropriate subscription page.

### Other APIs

You can use this with other APIs that are supported by BYOND, which currently only applies to Steam and only if the game is specially built for Steam support.

To check ownership of a Steam game or DLC (must be the current game's ID or one of its DLCs), use `"steam:NNNNNN"` for the passport string, where NNNNNN is a Steam app ID. Note that the user must be logged into Steam for this to work.

## Click proc (client)

See also:
  Click proc (atom)
  DblClick proc (client)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  Click(object,location,control,params)

When:
  Called when the player clicks on the map or in the stat panels.

Args:
  object: the object clicked
  location: the client stat panel, location (turf) of object on map, grid cell, or other control-specific info
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.Click(location,control,params).

### Example:

    client
      Click(O)
        usr << "You clicked [O]"
        ..() // do default action

Note that due to network lag, it is possible when clicking on moving objects for the location of those objects to have changed by the time the Click() proc is executed. That is the reason for the location argument. It tells you where the click originally took place.

The argument format for this verb is:

    Click(object as null|atom in usr.client,\
          location as null|turf|text in usr.client,\
          control as text, params as text)

## Command proc (client)

Format:
  Command(command as command_text)

When:
  Called when the player types in something that is not understood as a valid command, or if the player is connected via telnet.

Default action:
  None.

If this proc is used, players will be able to connect to your world via telnet. All telnet users' commands are routed through this proc instead of being parsed into verbs. Players who join the world through Dream Seeker will have their commands parsed as verbs first, and those commands will end up here only if there is no applicable verb.

Note that text received by this proc is not interpreted beforehand, so quotes " and backslashes \ should come through unaltered.

This proc is primarily useful if you want to handle parsing yourself (like for a MUD), or if your world is a chat server and verbs are not used much.

## DblClick proc (client)

See also:
  Click proc (client)
  DblClick proc (atom)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_over_pointer var (atom)
  show_popup_menus var (client)

Format:
  DblClick(object,location,control,params)

When:
  Called when the player double-clicks on the map or in the stat panels.

Args:
  object: the object double-clicked
  location: the client stat panel, location (turf) of object on map, grid cell, or other control-specific info
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.DblClick(location,control,params).

### Example:

    client
      DblClick(O)
        usr << "You double-clicked [O]"
        ..() // do default action

Note that due to network lag, it is possible when clicking on moving objects for the location of those objects to have changed by the time the DblClick() proc is executed. That is the reason for the location argument. It tells you where the click originally took place.

    DblClick(object as null|atom in usr.client,\
             location as null|turf|text in usr.client,\
             control as text, params as text)

## Del proc (client)

See also:
  Logout proc (mob)

Format:
  Del()

When:
  Called when the player disconnects from the world.

Default action:
  If the player is connected to a mob, call mob.Logout() to disconnect. If the player's connection to the world is still not dead, kill it.

Note that this does not automatically delete the player's mob. If you want to do that, you could do so in mob.Logout().

## East proc (client)

See also:
  Move proc (client)

Format:
  East()

Returns:
  1 on success; 0 on failure.

When:
  Called when the player presses the "right" key or cursor.

Default action:
  Calls src.Move() towards the east.

## Export proc (client)

See also:
  Import proc (client)
  New proc (client)
  hub var (world)
  savefile

Format:
  client.Export(file)

Args:
  file: file to send to client

This stores the file on the user's computer in a special location unique to each registered world.hub setting. This is most useful for writing a client-side savefile, but any type of file may be stored. The purpose of this is to exchange information between different worlds running under the same hub path.

When a file is exported to the player's computer, it replaces any previous file stored by a game with the same `world.hub` value. This should not be used for anything requiring high security, because any other world could make use of the same hub path and access the file. It is also possible for the user to tinker with the file, since it resides on their computer.

To delete the client-side file completely, call `client.Export()` with no argument at all.

### Example:

    mob/verb/save()
       var/savefile/F = new()
       F << usr     //write the player's mob
       usr.client.Export(F)

    client/New()
       var/client_file = Import()
       if(client_file)
          var/savefile/F = new(client_file) //open it as a savefile
          F >> usr  //read the player's mob
       return ..()

## GetAPI proc (client)

See also:
  SetAPI proc (client)
  CheckPassport proc (client)

Format:
  GetAPI(Api, Name)

Args:
  Api: the name of the API (e.g. "steam")
  Key: the name of the value to read

Interfaces with supported external APIs to read information. Currently this only has meaning for Steam, for specially built games that have a Steam app ID.

This proc returns null any time the call or its results are invalid: for instance, trying to query a Steam stat from a user who isn't logged into Steam.

Key | Return type | Description
--- | --- | ---
`"steam"` API Requires that the server and client are using a valid Steam app ID, such as when a game is built for standalone distribution.
id | text | Returns the user's numeric Steam ID, if any. Because this number is too big to fit in BYOND's numbering system, it is returned as text.
name | text | Returns the user's persona name on Steam.
stat:Name | num | Returns the value of the stat called `Name`.
achievement:Name | num | Returns the date (for use with time2text) the achievement called `Name`, or 0 if it hasn't been earned.
achievement-data:Name | list | Returns information about the achievement called `Name`. The result is an associative list with named values `name` (display name), `desc` (description), and optionally `hidden` and `icon`. (This call is the same no matter which client you call it for.)
achievements | list | Returns a list of all possible achievements. Each item in the list is the internal name of the achievement, and it is associated with a list in the form described for `achievement-data:Name`. (This call is the same no matter which client you call it for.)

## Import proc (client)

See also:
  Export proc (client)
  New proc (client)
  savefile

Format:
  client.Import(Query)

Args:
  Query: optional query parameters

When no query parameters are given, this returns the client-side file last exported with `client.Export()`. This comes as an entry in the resource cache, which can be opened as a savefile among other things. If there is no file, null is returned. For an example, see client.Export.

When there are query parameters, these may be used to import a file from some alternate source. Currently this is not supported.

## IsByondMember proc (client)

Format:
  IsByondMember()

Args:
  None.

This built-in procedure checks to see if the user is a BYOND Member. Use it to give special in-game rewards to those who support BYOND.

If the user is a Member, the result is the number of days left (rounded up) on their Membership, or -1 for lifetime Members.

### Example:

    mob/var
       special_features

    mob/Login()
       if(client.IsByondMember())
          special_features = 1
       else
          src << "For special features, <a href=\
                  'http://members.byond.com/' >become a BYOND Member</a>!"
       return ..()

## MeasureText proc (client)

See also:
  maptext var (atom)
  maptext_width var (atom)
  maptext_height var (atom)

Format:
  MeasureText(text, style, width=0)

Args:
  text: The text to be measured
  style: Stylesheet to be used (leave blank to use the default map control's styles, if any)
  width: Width limit, if you only want to measure height; 0 means no limit

Returns:
  A size value in `"[width]x[height]"` format, e.g. "60x16"

Because maptext rendering may vary by client, `MeasureText` lets you get a measurement of how text will be laid out, so you can adjust `maptext_width` and `maptext_height` accordingly.

## MouseDown proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDown proc (atom)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseDown(object,location,control,params)

Args:
  object: the object under the mouse pointer
  location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseDown(location,control,params).

This is called when the a mouse button is pressed while pointing to the object. Note that MouseUp() will always be called after MouseDown() is called, even if over empty space. That means object and location may be null.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through `Click()`, `DblClick()`, and `MouseDrop()`. The other procedures are simply available for completeness.

The argument format for this verb is:

    MouseDown(object as null|atom in usr.client,\
              location as null|turf|text in usr.client,\
              control as text, params as text)

Note: In BYOND 3.5 this procedure took three different arguments: `location`, `icon_x`, and `icon_y`. Since `icon_x` and `icon_y` have been replaced, old code will need to be modified. Games compiled before this change will still work normally.

## MouseDrag proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDown proc (client)
  MouseDrag proc (atom)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseDrag(src_object,over_object,src_location,over_location,src_control,over_control,params)

Args:
  src_object: the object being dragged
  over_object: the object under the mouse pointer
  src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
  over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
  src_control: The id of the skin control the object was dragged from
  over_control: The id of the skin control the object was dragged over
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseDrag(over_object,src_location,over_location,src_control,over_control,params).

This is called while dragging an object by pressing and holding the left mouse button over the object and moving the mouse. The over_object may be null if dragging over a stat panel or over other empty space.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.

The argument format for this verb is:

    MouseDrag(src_object as null|atom in usr.client,\
              over_object as null|atom in usr.client,\
              src_location as null|turf|text in usr.client,\
              over_location as null|turf|text in usr.client,\
              src_control as text, over_control as text, params as text)

## MouseDrop proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrop proc (atom)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseDrop(src_object,over_object,src_location,over_location,src_control,over_control,params)

Args:
  src_object: the object being dropped
  over_object: the object under the mouse pointer
  src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
  over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
  src_control: The id of the skin control the object was dragged from
  over_control: The id of the skin control the object was dropped onto
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseDrop(over_object,src_location,over_location,src_control,over_control,params).

This is called when a mouse button is released after dragging an object. The over_object may be null if dropping over a stat panel or over other empty space.

The argument format for this verb is:

    MouseDrag(src_object as null|atom in usr.client,\
              over_object as null|atom in usr.client,\
              src_location as null|turf|text in usr.client,\
              over_location as null|turf|text in usr.client,\
              src_control as text, over_control as text, params as text)

## MouseEntered proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (atom)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseEntered(object,location,control,params)

Args:
  object: the object under the mouse pointer
  location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseEntered(location,control,params).

This is called when no mouse buttons are pressed while pointing to the object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

The argument format for this verb is:

    MouseEntered(object as null|atom in usr.client,\
                 location as null|turf|text in usr.client,\
                 control as text, params as text)

## MouseExited proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (atom)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseExited(object,location,control,params)

Args:
  object: the object under the mouse pointer
  location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseExited(location,control,params).

This is called when the mouse moves off of an object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

The argument format for this verb is:

    MouseExited(object as null|atom in usr.client,\
                location as null|turf|text in usr.client,\
                control as text, params as text)

## MouseMove proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (atom)
  MouseUp proc (client)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseMove(object,location,control,params)

Args:
  object: the object under the mouse pointer
  location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseMove(location,control,params).

This is called when no mouse buttons are pressed while pointing to the object, and the mouse has moved. The first time the mouse moves over the object, MouseEntered() is called instead.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

The argument format for this verb is:

    MouseMove(object as null|atom in usr.client,\
              location as null|turf|text in usr.client,\
              control as text, params as text)

## MouseUp proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (atom)
  MouseWheel proc (client)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)
  show_popup_menus var (client)

Format:
  MouseUp(object,location,control,params)

Args:
  object: the object under the mouse pointer
  location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseUp(location,control,params).

This is called when a mouse button is released while pointing to an object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through `Click()`, `DblClick()`, and `MouseDrop()`. The other procedures are simply available for completeness.

The argument format for this verb is:

    MouseUp(object as null|atom in usr.client,\
            location as null|turf|text in usr.client,\
            control as text, params as text)

Note: In BYOND 3.5 this procedure took three different arguments: `location`, `icon_x`, and `icon_y`. Since `icon_x` and `icon_y` have been replaced, old code will need to be modified. Games compiled before this change will still work normally.

## MouseWheel proc (client)

See also:
  Click proc (client)
  DblClick proc (client)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)
  MouseWheel proc (atom)
  mouse_opacity var (atom)
  mouse_pointer_icon var (client)

Format:
  MouseWheel(object,delta_x,delta_y,location,control,params)

Args:
  object: the object under the mouse pointer
  delta_x,delta_y: amount of wheel movement
  location: the turf, stat panel, grid cell, etc. containing the object
  control: the name of the skin control involved
  params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

Default action:
  Call object.MouseWheel(delta_x,delta_y,location,control,params).

This is called when the mouse wheel is moved while over an object or control. It is NOT called if over a browser control, or any control that is currently scrollable.

Positive values of delta_x and delta_y refer to scrolling right or up, respectively. Negative values are left and down, respectively.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. If you only need wheel support on specific objects, use atom.MouseWheel() instead which is more selective.

The argument format for this verb is:

    MouseWheel(object as null|atom in usr.client,\
               delta_x as num, delta_y as num,\
               location as null|turf|text in usr.client,\
               control as text, params as text)

## Move proc (client)

See also:
  East proc (client)
  Move proc (movable atom)
  North proc (client)
  Northeast proc (client)
  Northwest proc (client)
  South proc (client)
  Southeast proc (client)
  Southwest proc (client)
  West proc (client)

Format:
  Move(loc,dir)

Returns:
  1 on success; 0 on failure

When:
  Called by the direction procs.

Default action:
  Calls src.mob.Move(). Also cancels any automated movement by calling walk(usr,0).

## New proc (client)

See also:
  Export proc (client)
  Import proc (client)
  Login proc (mob)
  New proc (datum)
  Topic proc (client)
  mob var (world)
  savefile

Format:
  New(TopicData)

Returns:
  The newly connected mob, client.mob, or null to disallow the connection.

When:
  Called when the player first tries to connect to the world.

Args:
  usr: The mob in the world with the same key as the player, if it exists.
  TopicData: If the player accessed the world with a "connection topic", this is the topic text. Otherwise it is null.

Default action:
  Look for an existing mob with the same key as the player. If found, connect the player to that mob (mob.Login()). Otherwise, look for a prototype mob with the same key as the player. If found, create a mob of that type and connect the player to it. Otherwise, create a mob of type world.mob, give it the same name and gender as the player's key, and connect the player to it. If TopicData is not null, call client.Topic(TopicData). Finally, the player's mob is returned.

This is a fairly low-level procedure that you would only want to override if you cannot accomplish the same thing in `mob/Login()` or `mob/New()`. One reason to override `client/New()` is if player mobs are created from a savefile. In that case, you don't need a temporary mob to be created first.

### Example:

    client/New()
       if(usr) return ..() //reconnecting to existing mob
       else
          var/player_sav = "players/[ckey].sav"
          if(length(file(player_sav)))        //if player savefile exists
             var/savefile/F = new(player_sav) //open it
             F >> usr    //create saved mob
          return ..()    //creates a new mob if necessary
    mob/Logout()
       var/player_sav = "players/[ckey].sav"
       var/savefile/F = new(player_sav)
       F << src
       del src

If you want to do any user-interaction before loading the saved mob, you will have to create a temporary mob first in order to interact with the player. In that case, you are better off doing things in `mob/Login()`, rather than `client/New()`.

Note that for the above example to work, you must make proper use of the tmp flag when defining new object variables. Otherwise, this can end up sucking large portions of your world into each player savefile, which can have all sorts of unexpected consequences!

## North proc (client)

See also:
  Move proc (client)

Format:
  North()

Returns:
  1 on success; 0 on failure.

When:
  Called when the player presses the "up" key or cursor.

Default action:
  Calls src.Move() towards the north.

## Northeast proc (client)

See also:
  Move proc (client)

Format:
  Northeast()

Returns:
  1 on success; 0 on failure.

When:
  Called when the player presses the "up-right" key or cursor.

Default action:
  Calls src.Move() towards the northeast.

## Northwest proc (client)

See also:
  Move proc (client)

Format:
  Northwest()

Returns:
  Returns 1 on success; 0 on failure.

When:
  Called when the player presses the "up-left" key or cursor.

Default action:
  Calls src.Move() towards the northwest.

## RenderIcon proc (client)

See also:
  vis_contents var (atom)
  Filter effects

Format:
  RenderIcon(object)

Args:
  object: An atom or appearance to render.

Returns:
  A single-image icon file in which the object is rendered with all its overlays, visual contents, etc.

Use this proc to render an atom or an appearance as a single icon. This is a client proc because the server is not capable of rendering anything on its own.

Any overlays, image objects known to this client that are attached to the object, visual contents, maptext, and so on will be included in the render. The returned icon is sized to fit all of the above, and to include room for any expansion due to filter effects.

### Example:

    mob/proc/GetFlatIcon()
        return client?.RenderIcon(src)

Important notes regarding this proc:

- The returned icon is a cache file, not an `/icon` datum.
- If `object` is an `/image` object, the image must be known to the client. Otherwise the return value is null.
- If this object doesn't appear on the client's map, it will be sent to them on the next map tick, along with any visual contents. The server will hold a reference to the object until the map tick ends, so an object you create temporarily should remain valid long enough to be rendered.
- render_source will not work unless the corresponding render_target appears in the same render stack. That is, this object or appearance will be rendered in an isolated "scene" rather than as part of the map, so it won't be able to use other objects on the map as render sources.

## SendPage proc (client)

Format:
  SendPage(msg,recipient,options)

Returns:
  Returns number of recipients successfully contacted.

Args:
  msg: text to send
  recipient: key or list of keys to page
  options: text string containing key=value options

The user is prompted to authorize sending of the pager message. The recipient may easily respond or jump to the sender's location by clicking on the link in the pager message. The effect is identical to that of the sending a page through the Dream Seeker pager.

The options are encoded in the same format read by text2params(). The valid options are:

summon (0/1)
  If not included in the options, this is 0. If included in the options without assigning it to anything, it is 1. A value of 1 sends the recipient the sender's location so they can join by clicking on the message.
email (0/1)
  If not included in the options, this is 0. If included in the options without assigning it to anything, it is 1. A value of 1 sends causes the message to be delivered as email. If this is not possible, it is delivered as a long-lived pager message. Normally, pager messages expire within a short time after being sent (half an hour).
subject
  For email messages, this specifies the subject to use.

## SetAPI proc (client)

See also:
  GetAPI proc (client)
  CheckPassport proc (client)

Format:
  SetAPI(Api, Key, Value)

Args:
  Api: the name of the API (e.g. "steam")
  Key: the name of the value to change
  Value: the new value to set

Interfaces with supported external APIs to write information. Currently this only has meaning for Steam, for specially built games that have a Steam app ID.

This proc returns null any time the call or its results are invalid.

Key | Return type | Description
--- | --- | ---
`"steam"` API Requires that the server and client are using a valid Steam app ID, such as when a game is built for standalone distribution.
stat:Name | num | Changes the value of the stat called `Name`. Returns 1 on success. This may fail if the stat change is too much or is out of range.
achievement:Name | num | Earns the achievement called `Name`, or clears it. Value is expected to be a number, or number in text form, where 0 will clear the achievement and 1 will earn it.

## SoundQuery proc (client)

See also:
  /sound datum
  sound proc

Format:
  SoundQuery()

Args:
  none

Returns:
  A list of `/sound` datums with information about currently playing sounds.

This proc is used to ask a client about sounds that are playing. The `/sound` datums in the returned list have the following vars set:

- file: Sound/music file, or null if none
- channel: Channel of sound, if one was set when the sound was played
- repeat: The `repeat` value of the sound
- status: Status flags active for this channel; currently only `SOUND_PAUSED` is supported
- offset: Current time index, in seconds, of the sound at the current frequency
- len: Total duration, in seconds, of the sound at the current frequency
- wait: Total duration of sounds queued to play later on this channel (does not apply to channel 0)

Not all info about the sounds is retrieved, such as `volume`, `frequency`, etc. If those are needed, it should be a simple matter to keep track of them in your code. The main purpose of `SoundQuery()` is to ascertain the current status of playing sounds.

## South proc (client)

See also:
  Move proc (client)

Format:
  South()

Returns:
  Returns 1 on success; 0 on failure.

When:
  Called when the player presses the "down" key or cursor.

Default action:
  Calls src.Move() towards the south.

## Southeast proc (client)

See also:
  Move proc (client)

Format:
  Southeast()

Returns:
  1 on success; 0 on failure.

When:
  Called when the player presses the "down-right" key or cursor.

Default action:
  Calls src.Move() towards the southeast.

## Southwest proc (client)

See also:
  Move proc (client)

Format:
  Southwest()

Returns:
  Returns 1 on success; 0 on failure.

When:
  Called when the player presses the "down-left" key or cursor.

Default action:
  Calls src.Move() towards the southwest.

## Stat proc (client)

See also:
  Stat proc (atom)
  stat proc
  statobj var (client)
  statpanel proc
  statpanel var (client)
  Info control (skin)

Format:
  Stat()

When:
  Called periodically by the client to update the stat window.

Default action:
  Call statobj.Stat().

If this procedure sleeps (or engages in some other waiting operation), it will not be called again until it finally returns. This allows you to effectively decrease the frequency of calls to the proc. You might want to do that if it is a fairly lengthy procedure, and frequent calls are slowing things down.

To increase the frequency of stat updates, you can lower `world.tick_lag`.

Note: Typically only the currently viewed statpanel is updated, which saves on some network activity and a little time. If however the proc sleeps, you need to be sure that any pending updates are displayed once the right panel is available. Therefore if you're resetting a var that indicates the proc should sleep next time, it should not be reset unless you know the player is looking at the right statpanel and has received the updates.

### Example

    client/var/updategold = 1       // set to 1 if gold changes
    client/var/updateinventory = 1  // set to 1 if inventory changes

    client/Stat()
        // if not ready to update, Stat() won't be called again till sleep is done
        while(!updategold && !updateinventory)
            sleep(5)
        if(statpanel("Gold")) // switch to Gold panel and ask if player is looking at it
            stat("Gold", mob.gold)
            updategold = 0  // we updated, so turn this flag back off
        if(statpanel("Inventory"))
            stat(mob.contents)
            updateinventory = 0

Because sleeping in Stat() requires more thinking through, it's best to do so only in cases where Stat() has to do a lot of intensive calculations.

## Topic proc (client)

See also:
  New proc (client)
  Topic proc (datum)
  link proc
  ref text macro

Format:
  Topic(href,href_list[],hsrc)

When:
  Called when a player connects to a world with a "connection topic" or when the player runs a hyperlink in the current world by clicking one embedded in text or generated by the link() instruction.

Args:
  href: The topic text (everything after the '?' in the full href).
  href_list: List of key/value pairs in href (produced from params2list(href)).
  hsrc: The object referenced by the "src" parameter in href or null if none.

Default action:
  Call the hsrc object's own Topic() proc.

The following example uses a very simple href value.

### Example:

    mob/Login()
      src << "Click <a href=?source>here</a> to download the source code."
      return ..()

    client/Topic(href)
      if(href == "source")
        usr << file("world.dm")
        usr << file("world.rsc")
      else ..()

Be sure to call the default handler unless you want to prevent rerouting of topics to other objects.

Always validate the input in `Topic()` calls to make sure it's correct and the query you're recieving is legitimate. For security reasons, you will probably want to control which objects a player has access to, since a player could spoof a topic link containing any arbitrary object reference. (Never trust those sneaky players!)

The next example demonstrates an href that gets handled by another object. This is how you would normally want to do things. It is best not to override client/Topic() (as in the example above) unless you need to intervene in the low-level details of routing the request to the right object.

You specify the object that will handle the request by using a parameter called "src".

### Example:

    mob/Login()
       src << "Click <a href='?src=\ref[src];action=startgame'>here</a> to start."
       return ..()

    mob/Topic(href,href_list[])
       switch(href_list["action"])
          if("startgame")
             usr << "Starting game..."
          else
             return ..()

Although it is slightly more complex, the use of the parameter list allows you to easily include extra data and new functionality. Just remember that the data in the list is always stored as text, so if you are expecting a number or an object, you must convert it yourself (with text2num(), locate(), or whatever).

## West proc (client)

See also:
  Move proc (client)

Format:
  West()

Returns:
  Returns 1 on success; 0 on failure.

When:
  Called when the player presses the "left" key or cursor.

Default action:
  Calls src.Move() towards the west.

## vars (client)

Built-in client vars:

client/var
  address
  authenticate
  bounds
  byond_build
  byond_version
  CGI
  ckey
  color
  command_text
  connection
  control_freak
  computer_id
  default_verb_category
  dir
  edge_limit
  eye
  fps
  gender
  glide_size
  images
  inactivity
  key
  lazy_eye
  mob
  mouse_pointer_icon
  perspective
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  preload_rsc
  screen
  script
  show_map
  show_popup_menus var
  show_verb_panel
  statobj
  statpanel
  tick_lag
  timezone
  verbs
  view
  virtual_eye

## CGI var (client)

In CGI mode, DreamDaemon is normally being executed by a web server and accessed by a web browser. The CGI object is an add-on to the basic client object for handling this case.

The CGI object is defined and documented in a separate code library `html/CGI.dm`. You can find the current version at www.byond.com.

## address var (client)

Default value:
  The network address of the player's client.

This is a read-only value which contains the player's network address.

## authenticate var (client)

This value may be set to 0 at compile-time to disable BYOND hub-based authentication of users. The default value is 1, which enables authentication. Hub authentication provides an additional level of assurance that the user is really the owner of the BYOND key in question.

When a world requests certification, Dream Seeker generates a random password and passes it through the hub (for certification) to the world. The certificate is saved for faster access in the future and for protection against possible hub outages.

Some applications do not depend on the validity of the user's identity. In that case, it would be more efficient to turn off the extra level of authentication. In other situations, the hub may not be available, such as from behind a firewall or on a LAN without internet access. In those cases, all hub access (including authentication) can be disabled by entering the command ".configuration hub-address none" in Dream Seeker.

Connections to worlds on the same machine are not hub-authenticated to allow for convenient offline testing.

## bounds var (client)

(Also `bound_x`, `bound_y`, `bound_width`, and `bound_height`.)

See also:
  bounds proc

The read-only bounds var returns the map coordinates, in pixels, covered by the client's viewport when accounting for pixel offsets, eye, step, etc. (The coordinates are only relevant to the default `client.dir` value of `NORTH`, and the `TOPDOWN_MAP` or `SIDE_MAP` map formats.)

If the viewport is not currently on the map (for instance, when the eye is at a null location), the var reads as null. Otherwise, it is a list with five values (x, y, width, height, z) in the same form used by the bounds proc.

The alias vars bound_x, bound_y, bound_width, and bound_height can also be used to retrieve the individual values from the list. They too will be null if the viewport is not on the map.

## byond_build var (client)

See also:
  DM_VERSION macro
  byond_version var (client)
  byond_version var (world)

This is the build number (minor version) of BYOND being run by this client. Typically this is not useful information, but it can come in handy when diagnosing issues reported by players using a beta build.

Clients running versions of BYOND prior to 512 (major version) will not have this information. It is also not guaranteed to exist for non-Dream Seeker connections. When not available, byond_build is 0.

## byond_version var (client)

See also:
  DM_VERSION macro
  byond_build var (client)
  byond_version var (world)
  system_type var (world)

This is the version of BYOND being run by this client. A game designed to work around known bugs in older versions could use this to adapt its behavior accordingly. It is also possible to prevent players with much older versions from joining the game.

## ckey var (client)

See also:
  ckey proc
  key var (client)

This is a read-only value that is the canonical form of the player's key (ie the value returned by ckey()). Among other things, this could be used as a unique directory name in a server-side save file for storing player information. See the ckey() proc for an example.

## color var (client)

See also:
  color var (atom)
  appearance_flags var (atom)

Casts a color multiplication or matrix effect over the entire main map. This behaves exactly the same as atom.color, and will be combined with atom.color (which comes first) where present. See atom.color for more information.

If a matrix is used, the alpha column and row will have no effect.

Icons that have the NO_CLIENT_COLOR value in appearance_flags will not be subject to client.color. This can be useful for HUD objects.

This value can be animated.

### Example:

    mob/proc/DayNight(is_day)
        if(client)
            client.color = is_day ? \
                null : \
                list(0.2,0.05,0.05, 0.1,0.3,0.2, 0.1,0.1,0.4)

## command_text (client)

See also:
  arguments (verb)
  command parameter
  macros (client script)
  Input control (skin)
  command parameter (skin)
  macros (skin)

Default value:
  null

Note: In BYOND 4.0 this var is deprecated. The command parameter for an Input control can be set to `!command` (`!` in front of your default command) which does the same thing.

This text is placed onto the command line, to be followed by whatever the user may type. It is usually the name of a verb followed by a space, such as `"say "`. The user can clear this and enter a different command by hitting backspace, escape, delete, or `/`.

### Example:

    client
       command_text = "say "

       verb/say(T as text)
          world << "[usr] says, '[T]'"

It is also possible to turn on macro mode, in which each keypress executes a keyboard macro, by setting `command_text` to `".alt "`. That stands for the Alt key, which can be used to execute macros in normal mode.

This variable could also be used to create a specialized command prompt. For example, a traditional style MUD command-line could be implemented like this:

### Example:

    client
       command_text = "> "
       verb/command(C as command_text)
          set name = ">"
          usr << "Your command: [C]"

This example uses the `command_text` input type, which accepts raw text, with no quoting, escaping, or translating, so that you can invent whatever syntax you want.

## computer_id var (client)

Default value:
  A unique numerical identifier for the player's computer. The value is in text form.

This is a read-only text value which contains a unique numerical identifier for the player's computer. Its primary purpose is to detect if players are connecting to a server with multiple accounts on the same machine, while still allowing for multiple accounts on the same network (eg, through a router).

## connection var (client)

This is a read-only var describing the type of client that is connected.

Possible values:
  "seeker" - The player is connected through Dream Seeker
  "telnet" - The player is connected through telnet
  "world" - The client is actually a world.Export() connection from another server
  "cgi" - The client is connected via CGI (irrelevant to most worlds)
  "web" - The client is connected via the Web client
  "http" - The client is an HTTP connection (used by the Web client's virtual server)

Other values may be supported in the future.

An empty value means the connection type is unknown because a full handshake hasn't been completed yet.

## control_freak (client)

See also:
  User interface skins
  macros (skin)
  macros (client script)

Default value:
  0

This var lets you set flags to turn off options that are normally present for the end user. You can combine these flags with the `|` operator. The value 1 is equivalent to `CONTROL_FREAK_ALL` and will disable everything.

CONTROL_FREAK_ALL
  If this value is used, it affects all the options below.
  - User-defined macros may not be used.
  - Only the world's skin or the default BYOND skin will be loaded, not a user-customized version.
  - The Options & Messages window in Dream Seeker is inaccessible. It will only come up while first connecting to a remotely hosted world, or if a world takes a long time to load. The .options command will not make it appear.
  - The menu items from Options & Messages are unavailable in Dream Seeker's system menu.
  - The default F2 macro for the .screenshot command is turned off. The command is then only accessible through the skin you create.
CONTROL_FREAK_SKIN
  Toggles the ability to create a custom version of the skin.
CONTROL_FREAK_MACROS
  Toggles the ability to use and define custom macros.

Using `CONTROL_FREAK_ALL` will default to disabling everything, and the other flags will reenable only the features you want. For example, `CONTROL_FREAK_MACROS` alone will disable the ability to use your own macros but nothing else. `CONTROL_FREAK_ALL | CONTROL_FREAK_MACROS` will disable everything except macros.

This value can be changed at runtime.

Note: If you define your own skin for the world, and disable the ability to use a custom skin or user-defined macros, you must be sure to define any macros your world may need. For instance, arrow keys may be needed for movement.

## default_verb_category var (client)

See also:
  category setting (verb)
  show_verb_panel var (client)

Default value:
  "Commands"

All verbs with category "" (the default value) are treated as though they had this category setting instead. In other words, this is the name of the panel that contains them. You could even turn that panel off by setting this value to null.

## dir var (client)

Default value:
  NORTH

This defines the relationship between the world's coordinate system and the player's screen. The default means that the player sees the map exactly as it was created (in the map-editor or at runtime). Changing it to one of the other directions causes the player to see the map as if it were rotated to that direction. This means that a player with client.dir = SOUTH would see the map inverted relative to a person with client.dir = NORTH. That's handy in two-player board games where you want both players to see their side in the same place.

Note that this does not turn icons upside down! The map is rotated, but the icons on the map remain in their normal orientation.

Movement keys are remapped so that a player with client.dir = SOUTH hitting the up arrow will generate a call to client.South() rather than the usual client.North().

## edge_limit var (client)

See also:
  eye var (client)
  lazy_eye var (client)
  perspective var (client)
  view var (client)
  screen_loc var (movable atoms)

Default value:
  null

This value determines the limits that a client's eye will display. If `client.perspective` uses the `EDGE_PERSPECTIVE` flag, the view shouldn't scroll beyond the bounds set by `edge_limit`. If the bounds of `edge_limit` are as big as or smaller than the client's view, no scrolling will occur even if `EDGE_PERSPECTIVE` is not used. Normally this value is null, which provides freedom for the eye to move anywhere on the map. It may be changed to a text value describing the limits in more detail.

The format is similar to `atom.screen_loc` which uses `"[x1],[y1] to [x2],[y2]"`. It can also use directions such as `"SOUTHWEST to NORTHEAST"`, which refer to the limits of the map.

### Example:

    area/house
      var/x1,x2,y1,y2

      Entered(mob/M)
        if(ismob(M) && M.client)
          M.client.edge_limit = "[x1],[y1] to [x2],[y2]"

      Exited(mob/M)
        if(ismob(M) && M.client)
          M.client.edge_limit = null

## eye var (client)

See also:
  edge_limit var (client)
  lazy_eye var (client)
  mob var (client)
  perspective var (client)
  glide_size var (client)
  view var (client)
  virtual_eye var (client)
  view var (world)
  step_x var (movable atom)
  step_y var (movable atom)

Default value:
  The connected mob, client.mob.

This value determines the center of the player's map. The default value simply means that the visible region is normally centered on the player's mob. Effects such as setting `perspective` to `EDGE_PERSPECTIVE` or using `lazy_eye` can move the map off-center temporarily. The eye is the ideal center, not necessarily the actual center; to find the actual center, use `virtual_eye`.

The eye's step_x/y vars, if present, are also used to allow smooth scrolling of the map. These also obey lazy_eye and edge_limit.

Note that the visibility of objects is still computed from the point of view of the mob rather than the eye. This allows the use of `lazy_eye` or similar effects that control the panning of the map while still having the player see only what the mob can see. To determine visibility from the eye, you can change the value of `client.perspective`.

If a player connects to a new mob M, client.eye automatically changes to M.

### Example:

    client
      eye = locate(5,5,1)

This fixes the center of the player's map at the turf coordinate (5,5,1). Since the eye is fixed, the map will not scroll even as the player's mob moves out of the visible range.

## fps var (client)

See also:
  fps var (world)
  tick_lag var (client)
  Pixel movement

Default value:
  0 (uses world.fps value)

This is a client version of world.fps, so that the client can run at a faster speed for animations. For example, setting client.fps to 40 while world.fps is the default 10 will mean that all animations and glides are smoothed out and displayed at 40 FPS, even though the server still runs at 10 FPS. The result is a nicer-looking game with no additional impact on the server.

When this value is 0, the client and server tick at the same rate.

## gender var (client)

See also:
  New proc (client)
  gender var (atom)
  key var (client)
  macros (text)

This is the client's gender, which is an attribute of the player's key. By default, when a new mob is made for a player (in client.New()), the new mob gets the same name and gender as the player's key. This influences text macros like `\he`, which may expand to "it", "he", "she", or "they". Valid values are:

    "neuter"
    "male"
    "female"
    "plural"

## glide_size var (client)

See also:
  eye var (client)
  glide_size var (movable atoms)

Default value:
  0

Note: The way this setting is used depends on world.movement_mode. See Gliding for more details.

This controls the number of pixels the map is moved in each step during scrolling of the map. The default value of 0 chooses automated control over this value, which generally results in a minimum step of 4 pixels that is increased when necessary to keep up with motion of the map.

Be careful about using small step sizes. Icons with high contrast pixel-level detail can look pretty ugly when displaced by short distances.

This was renamed from `pixel_step_size`.

## images var (client)

See also:
  image objects
  image proc

This is a list of images that are displayed to the user. The output operator is one way to add entries to this list. Deleting an image object will automatically remove it from the display, but if you want to retain an image (so other people can still see it), it can be removed by directly modifying this list.

### Example:

    var/image/I = new('image.dmi',usr)
    usr.client.images += I  //display it
    sleep(50)
    usr.client.images -= I  //remove it from the display

Displaying the image can also be achieved like this:

    usr << I

## inactivity var (client)

See also:
  tick_lag var (world)

This is equal to the amount of time (in server ticks, which default to 1/10s) since the player's last action (such as executing a verb, moving, clicking an object, or selecting a topic link). This value is reset to 0 after each new action so you can use it to determine the time that has passed since the last one.

### Example:

    mob/verb/inactivity()
      usr << "You have been inactive for [client.inactivity/10] seconds."

## key var (client)

See also:
  key var (mob)

Default value:
  The player's key identity.

This is a read-only value that contains the player's key. Once the player is attached to a mob M, M.key == M.client.key.

## lazy_eye var (client)

See also:
  view var (client)
  view var (world)

Default value:
  0

This is the maximum "lag" between client.eye and client.mob. The mob can stray up to this many tiles before the eye will move to keep it in view. The default value of 0 means that the eye always moves as the mob moves, keeping the mob at the center of the player's map.

Setting this value to a non-zero value automatically initializes client.eye to client.mob.loc (or to the center of the full map if that is possible). Thereafter, client.eye will stray from the mob as it moves about the map, making one big jump to catch up whenever the mob gets out of range.

### Example:

    client
      lazy_eye = 5

This setting allows client.mob to move onto the entire 11x11 visible region without changing the value of client.eye. The moment it steps out of this region, the entire region will shift 5 tiles in the direction of motion.

You can assign lazy_eye to any value valid as a view size, so, for example, if you have a non-square setting for client.view, say, "17x11", you could apply a similar setting to lazy_eye. You can even make one dimension lazy and the other one strictly centered: "0x5".

## mob var (client)

Default value:
  Determined in client.New(), by default world.mob.

This is the mob to which the client is connected. The client and its connected mob have the following symmetry:

    client == mob.client
    client.mob == mob
    client.key == mob.key

## mouse_pointer_icon var (client)

See also:
  Click proc (client)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrag proc (client)
  MouseUp proc (client)
  mouse_drag_pointer var (atom)
  mouse_drag_pointer var (atom)
  mouse_drop_zone var (atom)
  mouse_over_pointer var (atom)

Default value:
  null

This is an icon file (.dmi) containing custom mouse cursors to use in place of the standard ones. The different possible mouse states are distinguished by special icon state names:

""
  Activated when over empty space or an object with mouse_over_pointer = MOUSE_INACTIVE_POINTER.
"over"
  Activated when over an object with mouse_over_pointer = MOUSE_ACTIVE_POINTER.
"drag"
  Activated when dragging an object with mouse_drag_pointer = MOUSE_ACTIVE_POINTER.
"drop"
  Activated when dragging an object over with mouse_drop_pointer = MOUSE_ACTIVE_POINTER and the object underneath has mouse_drop_zone set.
"all"
  Always activated, no matter what the state of the mouse.

## perspective var (client)

See also:
  eye var (client)
  mob var (client)

Default value:
  MOB_PERSPECTIVE

Possible values:
  - MOB_PERSPECTIVE
  - EYE_PERSPECTIVE
  - EDGE_PERSPECTIVE

This controls the eye's apparent center and what can be seen by the client.

EYE_PERSPECTIVE determines how visibility calculations are performed when `client.eye` and `client.mob` are different. Normally, visibility is done from the position of the mob, rather than from the eye (which is actually just the center of the map view). The alternative flag is MOB_PERSPECTIVE, the default.

EDGE_PERSPECTIVE limits scrolling to the bounds of the map (1,1 to world.maxx,world.maxy), and does not keep the mob centered if it strays near the edge.

The above values can be used together via the | operator.

## pixel_x var (client)

See also:
  glide_size var (client)
  pixel_y var (client)
  pixel_w var (client)
  pixel_z var (client)

Default value:
  0

This displaces the player's viewpoint on the x-axis by the specified number of pixels. Can be animated with the animate() proc.

## pixel_y var (client)

See also:
  glide_size var (client)
  pixel_x var (client)
  pixel_w var (client)
  pixel_z var (client)

Default value:
  0

This displaces the player's viewpoint on the y-axis by the specified number of pixels. Can be animated with the animate() proc.

## pixel_w var (client)

See also:
  glide_size var (client)
  pixel_x var (client)
  pixel_y var (client)
  pixel_z var (client)
  map_format var (world)

Default value:
  0

This displaces the player's viewpoint horizontally by the specified number of pixels. This value is meant to be used when world.map_format is not set to a default top-down view. Can be animated with the animate() proc.

## pixel_z var (client)

See also:
  glide_size var (client)
  pixel_x var (client)
  pixel_y var (client)
  pixel_w var (client)
  map_format var (world)

Default value:
  0

This displaces the player's viewpoint vertically by the specified number of pixels. This value is meant to be used when world.map_format is not set to a default top-down view. Can be animated with the animate() proc.

## pixel_step_size var (client)

Renamed to glide_size.

## preload_rsc var (client)

Default value:
  1.

This variable controls whether resource files (icons and sounds) are automatically downloaded by Dream Seeker when first connecting, or whether they should be downloaded as needed. Resource files are cached (in byond.rsc) for future use, so this should only affect people who have not played the game before or who have not played it for some time.

The three possible settings are:

0
  do not preload any resources
1
  preload compiled-in resources only
2
  preload all resources including those uploaded by players
URL
  preload resources from specified file

Preloading resource files will eliminate delays later on, but may cause a very long initial delay when logging in.

Resources may also be distributed from a website to save bandwidth on the machine hosting the game. Simply zip up the .rsc file, upload it to a web site, and put the URL here.

### Example:

    client/preload_rsc = "http://dan.byond.com/mygame_rsc.zip"

Instead of putting the .rsc file in the .zip, you can also put the individual resource files there. This would allow you to select specific files that you would like to be preloaded. For example, you could create a different resource package for different parts of the game world and assign client.preload_rsc dynamically as the player moves into each different area.

Once Dream Seeker has downloaded a resource package, it caches it and will not download it again, even if you upload a new version of the file. This allows you to make small changes without forcing a complete refresh. Any files which are not found in the preload package are simply downloaded from the game server directly.

If you want to force a complete refresh, simply change the name of the resource package. For example, you could put a version number in the name of the file: `mygame_rsc_01.zip`, `mygame_rsc_02.zip`, and so on.

## screen var (client)

See also:
  HUD / screen objects
  screen_loc var (movable atoms)

This is a list of objects that are displayed on the user's screen. The object's screen_loc variable controls where it appears (if it appears at all). This allows one to create the elements of a graphical user interface, with such features as buttons, drag/drop areas, and stat monitors.

Screen objects (visible or otherwise) may also be used to make verbs available to users. To make them accessible, define verbs on the screen object like this:

    set src in usr.client.screen

## script var (client)

See also:
  #include directive
  PASSWORD_TRIGGER (client script)
  URL (client script)
  aliases (client script)
  browser configuration
  command_text (client)
  macros (client script)
  macros (skin)
  style sheets
  style sheets (in scripts)

Default value:
  none

Client scripts are mini-programs used to configure the client. The language they use is called DM Script, and will undoubtedly expand in the future. Currently, client scripts can be used to define style sheets, command aliases, and macros. When executed directly by a player, they can also be used to specify an initial URL to open and a password trigger (for some ancient telnet worlds that don't suppress password echo).

For the specific syntax of DM Script, see the relevant reference sections listed above.

The `client.script` variable may be assigned to script code in a text string (double quotes) or in a file (single quotes). You can also simply include the file in your project or explicitly use the `#include` statement. Files containing DM Script should have the extension `.dms`.

### Example:

    client/script = "<STYLE>BODY {font: monospace}</STYLE>"

This example selects a default monospace font for all output to the terminal.

In addition to scripts loaded via `client.script`, the player may have client-side scripts. These are either called connection scripts or post-connection scripts depending on whether they are used to automatically connect to a world or whether they are executed automatically after connecting to a world. In either case, the player's scripts are always executed before the designer's `client.script` script, so style sheets from the designer have higher precedence by default.

There are three post-connection client-side scripts for the three types of worlds the client can connect to: `byond.dms`, `telnet.dms`, and `irc.dms`. These are automatically executed if the player connects directly to a world without using a connection script to do so. The intention is to load any standard configurations such as style sheets and command aliases.

## PASSWORD_TRIGGER (client script)

Format:
  #define PASSWORD_TRIGGER "assword:"

This defines a special text trigger used to detect when the user is being prompted for a password in telnet mode. Most MUDs automatically suppress password echo, but if they do not, it is necessary to use this setting to hide it. Multiple triggers may be defined as necessary.

The example above is more robust than the more polite version because it works whether they capitalize the 'P' or not...

## URL (client script)

Format:
  #define URL "byond://byond.com:6000"

Defining a URL in a script, specifies the world to connect to when the script is executed by the player. This is referred to as a connection script, because the player uses it to connect to a world. Other post-connection scripts such as `byond.dms` or a script loaded through `client.script` are only used to configure the client after it has connected to a world. In those cases, the URL setting has no effect.

It is important to enclose the URL in double quotes. Otherwise, the `//` symbol would be mistaken for a comment.

## browser configuration

See also:
  URL (client script)

DM Script can be used to effectively make a hyperlink in a web document to a BYOND world. This is done by making a DM Script file that defines the desired URL. It need do nothing more than that. When a user clicks on the link in a web browser, DreamSeeker will pop up, execute the script, and connect to the specified URL.

Some browsers may need to be configured to know what to do with a DM Script file. For example, in Netscape, you can add an entry to the list of helper applications. You should add a MIME type called '`application/x-dms`' with the description 'DM Script' and the extension `dms`. Have this execute DreamSeeker with the `.dms` file as an argument.

### Example:

### myworld.dms

    /*If your browser shows you this, you either need
      to install BYOND (it's free!) from www.byond.com,
      or you need to configure your browser to execute
      DreamSeeker with DM Script (.dms) files.
    */
    #define URL "byond://myworld"

### myworld.html

    <html>

    <head><title>
    Welcome to My World
    </title></head>

    <body>

    <p>You can connect to my world
    <a href=myworld.dms>here</a>.

    </body>
    </html>

## aliases (client script)

See also:
  macros (client script)
  script var (client)
  verbs

Command aliases have a syntax similar to verbs. They define a command and a series of arguments which can then be used to execute a new command. The most common use for this is in a telnet world like a MUD. By defining aliases corresponding to the MUD commands, the player can have primitive command expansion and help.

The syntax of an alias definition is best illustrated by the following example:

    alias/say(msg as text)
       set desc = "speak your mind"
       return "say [msg]"

As you can see, it is just like a verb. Alias have all the same properties as verbs, except the `src` setting is always equal to the player.

The value returned by an alias is executed as a command. In telnet mode, the command to execute is often simply the same as the command that was entered (since the alias was only defined to provide command expansion and help). Since that is such a common case, the return value defaults to the alias name followed by each of the arguments. The example above, for instance, would have the same effect without an explicit return statement.

Note that commands executed via an alias are never interpreted as aliases. Otherwise, examples such as the one above would result in an infinite loop.

## macros (client script)

See also:
  macros (skin)
  aliases (client script)
  command_text (client)
  script var (client)
  verbs

Macros are just like aliases, except that they are triggered by a single key (or combination of keys) instead of a full command. When a macro is executed, it returns a text string which is then executed as a command. So a macro is just a short-cut for entering a command.

The following example illustrates the syntax for entering a typical set of macros.

### Example;

    macro
       ALT+I return "inventory"
       ALT+SHIFT+I return "inventory\nequipment" //multiple commands
       ALT+s return "say \..."             //command to be edited

Note: In old versions of BYOND, character keys required the Alt key to be pressed to trigger the macro, and did not include `"ALT+"` to do so. This behavior has changed, and the name of the macro is just like the format used in skin files. You can now use a key name, and modifiers like `SHIFT+`, `CTRL+`, `ALT+`, `+REP`, and `+UP`. Old .dms and client.script files (prior to version 507) should be updated accordingly when recompiling in a newer version.

## style sheets (in scripts)

See also:
  script var (client)
  style sheets

Style sheets may be included in DM Script by putting the style sheet inside the HTML tags `<STYLE>` and `</STYLE>`. In general, any text enclosed in start and end tags will be sent to the player's terminal, so you could use `client.script` to output a welcome message as well as loading a style sheet.

### Example:

    client/script = "<STYLE>BODY {background: black; color: aqua}</STYLE>"

This example style sheet makes the player's terminal have a black background and aqua colored text. When changing the background color, it is important to change the color of system and link text as well. See the section on style sheets for an example.

## show_map var (client)

See also:
  show_verb_panel var (client)
  view var (client)
  view var (world)

Default value:
  1

This variable may be used to turn off the view of the map in Dream Seeker. This could be useful for making text MUDs where the rooms are turfs (ie most rooms can be laid out on a grid but you don't want the user interface to show the map in any way).

The following example shows one useful combination of settings. Note that setting `world.view=-1` also disables the map, but it also sets the default value of the `view()` depth in such a way as to always return an empty list.

### Example:

    client
       show_map = 0 //Text is best!
    world
       view = 0     //You can interact only with objects in same turf.
    mob
       density = 0  //Allow multiple mobs in a room.

## show_popup_menus var (client)

See also:
  right-click parameter (skin)
  Click proc (client)
  DblClick proc (client)
  MouseDown proc (client)
  MouseDrag proc (client)
  MouseDrop proc (client)
  MouseEntered proc (client)
  MouseExited proc (client)
  MouseMove proc (client)
  MouseUp proc (client)

Default value:
  1

This variable may be used to turn off the popup "context" menus that are displayed by default when an object on the map or stat panels is right-clicked. If client.show_popup_menus==0, then right-clicks will instead be passed to the various mouse functions.

## show_verb_panel var (client)

See also:
  category setting (verb)
  default_verb_category var (client)
  show_map var (client)

Default value:
  1

Setting this to 0 turns off the verb panel in Dream Seeker. You might want to do that, for instance, if you've only got one verb (like "say") and the panel looks stupid with just one verb in it.

### Example:

    client
       show_verb_panel = 0

## statobj var (client)

See also:
  Stat proc (client)
  stat proc
  statpanel proc
  statpanel var (client)
  Info control (skin)

Default value:
  client.mob (the player's mob).

This value indicates which object the player currently has loaded in the stat panels.

## statpanel var (client)

See also:
  Stat proc (client)
  stat proc
  statobj var (client)
  statpanel proc
  Info control (skin)

Default value:
  null

This value indicates which stat panel is currently visible to the player. You can assign it to force a different panel to become the top panel. The special value "verbs" activates the panel of commands.

## tick_lag var (client)

See also:
  tick_lag var (world)
  fps var (client)
  Pixel movement

Default value:
  0 (uses world.tick_lag value)

This is a client version of world.tick_lag, so that the client can run at a faster speed for animations. For example, setting client.tick_lag to 0.25 while world.tick_lag is the default 1 will mean that all animations and glides are smoothed out and displayed at 40 FPS, even though the server still runs at 10 FPS. The result is a nicer-looking game with no additional impact on the server.

When this value is 0, the client and server tick at the same rate.

## timezone var (client)

See also:
  realtime var (world)
  timeofday var (world)
  timezone var (world)
  time2text proc

This is the time offset from UTC, in hours, for the client's time zone. It can be used in the `time2text()` proc.

## verbs list var (client)

See also:
  list

Default value:
  The list of verbs defined for the client.

This is a list of the client's verbs. Initially, it contains all of the verbs defined for the client. It may be used to add and remove verbs at runtime.

## view var (client)

See also:
  lazy_eye var (client)
  show_map var (client)
  view proc
  view var (world)

Default value:
  world.view (which is 5 by default)

Possible values:
  -1 to 34 or "WIDTHxHEIGHT"

This controls the size of the map window in Dream Seeker. Normally, you would simply compile with world/view assigned to whatever you want, but in some cases, you might want to customize the map size for different players, such as admins or subscribed users.

Like all other view sizes in DM, this may either be a view depth or an absolute size. A view depth is a single number that determines how far from a center point the edges of a square viewable region extend. A value of 5 creates edges which are 2*5+1 = 11 tiles long.

The newer, more flexible syntax is a text string of the form "WIDTHxHEIGHT". For example, a view depth of 5 corresponds to "11x11". Using this syntax, you can create non-square views as well.

The maximum view size is about 5000 tiles, or roughly 70x70.

## virtual_eye var (client)

See also:
  edge_limit var (client)
  eye var (client)
  lazy_eye var (client)
  mob var (client)
  perspective var (client)
  view var (client)

Default value:
  client.eye

This value determines the actual center of the player's map display. It is based on `client.eye` and whenever possible matches it; however it may instead be a turf, or null, when the eye is off-center.

The value of `virtual_eye` is read-only.

## database datum

See also:
  database query datum
  procs (database)
  stddef.dm file

A /database datum gives you the ability to create or access a database using SQLite, which allows you to run complex database queries on any platform.

Creating a /database/query datum will let you put together a query, and once it's ready you can call its Execute() proc to run it.

SQLite databases in BYOND support numerical values (such as INTEGER or FLOAT), text (TEXT), and cache files such as icons (BLOB). Null values are also allowed.

### Example:

    var/database/db = new("mydb.db")
    var/database/query/q = new("SELECT * FROM my_table WHERE name=?", usr.key)

    if(q.Execute(db) && q.NextRow())
        // returns a list such as list(name="MyName", score=123)
        return q.GetRowData()
    // no data found
    return null

## procs (database)

See also:
  database datum
  database query datum
  procs (database query)

Built-in database procs:

database/proc
  Close
  Error
  ErrorMsg
  New
  Open

## Close proc (database)

See also:
  database datum
  Open proc (database)

Format:
  Close()

If a database is currently open, this will close the database and any queries currently running in it. Usually you don't need to call this directly, because deleting the datum will do it for you.

## Error proc (database)

See also:
  database datum
  database query datum
  ErrorMsg proc (database)

Format:
  Error()

Returns the error code last received by the database.

## ErrorMsg proc (database)

See also:
  database datum
  database query datum
  Error proc (database)

Format:
  ErrorMsg()

Returns the error message last received by the database.

## Open proc (database)

See also:
  database datum
  Close proc (database)
  New proc (database)

Format:
  Open(filename)

Args:
  filename: The database filename to open

Opens a database file. If another database was already open, it is closed automatically. It is more common to simply open the database in New().

## New proc (database)

See also:
  database datum
  Open proc (database)

Format:
  New(filename)

Args:
  filename: The database filename to open (optional)

Creates a new database datum, and opens the file if a filename is provided.

## database query datum

See also:
  database datum
  procs (database query)
  stddef.dm file

This datum lets you create a query for a database, which can be run with the Execute() proc. The datum can be reused after a query is run by calling Clear() and adding new text with Add().

## procs (database query)

See also:
  database datum
  database query datum
  procs (database)

Built-in database query procs:

database/query/proc
  Add
  Clear
  Close
  Columns
  Error
  ErrorMsg
  Execute
  GetColumn
  GetRowData
  New
  NextRow
  Reset
  RowsAffected

## Add proc (database query)

See also:
  database query datum
  Clear proc (database query)

Format:
  Add(text, item1, item2, ...)

Args:
  text: Text to add to the query
  item1, item2, etc.: Items that will replace question marks in text

Adds text to a database query. If this datum was already used to run a query, Clear() will be called automatically.

If your text includes question marks, they will be replaced with the other items listed in the proc arguments. If that item is a string, quotes will be put around it for the query text. Files in the cache (such as icons) will be added as BLOB values.

After the query has been built, call Execute() to run it.

### Example:

    var/database/db = new("mydb.db")
    var/database/query/q = new
    q.Add("INSERT INTO quests (name, quest, complete) VALUES (?,?,?)", usr.key, quest_name, 1)
    q.Execute(db)

In the example above, the query text might look like this:

`INSERT INTO quests (name, quest, complete) VALUES ('Tom','Save the Dog',1)`

## Clear proc (database query)

See also:
  database query datum
  Add proc (database query)

Format:
  Clear()

Clears the query text so you can begin creating a new query. This is called automatically if you already called Execute() for the last query used by this datum.

## Close proc (database query)

See also:
  database query datum
  Clear proc (database query)
  Reset proc (database query)

Format:
  Close()

Ends a query that is in progress. This is usually done automatically and shouldn't be necessary to call in most cases.

## Columns proc (database query)

See also:
  database query datum
  Execute proc (database query)
  GetColumn proc (database query)
  GetRowData proc (database query)
  NextRow proc (database query)

Format:
  Columns()
  or
  Columns(column)

Args:
  column: The Nth column whose name should be read

Returns a list of column names for the current query, or the name of the Nth column.

You must call Execute() before calling Columns().

## Error proc (database query)

See also:
  database datum
  database query datum
  ErrorMsg proc (database query)

Format:
  Error()

Returns the error code last received for this query.

## ErrorMsg proc (database query)

See also:
  database datum

  database query datum
  Error proc (database query)
  Format:
    ErrorMsg()

  Returns the error message last received for this query.

  ## Execute proc (database query)

  See also:
  database datum
  database query datum
  Add proc (database query)
  Close proc (database query)
  GetColumn proc (database query)
  GetRowData proc (database query)
  NextRow proc (database query)
  Reset proc (database query)
  RowsAffected proc (database query)
  Format:
    Execute(database)
  Args:
    database: A /database datum with the database to be queried, or the name of the database file

  Runs a database query. Once the query is run, if the query is supposed to returns any rows you can call NextRow() until finished, and then GetColumn() or GetRowData() to get the information from each row. For queries that cause changes, RowsAffected() is also a useful call.

  The database argument is optional after the first time you use it.

  You can use a filename instead of a /database datum, as a shortcut; the datum will be created for you.

  After a query is executed, calling Add() to create new query text will clear out the old query text automatically.

  ### Example:

      var/database/db = new("mydb.db")
      var/database/query/q = new("SELECT quest,complete FROM quests WHERE name=?", usr.key)

      if(!q.Execute(db)) return null

      var/list/completed_quests = new
      while(q.NextRow())
          var/row = q.GetRowData()
          if(row["complete"]) completed_quests[row["quest"]] = 1
      return completed_quests

  ## GetColumn proc (database query)

  See also:
  database datum
  database query datum
  Columns proc (database query)
  Execute proc (database query)
  GetRowData proc (database query)
  NextRow proc (database query)
  Reset proc (database query)
  Format:
    GetColumn(column)
  Args:
    column: The column number whose value should be retrieved

  Gets the value from the Nth column in this row of results. If you haven't already called Execute() and NextRow(), you should do that first.

  To get the name of the column, not the value for this row, call Columns(column) instead.

  The value returned depends on what type the database table thinks it is. For instance if you defined a column as INTEGER or FLOAT, the value should be a number. TEXT is still text, and null values are returned as null. If an icon was saved into a BLOB field, the result is an icon file.

  ## GetRowData proc (database query)

  See also:
  database datum
  database query datum
  Columns proc (database query)
  Execute proc (database query)
  GetColumn proc (database query)
  NextRow proc (database query)
  Reset proc (database query)
  Format:
    GetRowData()

  Returns a list with the current result row for this query. If you haven't already called Execute() and NextRow(), you should do that first.

  The list returned is an associative list with name=value pairs. A typical result might look like this:

  `list("name" = "Tom", "quest" = "Save a Dog", complete = 1)`

  The values returned depend on what type the database table thinks they are. For instance if you defined a column as INTEGER or FLOAT, the value should be a number. TEXT is still text, and null values are returned as null. If an icon was saved into a BLOB field, the result is an icon file.

  ## New proc (database query)

  See also:
  database datum
  database query datum
  Add proc (database query)
  Format:
    New(text, item1, item2, ...)
  Args:
    text: Text to add to the query
    item1, item2, etc.: Items that will replace question marks in text

  Creates a new query and adds text by automatically calling Add(). See the Add proc for more information.

  Call Execute() to run the query.

  ## NextRow proc (database query)

  See also:
  database datum
  database query datum
  Execute proc (database query)
  GetColumn proc (database query)
  GetRowData proc (database query)
  Reset proc (database query)
  Format:
    NextRow()

  If there are result rows in this query (Execute() must be called to run the query first), NextRow() will retrieve the next row and return 1 if it found a row, or 0 if the results are all finished. NextRow() is typically called in a while() loop.

  After calling NextRow(), you can call GetColumn() or GetRowData() to get information about the results in this row.

  Call Reset() if you want to rewind the query to the beginning.

  ## Reset proc (database query)

  See also:
  database datum
  database query datum
  Execute proc (database query)
  NextRow proc (database query)
  Format:
    Reset()

  If a query returns any rows of results, Reset() will go back to the beginning just after Execute() was called. This is useful if you have called NextRow() repeatedly to retrieve a number of rows, but need to go back to the start of the query for some other reason. This can also be used to count the total number of result rows if needed, but for best performance that isn't recommended.

  ## RowsAffected proc (database query)

  See also:
  database datum
  database query datum
  Execute proc (database query)
  RowsAffected proc (database query)
  Format:
    RowsAffected()

  After running Execute() on a query that changes rows in the database (for instance, an UPDATE query), this proc returns the number of rows that were changed. This can be useful if you need to know whether a query actually did anything.

  ## datum

  See also:
  atom
  procs (datum)
  vars (datum)

  The datum object is the ancestor of all other data types in DM, with only a few exception called primitives. That means that the variables and procedures of /datum are inherited by almost all other types of objects.

  When you define a new "top level" object, if you do not specify a parent_type, it defaults to /datum.

  ### Example:

      datum
         //definitions to be shared by all object types
         proc/DebugMe()
            world.log << "/datum properties:"
            world.log << "type: [type]"
            world.log << "parent_type: [parent_type]"
            return ..()

      MyType
         var
            myvar = "test"
         DebugMe()
            world.log << "/MyType properties:"
            world.log << "myvar: [myvar]"
            return ..() //this calls /datum/proc/DebugMe()

  ### Primitives

  Primitive types do not descend from /datum. These have no subtypes, and may or may not be able to allow var and proc overrides.

  Type | User-defined | Can override | Notes
  --- | --- | --- | ---
  /world

procs only vars and procs
/client vars and procs vars and procs can manually set `parent_type=/datum`
can't be created in new
/list--
/savefile-byond_version
byond_build
/alist--
/pixloc--
/vector--
/callee--can't be created with new

## procs (datum)

Built-in datum procs:

datum/proc
  New
  Del
  Write
  Read
  Topic

## Del proc (datum)

See also:
  del proc

  garbage collection
  Format:
    Del()
  When:
    Called when the object is destroyed, for example by using the `del instruction.
  Default action:
    Delete the object. The contents of atomic objects are also destroyed at this time, as though `del were called on each one of them.

  When the world is destroyed, the `Del()` proc is not automatically called. The only object for which it is called is /world. If you need the `Del()` proc for a particular object to be called at that time, you should explicitly call it from `world/Del()`.

  Note: Always call `..()` at the end of the proc if you override it.

  ## New proc (datum)

  See also:
  New proc (atom)
  New proc (client)
  new proc
  Format:
    New()
  When:
    Called when the datum is created, for example by using `new, when reading an object that was stored in a savefile
, or when the world is initially created.

Default action:
  None.

You can use the New() procedure to do more complicated initializations than are possible in the object definition where you assign the initial value of variables to constants.

The following example makes use of the "Location" parameter that is passed to objects of type /atom. You can pass any number of additional arguments to New() by passing them to the `new` instruction which creates the object.

### Example:

    mob/night
       var/mob/squire/my_squire
       New(Location)
          my_squire = new(Location)
          return ..()

Also note that the type of object being created in this case was automatically inferred from the variable type on the left-hand side of the assignment. That's a handy little DM short-cut.

## Read proc (datum)

See also:
  >> operator (savefile)
  Write proc (datum)
  tmp vars

Format:
  Read(savefile/F)

When:
  Called when the object is read from a save file.

Args:
  F: the save file being read

Default action:
  Read the value of each variable from a directory by the same name as the variable. Variables marked tmp, global, or const and variables for which there is no directory are skipped.

## Topic proc (datum)

See also:
  Topic proc (client)

  ref text macro
  Format:
    Topic(href,href_list[])
  Args:
    href: the hyperlink data (following ? in the URL).
    href_list: key/value list (from params2list(href)).

  This procedure is called by the default `client.Topic()` proc when the href contains a parameter called "src" containing an object reference.

  ### Example:

      mob/verb/test()
         usr << "Click <a href='?src=\ref[src];action=startgame'>here</a>!"
      mob/Topic(href,href_list[])
         switch(href_list["action"])
            if("startgame")
               usr << "Starting game..."

  The above example uses an embedded reference to the player's own mob to create a hyperlink to that mob's `Topic()` proc. You can easily add different actions, parameters, and so forth. Just remember that the parameter values are always stored as text, so you need to convert those to whatever data format you need using procedures such as `text2num()`, `locate()`, etc.

  Always validate the input in `Topic()` calls to make sure it's correct and the query you're recieving is legitimate.

  ## Write proc (datum)

  See also:
  << operator (savefile)
  Read proc (datum)
  initial proc
  issaved proc
  tmp vars
  Format:
    Write(savefile/F)
  When:
    Called when the object is written to a save file.
  Args:
    F: the save file being written to
  Default action:
    Write the value of each variable to a directory by the same name as the variable. Variables marked tmp, global, or const and variables which are equal to their initial value are skipped.

  ## vars (datum)

  Built-in datum vars:

  datum/var
  type
  parent_type
  tag
  vars

  ## parent_type var

  Default value:
  The path of the object definition that contains this one.

  This variable is set at compile-time to specify the inheritance of an object type. Normally, a new type of object inherits its variables and procedures from the object type that contains it. For example:

      obj
         var
            weight
            color
         sword //parent type of 'sword' defaults to /obj
            weight = 30
            color = "black"

  Explicitly setting the parent type allows you to put the object definition any place you want. That often means putting it at the top "root" level. Example:

      Armor
         parent_type = /obj
         var
            strength
         plate //parent type is /Armor, which in turn inherits from /obj
            weight = 100
            color = "rusty"
            strength = 10

  If you don't specify the parent_type for an object defined at the top level, it defaults to /datum

  , which (with just a couple exceptions) is the ultimate ancestor of all object types. You could use that fact to define procedures or variables that you need all of your objects to share.

  ### Example:

      datum
         proc/Copy(datum/O)

      MyType
         var
            foo
         Copy(MyType/O)
            foo = O.foo
            return ..()

  ## tag var (datum)

  See also:
  locate proc
  Default value:
    null

  This may be assigned to a unique text string identifying a particular object. A reference to the object can then be obtained by using locate().

  One reason to use tags is when making references in the code to objects and locations that will be created on the map. You can simply edit the object in the map editor, set its tag, and then use that in the code relating to the object.

  The following example demonstrates how to set a tag and use it to obtain a reference to an object.

  ### Example:

      mob/verb/test()
      	var/obj/O = new()
      	O.tag = "My Object"

      	var/obj/O2 = locate("My Object")

      	ASSERT(O == O2) //this should always be true

  Setting a tag to "" or null removes it. Any object with a non-empty tag is immune to garbage collection, since the tag is treated as an implicit reference to that object.

  ## type var (datum)

  Default value:
  The "type path" of the object definition.

  This variable is read-only.

      mob/verb/test()
         usr << type //displays "/mob"

  ## vars list var (datum)
See also:
  initial proc
  issaved proc
  list
  list associations
  vars list var (global)

  This is a list of all the variables belonging to an object. The items in the list are the variable names. If the variable name is used as an index into the list, the value of that variable is accessed.

  ### Example:

      mob/verb/dump()
         var/V
         for(V in vars)
            usr << "[V] = [vars[V]]"

  This example displays all the variables belonging to your mob.

  ## exception

  See also:
  try and catch statements
  Error proc (world)
  throw statement
  EXCEPTION proc
  caller var (proc)
  stddef.dm file
  Vars:
    name: A text string (such as an error message) or other value
    file: The filename where the error occurred, if debugging info is present
    line: The line where the error occurred, if debugging info is present
    desc: Detailed error info including call stack, only used when sent to world.Error()

  This datum is created automatically when a runtime error is encountered, if it happens within a try/catch block or you have defined a global error handler with `world.Error()`. (The New() proc is not called when this happens.) This provides a convenient package for getting file and line number info associated with an error.

  If you throw your own exceptions, you do not have to use this, but the `EXCEPTION` macro is provided to easily create one with the current file and line number.

  The `desc` value is only filled in when you have a world.Error() handler and there is no try/catch handling this error. Just like when no handler is present, less detail will be provided after multiple runtime errors have occurred. This only exists as a convenience feature for logging errors if you want to use something other than world.log.

  ## icon object

  See also:
  procs (icon)
  icons
  image objects
  stddef.dm file

  An `/icon` object is created by loading an icon file into memory for direct access and manipulation. In order to be displayed, an `/icon` object always gets converted back into an icon file; this happens automatically when you assign atom.icon to an `/icon` object, since that variable may only refer to a static icon file, rather than a dynamic memory object.

  To create an `/icon` object, simply use `new/icon()`, or the short-cut `icon()` proc. The following example loads an icon file, reddens it, and then assigns it back to the player's icon, which implicitly creates a new icon file.

  ### Example:

      mob/verb/test()
         var/icon/I = new('player.dmi')
         I.Blend(rgb(40,0,0))
         usr.icon = I

  Note that merely displaying different icon states or directions can generally be achieved without any icon manipulation, which saves quite a bit of overhead. For example, the variables `atom.icon_state` and `atom.dir` can be used to control how `atom.icon` is displayed, without any need for generating a new icon file.

  Many things that used to require icon manipulation may not need you to do so anymore, as DM has evolved new capabilities.

  Operation | `/icon proc | New method
  --- | --- | ---
  Multiplying by color | `Blend

or SetIntensity procs color var
Adding color Blend proc color var (using color matrix)
Applying color matrix MapColors proc
Rotation Turn proc transform var
Flipping horizontal/vertical Flip proc
Scaling Scale proc
Overlaying/underlaying another icon Blend proc + `ICON_OVERLAY` Overlay/underlay + KEEP_TOGETHER
Layering filter

Note: Anything you can do with an atom var instead of using icon manipulation procs will usually perform much better. Games that use the new methods use fewer resources, use less memory, and also usually look better too.

## procs (icon)

See also:
  icon

icon/proc
  New
  IconStates
  Turn
  Flip
  Shift
  SetIntensity
  Blend
  SwapColor
  DrawBox
  Insert
  MapColors
  Scale
  Crop
  GetPixel
  Width
  Height

## Blend proc (icon)

See also:
  icon

  procs (icon)
  overlays var (atom)
  rgb proc
  Format:
    Blend(icon,function=ICON_ADD,x=1,y=1)
  Args:
    icon: an icon file, /icon object, or color
    function: the blending operation to use
    x, y: the position to blend the icon

  The valid blending operations are:

  - ICON_ADD
  - ICON_SUBTRACT
  - ICON_MULTIPLY
  - ICON_OVERLAY
  - ICON_AND
  - ICON_OR
  - ICON_UNDERLAY

  The result is a combination of each corresponding pixel in the two icons. In all but ICON_OVERLAY, ICON_UNDERLAY, and ICON_OR, the transparent regions of the two icons are ORed together. That means if either icon is transparent on a given pixel, the result will be transparent. With ICON_OVERLAY or ICON_UNDERLAY, on the other hand, the original icon shows through wherever the top icon is transparent, giving the same effect as an overlay object, but resulting in only a single icon. In ICON_OR, the transparent regions are ANDed together; solid pixels are added together where they exist in both icons, or just pass through if the other icon is transparent at that pixel.

  In addition to blending with an icon, an rgb() value may also be specified. This is treated identically to an icon of that same solid color, except that the x and y arguments will be ignored. Blending with a color blends the whole icon.

  By default, the icons will line up at their lower left corners. If you want to position the second icon in a different place for blending, use the x and y arguments to specify where its lower left corner will be. 1,1 is the default, which is the lower left. 11,1 for instance would be 10 pixels to the right, and 1,21 would be 20 pixels up.

  ## Crop proc (icon)

  See also:
  icon
  procs (icon)
  icon_size var (world)
  map_format var (world)
  Big icons
  Tiled icons
  Format:
    Crop(x1,y1,x2,y2)
  Args:
    x1,y1: Coordinates of one corner of the rectangle (1,1 is the lower left)
    x2,y2: Coordinates of the other corner

  A portion of the current icon is cropped (cut). If the crop region extends outside the icon, it will be padded with transparent pixels.

  If using the TILED_ICON_MAP value for map_format, all icons must be even multiples of world.tile_size, so the icon will be padded with transparent pixels to the top and right as needed.

  ### Example:

      // start with a simple icon
      var/icon/I = new('circle.dmi')
      // take the upper right 16x16 chunk
      I.Crop(17,17,32,32)
      // that chunk now appears in the lower left corner
      icon = I

  ## DrawBox proc (icon)

  See also:
  icon
  procs (icon)
  rgb proc
  Format:
    DrawBox(rgb,x1,y1,x2=x1,y2=y1)
  Args:
    rgb: `rgb(red,green,blue) or `null
    x1,y1: Coordinates of one corner of the rectangle (1,1 is the lower left)
    x2,y2: (optional) Coordinates of the other corner

  A rectangle (filled) of the given color is drawn over every frame in the icon. If x2 and/or y2 are omitted, a line or a single pixel is drawn. To draw a transparent box instead of an opaque color, use null as the color.

  ## Flip proc (icon)

  See also:
  Turn proc (icon)
  dir var (atom)
  icon
  procs (icon)
  Format:
    Flip(dir)
  Args:
    dir: direction in which to flip over the icon

  This flips the icon over in the specified direction. For example, Flip(NORTH) would be like turning the icon upside down by grabbing the bottom edge and flipping it up over the top edge. You would get the same result by doing Flip(SOUTH). In general, this is not the same as turning the icon by 180 degrees, because it produces a mirror image.

  If an icon is square, it may be flipped diagonally.

  ## GetPixel proc (icon)

  See also:
  icon
  procs (icon)
  rgb proc
  Format:
    GetPixel(x, y, icon_state, dir=0, frame=0, moving=-1)
  Args:
    x,y: coordinates of the pixel to grab; 1,1 is the lower left corner
    icon_state: a specific icon_state to use (may be null)
    dir: a specific direction of this icon to use
    frame: a specific animation frame to use (1 is the 1st frame)
    moving: non-zero for only movement states, 0 for non-movement states, or null (default) for either

  This finds the icon_state and the right animation/direction frame of your choosing (it will pick the first one available if you don't specify) and returns the rgb() value of a pixel at that location, in "#RRGGBB" form. If the pixel is totally transparent, it returns null. If the pixel is partially transparent, an alpha component is also returned in "#RRGGBBAA" form.

  ## Width proc (icon)

  See also:
  icon
  procs (icon)
  Height proc
  Format:
    Width()

  This finds the width, in pixels, of the icon.

  ## IconStates proc (icon)

  See also:
  icon
  procs (icon)
  icon_states proc
  Format:
    IconStates(mode=0)
  Args:
    mode: see icon_states proc

This returns a list of all icon state text strings that exist in the /icon object. This works in exactly the same way as icon_states(icon).

## Insert proc (icon)

See also:
  procs (icon)
  New proc
  map_format var (world)
  Big icons
  Tiled icons

Format:
  Insert(new_icon,icon_state,dir,frame,moving,delay)
  (supports named arguments

)

Args:
  new_icon: an icon file or /icon object to insert
  icon_state: an optional text string, specifying a single icon state to change or add to this icon
  dir: an optional direction; the inserted icon will only be added for this direction
  frame: an optional animation frame (starting at 1); the inserted icon will only be added for this frame
  moving: Non-zero to insert as a movement state, 0 for a regular non-movement state
  delay: 0 or null to leave unchanged; positive to set delay for a frame and turn rewind off; negative to set delay and rewind

This adds additional states or images to an existing icon, allowing you to build directional, animated, and multi-state icons on the fly. If the state you wish to insert already exists in the file, it will be altered; otherwise it will be added. An animation may be built a piece at a time, for example by inserting an icon into the NORTH direction for animation frame 3.

### Example:

    // start with a non-animated arrow icon
    var/icon/I = new('arrow.dmi')
    // make a new state called "blink"
    var/icon/J = new('arrow.dmi')
    I.Insert(J, "blink", delay=-1)  // set rewind flag
    // create darker shades of the arrow
    var/n = 2
    for(var/light=9, light>=5, light--)
       J = new('arrow.dmi')
       J.SetIntensity(light/10)
       I.Insert(J, "blink", frame=n++)
    // congratulations, you have a pulsating arrow
    icon = I

The icon resulting from this example has two states: The original arrow, and a new state called "blink" that pulsates between full and ½ luminance. To use the blinking state after that, set the atom's icon_state to "blink".

(Note for animations: When building an animated icon_state from scratch, you can only add 16 new animation frames at a time; i.e., frame<=total_frames+16. Higher values for frame will be ignored. This is a safety precaution.)

If you insert an icon of a different size, the src icon will be resized to match the size of new_icon. (The only exception is if you are using the TILED_ICON_MAP map_format, and new_icon is a single tile being inserted as a chunk into a larger icon. If icon_state, such as "2,0" or "open 0,0", already exists in src as one of its smaller pieces, then new_icon will be inserted in its place.)

When inserting an individual animation frame, you can change the delay for just that frame only. If you don't specify a delay, the nearest frame's delay will be used. If this is the first frame being inserted into an icon, then the delay will default to 1 tick. Remember, if your delay is positive, it will turn off the rewind flag for that entire icon state; negative will turn it on.

## MapColors proc (icon)

See also:
  icon
  procs (icon)
  rgb proc

Format:
  MapColors(rr, rg, rb, gr, gg, gb, br, bg, bb, r0=0, g0=0, b0=0)
  or
  MapColors(r_rgb, g_rgb, b_rgb, rgb0=rgb(0,0,0))
  or
  MapColors(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, r0=0, g0=0, b0=0, a0=0)
  or
  MapColors(r_rgba, g_rgba, b_rgba, a_rgba, rgba0)

Args:
  rr: portion of old red component -> new red component
  rg: portion of old red component -> new green component
  rb: portion of old red component -> new blue component
  ra: portion of old red component -> new alpha component
  r0: new base red component
  ...
or
  r_rgb: red component is converted to this color
  g_rgb: green component is converted to this color
  b_rgb: blue component is converted to this color
  rgb0: this color is added to the result

This is used for complex color mapping that can be used for many special effects. For the number form, values usually range from 0 to 1, but you can use anything you like, including negative numbers. 1 means 100% of the original color will be used. If rg=1, for example, then the amount of red in the original icon becomes the same amount of green in the new icon's colors.

There is also an alternate form that can use `rgb()` values instead, though it is less flexible. r_rgb is the color that will be used in place of 100% red; any darker shades of red will become a darker shade of that color. g_rgb converts green to another color, and b_rgb converts blue to still another color, and all of them are added together.

Either of these calls change the icon to grayscale:

    icon.MapColors(0.299,0.299,0.299, 0.587,0.587,0.587, 0.114,0.114,0.114, 0,0,0)
    // or...
    icon.MapColors(rgb(76,76,76), rgb(150,150,150), rgb(29,29,29), rgb(0,0,0))

The calculations are as follows:

- For any red in the original icon, add 29.9% gray to the output.
- For any green in the original icon, add 58.7% gray to the output.
- For any blue in the original icon, add 11.4% gray to the output.
- Add an additional 0% (nothing).

Or this will make a nice moonlight effect:

    icon.MapColors(0.2,0.05,0.05, 0.1,0.3,0.2, 0.1,0.1,0.4, 0,0,0)
    // or...
    icon.MapColors(rgb(51,13,13), rgb(26,77,51), rgb(26,26,102), rgb(0,0,0))

- For any red in the original icon, add rgb(51,12.75,12.75) (dark pink) to the output.
- For any green in the original icon, add rgb(25.5,76.5,51) (dark bluish green) to the output.
- For any blue in the original icon, add rgb(25.5,25.5,102) (dark grayish blue) to the output.
- Add an additional 0% (nothing).

Or a negative icon (invert all colors):

    MapColors(-1,0,0, 0,-1,0, 0,0,-1, 1,1,1)

The longer formats of MapColors() will allow you to also change alpha colors.

## New proc (icon)

See also:
  icon

  procs (icon)
  image proc
  new proc
  Format:
    New(icon,icon_state,dir,frame,moving)
    (supports named arguments
)

Args:
  icon: an icon file or /icon object
  icon_state: an optional text string, specifying a single icon state to load
  dir: an optional direction to extract
  frame: an optional animation frame to extract
  moving: Non-zero to extract only movement states, 0 for non-movement states, or null (default) for both

You generally don't call this directly but via new(). The specified icon file is loaded into memory for direct access and manipulation.

If the icon state is not specified, all icon states are loaded. Ditto for the direction, animation frame, or preference for movement states. Animation frames are numbered from 1 and up, so frame=4 is the 4th frame.

(Movement states are special versions of an existing icon_state with the same name, but appear in the Dream Maker editor with an "M" indicator. These states are used for animation when the atom using the icon_state moves from one tile to the next; otherwise only the normal non-moving state is displayed.)

The following contrived example, loads the EAST facing default icon state "" from the user's icon file, rotates that a bit, and then creates a new icon file for the user.

### Example:

    mob/verb/test()
       var/icon/I = new(usr.icon,icon_state = "",dir = EAST)
       I.Turn(90)   //rotate clockwise 90 degrees
       usr.icon = I

Note that merely displaying different icon states or directions can generally be achieved without any icon manipulation, which is good, because it saves quite a bit of overhead. For example, the variables atom.icon_state and atom.dir can be used to control how atom.icon is displayed, without any need for generating a new icon file.

## Scale proc (icon)

See also:
  icon
  procs (icon)
  icon_size var (world)
  map_format var (world)
  Big icons
  Tiled icons

Format:
  Scale(width, height)

Args:
  width,height: size of the new icon

The current icon is scaled to a new size.

If world.map_format is set to TILED_ICON_MAP and the new size is not in multiples of world.icon_size, the icon will be padded with transparent pixels to the top and right as needed. See map_format for more information.

Scale() automatically performs antialiasing to avoid unwanted artifacts.

## SetIntensity proc (icon)

See also:
  icon

  procs (icon)
  MapColors() proc (icon)
  Format:
    SetIntensity(r,g=r,b=r)
  Args:
    r: red component
    g: green component
    b: blue component

  This multiplies the pixel intensities by the specified amounts. A value greater than 1.0 increases the intensity and a value less than 1.0 decreases the intensity.

  ## Shift proc (icon)

  See also:
  dir var (atom)
  icon
  procs (icon)
  Format:
    Shift(dir,offset,wrap=0)
  Args:
    dir: direction in which to shift the icon
    offset: distance to shift the pixels
    wrap: if true, causes shifted pixels to wrap around to the other side

  This moves all of the pixels by the specified amount in a direction. For example, Shift(NORTH,1) would move everything one pixel to the north.

  By default, pixels that move off the edge are not wrapped around; transparent pixels are shifted onto the other side. Calling with wrap=1 causes it to shift the pixels around to the other side.

  ## SwapColor proc (icon)

  See also:
  icon
  procs (icon)
  rgb proc
  Format:
    SwapColor(old_rgb,new_rgb)
    or
    SwapColor(old_rgba,new_rgba)
  Args:
    old_rgba: the old rgba value to be replaced
    new_rgba: the new rgba value to use in its place

  This causes a color value in the icon's palette to be changed. You can use null in place of an RGB or RGBA value.

  If the old color is a full RGBA color with an alpha value, such as rgb(1,2,3,4) or "#01020304", then that exact color is the only one changed.

  If the old color is an RGB value with no alpha specified, such as rgb(1,2,3) or "#010203", then that color will change to the new one regardless of its alpha value, and the original icon's alpha will be kept intact. (If the new color is totally transparent, however, then the old color will be replaced with full transparency.)

  ## Turn proc (icon)

  See also:
  Flip proc (icon)
  dir var (atom)
  icon
  procs (icon)
  Format:
    Turn(angle)
  Args:
    angle: an angle in degrees

  This rotates the icon clockwise by the specified amount.

  ### Example:

      mob/verb/drink()
         //this effect is very confusing!
         var/icon/I = new(usr.icon)
         I.Turn(90)
         usr.icon = I
         usr << "You feel a little tipsy!"

         sleep(200)

         I.Turn(-90)  //turn it back
         usr.icon = I //should have just saved original value

  If an icon is not square, it cannot be turned.

  ## Height proc (icon)

  See also:
  icon
  procs (icon)
  Width proc
  Format:
    Height()

  This finds the height, in pixels, of the icon.

  ## image objects

  See also:
  icon var (atom)
  image proc
  vars (image)
  images var (client)
  overlays var (atom)
  override var (atom)

  The /image type contains data used to create a virtual image. Unlike other atomic objects, this object is a purely visual effect. It always appears attached to some other object and it behaves in every way as though it were part of that object (e.g. if the user clicks on it, this counts as a click on the atomic object, not the image).

  One reason for creating images is player-by-player control over visibility. Images only become visible when they are explicitly output to players:

  ### Example:

      var/image/I = image('icon.dmi',usr)  //make an image attached to usr
      usr << I    //allow usr to see it

  Images are also useful in the creation of overlays. Overlays are like images, since they are always attached to another object, but overlays obey the normal rules of visibility, so they are more convenient when you do not want to hide the effect from anybody. An overlay can be created directly from an icon file (or icon state), but when one wishes to override some additional parameter, the image() instruction is a convenient way to do it.

  ### Example:

      usr.overlays += image('shirt.dmi',icon_state = "red")

  In the above example, the icon state of an overlay was set by creating the overlay from an image with the desired icon state. Note that after the creation of an overlay, no link remains between the overlay and the object that was used to create it. If you change the image after that time, it will not change the overlay, which is simply a "snapshot" of the original image.

  ## vars (image)

  /image/var
  alpha
  appearance
  appearance_flags
  blend_mode
  color
  icon
  icon_state
  icon_w
  icon_z
  text
  dir
  filters
  loc
  maptext
  maptext_width
  maptext_height
  maptext_x
  maptext_y
  overlays
  override
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  plane
  render_source
  render_target
  transform
  underlays
  vis_contents
  x
  y
  z
  type
  tag
  parent_type

  ## loc var (image)

  The location of an image specifies the object to which the image is attached. Unless the image drawing layer is specified, the default will make it appear above this object, as though it were an overlay.

  Note that the image is not inside the specified location. In other words, this loc variable does not behave like /atom/movable/var/loc which specifies the container object. It is more like the image is on top of the specified object. If the object moves, the image will automatically move around with it.

  ## list
See also:
  list associations
  list proc
  islist proc
  procs (list)
  vars (list)

  Lists are used to represent groups of objects. Like objects, they have vars and procs associated with them. In order to access these attributes, list vars must be declared of type /list. These may then be assigned to existing lists, or used to create new lists.

  ### Example:

      var/list/L         // list reference
      L = world.contents // assign to existing list
      L = new/list()     // make a new list
      L = new()          // make a new list (implicit type)
      L.Add("futz")      // L contains: "futz"
      del(L)             // delete L

  Lists created with 'new()' have a default length of 0; this can be overridden by specifying the size; that is, new/list(size) creates a list with size (null) elements.

  The 'list()' proc may be used to more easily initialize list data.

  ### Example:

      var/list/L
      L = list("futz",3)   // L contains: ("futz", 3)

  Alternatively, lists may be declared by using brackets, '[]'. Empty brackets indicate a list reference, exactly as /list does, so list/L is equivalent to L[]. Setting an initial size within the brackets, for instance, L[10], creates a list of that initial size.

  ### Example:

      var/L[]   // same as var/list/L: list reference
      var/M[10] // initially empty list of size 10
      L = M     // L is now an empty list of size 10

  Once a list L is declared, a specific item can be accessed by putting its index in the brackets: L[index].

  Indices range from 1 to len. If the length of the list is changed, existing elements in the list will be preserved if they are less than the new length. New elements in the list will be given the initial value of null.

  ### Example:

      var/L[5]  // initial length of 5
      var/i

      for(i=1, i<=L.len, i++)
        L[i] = i
      // L contains: (1,2,3,4,5)

      L.len = 7           // expand list
      // L contains: (1,2,3,4,5,null,null)

      del(L)          // destroy list

  Multi-dimensional lists may be created by making a list of lists.

  ### Example:

      var/grid[10][5]
      grid[1][1] = 1
      grid[1][2] = 2
      ...

  Such a list may also be created by using new(). As in the previous example, the next one creates a list of 10 lists each having 5 elements.

  ### Example:

      var/grid = new/list(10,5)

  ## list associations

  See also:
  list
  list proc
  list proc
  list2params proc
  params var (world)
  params2list proc
  vars list var (datum)
  values_sum proc
  values_product proc
  values_dot proc
  values_cut_over proc
  values_cut_under proc

  Each unique text string or object in a list may be associated with another value. This is done by using the item as an index into the list.

  ### Example:

      var/params[0]

      params["player"] = "James Byond"
      params["score"] = 2000

      //List now contains ("player","score")
      //These are associated with ("James Byond",2000)

      usr << "Looping through list items:"
      var/p
      for(p in params)
         usr << "[p] = [params[p]]"

      usr << "Looping through array indices:"
      var/i
      for(i=1,i<=params.len,i++)
         p = params[i]
         usr << "[p] = [params[p]]"

  The above example illustrates the typical way in which list associations are managed. Note that an item in the list may be added by assigning its associated value. The example could have started by doing `params.Add("player","score")`, but that would have been redundant.

  Both `for` loops in the example have the same effect. The first one loops through each item in the list, and displays it along with its associated value. The second loop achieves the same thing by looping through the numerical indices (referred to as array indices as opposed to associative indices).

  Since numeric indices are treated differently, accessing the Nth item in the list, you may not assign an associated value to a numeric list item. Associations must have a text string or object reference as the index item. (`alist()` is an exception to this, and can use numeric associations. See alist() for more information.)

  Associated values default to null if none is assigned. This is also the value returned when the supplied index item does not exist in the list. The list defined above, for example, would return null for `params["time"]`.

  The list() or alist() instructions may also be used to create associative lists.

  ### Example:

      var/list/lst = list("player" = "James Byond", "score" = 2000)

  When the index values happen to be text strings that satisfy all the requirements for variable names, this may also be written in a convenient short-hand:

      var/list/lst = list(player = "James Byond", score = 2000)

  In other words, this is exactly the same syntax as for named arguments.

  The `alist proc creates lists that are strictly associative. This means that list items are treated as "keys" in key,value pairs. Unlike a regular list, each "key" is unique.

  ## list operators

  These operators are used for accessing list items.

  [] operator
  ?[] operator

  These operators all have special meaning when applied to lists.

    + operator
  += operator
  - operator
  -= operator
  | operator
  |= operator
  & operator
  &= operator
  ^ operator
  ^= operator
  in operator

  ## procs (list)

  See also:
    list
  list operators

  Built-in list procs:

  list/proc
    Add
    Copy
    Cut
    Find
    Insert
    Join
    Remove
    RemoveAll
    Splice
    Swap

  ## Add proc (list)

  See also:
    + operator
  Remove proc (list)
  RemoveAll proc (list)
  Format:
    list.Add(Item1,Item2,...)
  Args:
    One or more items to add to the list.

  Appends the specified items to the list. If an argument is itself a list, each item in the list will be added.

  ## Copy proc (list)

  See also:
    Cut proc (list)
  Format:
    list.Copy(Start=1,End=0)
  Returns:
    A new list.
  Args:
    Start: The list position in which to begin the copy.
    End: The list position immediately following the last element to be copied.

  Copy list[Start] through list[End-1] into a new list. The default end position of 0 stands for the position immediately after the end of the list, so by default the entire list is copied.

  ## Cut proc (list)

  See also:
    Copy proc (list)
  Insert proc (list)
  Format:
    list.Cut(Start=1,End=0)
  Args:
    Start: The list position in which to begin the cut.
    End: The list position immediately following the last element to be removed.

  Remove the elements between list[Start] and list[End-1], decreasing the size of the list appropriately. The default end position of 0 stands for the position immediately after the end of the list, so by default the entire list is deleted.

  ## Find proc (list)

  Format:
    list.Find(Elem,Start=1,End=0)
  Returns:
    The first position of elem in list, or 0 if not found.
  Args:
    Elem: The element to find.
    Start: The list position in which to begin the search.
    End: The list position immediately following the end of the search.

  Find the first position of Elem in the list. Elements between Start and End are searched. The default end position of 0 stands for the position immediately after the end of the list, so by default the entire list is searched.

  ## Insert proc (list)

  See also:
  Cut proc (list)
  Copy proc (list)
  Swap proc (list)
  Format:
    list.Insert(Index,Item1,Item2...)
  Returns:
    The index following the inserted items.
  Args:
    Index: The index where the new item will be inserted. Any value already at that index will be pushed forward.
    Item1: A value or list of values to insert.
    Item2...: (optional) Additional items to insert, immediately after the previous item(s).

  Insert values into a list at a specific point. Using Index=0 or Index=list.len+1 is the same as adding to the list.

  If any of the items you insert is itself a list, its elements will be inserted instead of the list itself.

  Note: This proc doesn't work with many special lists such as `contents` or `overlays`.

  ## Join proc (list)

  See also:
    jointext proc
  Format:
    list.Join(Glue,Start=1,End=0)
  Returns:
    A text string made up of the items in this list, joined together by Glue.
  Args:
    Glue: The text that will go between each item.
    Start: The list item on which to begin.
    End: The list item immediately following the last item to be joined.

  This is exactly the same as calling jointext(List,Glue,Start,End), and is provided for convenience.

  ## Remove proc (list)

  See also:
    - operator
  Add proc (list)
  RemoveAll proc (list)
  Format:
    list.Remove(Item1,Item2,...)
  Returns:
    1 if any items removed, 0 if not.
  Args:
    One or more items to remove from the list.

  Removes the specified items from the list. If an argument is itself a list, each item contained in it will be removed. Removal starts at the end of the list (highest index) so that this operation is an exact reversal of Add().

  ## RemoveAll proc (list)

  See also:
    Add proc (list)
  Remove proc (list)
  Format:
    list.RemoveAll(Item1,Item2,...)
  Returns:
    Number of items removed.
  Args:
    One or more items to remove entirely from the list.

  Removes all copies of the specified items from the list. If an argument is itself a list, each item contained in it will be removed.

  This is basically a faster version of the statement `while(list.Remove(Item1,Item2,...))` with an empty code block. For large lists this might be a big improvement because the list doesn't have to be traversed every time.

  ## Splice proc (list)

  See also:
    Copy proc (list)
  Cut proc (list)
  Insert proc (list)
  splicetext proc
  Format:
    list.Splice(Start=1,End=0,Item1,Item2...)
  Args:
    Start: The list index where the splice will begin.
    End: The index immediately following the last item to be cut from the list. 0 is the end of the list.
    Item1, Item2...: Items to be inserted.

  Cuts out items from a list, and inserts new items in their place. This is basically equivalent to calling `list.Cut(Start,End)` and then calling `list.Insert(Start,Item1,Item2...)`, but faster.

  ### Example:

      var/list/L = list("apple","banana","orange","pear")

      // cuts "banana" and "orange" and inserts four new items
      L.Splice(2,4,"firetruck","camel","joystick","balloon")

      // prints apple, firetruck, camel, joystick, balloon, pear
      for(var/item in L)
          usr << item

  As with `Insert()`, any items that are lists will insert their contents instead of themselves.

  The `Start` and `End` index values can be negative, which count backwards from the end of the list. If the index values are out of range, there will be no error; they will simply be clamped to the beginning or end of the list. If `End` comes before `Start`, the two values are swapped.

  Note: This proc doesn't work with many special lists such as `contents` or `overlays`.

  ## Swap proc (list)

  See also:
    Cut proc (list)
  Copy proc (list)
  Insert proc (list)
  Format:
    list.Swap(Index1,Index2)
  Returns:
    Nothing.
  Args:
    Index1: The index (1 to list.len) of one of the items to swap.
    Index2: The index of the other item.

  Swap two items in a list. If the list has associated values, they will be preserved. This is most useful for user-defined sorting routines.

  ### Example:

      var/item
      var/list/L = list("orange" = 3, "green" = 2, "blue" = 5)
      for(item in L) world << "[item] -> [L[item]]"
      world << ""
      L.Swap(1, 3)
      for(item in L) world << "[item] -> [L[item]]"

  ### Result:

      orange -> 3
      green -> 2
      blue -> 5

      blue -> 5
      green -> 2
      orange -> 3

  Note: This proc doesn't work with many special lists such as `contents` or `overlays`.

  ## vars (list)

  Built-in list vars:

  list/var
    len

  ## len var (list)

  See also:
    + operator
  += operator
  - operator
  -= operator

  This is the length of the list. Increasing it expands the list, initializing all new elements with null. Decreasing it contracts the list, making old elements inaccessible.

  ## map

  See also:
    #include directive
  area var (world)
  maxx var (world)
  turf var (world)
  Format:
    #include "mapname.dmm"

  One or more map files may be loaded into the world's map. These are loaded into successive z-levels. If no map files are specified, the default project map file will be used. This file has the same name as the project but has the extension .dmm.

  If no map files are loaded, the world's map size is determined by the world variables maxx, maxy, and maxz. The default content of this map is determined by the world variables turf and area.

  ### Example:

      #include "level1.dmm"
      #include "level2.dmm"
      #include "level3.dmm"

  ## matrix

  See also:
    matrix proc
  matrix operators
  matrix procs
  transform var (atom)
  stddef.dm file

  To display rotation, scaling, and other transformations on atoms, DM uses 2D matrices. The /matrix datum is a convenient way of handling the numbers involved, as it can be easily manipulated. There are six vars, a through f, laid out like so:

                a d 0
      x y 1  *  b e 0  =  x' y' 1
                c f 1

  When an x,y point is multiplied by the matrix, it becomes the new point x',y'. This is equivalent to:

      x' = a*x + b*y + c
      y' = d*x + e*y + f

  The default matrix is:

      1 0 0
      0 1 0
      0 0 1

  Matrices are created with the matrix() proc, or by calling new/matrix(). (See the matrix() proc for examples.) They are also created as needed whenever you read from atom.transform or use certain operators.

  Manipulation of matrices can be done with operators, or with procs. You can do the following with them:

  - Multiply: Multiplying two matrices together will chain together the transformations they represent. For instance, a scaling matrix multiplied by a rotation matrix says: Scale, then rotate. Multiplication of two matrices is sensitive to the order you use.
  - Scale: A simple scale matrix uses only the a and e values, to scale x and y by a certain amount.
  - Rotate: A rotation matrix can rotate an atom by whatever amount you like.
  - Translate: Translation is like a pixel offset, changing the atom's position.
  - Interpolate: You can calculate a matrix that lies somewhere between two other matrices, which can be helpful for animation.

  When you've built your matrix, you can assign it to atom.transform to change the way that atom is displayed.

  The matrices supported by this datum are not the same kind used to transform colors, as in the atom.color var and icon.MapColors() proc. For color matrices, see color matrix.

  ## matrix operators

  See also:
    matrix
  matrix procs
  See also:
    + operator
    += operator
    - operator
    -= operator
    * operator
    *= operator
    / operator
    /= operator
    ~ operator

  The operators listed above have special meaning when applied to matrices.

  The assignment operators will modify an existing matrix, and can also be used directly with atom.transform. Other operators will create a new matrix.

  ## matrix procs

  See also:
    matrix
  matrix operators
  turn proc (applied to a matrix)
  matrix/proc
    New
    Add
    Interpolate
    Invert
    Multiply
    Scale
    Subtract
    Translate
    Turn

  ## Add proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  += operator
  Format:
    Add(Matrix2)
  Args:
    Matrix2: another matrix
  Returns:
    src

  This adds Matrix2 to the current matrix.

  ## Interpolate proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  Format:
    Interpolate(Matrix2, t)
  Args:
    Matrix2: Another matrix
    t: The interpolation factor: from 0 (src) to 1 (Matrix2). Usually this is a value between 0 and 1.

  Calculates and returns a new matrix between src and Matrix2. If t is 0.5, then the result will be exactly halfway between both matrices.

  There are many ways to interpolate matrices. Whenever possible, DM will interpolate by doing scaling and/or shearing first, then rotation, then translation. This is done by trying to find the angle of rotation of each matrix first; a rotation of 180° is counted as a flip rather than a rotation.

  It is not strictly necessary for t to be between 0 and 1. Using a value out of bounds will extrapolate a matrix, continuing the change as far as t.

  ## Invert proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  ~ operator
  Format:
    Invert()
  Returns:
    src

  This inverts the current matrix, if possible.

  Not all matrices can be inverted. If it's not possible, the matrix is said to be degenerate. This happens if, for example, all of the values in the matrix are zero. A degenerate matrix will not be changed by this proc.

  ## Multiply proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  *= operator
  Format:
    Multiply(Matrix2)
    or
    Multiply(n)
  Args:
    Matrix2: another matrix
    n: a number
  Returns:
    src

  This multiplies the current matrix by Matrix2 or n. If the n format is used, this is just like scaling the whole matrix. If another matrix is multiplied, then it is like doing the two transformations in order: src, then Matrix2.

  Multiplication of one matrix by another depends on the order. You may get a different result multiplying A * B vs. B * A.

  ## Scale proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  Format:
    Scale(x,y)
  Args:
    x: The amount of scaling to do in the x direction
    y: The amount of scaling to do in the y direction
  Returns:
    src

  The matrix is scaled by the appropriate amounts.

  If y is omitted, x is used for both. E.g., Scale(2) is equivalent to Scale(2,2).

  ## Subtract proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  -= operator
  Format:
    Subtract(Matrix2)
  Args:
    Matrix2: another matrix
  Returns:
    src

  This subtracts Matrix2 from the current matrix.

  ## Translate proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  Format:
    Translate(x,y)
  Args:
    x: The amount of scaling to do in the x direction
    y: The amount of scaling to do in the y direction
  Returns:
    src

  The matrix is translated (moved) by the appropriate amounts. The x and y offsets applied by translation are in pixels.

  If y is omitted, x is used for both. E.g., Translate(2) is equivalent to Translate(2,2).

  ## Turn proc (matrix)

  See also:
    matrix
  matrix operators
  matrix procs
  turn proc (applied to a matrix)
  Format:
    Turn(angle)
  Args:
    angle: The angle of clockwise rotation, in degrees
  Returns:
    src

  The matrix is rotated clockwise, by the angle given.

  ## mutable appearance

  See also:
    appearance var (atom)
  image objects
  vars (mutable appearance)

  All atoms and images have an appearance, which is an immutable object that can be shared by many atoms. Making changes to an object's appearance generates new appearances, many of which may be temporary. For high-performance games, this can be a drawback. The `/mutable_appearance` type exists so that you can make multiple changes to an appearance without creating all the temporary objects, then turn it into a regular immutable appearance when finished.

  A new mutable appearance is created via `new/mutable_appearance`, and giving it an atom, image, or appearance as a source object. Assigning it to an object's appearance var will create a new immutable appearance.

  ### Example:

      mob/proc/GetAngry()
          var/mutable_appearance/ma = new(src)
          ma.color = rgb(51,255,51)   // green
          ma.transform = matrix(2,0,0,0,2,0)  // scale x2
          appearance = ma

  Reading certain vars, such as `overlays`, will create a temporary list object that can be modified easily. With regular appearances, making many changes to the `overlays` list results in a lot of churn.

  The `/mutable_appearance` datum is technically a descendant of `/image`, but this is only for convenience, and should not be relied on for any other purpose as it is subject to change in future versions.

  ## vars (mutable appearance)

  Built-in mutable appearance vars:

  mob/var
    alpha
  appearance
  appearance_flags
  blend_mode
  color
  density
  desc
  dir
  filters
  gender
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  underlays
  overlays
  layer
  luminosity
  maptext
  maptext_width
  maptext_height
  maptext_x
  maptext_y
  animate_movement
  mouse_over_pointer
  mouse_drag_pointer
  mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  plane
  render_source
  render_target
  screen_loc
  suffix
  text
  transform
  verbs
  vis_flags

  ## mob

  See also:
    atom
  movable atoms
  procs (mob)
  vars (mob)
  client

  Mobs are "mobile objects" derived from `/mob`, which derives from `/atom/movable`. Human players are associated with a mob when they log on. Mobs are typically used for other "creature" types as well such as NPCs. This type is slightly more complex than objs since it can be attached to a client.

  This example defines the mob type `/mob/guzzler`.

  ### Example:

      mob
        guzzler
          desc = "Mean, mad, and wicked bad."

  ## procs (mob)

  Built-in mob procs:

  mob/proc
    Bump
  Click
  Cross proc
  Crossed proc
  DblClick
  Del
  Enter
  Entered
  Exit
  Exited
  Login
  Logout
  MouseDown
  MouseDrag
  MouseDrop
  MouseEntered
  MouseExited
  MouseMove
  MouseUp
  MouseWheel
  Move
  New
  Read
  Stat
  Topic
  Uncross proc
  Uncrossed proc
  Write

  ## Login proc (mob)

  See also:
    Logout proc (mob)
  client var (mob)
  Format:
    Login()
  When:
    Called when a player's client tries to connect to a mob. This is called by default from client.New(), when the player logs into the world.
  Default action:
    If the mob has no location, place it near (1,1,1) if possible. Change the player's stat object (client.statobj) to the mob.

  One can typically tell if a player is connecting to a fresh mob versus reconnecting to an existing one by testing if the mob's location is null.

  ## Logout proc (mob)

  See also:
    Login proc (mob)
  client var (mob)
  key var (mob)
  Format:
    Logout()
  When:
    Called when a player's client has disconnected from a mob. This happens in client.Del() when the player logs out of the world. It may also happen when the player switches from one mob to another.
  Default action:
    None.

  One may wish to distinguish between a player who has disconnected from the game and one who is simply switching from one mob to another. In the case of a player switching to another mob, by the time `Logout()` is called, the original mob's key will be null, whereas the key will still be non-null in the case of a player disconnecting from the game.

  ## vars (mob)

  Built-in mob vars:

  mob/var
    alpha
  appearance
  appearance_flags
  blend_mode
  ckey
  client
  color
  contents
  density
  desc
  dir
  filters
  gender
  group
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  underlays
  overlays
  key
  layer
  luminosity
  maptext
  maptext_width
  maptext_height
  maptext_x
  maptext_y
  animate_movement
  loc
  mouse_over_pointer
  mouse_drag_pointer
  mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  parent_type
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  pixloc
  plane
  render_source
  render_target
  see_infrared
  see_invisible
  see_in_dark
  sight
  suffix
  tag
  text
  transform
  type
  vars
  verbs
  vis_contents
  vis_flags
  vis_locs
  x
  y
  z

  ## ckey var (mob)

  See also:
    ckey proc
  key var (mob)
  Default value:
    null

  This is the value of mob.key converted to canonical form (ie the form returned by the ckey() proc). Among other things, this could be used as a unique directory name in a server-side save file for storing player information. See the ckey() proc for an example.

  ## client var (mob)

  See also:
    client
  Default value:
    null

  This is a reference to a set of properties specific to the player. Therefore non-player mobs (NPCs) do not have a client (client = null).

  Setting a mob's client connects that player's client to the mob.

  ## group list var (mob)

  See also:
    Bump proc (movable atom)
  list
  Default value:
    (empty list)

  This is a list of mobs in the same group. By default, a mob will swap positions with another mob in its group if bumped. It is also possible to make verbs that are accessible only to members of the group.

  The following example handles addition of somebody else to your group.

  ### Example:

      mob/verb/join(mob/M)
         usr.group.Add(M)    // add M to usr's group
         view() << "[usr] joins [M]."
      mob/verb/disband(mob/M)
         usr.group.Remove(M) // remove M from group
         view() << "[usr] disbands [M]."

  Note that group lists may be asymmetric. Mob A may have mob B in his group list, but mob B may or may not. It is up to you to define whether mobs are added into both lists or not.

  Here is an example of a verb accessible to a group:

  ### Example:

      mob/verb/summon()
         set src in usr.group
         loc = usr.loc
         view() << "[usr] summons [src]."

  ## key var (mob)

  See also:
    ckey var (mob)
  client
  key var (client)
  Default value:
    null

  For player mobs (PCs) this is the value of the player's key. For non-player mobs (NPCs), this is the value of the "desired" key. This means that if a player with that key logs into the world, he will be connected to that mob (as opposed to a new one of type world.mob).

  Setting the mob's key will cause a client with the same key to connect to the mob. Any other mob with the same key will lose it.

  Key values are always compared in canonical form (ie the form returned by ckey()) so setting a mob's key to "Dan", "dan" are equivalent as far as controlling player linkage.

  ## parent_type var (mob)

  See also:
    parent_type var

  The default parent_type of /mob is /atom/movable.

  ## see_in_dark var (mob)

  See also:
    luminosity var (atom)
  see_infrared var (mob)
  see_invisible var (mob)
  sight var (mob)
  view proc
  Default value:
    2

  This determines how far the mob can see in the dark. The scale is just like luminosity: a value of 1 illuminates the mob and its location; 2 illuminates the immediate surrounds; and so on.

  ## see_infrared var (mob)

  See also:
    infra_luminosity var (atom)
  see_in_dark var (mob)
  see_invisible var (mob)
  sight var (mob)
  view proc
  Default value:
    0

  Setting this to 1 enables infravision, allowing the mob to see infrared objects in the dark.

  ## see_invisible var (mob)

  See also:
    invisibility var (atom)
  see_in_dark var (mob)
  see_infrared var (mob)
  sight var (mob)
  view proc
  Default value:
    0

  This is the maximum level of invisibility that the mob can see.

  ## sight var (mob)

  See also:
    invisibility setting (verb)
  invisibility var (atom)
  see_in_dark var (mob)
  see_infrared var (mob)
  see_invisible var (mob)
  view proc
  Default value:
    0

  This controls which objects on the map the mob can see. The default value of 0 means that the mob can see all objects that are visible and lit. Different flags in this var can be set to extend or limit this range.

  The following bit flags are encoded in mob.sight:

      SEE_INFRA // can see infra-red objects
      SEE_SELF  // can see self, no matter what
      SEE_MOBS  // can see all mobs, no matter what
      SEE_OBJS  // can see all objs, no matter what
      SEE_TURFS // can see all turfs (and areas), no matter what
      SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are
                // in a lit area (via pixel_x,y or smooth movement), can see those pixels
      SEE_THRU  // can see through opaque objects
      SEE_BLACKNESS // render dark tiles as blackness
      BLIND     // can't see anything

  ### Example:

      usr.sight |= BLIND     // turn on the blind bit
      usr.sight &= ~BLIND    // turn off the blind bit
      usr.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)  // turn on several bits at once
      usr.sight &= ~(SEE_MOBS|SEE_OBJS|SEE_TURFS) // turn off several bits at once

  `SEE_PIXELS` draws everything and then covers hidden turfs with blackness. It is supported in topdown maps only, not in other map formats. It does not mix well with other flags. In practice, `SEE_PIXELS` acts as if `SEE_BLACKNESS`, `SEE_TURFS`, `SEE_OBJS`, and `SEE_MOBS` are all turned on. That is, all atoms are drawn even on hidden tiles, and black squares are also drawn to cover them.

  The black tiles rendered by `SEE_BLACKNESS` and `SEE_PIXELS` are drawn on the default plane 0.

  ## obj

  See also:
    atom
  movable atoms
  procs (obj)
  vars (obj)

  There are two types of movable atoms: objs and mobs. The difference between them is that a mob can be attached to a human player, and is also typically used for NPCs and creatures. The obj type is a little bit simpler and is typically used for objects in the environment, items in inventory, etc.

  Objects are derived from `/obj`, which derives from `/atom/movable`.

  The following example defines the obj type `/obj/scooper`.

  ### Example:

      obj
        scooper
          desc = "Super pooper scooper."

  ## procs (obj)

  Built-in obj procs:

  obj/proc
    Bump
  Click
  Cross proc
  Crossed proc
  DblClick
  Del
  Enter
  Entered
  Exit
  Exited
  MouseDown
  MouseDrag
  MouseDrop
  MouseEntered
  MouseExited
  MouseMove
  MouseUp
  MouseWheel
  Move
  New
  Read
  Stat
  Topic
  Uncross proc
  Uncrossed proc
  Write

  ## vars (obj)

  Built-in obj vars:

  obj/var
    alpha
  appearance
  appearance_flags
  blend_mode
  color
  contents
  density
  desc
  dir
  filters
  gender
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  underlays
  overlays
  layer
  luminosity
  maptext
  maptext_width
  maptext_height
  maptext_x
  maptext_y
  animate_movement
  loc
  mouse_over_pointer
  mouse_drag_pointer
  mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  parent_type
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  pixloc
  plane
  render_source
  render_target
  suffix
  tag
  text
  transform
  type
  vars
  verbs
  vis_contents
  vis_flags
  vis_locs
  x
  y
  z

  ## parent_type var (obj)

  See also:
    parent_type var

  The default parent_type of /obj is /atom/movable.

  ## operators

  See also:
    operator overloading

  Operators are used extensively in DM to compute numerical values.

  The DM operators are:

      () . : / ::     // here . : / are path operators
      [] . :
      ?[] ?. ?:
      ~ ! - ++ -- * &     // unary operators (* and & here are pointer operators)
      **
      * / % %%
      + -
      < <= > >= <=>
      << >>
      == != <> ~= ~!
      &
      ^
      |
      &&
      ||
      ?               // ternary a ? b : c
      = += -= -= *= /= %= %%= &= |= ^= <<= >>= := &&= ||=
      in

  Each line has higher order of operations than the next. Operators within a line have equal precedence and therefore are processed from left to right as they occur in an expression. (Assignment, or operate-and-assign, are processed from right to left.)

  Expressions of the form `A #= B` are shorthand for `A = A # B` except for `~=` and `:=`.

  ### Example:

      var/N
      N = 0                          // 0
      N += 1+1*2                     // 3
      if(1 + 1 == 2) N = 2           // 2
      if(N==2 && 1/2==0.5) N = 0.5   // 0.5

  ## ! operator

  See also:
    && operator
  operators
  || operator
  Format:
    !A
  Returns:
    1 if A is a false value (zero, an empty string, or null); 0 otherwise.

  This operator inverts the truthiness of the value after it.

  The number 0, an empty string, or null are all false values. Everything else is true.

  ## != operator

  See also:
    > operator
  < operator
  <> operator
  == operator
  ~= operator
  ~! operator
  operators
  Format:
    A != B
  Returns:
    1 if A is not equal to B; 0 otherwise

  This is identical to the <> operator.

  To check if A and B are not equivalent, use the ~! operator.

  ## % operator

  See also:
    %= operator
  %% operator
  operators
  Format:
    A % B
  Returns:
    The remainder of A / B, where both A and B are integers.

  `A % B` is read "A modulo B", which stands for the remainder of A divided by B.

  This operator only works with integer values, for legacy reasons. A and B are truncated to integers before the modulo operation. There are uses for the integer truncation, but if you don't want that and want the fractional modulo instead, you can now use the `%%` operator.

  If A is a vector, its components are treated as integers; B can also be a vector in this case, and its components are also treated as integers. The result is a new vector.

  If A is a pixloc, it's treated like a 2D vector and the modulo operation is done with that instead.

  ## %% operator

  See also:
    % operator
  %%= operator
  operators
  Format:
    A %% B
  Returns:
    The remainder of A / B.

  `A %% B` is read "A modulo B", which stands for the remainder of A divided by B.

  This is a newer version of the `%` operator that supports all numbers, not just integers. It is equivalent to `B * fract(A / B)`. The `%` operator does the same thing, but truncates A and B to integers first.

  A can be a vector instead of a number; B can also be a vector in this case.

  If A is a pixloc, it's treated like a 2D vector and the modulo operation is done with that instead.

  ## %%= operator

  See also:
    %% operator
  operators
  Format:
    A %%= B

  Set A equal to `A %% B`. It is shorthand for `A = A %% B`.

  `A %% B` is read "A modulo B", which stands for the remainder of A divided by B. This version of the operator works with fractional values for A and B.

  If A is a vector, it will be modified by this operation.

  ## %= operator

  See also:
    % operator
  operators
  Format:
    A %= B

  Set A equal to `A % B`. It is shorthand for `A = A % B`.

  `A % B` is read "A modulo B", which stands for the remainder of A divided by B. A and B are truncated to integers before the modulo; use `%%=` instead to work with fractional values.

  If A is a vector, it will be modified by this operation.

  ## & operator

  See also:
    &= operator
  operators
  | operator
  Format:
    A & B
  Returns:
    The binary "and" of A and B.

  A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

  If A and B are lists, the result is a list that contains only items that were in both lists, in the order of list A.

  If A is an icon or /icon datum, it is blended with B which can be either a color or another icon. This is identical to the + operator. Transparent areas in either icon will be transparent in the result.

  ## & pointer operator

  See also:
    * operator (pointers)
  operators
  ispointer proc
  Format:
    &A
  Returns:
    A pointer to the var or list item A.

  Sometimes it is desirable to have easy access to a var without knowing its name, or send multiple items back from a proc. To do this, you can create a pointer to that var. A pointer is basically a way to look up and access a var without needing to know anything else about it, like its name or which object it might belong to. You can pass the pointer like any other piece of data, and use the `*` operator to read or write the var's value.

  ### Example:

      var/a=3, b=4
      var/p = &a
      world << *p   // same as world << a
      *p = 5    // same as a = 5

      var/list/L = list(1, 2, 3)
      var/list/pl = &L[2]
      *pl *= 10 // same as L[2] *= 10

  If you want the compiler to recognize that the item in your pointer var should be a certain type, you can give the pointer var that same type. Hence in the example above, `pl` is defined as a `/list`.

  You can also call procs this way. You can either wrap the pointer and the `*` operator in paretheses, like `(*p).MyProc()`, or you can skip the operator and just call `p.MyProc()` directly.

  The same also applies to the list index operator `[]`. If `p = &list` then you can use `(*p)[index]` or `p[index]` interchangeably.

  Pointers can be made for any of these kinds of vars:

  - Vars belonging to an object
  - Local vars in a proc, including `src`, `usr`, and the `.` var
  - Arguments in a proc
  - Global vars
  - An item in a list, including values in associative lists

  One advantage of pointers is that you can use them to alter a value in a suspended (sleeping) proc.

  Note: When spawn() is used, the current proc is forked, where one keeps running and a copy is scheduled to run later. If any pointers to proc vars were created, they belong to the original proc (the one that keeps running), not to the fork.

  ## && operator

  See also:
    ! operator
  operators
  || operator
  &&= operator
  Format:
    A && B
  Returns:
    First false value of either A or B; last true value otherwise

  The first false value from left to right completes the evaluation (a practice known as short-circuiting), meaning that any expressions after the first false value are skipped. The return value is equal to the last operand to be evaluated.

  ### Example:

      if(jumping && CanDoubleJump())
          DoubleJump()

  In this example, the `CanDoubleJump()` call is not performed if `jumping` is false.

  Although logical short-circuit operators are used most often in blocks such as `if` or `while`, they can be used elsewhere.

  ### Example:

      // check if current target is valid, if it exists at all
      // but don't call the proc if we don't have to
      var/target = current_target && TargetIsValid(current_target)

  ## &&= operator

  See also:
    && operator
  || operator
  ||= operator
  operators
  Format:
    A &&= B
  Returns:
    Value of `(A && B)` after it has been assigned to A. This expression can stand by itself; its result does not need to be assigned to anything else.

  First A is evaluated. If its value is true, B will be evaluated and assigned to A. If A is false, B will not be evaluated and A will remain unchanged.

  Note that this is slightly different from `if(A) A = B` if A is a complex expression such as `list[index++]`, because the expression is only evaluated once.

  This operator cannot be overloaded.

  ## &= operator

  See also:
    & operator
  operators
  |= operator
  Format:
    A &= B

  Set A equal to A & B. It is shorthand for A = A & B.

  This is commonly used to turn off certain bitfields in a word.

  ### Example:

      usr.sight &= ~BLIND // turn off the blind bit

  If A and B are lists, items in A that are not in B are removed.

  If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.

  ## > operator

  See also:
    >= operator
  < operator
  <=> operator
  == operator
  operators
  sorttextEx proc
  Format:
    A > B
  Returns:
    1 if A is greater than B; 0 otherwise.

  If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).

  ## >> operator

  See also:
    >> input operator
  >> operator (savefile)
  >> shift operator

  ## >> input operator

  See also:
    >> operator (savefile)
  file proc
  Format:
    F >> Var

  Cause input to be read from a file into a variable. The file may be a savefile or a file object corresponding to a text file.

  ## >> shift operator

  See also:
    >>= operator
  << shift operator
  operators
  Format:
    A >> B
  Returns:
    The bits of A shifted right B times.

  A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

  Bits shifted below the 24 low bits are lost.

  ## >>= operator

  See also:
    >> shift operator
  <<= operator
  operators
  Format:
    A >>= B

  Set A equal to A >> B. It is shorthand for A = A >> B.

  ## >= operator

  See also:
    > operator
  < operator
  <=> operator
  == operator
  operators
  sorttextEx proc
  Format:
    A >= B
  Returns:
    1 if A is greater or equal to B; 0 otherwise.

  If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).

  ## < operator

  See also:
    <= operator
  > operator
  == operator
  <=> operator
  operators
  sorttextEx proc
  Format:
    A < B
  Returns:
    1 if A is less than B; 0 otherwise.

  If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).

  ## <> operator

  See also:
    != operator
  > operator
  < operator
  == operator
  operators
  sorttextEx proc
  Format:
    A <> B
  Returns:
    1 if A is not equal to B; 0 otherwise

  This is identical to the != operator.

  ## << operator

  See also:
    << operator (savefile)
  << output operator
  << shift operator

  ## << output operator

  See also:
    << operator (savefile)
  output proc
  browse proc
  browse_rsc proc
  file proc
  ftp proc
  image proc
  link proc
  load_resource proc
  run proc
  sound proc
  Format:
    A << B

  Cause the value B to be output to any players connected to mobs specified in A.

  B may be an image, sound, or text. A may be a mob, the whole world, or any list containing mobs.

  ### Example:

      usr << "Hi, [usr.name]"
      view() << "To all in view"
      world << "Hi everybody!"

      usr << 'giggle.wav'
      view() << image(/obj/Fireball,usr)

  ## << shift operator

  See also:
    >> operator
  <<= operator
  operators
  Format:
    A << B
  Returns:
    The bits of A shifted left B times.

  A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

  Bits shifted beyond the 24 low bits are lost.

  ## <<= operator

  See also:
    >>= operator
  << shift operator
  operators
  Format:
    A <<= B

  Set A equal to A << B. It is shorthand for A = A << B.

  ## <= operator

  See also:
    > operator
  < operator
  <=> operator
  == operator
  operators
  sorttextEx proc
  Format:
    A <= B
  Returns:
    1 if A is less than or equal to B; 0 otherwise.

  If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).

  ## <=> operator

  See also:
    < operator
  > operator
  <= operator
  >= operator
  == operator
  operators
  sorttextEx proc
  Format:
    A <=> B
  Returns:
    -1 if A is less B; 1 if A is greater than B; 0 otherwise.

  If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).

  If either value is the special number NaN (not a number), the result is currently 0 but should be considered ambiguous.

  ## () operator

  See also:
    operators
  procs
  verbs

  Parentheses may be used in expressions to change the order of operations. Whatever is inside a pair of parentheses will be evaluated first.

  ### Example:

      usr << 2 + 3 * 2     // 8
      usr << (2 + 3) * 2   // 10

  They are also used for calling procs or verbs, by placing the parentheses after the name of the proc. Any arguments that will be sent to the proc go inside the parentheses; multiple arguments are separated by commas, or the parentheses can be left empty if no arguments are sent. For the same reason, parentheses are also used when defining a new proc or verb and the arguments (if any) that will be used.

  ### Example:

      // Defining a new proc
      proc/Distance(x, y)
          // return straight-line distance from 0,0
          return sqrt(x*x + y*y)

  ## * operator

  See also:
    *= operator
  + operator
  - operator
  / operator
  operators
  Format:
    A * B
  Returns:
    The product of A and B.

  Multiplies A and B. The result of the operation depends on the types of values being multiplied, mostly on A.

  A type | B type | Result
  --- | --- | ---
  num or null (0) | num or null (0) | Numeric product
  icon or /icon | icon or num or color | New blended icon via ICON_MULTIPLY
  matrix | matrix | New matrix, product of A and B
  num | New matrix scaling A by B
  vector | New matrix scaling A by B.x and B.y
  vector | vector | New vector with components multiplied together
  matrix | New vector with 2D transformation applied
  num | New vector scaling A by B

  ## * pointer operator

  See also:
    & pointer operator
  operators
  ispointer proc
  Format:
    *A
  Returns:
    The value pointed at by a pointer stored in A

  When using the `&` operator to get a reference pointer, you can access the value it points to with this version of the `*` operator. This can also be used on the left-hand side of assignment operations, for instance `*A = B` or `*X += Y`, to store the result in the place the pointer indicates.

  ### Example:

      atom/proc/PixelPos(px, py)  // get an exact step position
          *px = (x-1) * 32    // this code assumes a 32x32 icon size
          *py = (y-1) * 32

      atom/movable/PixelPos(px, py)  // get an exact step position
          ..()
          *px += step_x   // this code assumes a 32x32 icon size
          *py += step_y

      mob/verb/WhereAmI()
          var/X, Y
          PixelPos(&X, &Y)
          usr << "You are at [X],[Y] on level [z]"

  Note: If you try to read to or write from a pointer reference that is no longer valid, such as to a var inside a proc that has ended, the read or write will fail silently; reading will return a null value. (An exception is pointers to list items. If the index is out of bounds, you will get the expected error.)

  ## ** operator

  See also:
    log proc
  operators
  Format:
    A ** B
  Returns:
    A to the power of B.

  ### Example:

      usr << 2 ** 3 // outputs 8

  ## *= operator

  See also:
    * operator
  += operator
  -= operator
  /= operator
  = operator
  operators
  Format:
    A *= B

  Set A equal to A * B. It is shorthand for A = A * B.

  If A is an /icon, /matrix, or vector, it will be changed rather than creating a new value and re-assigning it to A.

  ## + operator

  See also:
    * operator
  += operator
  - operator
  / operator
  Add proc (list)
  operators
  icon
  matrix
  pixloc
  vector
  Format:
    A + B
  Returns:
    The sum of A and B.

  Adds A and B. The result of the operation depends on the types of values being added, mostly on A.

  A type | B type | Result
  --- | --- | ---
  num or null (0) | num or null (0) | Numeric sum
  text | text | New string concatenating A and B, in order
  icon or /icon | icon or color | New blended icon via ICON_ADD
  matrix | matrix | New matrix with components added together
  turf or pixloc | vector | New pixloc offset by B
  vector | vector | New vector with components added together
  turf or pixloc | New pixloc offset by A

  ## ++ operator

  See also:
    + operator
  += operator
  -- operator
  operators
  Format:
    ++A // pre-increment
    A++ // post-increment

  The pre-increment has the value (A+1) and the effect of adding 1 to A.

  The post-increment has the value (A) and has the effect of adding 1 to A.

  ### Example:

      var/A = 0
      world << "A++ = [A++]" // outputs "A++ = 0"
      world << "++A = [++A]" // outputs "++A = 2"

  ## += operator

  See also:
    *= operator
  + operator
  -= operator
  /= operator
  = operator
  operators
  Format:
    A += B

  Set A equal to A + B. It is shorthand for A = A + B.

  If A is an /icon, /matrix, pixloc, or vector, it will be changed rather than creating a new value and re-assigning it to A.

  ## - operator

  See also:
    * operator
  + operator
  -= operator
  / operator
  Remove proc (list)
  operators
  icon
  matrix
  pixloc
  vector
  Format:
    A - B
    -B
  Returns:
    The subtraction of B from A.

  Subtracts B from A. The result of the operation depends on the types of values being subtracted, mostly on A.

  A type | B type | Result
  --- | --- | ---
  num or null (0) | num or null (0) | Numeric subtraction
  icon or /icon | icon or color | New blended icon via ICON_SUBTRACT
  matrix | matrix | New matrix with components subtracted
  turf or pixloc | vector | New pixloc offset by -B
  pixloc | turf or pixloc | New vector from A to B
  vector | vector | New vector with components subtracted

  ## -- operator

  See also:
    ++ operator
  - operator
  -= operator
  operators
  Format:
    --A // pre-decrement
    A-- // post-decrement

  The pre-decrement has the value (A-1) and the effect of subtracting 1 from A.

  The post-decrement has the value (A) and has the effect of subtracting 1 from A.

  ### Example:

      var/A = 0
      world << "A-- = [A--]" // outputs "A = 0"
      world << "--A = [--A]" // outputs "A = -2"

  ## -= operator

  See also:
    *= operator
  += operator
  - operator
  /= operator
  = operator
  operators
  Format:
    A -= B

  Set A equal to A - B. It is shorthand for A = A - B.

  If A is an /icon, /matrix, pixloc, or vector, it will be changed rather than creating a new value and re-assigning it to A.

  ## / operator

  See also:
    * operator
  + operator
  - operator
  / path operator
  /= operator
  operators
  Format:
    A / B
  Returns:
    A divided by B.

  Divides A and B. The result of the operation depends on the types of values being multiplied, mostly on A.

  A type | B type | Result
  --- | --- | ---
  num or null (0) | num or null (0) | Numeric division; crashes if B is equivalent to 0
  icon or /icon | num or color | New icon dividing RGB components by color
  matrix | matrix | New matrix, product of A and the inverse of B
  num | New matrix scaling A by 1/B
  vector | New matrix scaling A by 1/B.x and 1/B.y
  pixloc | num or vector | Creates a 2D vector from pixloc's x,y and divides that by the rules below
  vector | 2D vector dividing x,y components by the divisor's x,y
  vector | vector | New vector with components divided
  matrix | New vector with 2D transformation applied in reverse
  num | New vector scaling A by 1/B

  ## /= operator

  See also:
    *= operator
  += operator
  -= operator
  / operator
  = operator
  operators
  Format:
    A /= B

  Set A equal to A / B. It is shorthand for A = A / B.

  If A is an /icon, /matrix, or vector, it will be changed rather than creating a new value and re-assigning it to A.

  ## : operator

  See also:
    . operator
  ?. operator
  ?: operator
  : path operator
  operators

  This is the runtime search operator. It is used to access a property (var or proc) of a var that is not explicitly prototyped. If the variable doesn't have the specified variable or proc, a runtime error occurs.

  ### Example:

      var/M
      M = usr
      M:name = "futz"  // access a mob property from a non-mob var

  The `.` operator behaves the same way, but it checks at compile time whether the property is available. If the var is assigned a value that isn't the correct type and doesn't have this property, a runtime error will still occur.

  Note: You should prefer the `.` operator in most situations, because it's better to catch a problem in the compiler instead of at runtime.

  ## :: operator

  See also:
    . path operator
  / path operator
  : path operator
  operators
  call proc
  initial proc
  nameof proc
  istype proc
  astype proc
  Format:
    ::A
    ::A()
    A::B
    A::B() (proc reference, not a call; see below)

  This is the scope operator. It has multiple uses.

  ### Global var and proc disambiguation

  `::A` is a shorthand for `global.A`, so if you have a local or object var with the same name this disambiguates to the global var. The same is true of `:A()` which will call `global.A()` with the arguments you give it.

  ### Static var disambiguation

  If `A` is a constant type and `B` is a static var, `A::B` refers to the static var. If you have a local var with the same name, this disambiguates to the static var. This is also the only case where `A::B` can be used as an Lvalue (modifiable expression).

  ### Initial value

  The most common use of the scope operator is to get the initial value for a var. If `A::B` isn't a static var, then it's equivalent to `initial(A:B)`. If `A` is a constant type path, the compiler will go even further by compiling this expression as the actual initial value instead of doing a runtime lookup.

  This can also be used when defining a var that overrides its parent, by using the `parent_type` keyword for `A`. Multiple `parent_type` levels can be chained together. Similarly, in a static var definition, `type` can be used for `A` the same way.

  ### Example:

      thing
          var/price = 60
          better
              price = parent_type::price + 40

  ### Proc reference

  If `B` is a proc, then `A::B()` is a reference to the proc for type `A`, which can be used in `call()`. In this case the parentheses are just a cue for the compiler to know this is a proc reference; it doesn't actually call the proc. Currently, `A` must be a constant type for this usage.

  ### Example:

      thing
          proc/DoSomething()
              world << "Did a thing"
          better
              DoSomething()
                  world << "Did a better thing"

      proc/Downgrade()
          var/thing/better/T = new

          // will print "Did a better thing" because T is /thing/better
          T.DoSomething()

          // deliberately calls /thing's original version; will print "Did a thing"
          call(T, /thing::DoSomething())()

  ## := operator

  See also:
    = operator
  operators
  Format:
    A := B

  This is the "assign into" operator. The value of B is evaluated, then A. If A is a datum that has an `operator:=` proc overloading this operator, then that proc will be called with A as its src and B as its only argument. The return value of the proc (which defaults to its src, the old value of A) is assigned into the var that holds A.

  If A was not a datum, then B is assigned into the var as if this were an ordinary A = B assignment.

  A common use of this operator might be to copy another datum. This is basically just "syntactic sugar" to make certain datums easier to work with, and is intended mainly for situations where you've overloaded the operator.

  ## = operator

  See also:
    *= operator
  += operator
  -= operator
  /= operator
  %= operator
  |= operator
  &= operator
  ^= operator
  <<= operator
  >>= operator
  := operator
  ||= operator
  &&= operator
  operators
  Format:
    A = B

  Set A equal to B.

  Note that this is not the same as the equality test (==), which tests if A is equal to B.

  All assignment operators, including calculate-and-assign (such as the += operator), can be chained together, and they are evaluated in right-to-left order. Therefore, a = b += c is a legal statement. It is equivalent to adding b and c, storing the result in b, then setting a to use the new value of b. (a = b) += c will, on the other hand, set a to equal b, then add c to a and store the result in a; b is never changed.

  ## == operator

  See also:
    != operator
  >= operator
  <= operator
  <=> operator
  ~= operator
  ~! operator
  operators
  Format:
    A == B
  Returns:
    1 if A and B are equal; 0 otherwise

  Note that this is not the same as the assignment operator (=), which sets A equal to B.

  To check if A and B are equivalent, use the ~= operator.

  ## . operator

  See also:
    : operator
  ?. operator
  ?: operator
  operators

  This is used to access the procs and vars of a prototyped object. The variable need not actually contain a value with the specified type, but must at least be a type with the specified variable or a runtime error will occur, causing the proc to crash.

  ### Example:

      var/mob/M = new
      M.name = "futz"  // assign 'name' mob var
      M.Move(0)        // call 'Move()' mob proc

  This is the same as the `:` operator, except that the compiler checks to see if the var type has this property, and throws a compiler error if not. It is good practice to use the `.` operator whenever possible, so more potential problems can be caught during compilation.

  If `.` follows a proc call, a list lookup, or a complex expression where the type can't be known, it will act like `:` instead.

  ## ? operator

  See also:
    operators
  Format:
    Expr ? TrueExpr : FalseExpr

  If Expr is true, this evaluates and returns TrueExpr. Otherwise, it evaluates and returns FalseExpr.

  ## ?. operator

  See also:
    . operator
  : operator
  ?: operator
  operators

  This is used to access the procs and vars of a prototyped object. It is just like the . operator, but if the object is null, the access does not happen and there will be no runtime error. (A runtime error can still happen if the object is valid but is a different type that doesn't have the property available.)

  When used in an expression to read a value or call a proc from a null object, the result of the expression is null. When used for assignment, the assignment will not happen, and the expression being assigned will not be evaluated, if the object is null.

  ### Example:

      var/mob/M           // M is null by default
      M?.name = "futz"    // assignment is skipped because M is null
      world << M?.name    // M?.name reads as null because M is null
      M?.Move(loc)        // call Move() mob proc; again nothing happens

      M = new
      M?.name = "futz"    // assignment is made because M is valid now
      world << M?.name    // outputs "futz"
      M?.Move(loc)        // call Move() mob proc for M

  When reading `A?.B`, it's roughly equivalent to `A && A.B` except that `A` is only evalulated once, even if it's a complex expression like a proc call. Making an assignment to `A?.B` is the same: A is evalulated only once, and if it's not null then an assignment is made to its B var.

  For a version of this operator that doesn't check at compile time if the property is available, use the ?: operator instead.

  If ?. is used after a proc call, a list lookup, or a complex expression where the type can't be known, it will act like ?: instead.

  ## ?: operator

  See also:
    . operator
  : operator
  ?. operator
  operators

  This is used to access the procs and vars of an object. It is just like the : operator, but if the object is null, the access does not happen and there will be no runtime error. (A runtime error can still happen if the object is valid but the property is not available.)

  When used in an expression to read a value or call a proc from a null object, the result of the expression is null. When used for assignment, the assignment will not happen, and the expression being assigned will not be evaluated, if the object is null.

  ### Example:

      var/mob/M           // M is null by default
      M?:name = "futz"    // assignment is skipped because M is null
      world << M?:name    // M?:name reads as null because M is null
      M?:Move(loc)        // call Move() mob proc; again nothing happens

      M = new
      M?:name = "futz"    // assignment is made because M is valid now
      world << M?:name    // outputs "futz"
      M?:Move(loc)        // call Move() mob proc for M

  When reading `A?:B`, it's roughly equivalent to `A && A:B` except that `A` is only evalulated once, even if it's a complex expression like a proc call. Making an assignment to `A?:B` is the same: A is evalulated only once, and if it's not null then an assignment is made to its B var.

  This is identical to the ?. operator, except that ?. will check at compile time if the property is valid for the object type (if known). For this reason ?. is usually safer.

  ## ?[] operator

  See also:
    list
  operators
  [] operator
  ?. operator
  ?: operator

  This is the null-conditional list index operator. It is used to access an element of a list, IF that list is not null. If the list is null, then the access will not happen and the index expression inside the brackets won't be evaluated. If this is the left-hand side of an assignment operator, such as `list?[index] = rhs`, then `rhs` is also not evaluated when the list is null.

  ### Example:

      var/list/good = list(5,6,7)
      var/list/bad
      var/idx = 1

      // prints null because bad is null; idx is not changed
      world << json_encode(bad?[idx++])
      // prints 5 because good is not null, and good[1] is 5; idx changes to 2
      world << json_encode(good?[1])

      idx = 1 // reset idx

      // bad is null, so idx does not advance and myproc() is not called
      bad?[idx++] = myproc()
      // good is not null, so idx advances after read, and myproc() is called
      good?[idx++] = myproc()

  This operator cannot be overloaded, but overloads to the `[]` operator will apply to this operator as well.

  ## [] operator

  See also:
    list
  operators
  ?[] operator

  This is used to access an element of a list.

  ### Example:

      var/L[2]  // declares list of size 2
      L[1] = 10 // assign first element

  If you want to use a datum like a list, you can overload the operator by defining an `operator[]` proc for reading a value, and `operator[]=` for writing a value. Those overloads also apply if you use the null-conditional `?[]` operator.

  ## ^ operator

  See also:
    ^= operator
  operators
  Format:
    A ^ B
  Returns:
    The binary "xor" of A and B.

  A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

  If A and B are lists, the result is a list containing items that are in either list but not both. list(1,2) ^ list(2,3) is equivalent to list(1,3). The items found only in A come first in the result, followed by any items found only in B.

  ## ^= operator

  See also:
    ^ operator
  operators
  Format:
    A ^= B

  Set A equal to A ^ B. It is shorthand for A = A ^ B.

  If A and B are lists, any items that are found in both lists are removed from A, and then any items found only in B are added to A.

  ## in operator

  See also:
    list
  operators
  ! operator
  locate proc
  input proc
  Format:
    A in List
  Returns:
  1 if A exists in List; 0 if not

  This is a relatively safe way to check if an item is in a list, because the value of `List` is allowed to be a non-list value, such as null. Compare to `List.Find(A)` which will fail if `List` is not an actual list.

  `List` can also be an atom, in which case `A in List` is equivalent to `A in List.contents`.

  The `in` operator has a lower precedence than `!`, which can be a point of confusion. If you want to check if something is not in a list, it's a common mistake to try `if(!A in List)`. Unfortunately the `!A` part is evaluated first and becomes 0 or 1, so you're really asking if 0 or 1 is in the list. The correct way to check if something is not in a list is to wrap the `in` operator and its operands with parentheses, as in `if(!(A in List))`.

  Similarly, the assignment operators also have higher precedence than `in`, so `has_thing = thing in src` will not be interpreted as you might expect. Again the solution is to use parentheses, e.g. `has_thing = (thing in src)`.

  The `in` operator is also a modifier for some procs such as locate() and input().

  Note: For associative lists there's a faster way to see if an item is in that list. The lookup of `List[A]` in an associative list is relatively fast, so if the associated value is always expected to be true (not null, 0, or an empty string), you can use `List[A]` instead of `A in List` in those situations.

  ## path operators

  See also:
    . path operator
  / path operator
  : path operator
  procs
  vars

  A "path" in DM is a constant value that identifies a particular definition in the code tree (i.e. an object, procedure, or variable definition). An example of this is the default mob type for new players `/mob`.

  Paths are used in two contexts. One is to "get to" a particular point in the code tree in order to modify the definition. The other is to reference a particular definition made elsewhere in the code tree. The syntax of a path is similar in both cases.

  When you are making a definition, you simply put the path at the beginning of a line like this:

      obj/clothes/gloves

  That automatically creates that path in the code tree if it does not already exist. When starting at the beginning of the line (no indentation) there is no need to begin the path with '/', but that is perfectly acceptable.

  When making definitions, DM equates the path separator '/' with indentation, so the above example is really just a more compact way of writing:

      obj
         clothing
            gloves

  One generally uses indentation when you have several things to define with a common parent path:

      obj
         clothing
            gloves
            sandals

  An important element of DM is that you can get to the same path in the code tree from multiple places in the source code. For example, given the above definition of `gloves` and `sandals`, you could modify a property of one of them from somewhere else using any path syntax you like:

      obj/clothing/sandals
         name = "Winged Sandals"

  While that was not a useful thing to do in this case, it can be a very powerful tool when organizing source code in large projects. Also note that the use of "/" can save your source code from getting too deeply indented, which may sound mundane, but which is quite important!

  The above examples used paths to make definitions. The other time when you use paths is when you need to refer to a particular definition. Creation of an object is one example:

      mob/Login()
         if(length(contents) == 0) //poor fellow has nothing
            //create sandals in his contents list
            new /obj/clothing/sandals (src)
         return ..()

  Another common use of paths is to declare the data type of a variable. In DM, variable types do not affect what type of data the variable may contain—variables that you define may contain any type of value. Instead, the variable type affects what properties of the data you can attempt to access.

  The following example defines variables for clothing that is occupying various positions on the body.

      mob
         var/clothing
            feet
            hands
            torso

  Since there were several variables of the same type, they were grouped under `var/clothing`. It can be done any number of ways, depending on the situation. The same path syntax applies to variable definitions as it does to anything else. This example produces the same effect:

      mob/var/clothing/feet
      mob/var
         clothing
            hands
            torso

  ### Provisos

  Just do not make a mistake like the following:

      mob/var
         /clothing/feet

  Beginning a path with '/' effectively ignores whatever indentation may precede it. That is why it is called an absolute path. The above example would therefore be the same as the following, which is not what you want:

      mob/var        //empty variable definition
      clothing/feet  //definition of object type /clothing/feet

  On a related note, parameter definitions in procedures should not begin with a "/".

      mob/Move(atom/Dest)     //correct
         src << "Moving to [Dest.x],[Dest.y]."
         return ..()

      mob/Move(var/atom/Dest) //ok
      mob/Move(/atom/Dest)    //WRONG

  Essentially, "var/" is prepended to each entry in the parameter list.

  ## / path operator

  See also:
    . path operator
  : path operator

  This is used to delimit paths in the DM code tree. A path beginning with '/' is an absolute path (which is independent of where in the code it is used). Otherwise, a path is relative, meaning it starts from the current position in the code.

  The following example uses a path in the code tree to define the type of object to create when leaving a corpse behind.

  ### Example:

      obj
         var
            poison
            nutrition

         corpse
            frog
               nutrition = 10
            spider
               nutrition = 6
               poison = 5
      mob
         var
            corpse = /obj/corpse
         Die()
            new corpse(src.loc) //create the corpse here
            del src

         spider
            corpse = /obj/corpse/spider
         frog
            corpse = /obj/corpse/frog

  ## : path operator

  See also:
    . path operator
  / path operator

  The colon operator may be used as a short-cut when specifying a path in the DM code tree. Instead of specifying the full path, you can insert a colon and the compiler will search down in the tree with the node you specify. This is known as a "downward" search. You should only use it when the target node is unique.

  The following example demonstrates the principle but it obviously doesn't save much typing!

  ### Example:

      world
         mob = :player  //short-cut to /mob/player

      mob/player
         Login()
            src << "Welcome, [name]."

  ## . path operator

  See also:
    / path operator
  : path operator

  The dot operator may be used as a short-cut when specifying a path in the DM code tree. Instead of specifying the full path, you can start a path with a dot and the compiler will search up in the code tree for the following node. This is known as a relative path with an "upward" search.

  Here are the beginnings of a text MUD that allows you to walk around between rooms using the arrow keys. The links between rooms are created in this example by referencing the object type of the destination room. Since there could potentially be a lot of rooms, they are grouped into sub-classes, and to avoid lengthy type paths such as /area/Village/Square, they are referenced using a relative path from the point of reference.

  ### Example:

      area
         var/area
            north_exit
            south_exit
            east_exit
            west_exit

         Entered(O)
            O << name
            return ..()

         Castle
            Main_Gate
               north_exit = .Castle_Entryway
               south_exit = .Moat_Bridge
            Castle_Entryway
               south_exit = .Main_Gate
            Moat_Bridge
               north_exit = .Main_Gate
               south_exit = .Village/Guard_Post
         Village
            Guard_Post
               north_exit = .Castle/Moat_Bridge
               south_exit = .Square
            Square
               north_exit = .Guard_Post

      //handle movement
      client/Move(Dest,Dir)
         var/area/room = usr.loc
         if(istype(room)) //in a room
            switch(Dir)
               if(NORTH) Dest = room.north_exit
               if(SOUTH) Dest = room.south_exit
               if(EAST)  Dest = room.east_exit
               if(WEST)  Dest = room.west_exit
         return ..()

      //set the starting position for new logins
      mob/Login()
         if(!loc) Move(locate(/area/Castle/Main_Gate))
         return ..()

  ## | operator

  See also:
    & operator
  operators
  |= operator
  Format:
    A | B
  Returns:
    The binary "or" of A and B.

  A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

  If A and B are lists, the result is a list containing items that are in either list. list(1,2) | list(2,3) is equivalent to list(1,2,3). The items from A come first in the result, followed by any extra items from B.

  If A is an icon or /icon datum, it is blended with B which can be either a color or another icon. Unlike the + or & operation, the result is transparent only in places where both icons were transparent.

  ## |= operator

  See also:
    &= operator
  operators
  | operator
  Format:
    A |= B

  Set A equal to A | B. It is shorthand for A = A | B.

  This is commonly used to turn on certain bitfields in a word.

  ### Example:

      usr.sight |= BLIND // turn on the blind bit

  If A and B are lists, any items in B that are not already in A are added to A.

  If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.

  ## || operator

  See also:
    ! operator
  && operator
  ||= operator
  operators
  Format:
    A || B
  Returns:
    First true value of either A or B; last false value otherwise

  The first true value from left to right completes the evaluation (a practice known as short-circuiting)), meaning that any expressions after the first true value are skipped. The return value is equal to the last operand to be evaluated.

  ### Example:

      mob/verb/Fly()
          if(swimming || IsStuck())
              src << "You can't fly right now!"
              return

  In this example, the `IsStuck()` call is not performed if `swimming` is true.

  Although logical short-circuit operators are used most often in blocks such as `if` or `while`, they can be used elsewhere.

  ### Example:

      // if current_target is null, pick a new one
      var/target = current_target || PickTarget()

  ## ||= operator

  See also:
    || operator
  && operator
  &&= operator
  operators
  Format:
    A ||= B
  Returns:
    Value of `(A || B)` after it has been assigned to A. This expression can stand by itself; its result does not need to be assigned to anything else.

  First A is evaluated. If its value is false, B will be evaluated and assigned to A. If A is true, B will not be evaluated and A will remain unchanged.

  Note that this is slightly different from `if(!A) A = B` if A is a complex expression such as `list[index++]`, because the expression is only evaluated once.

  This operator cannot be overloaded.

  ## ~ operator

  See also:
    operators
  Format:
    ~ A
  Returns:
    The binary "not" of A.

  A must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

  If A is a /matrix datum, the result is a new matrix which is the inverse of A.

  ## ~= operator

  See also:
    ~! operator
  == operator
  != operator
  operators
  Format:
    A ~= B
  Returns:
    1 if A and B are equivalent; 0 otherwise

  Equivalence is a looser version of equality:

  - Two lists are equivalent if their contents are the same. (This is a shallow comparison, so it doesn't check if the Nth items are also equivalent, only equal.)
  - Two /matrix values are equivalent if their components are the same.
  - Datums A and B are equivalent if A
  overloads the ~= operator with a proc that returns true for B. Without an overload, they are only equivalent if they're the same object.

  To check if A and B are equal, use the == operator.

  Note: For code compiled in version 516 or later, associated values in lists are also checked for equality. This was not the case for older versions.

  ## ~! operator

  See also:
    ~= operator
  == operator
  != operator
  operators
  Format:
    A ~! B
  Returns:
    1 if A and B are not equivalent; 0 otherwise

  Equivalence is a looser version of equality. See the ~= operator for more information.

  To check if A and B are not equal, use the != operator.

  ## operator overloading

  See also:
    datum
  operators

  DM allows you to overload most of the operators it uses when working with datums and other objects. This means that A + B can call a proc defined under A instead, with B as an argument, and the return value of that proc would be the result.

  The proc name for an overloaded operator is "operator" followed immediately by the operator itself, such as `operator*` to override the multiplication operator. `A * B` will call `A.operator*(B)` if the proc is available.

  ### Example:

      complex     // complex number a+bi
          var/a as num
          var/b as num

          New(_a,_b)
              a = _a
              b = _b

          proc/operator+(complex/C)
              if(istype(C)) return new/complex(a+C.a, b+C.b)
              if(isnum(C)) return new/complex(a+C, b)
              return src

          proc/operator+=(complex/C)
              if(istype(C))
                  a += C.a
                  b += C.b
              else if(isnum(C)) a += C

  The following operators may be overloaded:

  Operators | Proc | Notes
  --- | --- | ---
  Arithmetic and binary (return new value)
  A + B | A.operator+(B) |
  A - B | A.operator-(B) |
  -A | A.operator-() | Same proc as subtraction, but has no arguments
  A * B | A.operator*(B) |
  A / B | A.operator/(B) |
  A % B | A.operator%(B) |
  A %% B | A.operator%%(B) |
  A ** B | A.operator**(B) |
  A | B | A.operator|(B) |
  A & B | A.operator&(B) |
  A ^ B | A.operator^(B) |
  ~A | A.operator~() |
  A << B (shift) | A.operator<<(B) |
  A >> B (shift) | A.operator>>(B) |
  A << B (output) | A.operator<<(B,A,window) | Ignores return value ..() falls back on default behavior which breaks target into a list of clients and tries again (see notes below)
  A >> B (input) | A.operator>>(null,A) | Return value is assigned to B ..() falls back on default behavior
  Comparisons (return true or false)
  A ~= B | A.operator~=(B) |
  A ~! B | A.operator~!(B) |
  A < B | A.operator<(B) |
  A >= B | A.operator>=(B) |
  A > B | A.operator>(B) |
  A <= B | A.operator<=(B) |
  A <=> B | A.operator<=>(B) |
  Assignments with side effects (return value defaults to src)
  A += B | A.operator+=(B) |
  A -= B | A.operator--(B) |
  A *= B | A.operator*=(B) |
  A /= B | A.operator/=(B) |
  A %= B | A.operator%=(B) |
  A %%= B | A.operator%%=(B) |
  A |= B | A.operator|=(B) |
  A &= B | A.operator&=(B) |
  A ^= B | A.operator^=(B) |
  A <<= B | A.operator<<=(B) |
  A >>= B | A.operator>>=(B) |
  A := B | A.operator:=(B) |
  ++A | A.operator++() |
  --A | A.operator--() |
  A++ | A.operator++(1) |
  A-- | A.operator--(1) |
  List access
  A[idx] | A.operator[](idx) | Used for reading a list value
  A[idx] = B | A.operator[]=(idx, B) | Used for writing a list value; ignores return value
  Other
  turn(A, B) | A.operator_turn(B) |
  "[A]" | A.operator""() | Specifies a custom way for converting A to text (see notes below)

  If an overloaded proc is not available for an operator you try to use on a datum, a runtime error may result.

  ### Operators without overloads

  Operators | Notes
  --- | ---
  `= | Because vars are just buckets that can often hold any value, overloading the assignment operator isn't possible. The `:= operator

may be a solution if you're using an overload to apply a change to a value such as a datum.
`!` `&&` `||` `&&=` `||=` `?`Logical operators wouldn't make sense to overload.
`==` `!=`Equality operators can't be overloaded because they're needed to test direct equality. The equivalence operators ~= and ~! are the ones to use instead, since they can be overloaded.
`.` `:`Path operators can't be overloaded.

### Fallback overloads

Comparison operators come in opposing pairs: `~=` vs. `~!`, `<` vs. `>=`, `>` vs. `<=`. You only need to override one operator from each pair; DM is smart enough to know that `!(A ~= B)` is the same as `A ~! B`.

By the same logic, you don't have to define the assign-with-side-effect operators like `+=` if you don't want to. For instance if you override `+` but not `+=`, then `A += B` will be handled internally as `A = A + B`, which means the value of `A` after the statement may be a different datum than `A` was before. The value of `A` can also change if you do overload `+=` but the proc returns a value other than null; its return value will be the new `A`.

### List access

The list access operators have two different versions, because reading to a list and writing to it are different things. The `[]` overload is for reading, and `[]=` is for writing.

### Output

Output operations are given special treatment. If no overload is defined for the current left-hand-side value (the recipient), and the recipient isn't a client, then the recipient is broken down into a list of clients who would ordinarily receive the output as a broadcast. E.g., outputting to `world` will output to each individual client instead. Each client is then checked for an overload before they receive output. Calling `..()` will of course fall back on default output behavior.

Output overloads are always called with multiple arguments, to distinguish them from the bitwise left-shift operator which takes only one argument. Output can have a third argument when used with the `output()` proc, since that can include a window reference.

### Example:

    // Send an effect to a player or list of players
    proc/DoEffect(target, effect/E)
        if(istype(target, /client))
            ... // do something here to show the effect
        else
            target << E   // send as output overload

    client/proc/operator<<(out, target)
        if(target)
            if(istype(out, /effect)) DoEffect(src, out)
            else ..()

### Text operator

There is an overload for converting a datum to text. By having `operator""` return a text string, that text will automatically appear anywhere that you embed the datum in a string, use `json_encode()` on the datum, or many other situations.

It won't work for atoms being sent directly to output (e.g., `world << obj`) or other skin controls because the client has special handling for these situations, and the client isn't given any info about the overloaded text. Likewise, the overloaded text won't appear for objects in an `input()` prompt list, which is also handled mainly on the client and therefore can't call any procs on the server. Despite these limitations, the text overload offers greater flexibility.

## pixloc

See also:
  vars (pixloc)
  pixloc var (atom)
  pixloc proc
  bound_pixloc proc

A primitive type that encapsulates position information for an atom, with pixel movement included. I.e., it contains a turf (loc) and step_x and step_y offsets. Pixlocs can also be built from absolute world coordinates.

The pixloc of an atom is taken from its loc and step_x/y vars only. If you want the pixloc of its bounds edges or its center, use the `bound_pixloc()` proc for that.

Pixlocs support some math operations. A vector can be added or subtracted to a pixloc, and subtracting one pixloc from another will produce a vector. The % and %% operators are supported, returning a vector.

Other supported procs for pixlocs include:

min()
max()
clamp()
round()
floor()
ceil()
trunc()
fract() (returns a vector)

## vars (pixloc)

See also:
  pixloc

Built-in pixloc vars:

pixloc/var
  loc
  step_x
  step_y
  x
  y
  z

## loc var (pixloc)

See also:
  pixloc

  step_x var (pixloc)
  step_y var (pixloc)
  loc var (atom)

  The turf that this pixloc belongs to. If the map has resized so that this pixloc is no longer valid, this will be null.

  ## step_x var (pixloc)

  See also:
  pixloc
  loc var (pixloc)
  step_y var (pixloc)
  step_x var (movable atom)

  The step_x offset of this pixloc, relative to its loc. For instance a value of 4 means this is 4 pixels east from the southwest corner of the turf.

  ## step_y var (pixloc)

  See also:
  pixloc
  loc var (pixloc)
  step_x var (pixloc)
  step_y var (movable atom)

  The step_y offset of this pixloc, relative to its loc. For instance a value of 4 means this is 4 pixels north from the southwest corner of the turf.

  ## x var (pixloc)

  See also:
  pixloc
  y var (pixloc)
  z var (pixloc)

  The x value of this pixloc in world pixel coordinates, which start at 1. A value of x=1 means this is lined up to the western edge of the map. On a 100x100 tile map with a 32x32 icon size, x=3200 would be a pixel on the eastern edge of the map.

  Setting x will alter the loc and step_x values automatically. Out-of-bounds values are allowed.

  ## y var (pixloc)

  See also:
  pixloc
  x var (pixloc)
  z var (pixloc)

  The y value of this pixloc in world pixel coordinates, which start at 1. A value of y=1 means this is lined up to the southern edge of the map. On a 100x100 tile map with a 32x32 icon size, y=3200 would be a pixel on the northern edge of the map.

  Setting y will alter the loc and step_y values automatically. Out-of-bounds values are allowed.

  ## z var (pixloc)

  See also:
  pixloc
  x var (pixloc)
  y var (pixloc)

  The z value of this pixloc's turf (`loc`). It must be in the range of 1 to world.maxz.

  ## procs

  See also:
  vars (procs)
  arguments (proc)
  procs (area)
  procs (mob)
  procs (obj)
  procs (turf)

  Procs may be derived from /proc. These procs are "global", in that they can be called anywhere in the code.

  ### Example:

      proc/poof()
          world << "POOF!"

  The proc `poof()` may now be called anywhere in the code.

  Procs may also be attached to objects by defining them under the appropriate `object/proc` subnode. Currently DM allows procs to be defined or overridden for `/mob`, `/obj`, `/turf`, `/area`, `world`, and `/client`, as well as for datum objects derived from `/`. Predefined procs are discussed under the "procs" entry for the object type.

  ### Example:

      mob/proc/poof()
          world << "POOF!"

  This can be called by a mob var M, using `M.poof()`.

  ### Return types

  It is possible to define what type of value a proc is expected to return, by following its definition with an `as` clause. This can be a type path, such as `as /mob/player`, or a more intrinsic type like `as num` or `as list`.

  ### Example:

      mob/monster
          var/mob/player/target

          proc/GetTarget() as /mob/player
              if(!target)
                  // find a /mob/player in view
                  target = locate() in view(src)
              return target

  Currently the only purpose for using the `as` clause is for situations where the compiler needs to infer the type of an expression. Mainly this applies to the . and ?. operators in an expression such as `GetTarget()?.Attack(src)`. Giving `GetTarget()` a return type allows the compiler to check if `Attack()` is a valid proc for `/mob/player`. Otherwise, the `.` and `?.` operators act like `:` and `?:`, respectively; the compiler won't do any checking to see if `Attack()` is valid.

  ## . proc

  See also:
  .. proc
  Format:
    .(Args)
  Returns:
    The return value of the current proc.
  Args:
    The arguments to pass to the new invocation of the current proc. This defaults to current arguments.

  Call the current proc. A proc that calls itself is said to be recursive.

  ### Example:

      proc/factorial(N as num)
        if(N<=0) return 1
        return .(N-1)*N

  This computes the factorial N! by calling itself recursively.

  ## .. proc

  See also:
  . proc
  Format:
    ..(Args)
  Returns:
    The return value of the parent proc.
  Args:
    The arguments to pass to the parent proc. This defaults to the arguments to the current proc.

  If object O is derived from object P, P is called the parent of O. If a proc (or verb) is defined in both O and P, O can call P's version by using ..().

  ### Example:

      mob
        P
          verb/history()
            world << "P"

          O
            history()
              world << "O"
              ..()          // call P.history()

  Here O is derived from P. When P calls "history", his name is displayed. When O calls "history", his name is displayed, followed by the name of his parent, P.

  If O overrides the same proc more than once, ..() will search for the previous version and use that. For instance, you could have two O.history() procs; the second overrides the first, but the original could still be called via ..(). The original in turn could call ..() to reach P.history(). Overriding the same proc more than once in the same type should be avoided wherever possible, because it incurs extra overhead, it makes the code harder to read, and it isn't always clear which one gets called first. (Usually, the only time you'll want this to happen is when using libraries.)

  ..() can also be used for predefined procs.

  ### Example:

      mob/Move()            // override proc
        world << "moving..."
        return ..()         // call default

  This proc will print "moving..." whenever the mob moves.

  ## ASSERT proc

  See also:
  CRASH proc
  DEBUG definition
  stddef.dm file
  Format:
    ASSERT(expression)
  Args:
    expression: an expression which should always be true

  This is used to make a sanity check. If the given expression is false, the current procedure crashes, generating diagnostic debugging output, which includes the expression, a stack dump, and so forth.

  ## CRASH proc

  See also:
  ASSERT proc
  DEBUG definition
  Format:
    CRASH(msg)

  Crashes the current procedure, displaying the specified message and generating diagnostic debugging output, such as a stack dump.

  ## abs proc

  Format:
  abs(A)
  Returns:
  The absolute value of A.
  Args:
  A: A number.

  ### Example:

      usr << abs(1)  // outputs 1
      usr << abs(-1) // outputs 1

  ## addtext proc
See also:
  + operator
  Format:
    addtext(Arg1,Arg2,...)
  Returns:
    A text string with the arguments concatenated.
  Args:
    Any number of text strings.

  This instruction returns text containing the first argument followed by the second, followed by the third, etc. The arguments may be constants or variables containing text.

  ### Example:

      var/T
      T = "1"
      T = addtext(T,"*1 = ",T)  // T = "1*1 = 1"
      world << "The answer is: [T]"

  This instruction exists primarily for backwards-compatibility. You can accomplish the same thing with the + operator or by using embedded expressions.

  ## alert proc

  See also:
  input proc
  Format:
    alert(Usr=usr,Message,Title,Button1="Ok",Button2,Button3)
  Returns:
    Selected button

  This sleeps the current proc until the user clicks one of the named buttons. As with input(), the first argument may be entirely left out.

  ### Example:

      mob/verb/self_destruct()
         alert("Prepare to die.")
         del usr

  A slightly more complicated example provides the user with a choice in the matter:

  ### Example:

      mob/verb/self_destruct()
         switch(alert("Would you like to die?",,"Yes","No","Maybe"))
            if("Yes")
               del usr
            if("No")
               usr << "You have second thoughts."
            if("Maybe")
               usr << "You flip a coin..."
               if(rand(0,1))
                  usr << "Heads -- you lose."
                  del usr
               else
                  usr << "Tails -- you win!"

  ## alist proc

  See also:
  list associations
  list
  list proc
  values_sum proc
  values_product proc
  values_dot proc
  values_cut_over proc
  values_cut_under proc
  Format:
    alist(A=a,B=b,C=c,...)
  Returns:
    A new associative list with contents (keys) A, B, C, and associated values a, b, c.
  Args:
    Arbitrary number of elements to be inserted into the associative list.

  Creates a strictly associative list with key,value pairs. This is different from an ordinary list in several respects.

  - "Keys" can be numbers. This means list items can't be accessed by a numerical index.
  - Keys can't be repeated in the list, and always have an associated value (even if it's just null).
  - The order of keys in the list is not under user control.

  The point of using this type over a regular list is to eke out performance gains in tight code. Operators such as `+` and `-` have improved performance because of the rules above.

  In this proc the index values should be constants, and that usually means text constants. When these index values happen to be text strings that satisfy all the requirements for variable names, this may also be written in a convenient short-hand without the double quotes:

      var/alist/lst = alist(player = "James Byond", score = 2000)

  In other words, this is exactly the same syntax as for named arguments.

  ## animate proc

  See also:
  vars (atom)
  Format:
    animate(Object, var1=new_value1, var2=new_value2, ..., time, loop, easing, flags, delay, tag, command)
    animate(Object, appearance=new_appearance, time, loop, easing, flags, delay, tag, command)
    animate(Object)
  Args:
    Object: The atom, image, or client to animate; omit to add another step to the same sequence as the last `animate() call
    var1=new_value1, var2=new_value2, ...: Vars to change in the animation step
    var_list: An associative list of vars to change
    appearance: New appearance to use instead of multiple var changes (must be a named argument
)
  time: Time of this step, in 1/10s (may be a named argument)
  loop: Number of times to run this sequence, or -1 to loop forever (may be a named argument)
  easing: The "curve" followed by this animation step (may be a named argument)
  flags: Flags that impact how the animation acts (may be a named argument)
  delay: Delay time for starting the first step in a sequence (may be negative; may be a named argument)
  tag: Optional name for a new animation sequence (must be a named argument)
  command: Optional client command to run at the end of this step

  This proc creates an animation step, which may be the start of a sequence of multiple steps, that will be displayed to players. Starting with an atom or image, you can change one or more vars that affect its apprearance. This change will take place immediately, but will be displayed to users as a gradual change over a period of time. The actual interpolation between frames is all done on the client.

  If the `Object` argument is left out, a new animation step will be created for the previously used animation seqeunce. If all other arguments besides the object are left out, the animation is stopped completely.

  ### Example:

      mob/proc/GrowAndFade()
          // expand (scale by 2x2) and fade out over 1/2s
          animate(src, transform = matrix()*2, alpha = 0, time = 5)

      obj/spell/proc/Spin()
          // cast a spell on a monster: make the icon spin
          // this animation takes 3s total (6 ticks * 5)
          animate(src, transform = turn(matrix(), 120), time = 2, loop = 5)
          animate(transform = turn(matrix(), 240), time = 2)
          animate(transform = null, time = 2)

  The following vars will animate smoothly:

  - alpha
  - color
  - glide_size
  - infra_luminosity
  - layer
  - maptext_width, maptext_height, maptext_x, maptext_y
  - luminosity
  - pixel_x, pixel_y, pixel_w, pixel_z
  - transform

  These vars can be changed, but will change immediately on each step rather than smoothly:

  - dir
  - icon
  - icon_state
  - invisibility
  - maptext
  - suffix

  Other vars may apply:

  - space: A named var for the color space, if animating color; only applies to non-matrix color values.

  For convenience, you can use an associative list, appearance, or mutable appearance in place of the appearance vars. You can use `appearance` itself as a name for this argument, or leave the argument unnamed.

  ### Easing

  An animation step doesn't have to be strictly linear. Some changes look much better if they follow a curve. A cubic curve, for instance, will start slow, accelerate very quickly in the middle, and slow down again at the end. A sine curve could be used with a flip transformation to make a coin appear to spin. A text bubble can jump into place and bounce a little before it settles. The choice of curve you use is called easing, and you have several good choices to pick from.

  Time →
  EASE_IN
  EASE_OUT

LINEAR_EASING
  Default. Go from one value to another at a constant rate.
SINE_EASING
  The animation follows a sine curve, so it starts off and finishes slowly, with a quicker transition in the middle.
CIRCULAR_EASING
  Similar to a sine curve, but each half of the curve is shaped like a quarter circle.
QUAD_EASING
  A quadratic curve, good for gravity effects.
CUBIC_EASING
  A cubic curve, a little more pronounced than a sine curve.
BOUNCE_EASING
  This transitions quickly like a falling object, and bounces a few times.
  Uses `EASE_OUT` unless otherwise specified.
ELASTIC_EASING
  This transitions quickly and overshoots, rebounds, and finally settles down.
  Uses `EASE_OUT` unless otherwise specified.
BACK_EASING
  Goes a little bit backward at first, and overshoots a little at the end.
JUMP_EASING
  Jumps suddenly from the beginning state to the end. With the default or `EASE_OUT`, this happens at the end of the time slice. With `EASE_IN`, the jump happens at the beginning. With both flags set, the jump happens at the halfway point.

These can be combined with `EASE_IN` or `EASE_OUT` using the `|` operator, to use just the first or last part of the curve.

### Example:

    obj/coin/proc/Spin()
        var/matrix/M = matrix()
        M.Scale(-1, 1)  // flip horizontally
        animate(src, transform = M, time = 5, loop = 5, easing = SINE_EASING)
        animate(transform = null, time = 5, easing = SINE_EASING)

    obj/speech_bubble/New(newloc, msg)
        icon = 'bubble.dmi'

        var/obj/O = new
        O.maptext = msg
        O.maptext_width = width
        O.maptext_height = height
        overlays = O

        // start below final position and jump into place
        pixel_z = -100
        alpha = 0
        animate(src, pixel_z = 0, alpha = 255, time = 10, easing = ELASTIC_EASING)

Some easing functions may overshoot one line or the other, so it's fully possible to have a `pixel_w` value, for instance, animate from 0 to 100 but actually end up briefly outside of that range during the animation.

### Flags

Any combination of these flags may be used for animation (use `+` or `|` to combine them):

`ANIMATION_END_NOW`
  Normally if you interrupt another animation, it transitions from its current state. This flag will start the new animation fresh by bringing the old one to its conclusion immediately. It is only meaningful on the first step of a new animation. If using the `tag` argument, only a previous sequence with the same matching tag is stopped.
`ANIMATION_LINEAR_TRANSFORM`
  The transform var is interpolated in a way that preserves size during rotation, by pulling the rotation step out. This flag forces linear interpolation, which may be more desirable for things like beam effects, mechanical arms, etc.
`ANIMATION_PARALLEL`
  Start a parallel animation sequence that runs alongside the current animation sequence. The difference between where the parallel sequence started, and its current appearance, is added to the result of any previous animations. For instance, you could use this to animate pixel_y separately from pixel_x with different timing and easing. You could also use this to apply a rotational transform after a previous animation sequence did a translate. (When using this flag, the src var may be included, but it is optional.) This flag is implied if using the `tag` argument for a named sequence.
`ANIMATION_RELATIVE`
  The vars specified are relative to the current state. This works for maptext_x/y/width/height, pixel_x/y/w/z, luminosity, layer, alpha, transform, and color. For transform and color, the current value is multiplied by the new one. Vars not in this list are simply changed as if this flag is not present. (If you supply an appearance instead of individual vars, this flag is meaningless.)
`ANIMATION_CONTINUE`
  This flag is equivalent to leaving out the `Object` argument. It exists to make it easier to define an animation using a for loop. If `Object` differs from the previous sequence, this flag will be ignored and a new sequence will start.
`ANIMATION_SLICE`
  Following a series of `animate()` calls, you can view just a portion of the animation by using `animate(object, delay=start, time=duration, flags=ANIMATION_SLICE)`. The `loop` parameter may optionally be included. The `delay` is the start time of the slice, relative to the beginning of all the active animations on the object. (That is, earlier animations that have concluded will not be included.) You can call the proc again with a different slice if you want to see a different portion of the animation. A negative value for `time` will remove the slice and finish any existing animations.
`ANIMATION_END_LOOP`
  Tells previous animation sequences to stop looping and end naturally. The delay for starting this new sequence is adjusted based on that. If using the `tag` argument, only a previous sequence with the same matching tag is told to stop looping.

### Filters

Filters can be animated too. If you want to animate a filter, you need to specify the filter to be animated. If the last call to `animate()` used the same object as this filter, or a different filter for that object, then this will be treated as a new step in the same animation sequece. Likewise, if the last `animate()` call was to a filter, and this call is for the object that filter belonged to, again it will be treated as a continuation of the sequence.

### Example:

    atom/proc/BlurFade()
        filters += filter(type = "blur", size = 0)
        // Animating a filter of src
        animate(filters[filters.len], size = 5, time = 10)
        // Switching back to src to animate the next step
        animate(src, alpha = 0, time = 2.5)

### Named sequences

The `tag` argument allows you to refer to an animation sequence by name. This is useful for being able to replace or stop a previous animation sequence with the same name, but leaving other parallel sequences alone.

The `ANIMATION_PARALLEL` flag is always implied when using a named sequence. However, a named sequence will always supersede an earlier sequence with the same name, so you can't have two sequences with the same name running concurrently.

Stopping a named sequence is as simple as calling `animate(Object, tag=name)` with no other arguments.

### Client commands

If the `command` argument is present, a command will run on the client when this step ends. If this is part of a looping sequence, it will run each time. (If for any reason an entire loop runs in between client ticks, those loops will be ignored.)

The purpose of this is to synchronize events on the client, such as the .sound command, that otherwise couldn't be matched to the animation.

Using `[[*]]` in the command will expand it to a reference to the object being animated. (If this is a filter, it references the object that owns the filter.) The reference will be in the same format output by ref(), without quotes.

### Example:

    obj/bouncing_ball/New()
        // this is only here to ensure the sound is included in resources
        var/static/bounce = 'bounce.ogg'
        var/sound_command = @".sound 'bounce.ogg' atom=[[*]] transform=1,0,0,0,0.707,0.707,0,0,0 falloff=10"

        animate(src, pixel_z=16, easing=QUAD_EASING|EASE_OUT, time=5, loop=-1)
        animate(pixel_z=0, command=sound_command, easing=QUAD_EASING|EASE_IN, time=5)

## arccos proc

See also:
  arcsin proc
  arctan proc
  cos proc
  turn proc

Format:
  arccos(X)

Returns:
  The inverse cosine of X in degrees.

### Example:

    mob/verb/test()
       usr << arccos(0)        // 90
       usr << arccos(0.707107) // 45
       usr << arccos(1)        // 0

## arcsin proc

See also:
  arccos proc
  arctan proc
  sin proc
  turn proc

Format:
  arcsin(X)

Returns:
  The inverse sine of X in degrees.

### Example:

    mob/verb/test()
       usr << arcsin(0)        // 0
       usr << arcsin(0.707107) // 45
       usr << arcsin(1)        // 90

## arctan proc

See also:
  arcsin proc
  arccos proc
  tan proc
  turn proc

Format:
  arctan(Num)
  arctan(x, y)
  arctan(Vector)

Args:
  Num: A number
  x, y: 2D coordinates
  Vector: A vector (only 2 dimensions are used)

Returns:
  The inverse tangent in degrees.

When `arctan` is called with just one number argument, the number is a tangent, and the return value is the angle that produces that tangent. The resulting angle can range from -90 to 90.

The two-argument form returns a polar angle from -180 to 180. This angle starts at 0° for due east, and increases counter-clockwise from there. Therefore 1,0 has an arctangent of 0°, 0,1 is 90°, -1,0 is 180°, and so on. At point 0,0 the angle is undefined since it could be any angle, but `arctan` will return 0.

Finally, you can use a vector instead of a number. Only the x and y components of a vector will be used.

### Example:

    mob/verb/test()
       usr << arctan(0)        // 0
       usr << arctan(1)        // 45
       usr << arctan(sqrt(3))  // 60

       // polar coordinates
       usr << arctan(3, 4)     // 53.1301
       usr << arctan(-1, 1)    // 135
       usr << arctan(0, -5)    // -90

Here's another example, in which a rotating turret points to a target on another tile.

    mob/turret
       proc/PointAt(atom/target)
          if(!target) return
          var/dx = target.x - x
          var/dy = target.y - y
          // turret's icon normally faces east
          transform = matrix().Turn(-arctan(dx, dy))

## arglist proc

See also:
  arguments (proc)
  call proc
  call_ext proc
  list proc

Format:
  arglist(List)

Args:
  List: a list to be used as the arguments to a procedure

Normally, if you were to pass a list directly to a procedure, it would only come through as a singe argument to that procedure. In some cases, you might instead want the items in the list to become the arguments to the procedure. That is what `arglist()` achieves.

If the items in the list are associations, these are treated as named arguments. Each such list item is matched against the names of the procedure arguments and its associated value is assigned to that parameter.

Most built-in DM instructions do not support use of `arglist()`, but all user-defined procedures automatically support it. The built-in instructions which support named arguments will also support `arglist()`.

The following example shows how to use `arglist()` with both positional parameters and named arguments. Both of these examples could be replaced by a much simpler direct call without need for a list to hold the arguments; this is just to illustrate the syntax.

### Example:

    proc/MyProc(a,b)
       usr << "MyProc([a],[b])"

    mob/verb/test()
       var/lst = list(1,2)
       MyProc(arglist(lst))  //MyProc(1,2)

       lst = list(b=2,a=1)   //just to illustrate that order does not matter
       MyProc(arglist(lst))  //MyProc(b=2,a=1)  -->  MyProc(1,2)

## arguments (proc)

See also:
  named arguments (proc)
  path operators
  arglist proc
  args var (proc)

The parameters to a proc are referred to as arguments. To define argument variables, place them inside the ()'s in the proc definition. A default value may be specified. Otherwise, arguments default to null.

### Example:

    proc/Sum(a,b)
      return a + b

### Example:

    proc/set_mob_desc(mob/M,desc="big and bad")
      M.desc = desc
      world << "The new desc for [M] is [desc]."

Note how the variable type may be specified. It is just like any other variable definition, except "`var/`" is implicit and does not need to be typed.

## named arguments (proc)

See also:
  New proc (atom)
  arglist proc
  arguments (proc)

The parameters passed to a procedure are called arguments. These may either be passed in positional order, or they can be passed as named arguments. Not all procedures are defined with the intention of supporting named arguments, so consult the documentation for the procedure in question first. (This is mainly an issue of whether the argument names might change in the future.)

The following example shows several ways of producing the same call to a procedure.

### Example:

    mob/proc/MyProc(a,b,c)
    	src << "MyProc([a],[b],[c])"

    mob/verb/test()
    	MyProc(1,2,3)       //positional parameters
    	MyProc(a=1,b=2,c=3) //named arguments
    	MyProc(1,b=2,c=3)   //positional and named arguments
    	MyProc(c=3,a=1,b=2) //named arguments can come in any order

To prevent silent errors, named arguments that do not match any of the arguments of the procedure being called will generate a runtime error. This is somewhat different from the behavior of positional arguments in DM where it is perfectly acceptable to pass more arguments than were explicitly defined in the procedure.

As always, arguments that are not assigned in the call will simply be given the value null (or whatever default value is specified in the definition).

When an object procedure is overridden, the variable names in the new definition are the ones that get matched against named arguments in a call to that procedure. A procedure which is intended to support named arguments should therefore be defined with care so as to conform to the interface expected by users of the procedure. That doesn't stop you from changing that interface when overriding a procedure, but the normal case would be to preserve the argument names of the base procedure when overriding it.

The following example is not useful, but it illustrates a situation where a procedure is overridden so as to preserve the same argument names and positions. As mentioned above, you are not required to preserve either the names or positions, but that is usually what you want.

### Example:

    mob
       proc/MyProc(a,b,c)
          usr << "mob.MyProc([a],[b],[c])"

       mob/verb/test()
          MyProc(a=1,b=2,c=3)

       special_mob
          MyProc(a,b,c,d)
             if(d) ..()      //pass in same order
             else ..(c,b,a)  //pass in reverse order

          test()
             MyProc(a=1,b=2,c=3,d=0) //normal order
             MyProc(a=1,b=2,c=3,d=1) //reverse the order

This example merely used positional parameters in the call to `..()`, but one can use named arguments there too if it is desirable.

The best time to use named arguments is when calling a procedure that takes a lot of optional parameters. You can just name the ones that you want to assign and leave the rest unspecified. Trying to do the same thing with positional parameters can be much more awkward–especially when the arguments you do want to assign are preceded by a number of ones that you don't care to assign. It's easy to lose your place in the list or to forget what it does.

Since named arguments involve a slight amount of extra overhead, one should avoid them in code that is highly cpu intensive due to being called many many times. Otherwise, code clarity may be a bigger priority.

## ascii2text proc

See also:
  entities (text)
  text2ascii proc

Format:
  ascii2text(N)

Returns:
  A text string.

Args:
  N: A number.

ASCII codes are numerical values corresponding to keyboard and special characters. Among other things, they are used to represent many symbols in HTML. This proc converts an ASCII code to its corresponding text representation.

### Example:

    T = ascii2text(65)  // = "A"

BYOND now supports Unicode via UTF-8 encoding, so you can use the character code for any valid Unicode character, not just ASCII.

## astype proc

See also:
  istype proc
  __IMPLIED_TYPE__ macro

Format:
  astype(Val,Type)
  astype(Val)

Returns:
  Val if Val is derived from Type; null otherwise.

Args:
  Val: An object instance.
  Type: An object prototype or instance. If no type is specified, it will be implied (see below).

Forcibly casts an object to a type, returning null if it isn't valid.

### Example:

    astype(gift, /obj/potion)?.Drink()

Similarly to `istype()`, the type can be implied. The implied type is determined as follows:

1. If `astype()` is on the right-hand side of an assignment operation, the left-hand side's var type is the implied type, just like with the `new()` operator.
2. Otherwise, the var type of the first argument is the implied type, just as it is in `istype()`.

### Example:

    // if obstacle is of type /obj/box, it will be assigned to B; otherwise B is null
    var/obj/box/B = astype(obstacle)
    if(B?.closed) B.Open()

    // B is assigned no matter what, but astype() will return null if it isn't an /obj/box
    B = obstacle
    if(astype(B)?.closed) B.Open()

## block proc

See also:
  list

Format:
  block(Start,End)
  block(StartX,StartY,StartZ, EndX=StartX,EndY=StartY,EndZ=StartZ)

Returns:
  The list of turfs in the 3D block defined by Start and End (inclusive).

Args:
  Start: A turf to be the lower-left corner of the block.
  End: A turf to be the upper-right corner of the block.
  StartX, StartY, StartZ: XYZ coordinates of the lower-left corner of the block.
  EndX, EndY, EndZ: XYZ coordinates of the upper-right corner of the block.

The following example shows how to loop over a block of turfs.

### Example:

    world
       maxx = 20
       maxy = 20

    mob/verb/block_test()
       var/turf/T
       for(T in block(locate(1,1,1), locate(10,10,1)))
          T.text = " "

In the version that uses coordinates directly instead of two turfs, you can leave any of the EndX, EndY, or EndZ values as null, and omit the last arguments entirely; they will default to using the corresponding StartX, StartY, or StartZ. Therefore this example is equivalent to the one above:

### Example:

    world
       maxx = 20
       maxy = 20

    mob/verb/block_test()
       var/turf/T
       for(T in block(1,1,1, 10,10))
          T.text = " "

## bound_pixloc proc

See also:
  pixloc
  pixloc var (atom)
  pixloc proc
  bound_width var (movable atom)
  bound_height var (movable atom)

Format:
  bound_pixloc(Atom, Dir)

Returns:
  A `pixloc` object representing a corner, side, or center of atom bounds.

Args:
  Atom: An atom.
  Dir: The side or corner to use, or 0 for center.

Creates a new `pixloc` object based on an existing object's bounds. If either `bound_x` or `bound_y` are nonzero, then `bound_pixloc(atom, SOUTHWEST)` will differ from `atom.pixloc`.

If the atom is not directly on the map, this value is null.

### Example:

    mob/verb/DistanceTo(atom/A)
        var/my_center = bound_pixloc(src, 0)
        var/A_center = bound_pixloc(A, 0)
        var/vector/V = A_center - my_center
        return length(V)

## bounds proc

See also:
  obounds proc
  pixloc
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  icon_w var (atom)
  icon_z var (atom)
  step_x var (movable atom)
  step_y var (movable atom)
  locs list var (movable atom)
  Pixel movement
  bounds var (client)

Format:
  bounds(Ref=src, Dist=0)
  bounds(Ref, x_offset, y_offset, extra_width=0, extra_height=0)
  bounds(x, y, width, height, z)

Returns:
  A list of atoms (except areas) within the given bounding box.

Args:
  Ref: A turf, obj, mob, pixloc, or a pair of pixlocs as two arguments.
  Dist: A number (distance in pixels).
  x_offset, y_offset: Shifts bounding box position
  extra_width, extra_height: Adjusts bounding box size
  x, y, z: Lower left corner of bounding box in absolute coords; x=1,y=1 is lower left of map
  width, height: Size of bounding box in absolute coords

To leave Ref out of the results, use obounds() instead.

Calling bounds() will default to bounds(src,0), if src is a turf, obj, or mob. This returns all turfs, objs, and mobs (including src) within src's bounding box. If a single pixloc is used for Ref, it will have no width or height; you can use a pair of pixlocs instead to get a block between two pixlocs.

Changing the distance will return all objects within that distance from the bounding box. E.g., bounds(turf,12) will show you everything within 12 pixels of that turf.

An object's bounding box can also be offset. bounds(src,-6,0) shows what src would touching if it moved 6 pixels west. bounds(turf,-12,-12,24,24) is equivalent to bounds(turf,12).

In the final form, bounds() can use absolute coordinates and does not need an object to be Ref. Absolute coordinates start at 1,1 at the lower left corner of the map, by tradition.

Note: A vector may be used in place of any x/y or width/height pair.

## bounds_dist proc

See also:
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)
  bounds proc
  Pixel movement

Format:
  bounds_dist(Ref, Target)

Returns:
  The distance, in pixels, between Ref's and Target's bounding boxes.

Args:
  Ref: A turf, obj, or mob.
  Target: A turf, obj, or mob.

The value returned by bounds_dist() is the number of pixels that the two objects would have to move closer together (if this is even possible, of course) to be touching but not overlapping.

A return value of 12 for instance means the two objects have a gap of 12 pixels between them.

A return value of 0 means the two objects are not overlapping, but their bounding boxes touch.

A return value of -2 means the two objects are overlapping by 2 pixels; they would have to move 2 pixels apart to separate.

## break statement

See also:
  continue statement
  do proc
  for loop proc
  while proc
  switch proc
  #pragma syntax directive

Format:
  break
  break Label

Terminate the loop with the given label. If no label is specified, the innermost loop containing the `break` statement is assumed.

### Example:

    obj/zapper
      verb/use()
        var/mob/M

        for(M in view())
          if(!M.key) break

        if(!M) M = usr
        M << "ZAP!"
        del(M)

The zapper object kills the first mob it finds that doesn't belong to a player. If none can be found, it kills the user. Be careful! Note how this code takes advantage of the fact that the loop variable M will be `null` if the loop terminates normally.

For an example of how to use labeled loops, see the reference section for the `continue` statement.

The `break` statement can also be used inside of a `switch()` proc when using C-like syntax, where it breaks out of a `case` block to the end of the switch. See switch proc for more details.

## browse proc

See also:
  << output operator
  browse_rsc proc
  file proc
  link proc
  run proc
  output proc

Format:
  usr << browse(Body,Options)

Args:
  Body: html text, file, or null to close the browser.
  Options: optional parameters

This sends the html text or file to the user and optionally displays it in the web browser. The default action is to use the embedded browser panel in the Dream Seeker window; specifying an alternate window name (see below) causes it to appear in a popup window. Passing in 'null' for the html text causes the browser panel or named window to be closed.

The option parameters should either be omitted or they should be in a text string of the following format: `"window=name;file=name;display=1;
size=300x300;border=0;can_close=1;
can_resize=1;can_minimize=1;titlebar=1"`

You may use commas (,), ampersands (&), or semicolons (;) as the delimiter. Any or all of the parameters may be specified and they may be included in any order.

### General options

These control how to handle the text or file.

window
  This is the name used to identify the popup window. It is not visible to the user. Multiple calls to browse() with the same window name overwrite previous contents of the same popup window. If window is not specified, the embedded browser panel will be used.
file
  When this is unspecified, the client will store the generated html file in the user's byond "cache" directory with an appropriate name. If Body is a text string, the client will generate a unique name. If it is a file, it will use the name of the file. You can override this by setting this parameter. This is only useful when you need to reference the file later, typically in tandem with the display setting below.
display
  This controls whether the browser actually displays Body in the web browser or not. If it is turned off (display=0), the text or file is simply sent to the user and expected to be referenced later. This might be useful, for instance, to first send an image to a user and then display a web page that uses that image:

      usr << browse('monster.png',"display=0")
      usr << browse("<img src=monster.png>A scary monster appears from the mist!")

  Note that this performs the same function as the browse_rsc proc (preserved for legacy reasons). It is a little more powerful because you can use it to send html text as well as files. In that case, you'll have to also supply the file=name argument so that you can reference the html text from within a later browse().

  When display=0, all of the other arguments besides file are ignored.

### Popup options

These control how the popup window initially appears. Setting these parameters for an existing popup window or the embedded browser has no effect.

border
  This is the width of the border between the edges of the dialogue and the window content. The default value is 0, meaning that the entire window is filled with html content.
size
  This is the size of the popup window in pixels. The format is `WIDTHxHEIGHT`.
can_close
  This specifies whether the window should be closable. The default value is 1, which enables the standard "X" button for closing.
can_resize
  This controls whether the window is resizable. The default value is 1, enabling resizing and maximizing.
can_minimize
  This controls whether the window is minimizable. The default value is 1, enabling the standard minimization button.
titlebar
  The default titlebar=1 enables the standard bar at the top of the window. Turning it off disables can_close and can_minimize.

Note also that many display options can be controlled through the html itself. For instance, to turn off the scrollbars, you can do: `<body scroll=no>`; to add a title, you can do: `<head><title>My Title</title></head>`; and so forth.

The following example displays a help page in a popup window.

### Example:

    var/const/help = {"
    <html>
    <head><title>Help!</title></head>
    <body>

    You are beyond help!

    </body>
    </html>
    "}
    client/verb/help()
       usr << browse(help,"window=help")

You can use commands like output() and winset() to interact with popups. The name of the window is the same name you gave the popup, and the browser is "[windowname].browser".

### Example:

    client/verb/more_help()
       usr << output("You are still beyond help!", "help.browser")

## browse_rsc proc

See also:
  browse proc

Format:
  usr << browse_rsc(File,FileName)

Args:
  File: a resource file (such as an image)
  FileName: name of file (if different from source file)

This sends the specified resource file to usr (or anybody else) and stores it in their `cache` directory with the specified name. In subsequent `browse()` output, you can then refer to that file.

If your world is always running on the internet, you can save yourself the trouble and simply link to the image files through a web server. However, if it may be played offline, you can compile in the resource files and manually send them to players with `browse_rsc()`.

Note that no data is transmitted if it already exists in the user's cache, so there is little overhead in calling this every time you are about to use `browse()`.

### Example:

    area
       var
          room_graphic = 'cozy_room.jpg'
       Enter(O)
          . = ..() //do default checks
          if(.)    //if we got clearance to enter
             O << browse_rsc(room_graphic,"room.jpg")
             O << browse("<p><img src=room.jpg></p>[desc]")

## call proc

See also:
  arglist proc
  call_ext proc
  hascall proc
  path operators

Format:
  call(ProcRef)(Arguments)
  call(Object,ProcName)(Arguments)
  call(LibName,FuncName)(Arguments) (use `call_ext()` instead)

Args:
  ProcRef: path of proc (/proc/MyProc)
  Object: source of proc or verb
  ProcName: name of proc or verb ("MyProc")
  LibName: name of external library ("test.DLL")
  FuncName: name of function in external library ("func")

Returns:
  The return value of the proc being called.

This instruction exists in order to call procs dynamically, since the proc reference or name may be an expression rather than a hard-coded value. This may serve the same purpose as a "function pointer" in C programs.

The following examples do not demonstrate why you would want to do this, but the syntax is illustrated. The first one calls a specific procedure by using a path reference to that procedure.

### Example:

    /proc/MyProc(Arg)
       usr << "MyProc([Arg])"
    mob
       var
          MyProc = /proc/MyProc
       verb
          call_myproc()
             call(MyProc)("Hello, world!")

The next example calls an object procedure (or verb) by name, rather than by path.

### Example:

    mob
       proc
          Proc1(Arg)
             usr << "Proc1([Arg])"
          Proc2(Arg)
             usr << "Proc2([Arg])"
       verb
          call_proc(Proc in list("Proc1","Proc2"))
             call(src,Proc)("Hello, world!")

Note: In prior versions, `call()` was also used to access third-party libraries (.DLL files on Windows, .SO files on Unix), but this has been moved to call_ext() for clarity.

## call_ext proc

See also:
  load_ext proc
  arglist proc
  call proc
  path operators
  Byondapi

Format:
  call_ext(LibName,FuncName)(Arguments)
  call_ext(LoadedFunc)(Arguments)

Args:
  LibName: name of external library ("test.DLL") (note: the .dll or .so suffix is not required)
  FuncName: name of function in external library ("func"), which may have prefixes to describe the type of function
  LoadedFunc: reference to a function that was loaded via `load_ext()`

Returns:
  The return value of the external library function.

This instruction exists in order to access third-party libraries (.DLL files on Windows, .SO files on Unix), as long as the one or more of the following conditions is met:

- The library is located in the BYOND user `bin/` folder (`~/.byond/bin` on Unix, typically `%APPDATA%/Documents/BYOND/bin/` on Windows). This is intended to allow the user to install permanently "trusted" libraries. OR
- The server is run in `-trusted` mode. OR
- The server grants permission to access the library at runtime, through a prompt query.

If the library access or lookup fails for any reason, a runtime error will be thrown.

Normally you use LibName and FuncName, and `call_ext()` will look up the function for you. However you can save a little time by using `load_ext()`, which will do the lookup once and let you reuse the reference to that function as often as you need to, which should be helpful for performance-hungry code.

### String version

The standard way of making external calls (and until version 515, the only way) uses strings for everything. Any arguments that are not strings are passed as empty strings instead. The call is prototyped in the DLL this way:

    extern "C" char *func(unsigned int argc, char *argv[]);

The `argc` argument is a number of arguments, and `argv` is an array of the arguments themselves. The integer must be 32-bit.

As the library prototype is `char**`, the `call_ext()` arguments must be strings. Other types (like numbers) will be passed as the empty string (`""`) into the library function.

### Example:

    // test.dll, a win32 C++ library compiled in VC++:
    #include <string.h>
    // This is an example of an exported function.
    // Windows requires __declspec(dllexport) to be used to declare public symbols
    // The name of the function from within the dll may be compiler-dependent
    // (in this case it will usually be "merge" or "_merge").
    // Google "name decoration" for more information on this exciting topic.
    extern "C" __declspec(dllexport) char *merge(int n, char *v[])
    {
        static char buf[500];
        *buf=0;
        for(int i=0; i<n; i++) {
            strcat(buf,v[i]); // we should bounds-check but it's a stupid example!
        }
        return buf;
    }

    // DM code to use test.dll
    mob/verb/test()
        usr << call_ext("test.dll","merge")("fee","fi","fo") // returns "feefifo"

    // As with the other call() versions, arglist() may be used to do runtime arguments:
    mob/verb/argtest()
        var/L = list("fee","fi","fo")
        usr << call_ext("test.dll","func")(arglist(L)) // returns "feefifo"

The `char *` pointer returned by the library is expected to be cleaned up by the library when it's unloaded, or it can be cleaned up on a subsequent function call. BYOND makes a copy of the string when the function returns and does not need it after that.

### Byondapi version

A newer and more flexible way of calling external libraries is now available, and it allows you to pass strings, numbers, and references, and also get other types of valus in return. This uses Byondapi and requires your external library to be compiled with the `byondapi.h` header file (if using C or C++). Byondapi also includes helpful C++ wrapper classes in separate files.

With Byondapi calls, the function name you use in `call_ext()` should be prefixed by `byond:` so that the engine knows what type of function it is. In your library, the call is prototyped like so:

    extern "C" CByondValue func(u4c argc, CByondValue argv[]);

The `u4c` type is an unsigned 32-bit integer, defined in `byondapi.h`. `CByondValue` is also defined there. Interacting with a CByondValue structure requires the functions exported as part of Byondapi.

### Example:

    // test_byondapi.dll, a win32 C++ library compiled in VC++:
    #include <byondapi.h>
    #include <stdlib.h>
    #include <string.h>

    // a different take on the merge example above
    extern "C" BYOND_EXPORT CByondValue merge(u4c n, CByondValue v[])
    {
        CByondValue result;
        u4c buflen = 1024;  // initial size of buffer
        u4c totallen = 0;   // length of total string so far (not including trailing null)
        char *buf = (char*)malloc(buflen);

        if(!buf) {  // we couldn't allocate memory
            ByondValue_Clear(&result);
            return result;
        }

        for(int i=0; i<n; i++) {
            u4c len = buflen - totallen;    // # of bytes left in buffer
            bool success = Byond_ToString(v[i], buf+totallen, &len);
            // on success, len is filled with # of bytes written (including trailing null)
            if(success) {
                totallen += (len-1);
            }
            // if we failed but len > 0, it's the new size of the buffer we need
            else if(len) {
                len = (len + 1023) & ~1023; // round up to 1K increments
                char *newbuf = (char *)mallloc(len);
                if(!newbuf) {   // out of memory; stop here
                    ByondValue_Clear(&result);
                    return result;
                }
                memcpy(newbuf, buf, totallen+1);    // include trailing null in copy
                free(buf);
                buf = newbuf; buflen = len;
                --i;  // retry Byond_ToString() for this argument
            }
            // if we failed but len == 0, there was an error
            else {
                free(buf);
                ByondValue_Clear(&result);
                return result;
            }
        }
        ByondValue_SetStr(&result, buf);    // create a new internal string
        free(buf);  // free the buffer
        return result;
    }

    extern "C" BYOND_EXPORT CByondValue average(u4c n, CByondValue v[])
    {
        CByondValue result;
        float total = 0.0f;
        int count = 0;
        for(int i=0; i<n; i++) {
            if(!ByondValue_IsNum(v[i])) continue;
            total += ByondValue_GetNum(v[i]);
            ++count;
        }
        if(count) ByondValue_SetNum(&result, total / count);
        else ByondValue_Clear(&result); // return null on failure
        return result;
    }

    // DM code to use test_byondapi.dll
    mob/verb/test()
        usr << call_ext("test_byondapi","byond:merge")("fee","fi","fo") // returns "feefifo"

    mob/verb/average()
        usr << call_ext("test_byondapi","byond:average")(1,6,8)  // returns 5

You are of course allowed to mix different argument types, so they don't all have to be numbers or all strings. Your library code can use the Byondapi functions to interact with these values.

### Reference counting in Byondapi

Reference counting in Byondapi is done by calling `ByondValue_IncRef()` to increment the reference count, and `ByondValue_DecRef()` to decrement the count (and possibly initiate garbage collection). If you use the C++ wrappers, a lot of this is taken care of for you via the `ByondValue` class (see below).

Byondapi calls that fill pointers or arrays with results will automatically increment the reference count, so for instance the value that goes into the result for `Byond_ReadVar()`, or every value received in `Byond_ReadList()`, has been incremented. You will need to clean these references up when you're done with them.

The value you return from your library function back to DM should be incremented. If you got it from a function like `Byond_ReadVar()` then that's already been done for you.

You don't have to call `ByondValue_DecRef()` on any of the arguments sent to your function. Their reference counts will be decremented when the call returns to DM.

### C++ wrappers

The C++ wrapper file included for Byondapi defines a new `ByondValue` class that handles all your reference counting for you. All of the functions are wrapped so you send them a `ByondValue` reference instead of a `CByondValue` pointer. Anything that can fail with an error can throw an exception for you to catch.

The `ByondValue` class contains a referenced `CByondValue`. The destructor calls `ByondValue_DecRef()` for you. You can manage references in a few ways:

- `Assign()` or the `=` operator assigns a new value. It increments the new value's reference count and decrements the old value.
- `Attach()` sets a new value by adopting an existing reference. When you call this, the new value is not incremented, but the old one is still decremented.
- `Detach()` clears out this structure and sets it to null, but returns the old value; the old value's reference count doesn't get decremented.
- The `ByondValue(CByondValue)` constructor is an attach constructor.

The value you send back to a call from DM should have a reference. Therefore you can't return a `ByondValue` directly, since the destructor will decrement the reference count. Instead, your return type should be `ByondValueResult`. When `ByondValue` is cast to `ByondValueResult`, it calls `Detach()` for you. Alternatively, you can return a `CByondValue` but call `Detach()` manually.

This is what your function would look like with the C++ wrappers:

    extern "C" BYOND_EXPORT ByondValueResult average(u4c n, ByondValue v[])
    {
        float total = 0.0f;
        int count = 0;
        for(int i=0; i<n; i++) {
            if(!ByondValue_IsNum(v[i])) continue;
            total += ByondValue_GetNum(v[i]);
            ++count;
        }
        return count ? ByondValue(total / count) : ByondValue();  // return null on failure
    }

Here's a different example reading from a list:

    extern "C" BYOND_EXPORT ByondValueResult addstrings(u4c n, ByondValue v[])
    {
        if(!n) return ByondValue(); // not given a list

        std::string str;
        std::vector list = Byond_ReadList(v[0]);

        for(int i=0; i<list.size(); i++) {
            str += list[i].ToString();
        }
        return ByondValue(str);
    }

Because every value is defined as a `ByondValue` rather than a `CByondValue`, they clean up after themselves. The return value gets cast to `ByondValueResult` so it automatically detaches, meaning the reference count doesn't go down. The caller will use this reference and decrement it later.

### Asynchronous Byondapi calls

For Byondapi, there is also an asynchronous version you can call. In `call_ext()` or `load_ext()` the function name should be prefixed with `byond,await:` instead of `byond:`, and the function in your library has a different format.

    extern "C" void async_func(u4c argc, CByondValue argv[], CByondValue waiting_proc);

The function has no return value, and accepts a third argument which is the /callee object of the calling proc. Your BYOND proc will sleep when it calls `call_ext()` for this function. In your library function you would typically either spawn a new thread or pass `waiting_proc` to an existing thread. When it's ready to return, you call `Byond_Return(waiting_proc, return_value)`.

### Example:

    extern "C" BYOND_EXPORT void Sleep2sec(u4c n, CByondValue v[], CByondValue waiting_proc)
    {
        std::thread t([](CByondValue waiting_proc) {
            CByondValue result;
            std::this_thread::sleep_for(std::chrono::seconds(2));
            ByondValue_SetNum(&result, 1);
            Byond_Return(waiting, result);
        }, waiting_proc);
        t.detach();
    }

    // this call will sleep until the library calls Byond_Return()
    usr << "Sleeping now..."
    usr << call_ext("mylib", "byond_await:Sleep2sec")()

When `Byond_Return()` is called, the sleeping proc is added to the scheduler as if it had been spawned. This is the same behavior you would see in a call such as `winget()` that has to wait for a response.

### Other prefixes

For advanced users: on Windows, `call_ext()` uses the `__cdecl` convention by default. If you are designing or linking to a DLL that uses the `__stdcall` convention instead, you can inform `call_ext()` by prefacing the function name with the `"@"` symbol. E.g., `call_ext("test.dll","@merge")` would call a version of `merge` declared with the `__stdcall` convention. Likewise if you use the Byondapi version, you can use `call_ext("test.dll","@byond:merge")` or `call_ext("test.dll","byond:@merge")` (it doesn't matter which order the prefixes go in).

## ceil proc

See also:
  floor proc
  round proc
  trunc proc
  fract proc
  sign proc

Format:
  ceil(A)

Returns:
  the ceiling of A

Args:
  A: A number, pixloc, or vector.

Returns the ceiling of A (the largest integer greater than or equal to A).

### Example:

    usr << ceil(1.45) // outputs 2

    usr << ceil(-1.45) // outputs -1

## ckey proc

See also:
  ckeyEx proc
  ckey var (mob)
  savefile

Format:
  ckey(Key)

Args:
  Key: The player key to convert to canonical form.

Returns:
  The key in canonical form. To do this, it strips all punctuation and space from the key and converts to lowercase. The result is still unique for each different key.

The result could be used as a unique directory name in a server-side save file. Each player could be stored in a separate directory. By converting to canonical form, possible problems resulting from punctuation (like the path delimiter '/') in the key would be avoided. If players are saved in stand-alone files, it could be equally useful for generating a unique file name.

Note that this may be used on any text string. It is not just limited to keys.

### Example:

    var/savefile/SaveFile = new("world.sav")
    proc/SavePlayer(mob/M)
      var/keydir = ckey(M.key)
      SaveFile.cd = "/players"
      SaveFile.cd = keydir
      M.Write(SaveFile)

    proc/LoadPlayer(mob/M)
      var/keydir = ckey(M.key)
      SaveFile.cd = "/players"
      if(!SaveFile.Find(keydir)) return 0
      SaveFile.cd = keydir
      M.Read(SaveFile)
      return 1

This example defines two procs for saving and loading players to a server-side file. These could be called in mob.Login() and mob.Logout(). Notice that instead of calling SaveFile.Write(M), this example instead calls M.Write(SaveFile) directly. The difference is that in this example we did not want a new mob to be created when loading the player but instead wanted to load information into an existing mob.

In this example, the ckey() proc was used, but it would be more efficient to use mob.ckey, which is the same value precomputed.

## ckeyEx proc

See also:
  ckey proc

Format:
  ckeyEx(Text)

Args:
  Text: The text string to convert to case-sensitive canonical key form.

Returns:
  The same text stripped of all punctuation and space. Unlike, ckey(), case is preserved as are the '-' and '_' characters.

The true canonical form of a key is in all lowercase, but occasionally, it is nice to preserve case when stripping a key (or other text) of any special characters.

Note: This proc used to be named `cKey`, like `ckey` but with a capital k. To avoid confusion it has been renamed, but old code will still compile with a warning.

## clamp proc

See also:
  min proc
  max proc

Format:
  clamp(Value, Low, High)
  clamp(List, Low, High)

Args:
  Value: A number, text, pixloc, or vector (or null, treated as 0).
  List: A list of values.
  Low: The lowest value that can be returned.
  High: The highest value that can be returned.

Returns:
  A copy of the original Value, constrained between Low and High.
  The original List, whose contents have all been clamped.

"Clamps" a value, usually a number, to a given allowable range from `Low` to `High`. If the value is already in that range, it is unchanged. Otherwise, the closer of `Low` or `High` is returned.

If the `Low` and `High` values are out of order, it doesn't matter.

This is effectively equivalent to `min(max(Value, min(Low,High)), max(Low,High))`, but slightly faster.

### Example:

    usr << clamp(5, 0, 10)  // 5; it falls between 0 and 10
    usr << clamp(-1, 0, 10) // 0; it is less than 0
    usr << clamp(20, 0, 10) // 10; it is more than 10

If the compared items are objects such as pixlocs or vectors, the result of clamping them is a new object, not one of the objects that was compared.

The list format will accept a list in place of a value as the first argument, and it behaves as if you looped through the entire list and ran `clamp()` on each value. Please note the original list will be modified. If you want to leave the original list alone, use the `Copy()` proc to pass a copy to `clamp()` instead.

## cmptext proc

See also:
  cmptextEx proc

Format:
  cmptext(T1,T2,...)

Returns:
  1 if all arguments are equal; 0 otherwise.

Args:
  Any number of text strings to compare.

This instruction is NOT sensitive to case. It also ignores the `\proper` and `\improper` text macros. The case-sensitive version is cmptextEx().

### Example:

    if(cmptext("Hi","HI"))
       world << "Equal!"
    else
      world << "Not equal!"

This outputs "Equal!" since "Hi" and "HI" are the same, ignoring case.

## cmptextEx proc

See also:
  cmptext proc

Format:
  cmptextEx(T1,T2,...)

Returns:
  1 if all arguments are equal; 0 otherwise.

Args:
  Any number of text strings to compare.

This instruction is sensitive to case. The case-insensitive version is cmptext().

Because identical text is internally combined to conserve memory, cmptextEx(T1,T2) is equivalent to (T1 == T2).

### Example:

    if(cmptextEx("Hi","HI"))
       world << "Equal!"
    else
      world << "Not equal!"

This outputs "Not equal!" since "Hi" and "HI" are different when taking case into account.

Note: This proc used to be named cmpText, like cmptext but with a capital T. To avoid confusion it has been renamed, but old code will still compile.

## continue statement

See also:
  break statement
  do proc
  for loop proc
  while proc

Format:
  continue
  continue Label

Begins the next iteration of the loop with the given label. If no label is specified, the innermost loop containing the continue statement is assumed.

In a `for(Init,Test,Inc)` loop, the `continue` statement will jump to the `Inc` portion (if any) and move on to the conditional `Test`. In a `for(item in list)` loop, it will skip to the next item in the list. In a `while` or `do-while` loop, `continue` jumps to the condition in the `while` statement.

### Example:

    client/verb/who()
      var/mob/M
      usr << "Players:"
      for(M in world)
        if(M == usr) continue
        if(M.key) usr << M.key

This displays a list of players who have a mob in the world. The `continue` statement is used here to avoid including the user in the list. The same thing could have been achieved by using only the `if` statement. In more complicated situations, however, very long conditional expressions and deeply nested `if` statements can be avoided by using `continue` and its companion `break`.

Here is an example using a label to continue an outer loop from inside an inner one:

     client/verb/loners()
      var/mob/M
      var/mob/G

      usr << "Loners:"
      finding_loners:
        for(M in world)
          for(G in world)
            if(M in G.group) continue finding_loners

          //found a loner
          usr << M.name

This displays a list of mobs who do not belong in anyone else's group. Notice the syntax for labeling a list. The name of the block is simply placed in the code followed by a colon and its contents are indented inside it.

## copytext proc

See also:
  splicetext proc
  findtext proc
  splittext proc
  trimtext proc
  Copy proc (list)

Format:
  copytext(T,Start=1,End=0)

Returns:
  A text string.

Args:
  T: A text string.
  Start: The text byte position in which to begin the copy.
  End: The text byte position immediately following the last character to be copied.

Copy characters in T between Start and End. The default end position of 0 stands for `length(T)+1`, so by default the entire text string is copied.

### Example:

    pre = copytext("Hi there",1,3))// = "Hi"
    post = copytext("Hi there",4)) // = "there"

If the start or end position is negative, it counts backwards from the end of the string.

### Example:

    post = copytext("Hi there",-5)) // = "there"

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `copytext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## cos proc

See also:
  arccos proc
  sin proc
  tan proc
  turn proc

Format:
  cos(X)

Returns:
  The cosine of X, where X is in degrees.

### Example:

    mob/verb/test()
       usr << cos(0)  // 1
       usr << cos(45) // 0.707...
       usr << cos(90) // 0

## del proc

See also:
  Del proc (datum)
  garbage collection
  refcount proc

Format:
  del Object

Args:
  Object: Any data object (datum, savefile, world, you name it)

Destroy an object and null out all references to it. Procs that are executing with `src` equal to that object are silently killed, causing execution to return to the caller. If that is not what you want, you should detach the proc from the source object by setting `src` to `null`.

When an object is deleted, its Del() procedure is called. Currently, if the Del() procedure does not execute the default action (by calling ..()), then the deletion of the object is aborted. You should not depend on this, as it may change. In other words, be sure to always call the default handler after doing your own stuff.

### Example:

    mob/Del()
       src << "Aaaaaaaah!"
       ..()
    mob/verb/self_destruct()
       del usr

While manual object deletion is useful in many cases, the search for live references to an object does take some time. The more active objects in the world, and the more variables in those objects, the longer the search will take. For larger projects, this search time can become significant. In these cases, as a best practice, manual deletion should be avoided by ensuring that all references to an object are taken care of when the need for object destruction arises. Objects that have no references are deleted automatically without the need for a search. See garbage collection for more details.

## do proc

See also:
  break statement
  continue statement
  for loop proc
  while proc

Format:
  do Statement while( E )

Execute Statement. If E is true (non-zero) do it over again. Continue until E is false (zero).

Statement may be a block of code or a single statement.

### Example:

    var/i = 3
    do
      world << i--
    while(i)

This outputs:

    3
    2
    1

## EXCEPTION proc

See also:
  try and catch statements
  throw statement
  exception
  stddef.dm file

Format:
  EXCEPTION(value)

Args:
  value: A text string (such as an error message) or other value identifying the exception.

This is used to create an /exception datum, and is shorthand for calling new/exception(value, __FILE__, __LINE__). The value you provide will be in exception.name.

## fcopy proc

See also:
  fcopy_rsc proc
  shell proc

Format:
  fcopy(Src,Dst)

Args:
  Src: file to copy
  Dst: new copy to make

Returns:
  1 on success; 0 otherwise.

Src may be either a cache file, a savefile, or the name of an external file. Cache files are specified in single quotes and external files are in double quotes. If the path to the destination file does not already exist, it will be created.

If the source and target are paths ending in "/", the contents of the source directory (including sub-directories) will be copied to the target path.

This instruction could be useful when players upload files (like code) that you might want to dump to an external file.

### Example:

    mob/verb/change_world(F as file)
      fcopy(F,"world.dm")
      shell("DreamMaker world")
      world.Reboot()

This (somewhat dangerous) example allows players to upload code, recompile, and reboot the world. It assumes that DreamMaker is in the path where the shell looks for executable files and also that the name of the running world is world.dmb.

## fcopy_rsc proc

See also:
  cache
  fcopy proc
  file proc
  load_resource proc

Format:
  fcopy_rsc(File)

Args:
  File: file to copy into the resource cache

Returns:
  reference to the file as a cache entry

The file to copy may either be a file name (text string) or the return value of file() operating on the same. If a cache entry is passed as the argument, it will simply be returned with no action necessary.

Once a file has been copied into the resource cache (i.e. the world's .rsc file), it may be used as an icon or a sound or whatever is appropriate. Most internal operations involving resource files automatically perform this operation when you try to use an external file in place of a cache entry. For example, when assigning a file() object to atom.icon, fcopy_rsc() is implicitly invoked.

The main reason you would ever want to call this explicitly is if you are storing references to resource files in your own data structures and you want to ensure that all values are converted to cache entries so they may be directly compared to one another.

## fdel proc

See also:
  shell proc

Format:
  fdel(File)

Args:
  File: name of file to delete

Returns:
  1 on success; 0 otherwise.

If the specified file ends in '`/`', it is treated as a directory. Any contents (including sub-directories) are deleted as well.

Be careful!

## fexists proc

See also:
  flist proc
  ftime proc
  length proc

Format:
  fexists(File)

Args:
  File: name of file to test

Returns:
  1 if file exists; 0 otherwise.

## file proc

See also:
  << output operator
  fcopy_rsc proc
  ftp proc
  isfile proc
  link proc
  run proc
  savefile
  sound proc

Format:
  file(Path)

Returns a file object corresponding to the named file. This file object can then be used in a variety of ways. One would be to send it to a player to view using the browse() instruction. Output may also be appended to the file using the << operator.

Note that the file exists in the external filesystem (ie the hard disk) and not the cache. That means the path is specified in double quotes and will be evaluated at run-time rather than compile-time. The file need not exist at compile time and may even be modified at a later date. This is the principle reason for using a file in the filesystem rather than a cached resource file (specified in single quotes).

### Example:

    mob/verb/help()
      usr << browse(file("help.html"))

Many DM instructions that deal with files treat file("name") and "name" the same. There are cases such as browse() where a simple text string is not interpreted as a filename; it is in those situations where file() is really necessary.

## file2text proc

See also:
  shell proc
  text2file proc

Format:
  file2text(File)

Args:
  File: file to read

Returns:
  the contents of the file.

This can be useful when interacting with external applications that generate output in a text file. For example, you might have an external program that mimics conversation:

### Example:

    mob/oracle/verb/tell(T as text)
      text2file(T,"talk.in")
      shell("talk < talk.in > talk.out")
      usr << file2text("talk.out")

## filter proc

See also:
  filters var (atom)
  Filter effects

Format:
  filter(type = Type, parameter = Value, ...)

Creates a graphical filter that can be assigned or added to a list of filters on an atom or image.

This proc uses named arguments, and the "type" value must always be included. To see which types of filters are available and what parameters they accept, see Filter effects.

### Example:

    atom/proc/Highlight(apply)
        if(apply)
            filters = filter(type="outline", size=1, color=rgb(255,0,0))
        else
            filters = null

A filter created with this proc is an abstract filter; it is not associated with any atom. When you add it to atom's filters, the atom gets a copy of this filter, so changing the abstract filter's values afterward will not change the atom's filters. For the same reason, an abstract filter can't be animated.

A filter that is part of an atom's filters list, like obj.filters[1], is an attached filter. Changing the values for an attached filter will change how that atom is displayed, and attached filters can be animated.

### Named Filters

Filters can also be given a `name` argument, and can be referred to in an atom's `filters` list via that name (e.g. as `filters["shadow"]`) instead of a numeric index.

## findlasttext proc

See also:
  findtext proc
  findtextEx proc
  findlasttextEx proc

Format:
  findlasttext(Haystack,Needle,Start=0,End=1)

Returns:
  The last position of Needle in Haystack; 0 if not found.

Args:
  Haystack: The text string to search.
  Needle: The sub-text to search for.
  Start: The text byte position in Haystack in which to begin the search. Because this searches backwards, the default is the end of the string (0).
  End: The earliest position in Haystack that can be matched as a result.

This instruction is NOT sensitive to the case of Haystack or Needle. The case-sensitive version is findlasttextEx().

If the start or end position is negative, the position is counted backwards from the end of the string. E.g., findlasttext("Banana", "na", -3) starts three characters from the end and will skip over the last "na".

Note: Unlike findtext(), a regular expression may NOT be used as the Needle. Searching backwards is simply too complex for the regular expression engine.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `findlasttext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## findlasttextEx proc

See also:
  findtext proc
  findtextEx proc
  findlasttext proc

Format:
  findlasttextEx(Haystack,Needle,Start=0,End=1)

Returns:
  The last position of Needle in Haystack; 0 if not found.

Args:
  Haystack: The text string to search.
  Needle: The sub-text to search for.
  Start: The text byte position in Haystack in which to begin the search. Because this searches backwards, the default is the end of the string (0).
  End: The earliest position in Haystack that can be matched as a result.

This instruction is sensitive to the case of Haystack and Needle. The case-insensitive version is findlasttext().

If the start or end position is negative, the position is counted backwards from the end of the string.

Note: Unlike findtextEx(), a regular expression may NOT be used as the Needle. Searching backwards is simply too complex for the regular expression engine.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `findlasttextEx_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## findtext proc

See also:
  findlasttext proc
  findtextEx proc
  replacetext proc
  Regular expressions

Format:
  findtext(Haystack,Needle,Start=1,End=0)

Returns:
  The first position of Needle in Haystack; 0 if not found.

Args:
  Haystack: The text string to search.
  Needle: The sub-text to search for. May be a regular expression (regex).
  Start: The text byte position in Haystack in which to begin the search.
  End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is NOT sensitive to the case of Haystack or Needle. The case-sensitive version is findtextEx().

### Example:

    if(findtext("Hi There","there")==0)
      world << "Not found!"
    else
      world << "Found!"

This outputs "Found!", since "there" is a part of the string "Hi There", ignoring case.

If the start or end position is negative, the position is counted backwards from the end of the string. E.g., findtext("Banana", "na", -3) starts three characters from the end and only searches the final "ana".

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `findtext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## findtextEx proc

See also:
  findtext proc
  replacetextEx proc
  Regular expressions

Format:
  findtextEx(Haystack,Needle,Start=1,End=0)

Returns:
  The position of Needle in Haystack; 0 if not found.

Args:
  Haystack: The text string to search.
  Needle: The sub-text to search for. May be a regular expression (regex).
  Start: The text byte position in Haystack in which to begin the search.
  End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is sensitive to the case of Haystack and Needle. The case-insensitive version is findtext().

### Example:

    if(findtextEx("Hi There","there")==0)
      world << "Not found!"
    else
      world << "Found!"

This outputs "Not found!", since "there" is not a part of the string "Hi There", taking into account case.

If the start or end position is negative, the position is counted backwards from the end of the string. E.g., findtextEx("Banana", "na", -3) starts three characters from the end and only searches the final "ana".

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `findtextEx_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

Note: This proc used to be named `findText`, like `findtext` but with a capital T. To avoid confusion it has been renamed, but old code will still compile.

## flick proc

See also:
  icon_state var (atom)

Format:
  flick(Icon,Object)

Args:
  Icon: An icon file or state name.
  Object: The target object.

Cause the icon attached to Object to be temporarily replaced with the specified icon or icon state for the duration of the animation. This is a purely visual effect and does not effect the actual value of the object's icon variable.

### Example:

    flick('blink.dmi',usr) //show another icon
    flick("fight",usr)     //show usr's fight state

The target object may be any atom or image.

## flist proc

See also:
  fexists proc

Format:
  flist(Path)

Args:
  Path: The path in the filesystem to get a listing of.

Returns:
  A list of files contained in the specified directory and whose names begin with the specified text. The names of sub-directories are listed too, and are marked by a trailing "/".

The path is of the form "dir1/dir2/.../file". Only files beginning with the "file" part are listed, so be sure to end a directory name with "/" if you wish to see its contents. Otherwise you will just get that directory name back with a "/" appended.

Only files and sub-directories directly contained in the specified path are listed (ie not the contents of the sub-directories too). The file names in the list do not include the path information but just the bare file name.

## floor proc

See also:
  ceil proc
  round proc
  trunc proc
  fract proc
  sign proc

Format:
  floor(A)

Returns:
  the floor of A

Args:
  A: A number, pixloc, or vector.

Returns the floor of A (the largest integer less than or equal to A).

### Example:

    usr << floor(1.45) // outputs 1

    usr << floor(-1.45) // outputs -2

## for proc

See also:
  for list proc
  for loop proc

The for proc can be used to iterate values over a fixed range or list. Consult the appropriate entry for more information.

## for list proc

See also:
  for loop proc
  list
  list associations
  istype

Format:
  for (Var [as Type] [in List]) Statement
  for (Var in Start to End [step Step]) Statement
  for (Key [as Type], Value in List) Statement

Args:
  Var: A variable to sequentially contain each member of the list.
  List: The list to loop through. This defaults to the whole world.
  Type: One or more of area, turf, mob, or obj, ORed together. If no type is specified, the declared type of Var will be used to skip over inappropriate elements in the list.
  Start: A starting numeric value.
  End: An ending numeric value (inclusive).
  Step: An increment for the numeric value; default is 1.
  Key: A variable to sequentially contain each "key" in a key,value pair from an associative list
  Value: A variable to sequentially contain each associated value in a key,value pair list

### Example:

    usr << "Mobs:"
    var/mob/M
    for(M in view())
       usr << M.name

This loops M through the mobs in view(), outputting the name at each iteration.

When you loop through a list, with the exception of looping through world, you're actually looping through a copy of that list. If the list changes, those changes won't have any bearing on this loop. If you want to be able to handle a list that might change, you'll need to use the for loop proc instead.

You can declare the variable right inside the for statement. Its scope is entirely contained within the for statement, so it will not conflict with a similar variable declared elsewhere in the same procedure.

### Example:

    client/verb/who()
       for(var/client/Player)
          usr << Player

If the loop var has a type, a hidden `istype()` call is included in the code. Only items of that type, or its descendants, are handled within the loop. That means null values and objects of unrelated types will be skipped.

### Numeric loop

The numeric loop form is a quick internal version of the for loop proc. It's equivalent to `for(Var = Start, Var <= End, Var += Step)` unless Step is negative, in which case a >= comparison is used instead. The main difference is that unlike in a for loop proc, the values of Step and End are calculated at the beginning and never change after that, so an expression like `list.len` that might be subject to change will not be read again—in much the same way that looping through a list only loops through a copy of that list.

### Example:

    for(var/count in 1 to 100)
       src << count

Note: Although you can use fractional values for `step` in this numeric format, there may be accuracy considerations to keep in mind. See Numbers for more information.

### Key,value pair loop

The key,value pair loop is meant for quickly traversing the items in an associative list, without having to do an additional lookup of `List[Key]` in the list. Additionally this also copies the associated values when the list is copied, so the loop won't react to changes in the original list.

### Example:

    var/alist/prices = alist(/obj/item/weapon/sword = 100, /obj/item/armor/helmet = 50)
    player << "<b>Welcome to my shop!</b>"
    for(var/item,price in prices)
        player << "[item::name] - $[price]"

If the key var has a type, a hidden `istype()` call is included in the loop, just like in a regular `for(Var in List)` loop. You can also use the `as` clause to specify basic types like `obj`, `num`, `text`, etc.

If this format is used with non-associative lists, then the associated value will always be assigned null.

## for loop proc

See also:
  break statement
  continue statement
  do proc
  for list proc
  while proc

Format:
  for(Init, Test, Inc) Statement

First execute Init. Then if Test is true (non-zero), execute Statement. After this execute Inc. Continue checking Test, doing Statement, and performing Inc until Test turns out to be false (zero).

Statement may be a code block or a single statement. Semicolons may be substituted for commas inside the parentheses as a convenience to C/C++ programmers.

Init and Inc may be omitted. If Test is omitted, the loop will continue forever (unless a break, goto, or return instruction is used to get out of the loop).

### Example:

    var/i
    for(i=0, i<3, i++)
        world << i

This outputs:

    0
    1
    2

Note: An Inc statement like `i += 0.1` is perfectly valid, but you should keep in mind that numerical accuracy is not exact. See Numbers for more information.

### C-like syntax

Using the `#pragma syntax` directive you can change `for()` to be more like other languages such as C. This uses a semicolon `;` in place of commas to separate Init, Test, and Inc. Instead the comma is treated as a way of stringing multiple statements together.

### Example:

    // make this syntax change temporary
    #pragma push
    #pragma syntax C for

    var/i,j
    for(i=j=0; i<=10; ++i,j+=i)
        world << "A triangle [i] block\s high has [j] block\s total."

    #pragma pop

## fract proc

See also:
  trunc proc
  floor proc
  ceil proc
  round proc
  sign proc

Format:
  fract(A)

Returns:
  fractional part of A

Args:
  A: A number, pixloc, or vector.

Returns the fractional part of the number A, with the same sign. This is everything after the decimal point.

### Example:

    usr << fract(1.45) // outputs 0.45

    usr << fract(-1.45) // outputs -0.45

If A is a pixloc, it will be treated as a vector with just its x and y parts, and the result will be a vector.

## ftime proc

See also:
  time2text proc
  flist proc
  fexists proc
  length proc

Format:
  ftime(File, IsCreationTime)

Args:
  File: name of file to test
  IsCreationTime (optional): true to return file creation time, false (default) to return last-modified time

Returns:
  A time value that can be sent to time2text().

## ftp proc

See also:
  << output operator
  browse proc
  file proc
  link proc
  run proc
  sound proc

Format:
  target << ftp(File, Name)

Sends a file to the target with the (optional) suggested name for saving to disk. The file may be a cache file (loaded at compile time) or an external file (accessed at run-time). Cache files are specified in single quotes, and external files are in double quotes.

This function could be used to distribute source code, supplementary documentation, or anything.

### Example:

    mob/verb/geticon(O in view())
      usr << ftp(O:icon)

This example allows the user to download the icons from other objects in the game.

## generator proc

See also:
  Generators
  Particle effects
  color var (atom)
  Color matrix
  vector
  stddef.dm file

Format:
  generator(type, A, B, rand)

Args:
  type: The type of generator object, which determines what kind of results it produces
  A: One extreme of the generator results
  B: The other extreme
  rand: Type of random distribution used

Creates a generator that can be used to produce a random value. This generator can be used in client-side particle effects, or it can be used in proc code. The types of values it can produce are numbers, 2D or 3D vectors, or colors (a text string like "#rrggbb" or a color matrix).

Generator type | Result type | Description
--- | --- | ---
num | num | A random number between A and B.
vector | vector | A random vector on a line between A and B.
box | vector | A random vector within a box whose corners are at A and B.
color | color (string) or color matrix | Result type depends on whether A or B are matrices or not. The result is interpolated between A and B; components are not randomized separately.
circle | vector | A random XY-only vector in a ring between radius A and B, centered at 0,0.
sphere | vector | A random vector in a spherical shell between radius A and B, centered at 0,0,0.
square | vector | A random XY-only vector between squares of sizes A and B. (The length of the square is between A*2 and B*2, centered at 0,0.)
cube | vector | A random vector between cubes of sizes A and B. (The length of the cube is between A*2 and B*2, centered at 0,0,0.)

The optional `rand` argument determines the type of random distribution.

UNIFORM_RAND | Default. Random values are uniformly likely to be chosen.
NORMAL_RAND | Approximates a Gaussian normal distribution, but on a finite interval. Values closest to the mean are more likely to be chosen, while the extremes are much less likely.
LINEAR_RAND | The probability of choosing a number is proportional to its absolute value.
SQUARE_RAND | The probability of choosing a number is proportional to its square.

The result of calling `generator()` is a datum of type `/generator` and you can get a random value from it by calling its `Rand()` proc.

### Example:

    var/generator/G = generator("num", -1, 1)    // generates a random number between -1 and 1
    world << G.Rand()   // generate a number and output it to world

Note: Worlds compiled in older BYOND versions before vector will return lists from vector generators.

## get_dir proc

See also:
  dir var (atom)

Format:
  get_dir(Loc1, Loc2)

Returns:
  The direction from Loc1 to Loc2. Possible results are `NORTH`, `SOUTH`, `EAST`, `WEST`, `NORTHEAST`, `NORTHWEST`, `SOUTHEAST`, and `SOUTHWEST`.

Args:
  Loc1: An object on the map.
  Loc2: An object on the map.

If the direction is not directly lying along one of the four primary cardinal directions, the result will become the nearest diagonal direction (eg. if `Loc2` is mostly north but a little to the east of `Loc1`, the direction returned will be `NORTHEAST`).

## get_dist proc

See also:
  bounds_dist proc

Format:
  get_dist(Loc1, Loc2)

Returns:
  The distance between `Loc1` and `Loc2`, in tiles. This is the number of full-tile movements (disregarding any obstacles and allowing diagonal moves including across Z levels) required to go from one to the other. You can think of it as the max of their x, y, and z distances.

Args:
  Loc1: An object on the map.
  Loc2: An object on the map.

For a distance in pixels, use `bounds_dist()`.

`get_dist()` will return -1 when `Loc1` and `Loc2` are the same object. If one or both of them is not on the map, an infinite value is returned.

Note: Prior to BYOND 515, `get_dist()` never returned a value greater than 127, which it counted as "infinite".

## get_step proc

See also:
  step proc
  walk proc

Format:
  get_step(Ref, Dir)

Returns:
  The location of the new position.

Args:
  Ref: Starting point or object.
  Dir: One of `NORTH`, `SOUTH`, `EAST`, `WEST`, `NORTHEAST`, `NORTHWEST`, `SOUTHEAST`, `SOUTHWEST`.

Calculate the position of a step from `Ref` in the direction `Dir`.

## get_step_away proc

See also:
  step_away proc
  walk_away proc

Format:
  get_step_away(Ref, Trg, Max=5)

Returns:
  The location of the new position, or 0 if no change.

Args:
  Ref: Starting point or object.
  Trg: An object on the map.
  Max: The maximum distance between Ref and Targ before movement halts.

Calculate position of a step from `Ref` on a path away from `Trg`, taking obstacles into account. If `Ref` is farther than `Max` steps from `Trg`, 0 will be returned.

## get_step_rand proc

See also:
  step_rand proc
  walk_rand proc

Format:
  get_step_rand(Ref)

Returns:
  The location of the new position, or 0 if no change.

Args:
  Ref: Starting point or object.

Calculate position of a step from `Ref` in random motion.

## get_step_to proc

See also:
  step_to proc
  walk_to proc
  get_steps_to proc

Format:
  get_step_to(Ref, Trg, Min=0)

Returns:
  The location of the new position, or 0 if no change.

Args:
  Ref: Starting point or object.
  Trg: An object on the map.
  Min: The minimum distance between Ref and Trg before movement halts.

Calculate the position of a step from `Ref` on a path to `Trg`, taking obstacles into account.

If `Ref` is within `Min` steps of `Trg`, no step is computed. This is also true if the target is too far away (more than twice `world.view` steps). In either case, null is returned.

## get_step_towards proc

See also:
  step_towards proc
  walk_towards proc

Format:
  get_step_towards(Ref, Trg)

Returns:
  The location of the new position.

Args:
  Ref: Starting point or object.
  Trg: An object on the map.

Calculate the position of a step from `Ref` in the direction of `Trg`.

## get_steps_to proc

See also:
  step proc
  step_to proc
  walk_to proc
  get_step_to proc

Format:
  get_steps_to(Ref, Trg, Min=0)

Returns:
  A list of directions to step.

Args:
  Ref: Starting point or object.
  Trg: An object on the map.
  Min: The minimum distance between Ref and Trg before movement halts.

Calculate a set of steps from `Ref` on a path to `Trg`, taking obstacles into account. The result of the proc is a list of directions that can be used with `step()`, or null if a path could not be found.

If `Ref` is within `Min` steps of `Trg`, no steps are computed. This is also true if the target is too far away (more than twice `world.view` steps). In either case, null is returned.

## goto proc

See also:
  break statement
  continue statement
  do proc
  for loop proc
  for list proc
  while proc

Format:
  goto node

Jump to the specified node in the current proc.

### Example:

    goto End
    world << "ERR"
    End
    world << "The end"

This displays "The end".

Note: `goto` should be used judiciously. It's easy to fall into the trap of "spaghetti logic" where `goto` is relied on so much that it becomes too difficult to follow how the flow of code execution will proceed. Normally, you'll want to use a construct like `while()` or `for()` loops, and `break` and `continue` statements. `goto` is for more complex situations that aren't readily handled by any of these.

## gradient proc

See also:
  Color gradient
  rgb proc
  rgb2num proc
  Color space

Format:
  gradient(Item1, Item2, ..., index)
  gradient(Gradient, index)

Args:
  Gradient: A color gradient list
  Item1, Item2...: Elements of a color gradient list
  index: The index along the gradient where the interpolation is done.

Returns:
  A color, represented by a text string in #RRGGBB or #RRGGBBAA format

Interpolates between two or more colors along a color gradient. By default, gradients extend from an index of 0 to 1, but they are allowed to go beyond that if you choose.

The simplest way to use this proc is to interpolate between two colors:

### Example:

    // 20% of the way from red to black
    // prints #cc0000 which is rgb(204,0,0)
    src << gradient("red", "black", 0.2)

Anything that applies to color gradients can be used in this proc, so you can have a looping gradient, or a gradient that uses a color space other than RGB.

In the first format where you specify all the items separately, you can use named arguments for `index` and `space` (the gradient's color space). If you don't specify an argument called "index", the last argument is assumed to be the index.

### Example:

    // This gradient loops through all the hues and goes from 0 to 6.
    // Because this is a looping gradient, index=10 becomes index=4.
    // In HSL, this will give you blue (#0000ff).
    src << gradient(0, "#f00", 3, "#0ff", 6, "#f00", "loop", space=COLORSPACE_HSL, index=10)

The `gradient(Gradient, index)` format is used for cases where you want to pass an existing gradient to the proc.

### Example:

    var/candy_cane_gradient = list(0.5,"red",0.5,"white","loop")

    // the color output alternates between red and white depending on the current time
    src << gradient(candy_cane_gradient, world.time/100)

## hascall proc

See also:
  call proc

Format:
  hascall(Object,ProcName)

Args:
  Object: source of proc or verb
  ProcName: name of proc or verb ("MyProc")

Returns:
  1 if object has such a proc or verb; 0 otherwise

## hearers

See also:
  ohearers
  view proc
  viewers

Format:
  hearers(Depth=world.view,Center=usr)

This is just like `viewers()`, but it is a list of mobs that can hear the center object. Currently, this is computed on the assumption that opaque objects block sound, just like they block light.

## html_decode proc

See also:
  html_encode proc

Format:
  html_decode(HtmlText)

Args:
  HtmlText: text to be "unescaped"

Returns:
  unescaped text

Special characters such as < and > are not displayed literally in html and may produce garbled output. To display these characters literally, they must be "escaped". For example, < is produced by the code `&lt;` and > is produced by the code `&gt;`.

The `html_decode()` instruction takes a text string containing such escaped symbols and turns them into their literal counterparts. The more useful function is `html_encode()` which does the reverse.

## html_encode proc

See also:
  html_decode proc

Format:
  html_encode(PlainText)

Args:
  PlainText: text to be html "escaped"

Returns:
  escaped text

Special characters such as < and > are not displayed literally in html and may produce garbled output. If you want to ensure that an entire text string is displayed literally, you can "escape" those characters. For example, < is produced by the code `&lt;` and > is produced by the code `&gt;`.

The `html_encode()` instruction does this for you automatically. If you wanted to disallow html input from players, you could use this to force their text to be displayed literally:

### Example:

    mob/verb/say(T as text)
       view() << "[usr] says, '[html_encode(T)]'"

If a URL is included in the text, special characters like & that are part of the URL will be skipped. This keeps automatically created links in the output from being broken.

Note for BYOND oldies: the old-style formatting codes such as "\red" which are still parsed but not encouraged are completely stripped out by html_encode().

## icon proc

See also:
  file proc
  icon_states proc
  icons

Format:
  icon(icon,state,dir,frame,moving)
  (supports named arguments)

Args:
  icon: an icon file or /icon object
  icon_state: an optional text string, specifying a single icon state to load
  dir: an optional direction to extract
  frame: an optional animation frame to extract
  moving: Non-zero to extract only movement states, 0 for non-movement states, or null (default) for both

This is equivalent to new/icon(). It creates an /icon object, which is initialized to contain the same graphical data as the given file. If an icon state or direction are specified, only those parts of the original icon will be included in the new icon object.

## icon_states proc

See also:
  icons
  icon_size var (world)
  map_format var (world)
  Big icons
  Tiled icons

Format:
  icon_states(Icon, mode=0)

Returns:
  A list of text strings.

Args:
  Icon: the icon being accessed
  mode: applies to icons larger than one tile when using map_format=TILED_ICON_MAP; see below

Icons may have one or more internal states, which are identified by name. The state "" is the default.

If you are not using the TILED_ICON_MAP value for world.map_format, you can ignore the mode argument.

When graphics bigger than world.icon_size are used as an icon, and the map_format in use is TILED_ICON_MAP, they are internally broken up into tiles, one per icon state. The `mode` argument was added for big icons that get split into several smaller tiles. Those icons have several smaller states per true icon_state. For example if your 64×64 icon has a state named "open", it will contain states "open", "open 0,0", "open 1,0", "open 0,1", and "open 1,1" which are all used internally. (If the state name is blank, the sub-states are just "0,0", etc.) When using the TILED_ICON_MAP format, you need these for displaying the icon over several different atoms.

mode=0 will only show the sub-states ("open 0,0" and so on), all of which can be safely extracted in a single-tile icon via the `icon()` proc. mode=1 will show the main state names ("open"); any time you work with that state name you're working with the full-size icon. mode=2 will show all of the states.

## if proc

See also:
  goto proc

Format:
  if( E ) Statement1
  else if( E2 ) Statement2
  else Statement3

If the expression E is true (non-zero) then execute Statement1. Otherwise, test E2, etc. Finally, if none of the expressions are true, execute Statement3. The else nodes are all optional.

Statement1, Statement2, and Statement3 may be a single statement or a code block with optional braces: {}.

### Example:

    if(T==1) world << "TRUE"
    else world << "FALSE"

This will display "TRUE" if T has value 1, and "FALSE" otherwise.

## image proc

See also:
  << operator
  del proc
  icon
  image objects
  images var (client)
  overlays var (atom)

Format:
  image(icon,loc,icon_state,layer,dir)
  (supports named arguments)

Returns:
  An image reference on success; 0 on failure.

Args:
  icon: An icon, icon_state, object prototype, object instance, or other image.
  loc: The location at which to display the image.
  icon_state: The icon state to use.
  layer: The drawing layer to use.
  dir: The direction to orient the image.

Images are "virtual" objects, which have a purely visual effect. Once created, they can be made to appear to selected players. The image() instruction is simply a short-hand for new/image().

The image remains attached to the location specified by loc. For example, if loc is a mob, the image will appear above the mob until it is destroyed.

The `icon` argument can be anything that can be interpreted as an appearance, i.e. anything you might add to an overlays list. If this argument is interpreted as an appearance, it will be used instead of the appearance of the image type. A null value will use the image type's own default appearance. An icon value will use the default appearance but change the icon. A text string will be interpreted as the `icon_state` argument if one is not present, but otherwise will be interpreted as an appearance.

The arguments icon_state, layer, and dir may be used to override the settings associated with the icon or object used to create the image. For example, the default drawing layer for an plain icon is FLY_LAYER (above all other objects), but you could change this to OBJ_LAYER to make it appear under mobs on the map.

### Example:

    var/Box
    Box = image ('highlight.dmi', usr)
    usr << Box
    ...
    del(Box)  //when done, remove image

Another common use of images is in making an overlay:

    overlays += image('pants.dmi',icon_state = "red")

Since the `loc` argument could never be a text string, the above statement can be further shortened:

    overlays += image('pants.dmi',"red")

This is much preferable to achieving the same effect with `icon('pants.dmi',"red")`, since that involves the overhead of creating a new icon file, which should only be done when it is really necessary.

Note: The fact that `image` is essentially a wrapper for `new/image()` means that the arguments in image/New() are always treated the same way as defined in this article. This applies even to subtypes, like `/image/thing`. If you create a user-defined subtype like `new/image/thing()` it will still use the arguments the same way as in `image()`. You can't meaningfully customize the arguments in `New()` for images.

## initial proc

See also:
  :: operator
  issaved proc
  vars list var (datum)

Format:
  initial(Var)

Args:
  Var: A variable to find the initial value of.

This returns the original compile-time value of a variable. It could be used to reset a variable to its default value or to check if a variable has changed.

### Example:

    obj/verb/set_icon(I as null|icon)
       if(!I) I = initial(icon)
       icon = I

This example allows an object's icon to be modified. If the user does not specify a new icon, it will be reset to the original one.

## input proc

See also:
  alert proc
  arguments (verb)

Format:
  input(Recipient=usr,Message,Title,Default) as Type in List

Returns:
  User's response.

Args:
  Recipient: The user who will see this input prompt.
  Message: A message in the prompt, to tell the user what it's asking for.
  Title: The title of the prompt window.
  Default: Default value if the user cancels the input.
  Type: A verb input type, such as `text`, `message`, `num`, `anything`. If you omit "as Type", the type defaults to `text`.
  List: An optional list of items to choose from.

Creates a prompt dialog that asks the user for a response. The current proc sleeps until they respond.

The only required argument is the message. The type may be any combination of input types allowed for verb arguments, which can be combined with the `|` operator. The `null` type will allow the user to cancel, e.g. `as null | anything in contents`.

### Example:

    mob/verb/create_character()
       usr.name = input("Choose a name for your character.",
                        "Your Name",
                        usr.name)

       usr.gender = input("Select a gender for your character.",
                          "Your Gender",
                          usr.gender) in list("male","female","neuter")

If the target of the input prompt is not a player, the result will be the default value. If no default value is specified and null is allowed by the input type, null will be returned. Otherwise, an error will result, crashing the proc that called `input()`.

A more common use for `input()` is to give a player a list of things to choose from. For example, this is a simple shopkeeper NPC, where the shopkeeper's inventory is its contents.

### Example:

    mob/shopkeeper/verb/Buy()
       var/list/options = list()
       var/obj/item
       for(item in src)
          // show a pretty list of options with prices included
          options["[item]: $[item.price]"] = item
       var/choice = input("Buy something!", "Shop") as null|anything in options
       item = options[choice]
       if(!item) return     // user canceled
       if(item.price > usr.gold)
          usr << "You can't afford that."
       else
          // give the buyer a copy of the item
          var/t = item.type
          new t(usr)
          usr.gold -= item.price
          usr << "You bought \a [item] for $[item.price]."

Using `as num` is another popular input choice, which you might use for haggling, deciding how many of an item to pick up or drop, etc.

This next part is important! Always validate input from a user to make sure it's correct.

You should be sure to sanitize any user input to make sure the value is valid. For instance, if you have a verb that gives gold to another player, you should check that the amount isn't negative and doesn't contain any fractions, and isn't more than they have.

### Example:

    mob/player/verb/Give_Gold()
       set src in oview(1)
       var/amount = input("How much?", "Give gold") as null|num
       if(isnull(amount)) return
       amount = floor(amount)   // round down to a whole number
       amount = min(amount, usr.gold)   // don't give more than you have
       if(amount <= 0) return   // ignore negatives and 0
       gold += amount
       usr.gold -= amount
       usr << "You gave [src] $[amount]."
       src << "[src] gave you $[amount]."

Likewise if you're allowing a user to input text, it too should be sanitized. If they shouldn't enter multi-line text, you should strip out `"\n"` characters. If they're putting in something like a character name, strip out any HTML via `html_encode()`, or you can simply reject anything that contains invalid characters and make them do it again.

## isarea proc

See also:
  isloc proc

Format:
  isarea(Loc1, Loc2 ...)

Args:
  Any number of locations to test.

Returns:
  1 if all args are valid areas; 0 otherwise

## isfile proc

See also:
  cache
  file proc
  isicon proc

Format:
  isfile(File)

Args:
  File: the value to test

This returns a true value when given a file. Both objects returned by file() and files stored in the resource cache qualify.

## isicon proc

See also:
  cache
  icon
  isfile proc

Format:
  isicon(Icon)

Args:
  Icon: the value to test

Returns:
  1 if the value is a valid icon; 0 otherwise.

This returns a true value when given an icon. Both `/icon` memory objects and icon files stored in the resource cache qualify.

## isinf proc

See also:
  isnum proc
  isnan proc
  Numbers

Format:
  isinf(n)

Args:
  n: A number

Returns:
  1 if this is an infinite numeric value, either positive or negative; 0 otherwise

## islist proc

See also:
  list
  list proc

Format:
  islist(Object)

Args:
  Object: The value to test

Returns:
  1 if the object is a valid list; 0 otherwise.

Tests whether an object is a list. This includes user-defined lists, special lists like `contents` and `overlays`, and more.

## isloc proc

Format:
  isloc(Loc1, Loc2 ...)

Args:
  Any number of locations to test.

Returns:
  1 if all args are valid locs; 0 otherwise.

Tests validity of a location. If all arguments are mobs, objs, turfs, or areas, this returns 1.

For a single argument this is equivalent to: `(ismob(Loc) || isobj(Loc) || isturf(Loc) || isarea(Loc))`.

## ismob proc

See also:
  isloc proc
  ismovable proc

Format:
  ismob(Loc1, Loc2 ...)

Args:
  Any number of locations to test.

Returns:
  1 if all args are valid mobs; 0 otherwise

## ismovable proc

See also:
  isloc proc
  isobj proc
  ismob proc

Format:
  ismovable(Loc1, Loc2 ...)

Args:
  Any number of locations to test.

Returns:
  1 if all args are valid objs or mobs; 0 otherwise

Movable atoms are either objs or mobs, so this combines the `isobj` and `ismob` tests into a single proc.

## isnan proc

See also:
  isnum proc
  isinf proc
  Numbers

Format:
  isnan(n)

Args:
  n: A number

Returns:
  1 if this is a numeric value but is an invalid "not a number" (NaN); 0 otherwise

Some math operations return the special number `NaN` if they're undefined, such as dividing 0 by 0. This tells you if a number is that type.

NaN is never greater than, less than, or equal to another number, even itself.

## isnull proc

See also:
  null

Format:
  isnull(Val)

Returns:
  1 if Val is null; 0 otherwise

## isnum proc

See also:
  isinf proc
  isnan proc
  Numbers

Format:
  isnum(Val)

Returns:
  1 if Val is a number; 0 otherwise

## isobj proc

See also:
  isloc proc
  ismovable proc

Format:
  isobj(Loc1, Loc2 ...)

Args:
  Any number of locations to test.

Returns:
  1 if all args are valid objs; 0 otherwise

## ispath proc

See also:
  typesof proc

Format:
  ispath(Val)
  ispath(Val,Type)

Returns:
  single-argument: 1 if Val is a type path
  double-argument: 1 if Val is a type path derived from Type; 0 otherwise.

Args:
  Val: A type path.
  Type: A type path or instance.

### Example:

    var/M
    M = /mob/ugly/duckling
    if(ispath(M,/mob/ugly))  //true
    if(ispath(M))            //true
    if(ispath(new/mob))      //false

## ispointer proc

See also:
  * operator (pointers)
  & operator (pointers)

Format:
  ispointer(Value)

Args:
  Value: The value to test

Returns:
  1 if the value is a pointer; 0 otherwise.

Tests whether an value is a pointer.

Note: This does not check if the pointer is still valid, like for instance if the object it belongs to has been deleted, or if it points to a list index that is now out of bounds.

## issaved proc

See also:
  initial proc
  savefile
  tmp vars
  vars list var (datum)

Format:
  issaved(Var)

Args:
  Var: The variable to test.

This returns 1 if the given variable should be automatically saved when writing an object to a savefile and 0 otherwise. Variables which are not global, const, or tmp will return 1.

## istext proc

Format:
  istext(Val)

Returns:
  1 if Val is text; 0 otherwise

## isturf proc

See also:
  isloc proc

Format:
  isturf(Loc1, Loc2 ...)

Args:
  Any number of locations to test.

Returns:
  1 if all args are valid turfs; 0 otherwise

## istype proc

See also:
  ispath proc
  locate proc
  typesof proc
  astype proc
  __IMPLIED_TYPE__ macro

Format:
  istype(Val,Type)
  istype(Val)

Returns:
  1 if Val is derived from Type; 0 otherwise.

Args:
  Val: An object instance.
  Type: An object prototype or instance. If no type is specified and a variable was passed in as the first argument, it will default to the declared type of the variable.

If you don't have an object instance to test, but just want to see if one prototype derives from another one, use ispath() instead.

### Example:

    var/M
    M = new/mob/ugly/duckling()
    if(istype(M,/mob/ugly))  //this will be true
      usr << "[M] is ugly!"

Using implicit types, that same example can be rewritten as follows:

    var/mob/ugly/M
    M = new/mob/ugly/duckling()
    if(istype(M))  //this will be true
      usr << "[M] is ugly!"

## jointext proc

See also:
  splittext proc
  Join proc (list)

Format:
  jointext(List,Glue,Start=1,End=0)

Returns:
  A text string made up of the items in List, joined together by Glue.

Args:
  List: The list to be joined.
  Glue: The text that will go between each item.
  Start: The list item on which to begin.
  End: The list item immediately following the last item to be joined.
  include_delimiters: True if any delimiters found should be included in the result.

Any items in List that are not already text will be converted to text. The Glue string only goes between two items, so a single-item list is the same as converting that one item to text, and an empty list becomes an empty string.

### Example:

    var/list/items = list("apples", "oranges", "bananas")
    usr << jointext(items, ", ")

If the start or end position is negative, the position is counted backwards from the end of the list.

Calling List.Join(Glue,Start,End) is the same thing, as long as List is a valid list.

## json_decode proc

See also:
  json_encode proc

Format:
  json_decode(JSON)
  json_decode(JSON, flags)

Returns:
  A value interpreted from a JSON-formatted text string.

Args:
  JSON: The JSON-formatted text to decode.
  flags: A set of flags that tell the decoder how to act.

Arrays like `[1,2,3]` will be converted to regular lists like `list(1,2,3)`.

Object literals like `{"a":1}` will be converted to associative lists such as `list("a"=1)`. Each item in the list is also decoded. Except in strict mode, non-string values are allowed as the "keys" in an associaitve list, even though that's not valid JSON, and strings used as keys can be left unquoted. BYOND doesn't care, as long as it can understand the formatted text it's given. The only exception is that a number isn't allowed to be an associative list key, and will be converted to a string instead, so `{1:2}` becomes `list("1"=2)`.

Special numbers `NaN` and `Infinity` are recognized correctly (these are case-sensitive). All other numbers are parsed and stored in the regular BYOND format (32-bit floating point).

Since BYOND doesn't have dedicated boolean values, `true` and `false` are interpreted as 1 and 0, respectively.

The `JSON_STRICT` flag uses stricter JSON parsing rules and will not allow some things. In strict mode:

- All strings must be double-quoted.
- Special numbers `NaN` and `Infinity` are not allowed, but the `{__number__:"NaN"}` format used by `json_encode()` is recognized as a number.
- Keys in an associative list must always be strings, and must be double-quoted.

The `JSON_ALLOW_COMMENTS` flag allows you to include `//` single-line comments and `/* ... */` long-form comments in the text to be decoded. This can be mixed with the strict flag. This flag is now used by default.

## json_encode proc

See also:
  json_decode proc

Format:
  json_encode(Value)
  json_encode(Value, flags)

Returns:
  A JSON-formatted text string representing Value.

Args:
  Value: The value to encode.
  flags: A set of flags that tell the encoder how to act.

If Value is a simple list or a matrix, the result will be formatted as a JSON array, and each item in the list is encoded.

If Value is an associative list, the result will be formatted as a JSON object literal, and each item and associated value is encoded. (The keys in the object literal don't have to be strings. Even though that isn't valid JSON, BYOND doesn't care. Be aware however that strict JSON parsers will care.)

Datums are not serialized, but are converted to the equivalent of `"[Value]"` instead.

The special numbers NaN and infinity will be encoded as object literals in a form like `{"__number__":"NaN"}`.

### Example:

    var/list/info = list("name"="fridge", "power"=12)
    // send {"name":"fridge","power":12} to a JavaScript function
    usr << output(url_encode(json_encode(info)), "mybrowser:myJSfunction")

BYOND formatting such as \red is removed from encoded strings.

Situations where a list has a reference to itself will cause the nested version to print a null value instead.

The `JSON_PRETTY_PRINT` flag introduces spacing into the output for improved readibility. Spaces will be added after colons and commas. Non-empty arrays and object literals will have a line break and tabs before each item, and a line break with one fewer tab before the closing bracket or brace. (The special formatting for numbers like Infinity, or the list form for matrices, will not be given tabs and line breaks.)

## length proc

See also:
  vector

Format:
  length(E)

Returns:
  The length of the data associated with E.

Args:
  E: text, list, file, or vector

### Example:

    world << length("Hi")

This outputs, "2", the length of the string "Hi".

### Example:

    world << length(list(1,2,3))

This outputs, "3", the length of the list.

### Example:

    world << length(file("test.txt"))

This outputs the length of the file.

Note: In strings containing non-ASCII characters, this is the length in bytes, not characters; a character may span multiple bytes. Use `length_char()` to work with character counts instead of bytes. See the Unicode section for more information.

For vectors, the length is the order of the vector, as in 2 for a 2D vector or 3 for a 3D vector. See vector.len.

## lentext proc

See also:
  length proc

Format:
  lentext(T)

Returns:
  The length of text T.

Args:
  T: A text string.

Use length() instead.

## lerp proc

See also:
  vector
  pixloc
  Interpolate proc (matrix)

Format:
  lerp(A, B, factor)

Returns:
  An interpolated value between A and B

Args:
  A: A number, matrix, vector, or turf/pixloc.
  B: Another number, matrix, vector, or turf/pixloc.
  factor: Interpolation factor, usually 0 to 1

Returns an interpolation or extrapolation from A to B. If factor is 0, A is returned; if factor is 1, B is returned. Otherwise an interpolated value between A and B is returned, based on the value of factor. The types of A and B must match, with few exceptions.

This is basically equivalent to returning `A + (B-A) * factor` for most things. When interpolating objects such as vectors, the returned value is always a new value, never a direct copy of A or B.

### Example:

    usr << lerp(1, 5, 0.25)   // outputs 2

Turfs can be treated like pixlocs in `lerp()`, so you can interpolate between turfs. Note that they must have the same Z coordinate.

Matrix interpolation behaves according to the rules in the matrix Interpolate() proc. For linear interpolation you need to use `A + (B-A) * factor` instead.

## link proc

See also:
  << output operator
  Topic proc (client)
  file proc
  run proc

Format:
  O << link(url)

This causes the recipient (O) to view the specified url. The url could be a web or BYOND address. In the latter case, the player will disconnect from the current world and connect to the specified one.

The format of a BYOND url is as follows:

    byond://address:port?TopicData

To access a registered world, address:port may be replaced by the registered name in the hub. The optional topic data is processed by the world once the player has connected. If only a topic is specified, the current world processes it.

### Example:

    usr << link("byond://byond.com:6000") //BYOND address
    usr << link("http://www.byond.com")   //web address
    usr << link("?myTopic")                //topic

## list proc

See also:
  arglist proc
  list
  list associations

Format:
  list(A,B,C,...)
  or
  list(A=a,B=b,C=c,...)

Returns:
  A new list with contents A, B, C, and (optional) associated values a, b, c.

Args:
  Arbitrary number of elements to be inserted into the list.

Assign elements to a list.

### Example:

    var/L[]
    L = list(1,2,3)

This creates a new list 'L' that initially contains elements 1, 2, and 3. The length of L is 3.

The `list()` instruction may also be used to create associative lists.

### Example:

    var/list/lst = list("player" = "James Byond", "score" = 2000)

That creates a list with contents ("player, "score") and associated values ("James Byond", 2000) respectively.

The index values should be constants, and that usually means text constants. When these index values happen to be text strings that satisfy all the requirements for variable names, this may also be written in a convenient short-hand without the double quotes:

    var/list/lst = list(player = "James Byond", score = 2000)

In other words, this is exactly the same syntax as for named arguments.

## list2params proc

See also:
  Topic proc (client)
  list associations
  params var (world)
  params2list proc
  text2num proc

Format:
  list2params(List)

Args:
  List: List to encode as a text string.

This instruction converts a list of parameter names and associated values into a single text string suitable for use in a URL or similar situation. The format of the resulting text string is:

    "name1=value1&name2=value2&..."

Special characters such as '=' and '&' inside the parameter names or values are written in the form: `%xx` where `xx` are two hexadecimal digits representing the ASCII value of the character. For Unicode characters, their UTF-8 encoding will be processed this way, which may make up multiple `%xx` sequences. In addition, spaces are converted to `+`.

This parameter format is the same one used by most HTML forms and is known by the MIME type `application/x-www-form-urlencoded`. It is often used in DM to pack information into topic links.

The original list has items `"name1"`, `"name2"`, and so on. These in turn are associated with the corresponding values `"value1"`, `"value2"`, and so on.

### Example:

    var/plist[0]

    plist["offense"] = "jwalk"
    plist["time"] = "10:00"

    usr << list2params(plist)

The above example creates a simple parameter list which associates the item "offense" with the value "jwalk" and the item "time" with the value "10:00". This will produce the text string "offense=jwalk&time=10:00".

Object values in the list (like say a mob) get turned into references in the parameter text, just as though you had embedded them with "\ref[Object]". When read back in with params2list(), you could convert these values back into real references by using locate().

## load_ext proc

See also:
  call_ext proc
  Byondapi

Format:
  load_ext(LibName,FuncName)

Args:
  LibName: name of external library ("test.DLL") (note: the .dll or .so suffix is not required)
  FuncName: name of function in external library ("func"), which may have prefixes to describe the type of function

Returns:
  A reference to a function in an external library, for use with `call_ext()`.

Use `load_ext()` to pre-load external library functions you intend to use often, when maximum performance is required. (See call_ext() for the rules for loading libraries.)

The result of this proc can be passed to `call_ext()` as a single argument in lieu of the normal LibName and FuncName.

If the lookup fails for any reason, a runtime error will be thrown.

### Example:

    var/logfunc

    proc/LogLine(msg)
        logfunc ||= load_ext("my_lib", "byond:OutputToLog")
        call_ext(logfunc)(msg)

## load_resource proc

See also:
  << output operator

Format:
  Player << load_resource(File)
  Player << load_resource(File, KeepTime)
  Player << load_resource(File1, File2..., KeepTime1, File3, File4..., KeepTime2...)

Args:
  Player: A mob or client, a list of them, or world
  File: A resource file (image or sound)
  KeepTime: Minimum time (in seconds) to keep the file loaded; 0=default, -1=forever

Tells the player's client (or multiple players) to load the specified resources now, and how long to keep them. If you do not specify a keep time, 0 is used which will use the default time.

This may be useful for loading sounds into memory before they play, or to load an icon as soon as possible even if it hasn't been displayed yet. This can avoid delays later on when the resources are needed.

Dream Seeker keeps most assets loaded for at least 5 minutes (300 seconds) after their last use. However if you think a more appropriate time is closer to half an hour, you can set a keep time of 1800 seconds. Or if you want them to stay loaded indefinitely, set a keep time of -1.

### Example:

    mob/Login()
        ..()
        // load up these songs now and keep them loaded indefinitely
        src << load_resource('music1.ogg', 'music2.ogg', 'music3.ogg', -1)

In cases of extreme memory duress, Dream Seeker's garbage collector will get more aggressive and can still override your choices if need be.

## locate proc

See also:
  istype proc
  tag var (datum)
  __IMPLIED_TYPE__ macro

Format:
  locate(Type) in Container
  locate(X,Y,Z)
  locate(Tag)
  locate(TextRef)

Returns:
  An object of the specified type or the turf at the given coordinates. If a text string is given in place of an object type, the object with the same tag is found. If a container is given, only objects directly within that object are searched.

Args:
  Type: An object prototype or tag. If locate() is being used in an assignment to a variable with a declared type, this argument is optional and will default to the type of the variable being assigned.
  Container: An optional container object. (The default is `world`.)
  X,Y,Z: A set of numerical coordinates.
  Tag: The value of an object's tag variable (must be unique).
  TextRef: An embedded object reference created by the \ref text macro.

Types are matched in the same manner as istype(). In other words, locate(/obj) could return an instance of something derived from /obj, such as /obj/armor.

If there is more than one instance of the specified type, the first one found will be chosen.

### Example:

    var/mob/shopkeeper/M = locate()
    if(M)
      usr << "Found the shopkeeper."
    else
      usr << "Could not find the shopkeeper."

This looks for a mob of a type /mob/shopkeeper in the world (world.contents).

### Example:

    usr.Move(locate(/turf/Home))

This "teleports" the usr to a turf of the type /turf/Home.

### Example:

    usr.Move(locate(1,2,3))

This moves the usr to the turf at coordinates (x,y,z) = (1,2,3).

## log proc

See also:
  ** operator

Format:
  log(X,Y)
  log(Y)

Returns:
  The logarithm (base X) of Y. If X is not specified, a natural logarithm is computed (base 2.718...).

The logarithm is the power to which you have to raise X in order to get Y. In other words, the following is true (ignoring round-off error):

    X ** log(X,Y) == Y

One nice property of this function is that it gradually increases, with a slope that continuously tapers off. In other words, it can be useful to represent diminishing returns from some input, such as money, experience points, and so forth.

## lowertext proc

See also:
  uppertext proc

Format:
  lowertext(T)

Returns:
  A lowercase text string.

Args:
  T: A text string.

Make all of the characters of T lowercase.

### Example:

    L = lowertext("HI THERE") // = "hi there"

## matrix proc

See also:
  matrix
  transform var (atom)

Format:
  matrix()
  matrix(Matrix)
  matrix(a, b, c, d, e, f)
  matrix(x, y, MATRIX_SCALE)
  matrix(n, MATRIX_SCALE)
  matrix(angle, MATRIX_ROTATE)
  matrix(x, y, MATRIX_TRANSLATE)

Returns:
  A new matrix.

Args:
  Matrix: a matrix to copy
  a - f: The individual matrix components (in column-major order)
  x, y: Arguments affecting how the shortcut matrix format affects x and y
  n: The same value used for x and y together
  angle: Rotation angle in degrees, clockwise

If no arguments are provided, a new default (identity) matrix is created.

There are also several "shortcut" matrix calls that can be made:

matrix(x, y, MATRIX_SCALE)
matrix(n, MATRIX_SCALE)
  A scaling matrix, scaling either x and y independently or both together
matrix(angle, MATRIX_ROTATE)
  A matrix that rotates by the angle in degrees, clockwise
matrix(x, y, MATRIX_TRANSLATE)
  A matrix that translates by x and y

## max proc

See also:
  min proc
  clamp proc

Format:
  max(A,B,C,...)

Returns:
  the maximum of the arguments.

### Example:

    usr << max(1,2,3)

This example displays 3.

If a single argument is specified, this is expected to be a list and the maximum item from the list is returned.

Items to be compared may be numbers, text strings, pixlocs, or vectors, or null, but different types may not be mixed. (Null values can be mixed with nums or text, but that's the only exception.)

If the compared items are objects such as pixlocs or vectors, the result is a new object, not one of the objects that was compared.

## md5 proc

See also:
  sha1 proc
  file proc

Format:
  md5(T)
  md5(F)

Returns:
  text or null.

Args:
  T: A text string.
  F: A file.

This proc implements MD5 hashing. A hash function is a one-way process that compacts information to a short value: a hash. The same value will always have the same hash. Among other uses, most computers use hashing to store passwords. By storing just the hash, the password file contains very little sensitive information, but the password can still be verified by confirming that `md5(password)==hash`. MD5 is a widely-used hash function.

### Example:

    mob/var/hash

    mob/Read(savefile/S)
      ..()
      // hash was saved in the file along with other values
      if(md5("[level]/[exp]/[exp_needed]") != hash)
        src << "Cheater!"
        del(src)

In the example, a few vars belonging to a mob were saved along with a hash of those values. When the mob is loaded again, the game compares the hash to the values to make sure it's still accurate. If the values or hash had been changed by a sneaky player, they wouldn't match. (But a sneaky player could still calculate `hash` themselves if they knew the exact text used to make it, so this should be kept secret.)

If the argument is a file, `md5()` will read the file and return the MD5 hash of the file's entire contents. If the file doesn't exist, it returns null. The file may be a cache file or an external file.

### Examples:

    var/hash = "(insert hash value here)"	// Compute this ahead of time

    // Check that the cached default icon is still the same
    if (md5('default.dmi') != hash)
      world << "The default icon has been modified!"

    // Or check that the entire game resource file is pristine
    if (md5(file("mygame.rsc")) != hash)
      world << "The game resources have been modified!"

Note that you must pass the result of file() in order to compute the hash of an external file's contents at runtime. Otherwise `md5()` will treat the filename as text and return the hash of the name only.

If `T` is anything but a text string or file, the proc returns null.

## min proc

See also:
  max proc
  clamp proc

Format:
  min(A,B,C,...)

Returns:
  the minimum of the arguments.

### Example:

    usr << min(1,2,3)

This example displays 1.

If a single argument is specified, this is expected to be a list and the minimum item from the list is returned.

Items to be compared may be numbers, text strings, pixlocs, or vectors, or null, but different types may not be mixed. (Null values can be mixed with nums or text, but that's the only exception.)

If the compared items are objects such as pixlocs or vectors, the result is a new object, not one of the objects that was compared.

## missile proc

Format:
  missile(Type, Start, End)

Args:
  Type: An object prototype or icon file.
  Start: The starting location.
  End: The ending location.

Send a missile of the given Type between two locations. The effect is purely visual. When Type is an object, its icon is used for the missile.

### Example:

    missile(/obj/fireball, usr, loc)

## nameof proc

See also:
  :: operator

Format:
  nameof(Var)
  nameof(ProcRef)
  nameof(Path)

Args:
  Var: A variable, e.g. src.density or foo::bar.
  ProcRef: A proc reference, e.g. /mob::Enter().
  Path: A type path, e.g. /obj/item/barrel.

This returns the name of a var or proc, or the last part of a type path. This proc only exists at compile-time.

The main purpose of this proc is to turn a proc reference into a name, which is useful in some esoteric situations.

### Example:

    var/list/event_queue

    proc/CallLater(object, procref, a, b, c)
        var/list/forlater = list(object, nameof(procref), a, b, c)
        event_queue ||= list()
        event_queue[++event_queue.len] = forlater

    world/Tick()
        while(length(event_queue))
            var/list/forlater = event_queue[1]
            event_queue.Cut(1,2)
            var/object = forlater[1]
            var/procname = forlater[2]
            var/a = forlater[3]
            var/b = forlater[4]
            var/c = forlater[5]
            call(object, procname)(a, b, c)

## new proc

See also:
  New proc (atom)
  New proc (datum)
  New proc (icon)
  newlist proc
  path operators
  __IMPLIED_TYPE__ macro

Format:
  new Type(Args)

Returns:
  A reference to a new instance of Type.

Args:
  Type: The type of object to create.
  Args: Arguments for the Type.New() proc.

A new instance of Type is created. The arguments (Args) are passed to its New() proc. A handy short-cut: if Type is not specified and new() is being used in an assignment, the variable type of the left-hand-side will be used as the default type.

The atom types /area, /turf, /obj, and /mob all take a location argument specifying the initial position. If not specified, it defaults to null.

Newly created areas or turfs replace any existing area or turf at the specified location.

### Example:

    obj/stick
    mob/verb/magic_stick()
       var/obj/stick/S = new(src)  //create a stick in my inventory
       S.desc = "This is no ordinary stick!"
       view() << "[src] creates \an [S] from thin air!"

## newlist proc

See also:
  list proc
  new proc

Format:
  newlist(A,B,C,...)

Returns:
  A list of new objects, just as though you had done `list(new A,new B,new C,...)`.

Args:
  Arbitrary number of types to be created in the list.

### Example:

    mob/contents = newlist(/obj/scroll/readme)

This causes new mobs to be created with a readme scroll in their inventory.

It is possible to make simple initializations when you want variables to have values other than the default for the particular type you are creating.

### Example:

    mob/contents = newlist(
       /obj/scroll/readme {
          name = "Introduction"
          desc = "The fate of Bracolia depends on you ..."
       }
    )

This is the most common use of "modified types", but it is not specific to the newlist instruction. Anywhere a type value may be used in DM, it may be followed by a list of initializations. The general syntax for a modified types is:

path {var1 = val1; var2 = val2}

The semicolon is necessary if you put several variable assignments on the same line. The braces are necessary, even though they are generally optional in DM (since the compiler looks at your indentation). The reason is that the path + initializations must be parsed as a single expression, which is a different context from the usual use of braces in DM when you are defining a true type. Also, indentation inside of an argument list is always ignored anyway.

## noise_hash proc

See also:
  rand proc
  rand_seed proc

Format:
  noise_hash(num1, num2, num3...)
  noise_hash(list_of_nums)
  noise_hash(hash_name, num1, num2, num3...)
  noise_hash(hash_name, list_of_nums)

Returns:
  A number between 0 and 1 (excluding 1 itself)

Args:
  num1, num2, num3...: Numbers to be hashed (at least one)
  list_of_nums: A list containing the numbers to hash
  hash_name: A text string indicating the hash type (reserved for future use)

For some games using concepts of procedural generation, it's nice to be able to reliably create pseudo-random numbers in a repeatable, reliable way. This proc takes all the numbers put into it and hashes them together to get a value from 0 to 1. That output value will be the same for any given set of input numbers. This can be used on its own or as part of a more in-depth noise algorithm.

If the first argument is a string, that may be used in future versions to specify the type of hash to use. For now it is not used.

Non-numbers provided to the proc will be interpreted arbitrarily. Don't do that.

## nonspantext proc

See also:
  findtext proc
  spantext proc
  splittext proc

Format:
  nonspantext(Haystack,Needles,Start=1)

Returns:
  The number of consecutive characters, from the start position, that do NOT match the characters in Needles.

Args:
  Haystack: The text string to search.
  Needles: A text string with all the characters that should not match.
  Start: The text byte position in Haystack in which to begin the search.

This proc is case-sensitive. A common use for this proc is in parsing. For instance nonspantext("apples, oranges",", ") will return 6, because the first 6 characters don't match a comma or a space.

If the start position is negative, the position is counted backwards from the end of the string.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `nonspantext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## num2text proc

See also:
  isnum proc
  text2num proc

Format:
  num2text(N, SigFig=6)
  num2text(N, Digits, Radix)

Returns:
  A text string.

Args:
  N: A number.
  SigFig: Number of significant digits.
  Digits: Minimum number of digits
  Radix: The base of the number, e.g. 16 is hexadecimal.

Get the text string for a number. The number of significant digits determines when scientific notation is used. The default is 6, so scientific notation will only be used when there are more than 6 digits.

### Example:

    T = num2text(12)  // = "12"
    T = num2text(12,1)  // = "1.2e1"

The Radix format is intended for converting numbers to bases other than 10, although you can still use 10. In this format, Digits represents the minimum number of digits to use, and the result will be left-padded with zeroes if necessary. Also, in this form only the integer part of the number is used, and it can't be any larger than what a 32-bit integer could store (about 4 billion). These limitations may be lessened or removed in the future, but this format was mainly intended for simple conversions.

### Example:

    world << num2text(11, 2, 16)  // "0b"
    world << num2text(343, 0, 7)  // "1000"

## obounds proc

See also:
  bounds proc

Format:
  obounds(Ref, Dist=0)
  obounds(Ref, x_offset, y_offset, extra_width=0, extra_height=0)

Returns:
  A list of atoms (except areas) within Ref's bounding box, excluding Ref.

Args:
  Ref: A turf, obj, or mob.
  Dist: A number (distance in pixels).
  x_offset, y_offset: Shifts bounding box position
  extra_width, extra_height: Adjusts bounding box size

The results from obounds() are identical to bounds(), but obounds() leaves Ref out of the results.

## ohearers

See also:
  hearers
  oview proc
  oviewers

Format:
  ohearers(Depth=world.view,Center=usr)

This is just like `hearers()`, but it excludes the center object and its contents from the list. It is a list of all other mobs that can hear the center object.

## orange proc

See also:
  << output operator
  block
  oview proc
  range proc

Format:
  orange(Dist,Center=usr)

Returns:
  A list of objects within Dist tiles of Center, excluding Center.

Args:
  Dist: A number.
  Center: An object on the map.

This instruction is identical to oview() except visibility is ignored. All objects are included in the list whether they are visible or not. The center object and its contents are excluded.

## output proc

See also:
  << output operator
  winclone proc
  winset proc

Format:
  output(msg, control)

Args:
  msg: Text, an atom, a file, or null
  control: The ID of a control in the player's skin, or null for the default

This is used in conjunction with the << output operator to send output to a particular control in the player's skin. If null is sent, the control will be cleared.

### Example:

    usr << output("Your score is [score].", "scorepane.output")

As with `winset()`, the control name may be in the form `":[type]"` which sends to the default control of that type, e.g. `":output"`.

The control ID can be followed by a colon and extra info such as a name or a grid cell, which can send the output to the control in a different way. In a grid, this can output directly to a specific grid cell, like so:

### Example:

    usr << output("Column 3, Row 2", "examplegrid:3,2")

For a browser control, the extra info is a JavaScript function. The format for sending a script to the browser control is `output("[params]","[control]:[scriptname]")` where "[params]" is a URL-encoded list of string arguments to the javascript function, as formatted by list2params().

### Example:

    mob/Login()
        . = ..()
        usr << output(\
    {"
    <script type="text/javascript">
    function replace(v) {
      document.getElementById('foo').innerHTML =
        v.replace(/&/g, '&amp;').replace(/</g, '&lt;');
    }
    </script>
    <div id="foo">This text can change.</div>
    <p>And this can't.</p>
    "},
        ":browser");

    #define LP(str) list2params(list(str))
    mob/verb/newtext(T as text)
        usr << output(LP(T), ":browser:replace")

This allows for the creation of more dynamic interfaces, since javascript provides access to many client-side operations and flicker-free updates.

## oview proc

See also:
  << output operator
  orange proc
  view proc

Format:
  oview(Dist,Center=usr)

Returns:
  A list of visible objects within Dist tiles of Center, excluding Center.

Args:
  Dist: A number.
  Center: An object on the map.

This instruction is just like view() except it doesn't include Center or its contents in the list.

### Example:

    oview() << "to others in sight of [usr]"

## oviewers

See also:
  hearers
  oview proc
  oviewers

Format:
  oviewers(Depth=world.view,Center=usr)

This is just like `viewers()`, but it excludes the center object and its contents from the list. It is a list of all other mobs that can see the center object.

## params2list proc

See also:
  Topic proc (client)
  list associations
  list2params proc
  params var (world)
  text2num proc

Format:
  params2list(Params)

Args:
  Params: Text string of parameter values.

Returns:
  An associative list of parameter names and values.

This instruction converts a parameter text string to a list of individual parameters and associated values. The format of the parameter text is:

    "name1=value1&name2=value2&..."

The field separator `;` may be used in place of `&`.

Special characters such as `=`, `;`, and `&` inside the parameter names or values should be written in the form `%xx`, where `xx` are two hexadecimal digits representing the ASCII value of the character. (For Unicode characters, this may be several `%xx` sequences using UTF-8 encoding.) For example, `=` would be written `%3d`, `;` would be `%3b`, `&` would be `%26`, and `%` would be `%25`. These "escaped" codes are automatically translated into the corresponding character when read by `params2list()`.

This parameter format is the same one used by most HTML forms and is known by the MIME type `application/x-www-form-urlencoded`. It is often used in DM to pack information into topic links. Though DM does not require it, the standard format is for newlines to be written as CR LF pairs (`%0d%0a`) and spaces to be written as `+` characters. That means if you want to write a `+` symbol, you will have to use `%2b`.

The list produced from the parameter text has items `"name1"`, `"name2"`, and so on. To access the values associated with these, you use the parameter name as the list index.

### Example:

    var/ptext = "offense=jwalk&time=10:00"
    var/plist[] = params2list(ptext)

    var/p
    for(p in plist)
       usr << "[p] = [plist[p]]"

The above example defines a simple parameter text string containing two parameters: `"offense"` and `"time"`. These are associated with the values `"jwalk"` and `"10:00"`. The `for` loop illustrates how one might loop through the list and print out each setting.

Note that all values are stored as text strings in the list. If you wish to perform a numerical operation (such as addition), you should convert the value to a number first using `text2num()`. If the value is an object text reference, you can convert that into the object itself by using `locate()`.

If you have multiple items with the same name, they will be combined into a list of text strings. For example, `"key=value1;key=value2"` would set `list["key"]` to a list containing `"value1"` and `"value2"`, not necessarily in that order.

## pick proc

See also:
  prob proc

Format:
  pick(Val1,Val2,...)
  pick(List)

Returns:
  One of the given values randomly chosen.

Randomly chooses an item from a list or from the arguments provided. If only one argument is included and it is a list, then the item is chosen from that list.

When not using the list form, you can make a particular value more or less likely to be chosen by providing a relative probability like this:

    prob(P); Val
      Or
    P; Val

A value for P of 200 makes it twice as likely as the norm, 50 half as likely, and so on.

### Example:

    obj/food
      verb/eat()
        usr << pick (
            "[usr] eats \a [src].",
          prob(50)
            "[usr] devours \a [src].",
          prob(25)
           "[usr] wolfs down \a [src]."
        )
        del(src)

There is no analogous weighted format for the list version of this proc.

## pixloc proc

See also:
  pixloc
  pixloc var (atom)
  bound_pixloc proc

Format:
  pixloc(x, y, z)
  pixloc(Atom)
  pixloc(Atom, x, y)
  pixloc(Atom, Vector)
  pixloc(Pixloc)
  pixloc(Pixloc, x, y)
  pixloc(Pixloc, Vector)

Returns:
  A new `pixloc` object or null.

Args:
  x, y, z: Pixel coordinates in world space (starting at 1,1,1). When the first argument is an atom or pixloc, x and y are offsets.
  Atom: An atom whose pixloc will be copied.
  Pixloc: An existing pixloc to copy.
  Vector: A 2D vector to offset the new pixloc by.

Creates a new `pixloc` object based on an existing object's location or using raw world coordinates. If the pixloc can't be created, for instance if the Atom argument is not directly on the map, the result is null.

### Example:

    mob/proc/GoToStrangeForest()
        // in a world with 32x32 icon size, this is x=18, y=29, step_x=5, step_y=11
        mob.pixloc = pixloc(550, 907, 1)

When the pixloc is created with world coordinates, x and y are a combination of tile x and step_x, and tile y and step_y, starting at a value of 1. The world x and y for any tile and step combo can be calculated like so (if for any reason you needed to):

    world_x = (tile_x - 1) * pixels_per_x_tile  + step_x + 1
    world_y = (tile_y - 1) * pixels_per_y_tile + step_y + 1

## prob proc

See also:
  pick proc
  rand proc
  rand_seed proc
  roll proc

Format:
  prob(P)

Returns:
  1 with probability P percent; otherwise 0

Args:
  P: A number.

## rand proc

See also:
  pick proc
  prob proc
  rand_seed proc
  roll proc

Format:
  rand(L=0,H) or rand()

Returns:
  A random integer between L and H inclusive; or a random number from 0 up to 1 if L and H are omitted.

Args:
  L: A number for the lower-bound.
  H: A number for the upper-bound.

## rand_seed proc

See also:
  pick proc
  prob proc
  rand proc
  roll proc

Format:
  rand_seed(Seed)

Args:
  Seed: An integer used to initialize the random number generator.

Many DM procedures make use of a pseudo-random number generator. You can use rand_seed() to initialize the generator. The sequence returned by the generator is identical each time it is initialized with the same seed, so you could use this to reproduce the same output from an algorithm that uses the random number generator. If you never call rand_seed(), the generator is initialized with a seed from the system clock, so it is effectively random.

Note that with multiple realtime algorithms making calls to the generator at unpredictable times, you are likely not to get the same result even when using the same seed. The overall sequence will be the same, but individual sub-components of your world might call it in a different order.

The pseudo-random number generator is system dependent, so do not expect the sequence generated from a particular seed to be identical on two different machines or operating systems.

## range proc

See also:
  << output operator
  block
  view proc
  orange proc

Format:
  range(Dist,Center=usr)

Returns:
  A list of objects within Dist tiles of Center.

Args:
  Dist: A number.
  Center: An object on the map.

This instruction is identical to view() except visibility is ignored. All objects are included in the list whether they are visible or not.

A Dist of 0 includes Center, the contents of Center (normally usr.contents), its location (normally the turf a mob is standing on), and any other contents of that location. A value of 1 extends the region to the neighboring squares on the map and so on. You can also use a rectangular box size using a text string such as "13x11". Both arguments are optional and may be passed in any order.

## ref proc

See also:
  \ref text macro
  locate proc

Format:
  ref(Object)

Args:
  Object: The object to get a reference for

Returns:
  A string containing a reference ID.

This is a shortcut for `"\ref[Object]"`.

## refcount proc

See also:
  garbage collection

Format:
  refcount(Object)

Args:
  Object: The object to get a reference count for

Returns:
  A count of references for the object.

This gets a reference count for a value, not including the reference that was placed on the stack while evaluating this proc.

A return value of 0 can mean one of several things: Either this was the last reference and the object was subsequently deleted after refcount(), or the value doesn't support reference counting.

Note: A nonzero return value does not necessarily mean the object will be deleted when its count reaches zero; mobs for instance will not be soft-deleted by the garbage collector if their `key` var is set, and some objects like clients and areas never soft-delete. A zero value also does not necessarily mean the object is immortal; it may be transient, like the `args` list in a proc that only lives as long as that copy of the proc lives.

## regex proc

See also:
  Regular expressions
  regex datum
  regex procs
  findtext proc
  replacetext proc
  splittext proc
  REGEX_QUOTE proc

Format:
  regex(pattern, flags)
  regex(Regex)

Returns:
  A new /regex datum.

Args:
  pattern: The pattern string to search for
  flags: (optional) A text string containing any combination of modifier flags
  Regex: an existing /regex datum to copy

Creates a regular expression, stored in a /regex datum, that can be used for searching and/or replacing text.

## REGEX_QUOTE proc

See also:
  regex proc
  regex datum
  stddef.dm file

Format:
  REGEX_QUOTE(text)
  REGEX_QUOTE_REPLACEMENT(text)

Returns:
  REGEX_QUOTE: A version of the text with any special regular expression characters escaped by backslashes.
  REGEX_QUOTE_REPLACEMENT: A version of the text with $ characters escaped by a second $.

Args:
  text: The text to escape

Quotes a piece of text so that it can be used inside a regular expression without fear of being treated as pattern instructions.

### Example:

    proc/FindWord(text, word)
        // The \b pattern is a word break, to search for the word
        // on its own instead of as part of another word.
        var/regex/R = regex("\\b[REGEX_QUOTE(word)]\b", "i")
        // find the pattern in the text
        return R.Find(text)

## replacetext proc

See also:
  findtext proc
  replacetextEx proc
  Regular expressions
  Replace proc (regex)

Format:
  replacetext(Haystack,Needle,Replacement,Start=1,End=0)

Returns:
  The Haystack text with all cases of Needle replaced by Replacement

Args:
  Haystack: The text string to search.
  Needle: The sub-text to search for. May be a regular expression (regex).
  Replacement: The replacement text, or a proc.
  Start: The text byte position in Haystack in which to begin the search.
  End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is NOT sensitive to the case of Haystack or Needle. The case-sensitive version is replacetextEx(). If the Needle is a lowercase word, the replacement will be changed to uppercase or all caps if the found text is uppercase or all caps.

### Example:

    world << replacetext("One on one", "one", "two")

This outputs "Two on two", where the first case's "One" is identified as uppercase.

You may use a proc as the Replacement value. In that case, the proc will be called with the found text as an argument, and its return value will be the replacement. There will be no automatic correction to uppercase or all caps in this case.

When the Needle value is a regular expression, this proc behaves identically to the regex Replace() proc. Case-sensitivity, and whether one match or all are replaced, depend on the regular expression.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `replacetext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## replacetextEx proc

See also:
  findtextEx proc
  replacetext proc
  Regular expressions
  Replace proc (regex)

Format:
  replacetextEx(Haystack,Needle,Replacement,Start=1,End=0)

Returns:
  The Haystack text with all cases of Needle replaced by Replacement

Args:
  Haystack: The text string to search.
  Needle: The sub-text to search for. May be a regular expression (regex).
  Replacement: The replacement text, or a proc.
  Start: The text byte position in Haystack in which to begin the search.
  End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is sensitive to the case of Haystack and Needle. The case-insensitive version is replacetext().

### Example:

    world << replacetext("One on one", "one", "two")

This outputs "Two on two", where the first case's "One" is identified as uppercase.

You may use a proc as the Replacement value. In that case, the proc will be called with the found text as an argument, and its return value will be the replacement. There will be no automatic correction to uppercase or all caps in this case.

When the Needle value is a regular expression, this proc behaves identically to the regex Replace() proc. Case-sensitivity, and whether one match or all are replaced, depend on the regular expression.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `replacetextEx_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## return statement

See also:
  . var (proc)

Format:
  return E

Stop execution of the current proc and return the value of E to the caller. If no value is specified, the value of `.` will be returned, which defaults to null.

## rgb proc

See also:
  rgb2num proc
  gradient proc
  Color space
  HTML colors
  color var (atom)
  Blend proc (icon)
  Color matrix
  Color matrix filter
  Particle effects

Format:
  rgb(R,G,B)
  rgb(R,G,B,A)
  rgb(x,y,z,space=color space)
  rgb(x,y,z,a,space)

Args:
  R,G,B: Numbers from 0-255 corresponding to the red, green, and blue components of a color.
  A: Optional alpha component; 0 is transparent, 255 is opaque.
  x,y,z: Color components for a different color space
  space: Color space; defaults to `COLORSPACE_RGB`

Returns:
  A color, represented by a text string in #RRGGBB or #RRGGBBAA format

A way of representing a color to be used in conjunction with icon arithmetic, atom.color, or other effects. The colors `rgb(0,0,0)` and `rgb(255,255,255)` represent black and white, two corners of the "color cube".

### Example:

    mob/proc/hurtme() // make a mob look damaged by adding red to its icon
      src.icon += rgb(20,0,0)

This proc returns a text string in the form used by HTML (#RRGGBB). rgb(255,0,128) for example becomes "#ff0080". If you use an alpha component, the format is #RRGGBBAA. You can use strings like this in most procs that use colors such as icon blending operations, and you can also use the short form #RGB or #RGBA. So if you know in advance that you want to use the color white, you can simply use"#fff" instead of rgb(255,255,255).

You can create colors other ways by specifying a different color space. A color space can be specified by using a named "space" argument, or by using a 5-argument format (you can leave the alpha value blank or null to skip it), or by using named arguments for the other components.

### Example:

    // All of these lines are equivalent.
    // They create (0,100,50) in HSL which is red (#ff0000).
    src << rgb(0, 100, 50, space=COLORSPACE_HSL)
    src << rgb(0, 100, 50, , COLORSPACE_HSL)
    src << rgb(h=0, s=100, l=50)

Named arguments that are valid in `rgb()` are:

- `space`
- `red`
- `green`
- `blue`
- `alpha`
- `hue`
- `saturation`
- `chroma`
- `value`
- `luminance`
- `y` (HCY luminance)

With the exception of `space`, only the first letter of the argument name matters, so `r` and `red` are the same thing.

## rgb2num proc

See also:
  rgb proc
  gradient proc
  Color space
  HTML colors

Format:
  rgb2num(color)
  rgb2num(color, space)

Args:
  color: A color value (see HTML colors)
  space: Color space; default is `COLORSPACE_RGB`

Returns:
  A list with the components of this color

Parses a color into a list with 3 or 4 component values; the 4th value is alpha, if it's part of the color provided.

### Example:

    var/list/RGB = rgb2num("#ff8000")
    src << RGB[1]     // red (255)
    src << RGB[2]     // green (128)
    src << RGB[3]     // blue (0)

By specifying a different color space, you can convert a color into a different format.

### Example:

    var/list/HSL = rgb2num("#5af", COLORSPACE_HSL)
    src << HSL[1]     // hue (210)
    src << HSL[2]     // saturation (100)
    src << HSL[3]     // luminance (66.6667)

## roll proc

See also:
  rand proc

Format:
  roll(ndice=1,sides)
  roll(dice)

Returns:
  The sum of the rolled dice.

Args:
  ndice: number of dice to role.
  sides: number of sides to the dice.
  dice: a text string encoding both ndice and sides (see below).

The sides of the dice are numbered 1 through the total number of sides and each is equally likely.

An alternate form takes the dice parameters in a single text value such as "3d4". This may be useful when you want to store the dice information in a single variable. You can even specify an offset, such as "3d4+5". That adds 5 to the sum of 3 dice having 4 sides each.

### Example:

    obj/potion/healing
      var/dice = "3d6"
      verb/drink()
        var/h = roll(dice)
        if(h>15) usr << "Very refreshing!"
        else usr << "You feel better."

## round proc

See also:
  floor proc
  ceil proc
  trunc proc
  fract proc
  sign proc

Format:
  round(A)
  round(A,B)

Returns:
  rounded A

Args:
  A: A number, pixloc, or vector.
  B: The nearest multiple to round A.

The first format returns the floor of A (the largest integer less than or equal to A), and has been deprecated in favor of `floor(A)`. The second format rounds A to the nearest multiple of B.

### Example:

    usr << round(1.45) // outputs 1

    usr << round(-1.45) // outputs -2

    usr << round(1.45,1.5) // outputs 1.5

If A is a vector, B can also be a vector to round each component separately.

If A is a pixloc, only the x and y portions will be considered. B may be a vector.

## run proc

See also:
  << output operator
  file proc
  link proc

Format:
  O << run(File)

This is similar to link() but instead of a URL, you can pass a file to be viewed directly. The file may be a cache file or an external file.

### Example:

    mob/var/picture = 'mob.jpg'
    mob/verb/view_pic(mob/M as mob in view())
      usr << run(M.picture)

    mob/verb/set_pic(F as file)
      usr.picture = F

This example defines a picture to be associated with each mob and a verb for viewing another mob's picture. Players can also configure their own pictures.

## settings (proc)

proc settings: ``

    verb/set
      name
      desc
      category
      hidden
      popup_menu
      instant
      invisibility
      src
      background
      waitfor

Procs and verbs are the same "type" so these attributes may be set for both procs and verbs; most of them only apply to verbs, so they only take effect if the proc is invoked as a verb (by adding it to a verb list).

## background setting (proc)

See also:
  sleep proc
  spawn proc

To avoid lag from procedures that hog the CPU for too long, you can turn on background processing. This will cause it to periodically sleep for long enough to allow other events to be processed.

The following example is a typical "ticker" procedure. It spawns off an infinite loop which does some work and then sleeps before iterating again. By running this in the background, you ensure that the work being done does not create large delays. You could achieve a similar thing by sprinkling calls to sleep(0) or sleep(-1) in the "working" part of the loop.

### Example

    proc/Ticker()
       set background = 1
       spawn while(1)
          for(var/mob/M in world)
             M.Tick()
          sleep(10)

Since the background procedure sleeps at unpredictable times, you must be aware that race conditions are possible if the background procedure interacts with variables modified by other procedures. It's still much safer than multi-threaded programs because the background procedure never interrupts other code; but other code may interrupt the background procedure.

Note that procedures that are called by the background procedure do not automatically run in the background unless they too have the background setting turned on. For instance, the code in the above example does not imply that the mob Tick() procs would run in the background. This is convenient, because you should only ever apply background processing to code after checking that there are no potential race conditions involved.

If you have an eye for race conditions, you might think that the above code has one in which a mob gets deleted after it is assigned to M but before the call to M.Tick() is executed. However, background processing is only interrupted at loop points in the code, so the above code is safe. It would only ever be interrupted at the end of the `for` or `while` loops.

## waitfor setting (proc)

See also:
  sleep proc
  spawn proc
  . var (proc)

By default, procs that sleep usually expect their callers to wait for them to finish, so the callers must sleep as well. Using `set waitfor=0` will disable that behavior, causing any sleep to return control to the caller immediately.

### Example

    mob/proc/LongLoop()
       set waitfor = 0
       while(1)
          UpdateAI()
          // proc will return to caller here
          sleep(1)

This setting will also dictate what happens if a callee sleeps. Consider an example where proc A calls proc B which calls proc C, and proc B has `waitfor` set to 0. When proc C sleeps, proc B will also sleep, but proc A will continue running as if proc B returned early. The `.` var currently in proc B will be used as its return value to A. When proc C wakes up and finishes, it will wake up proc B, but now B's return value will be ignored since A is no longer waiting for it.

In older versions, the `New` proc always had `waitfor` set to 0 by default, but this was later changed. Now 1 is always the default, so setting `waitfor` to 1 will result in a warning that it is no longer necessary.

## sha1 proc

See also:
  md5 proc
  file proc

Format:
  sha1(T)
  sha1(F)

Returns:
  text or null.

Args:
  T: A text string.
  F: A file.

This proc implements SHA1 hashing. A hash function is a one-way process that compacts information to a short value: a hash. The same value will always have the same hash. Among other uses, most computers use hashing to store passwords. By storing just the hash, the password file contains very little sensitive information, but the password can still be verified by confirming that `sha1(password)==hash`. SHA1 is a widely-used hash function.

### Example:

    mob/var/hash

    mob/Read(savefile/S)
      ..()
      // hash was saved in the file along with other values
      if(sha1("[level]/[exp]/[exp_needed]") != hash)
        src << "Cheater!"
        del(src)

In the example, a few vars belonging to a mob were saved along with a hash of those values. When the mob is loaded again, the game compares the hash to the values to make sure it's still accurate. If the values or hash had been changed by a sneaky player, they wouldn't match. (But a sneaky player could still calculate `hash` themselves if they knew the exact text used to make it, so this should be kept secret.)

If the argument is a file, `sha1()` will read the file and return the SHA1 hash of the file's entire contents. If the file doesn't exist, it returns null. The file may be a cache file or an external file.

### Examples:

    var/hash = "(insert hash value here)" // Compute this ahead of time

    // Check that the cached default icon is still the same
    if (sha1('default.dmi') != hash)
      world << "The default icon has been modified!"

    // Or check that the entire game resource file is pristine
    if (sha1(file("mygame.rsc")) != hash)
      world << "The game resources have been modified!"

Note that you must pass the result of file() in order to compute the hash of an external file's contents at runtime. Otherwise `sha1()` will treat the filename as text and return the hash of the name only.

If `T` is anything but a text string or file, the proc returns null.

## shell proc

See also:
  fcopy proc
  fdel proc
  file2text proc
  process var (world)
  system_type var (world)
  text2file proc

Format:
  shell(Command)

Args:
  Command: system command to run

Returns:
  null on failure to execute command
  exit code of command otherwise

This function is used to run an external program. The syntax of Command depends on the server machine's operating system. Be sure to redirect input and output to files if there is any. Also realize that the command will fail if the program you try to run is not in the path where the shell expects to find executable files (unless you specify a full path).

Since shell() allows arbitrary access to the system, each call requires authorization from the person hosting the world, unless running in trusted mode. Authorization is only sought when running in Dream Seeker, since Dream Daemon is intended to be non-interactive. Calling shell() with no arguments is a way of checking if it is allowed by the current safety settings. It will return true if running in Dream Seeker (regardless of safety mode) or if running in Dream Daemon in trusted mode.

The calling proc will sleep until the command is finished executing.

### Example:

    mob/verb/dir(Path as text)
      shell("dir [Path] > dir.out")
      usr << file2text("dir.out")

This example displays the output of the "dir" command to the user.

## shutdown proc

See also:
  Export proc (world)
  startup proc

Format:
  shutdown(Addr,Natural=0)

Args:
  Addr: This is the address of the child world returned by startup().
  Natural: Specifies whether to wait for the child world to die naturally, or whether it should be killed with the "Del" world topic. The default value of 0 kills the child, and a value of 1 waits for the child to exit of its own accord.

If no address is specified, the current world is shut down.

## sign proc

See also:
  floor proc
  ceil proc
  round proc
  trunc proc
  fract proc

Format:
  sign(A)

Returns:
  1 if A > 0, -1 if A < 0, 0 if A == 0

Args:
  A: A number or a vector.

Returns the sign of A. If used with a vector, a new vector is returned where `sign()` has been applied to each component.

### Example:

    usr << sign(20) // outputs 1
    usr << sign(0)  // outputs 0
    usr << sign(-3) // outputs -1

## sin proc

See also:
  arcsin proc
  cos proc
  tan proc
  turn proc

Format:
  sin(X)

Returns:
  The sine of X, where X is in degrees.

### Example:

    mob/verb/test()
       usr << sin(0)  // 0
       usr << sin(45) // 0.707...
       usr << sin(90) // 1

## sleep proc

See also:
  background setting (proc)
  waitfor setting (proc)
  spawn proc
  tick_lag var (world)

Format:
  sleep(Delay)

Args:
  Delay: The amount of time to sleep, in 1/10 seconds.

Pause the current proc (and its callers) for a specified amount of time. If no delay is specified, it will be scheduled to resume as soon as other immediately pending events are processed.

Note that sleeping in some procedures results in the return value being lost. For example, if you sleep inside `Entered()` or `Exited()`, it will be as if you returned immediately where you started sleeping. This is because `Move()` calls them in away that says the return value should be ignored. Also if a proc has its waitfor setting changed to 0, it will return the value of the `.` var to its caller immediately if it or one of its callees sleeps.

Also be aware that a sleeping procedure whose src object gets deleted will automatically terminate when execution returns to it. This is to protect you against trying to access properties or procedures of a deleted (and therefore `null`) object. If you do not want the procedure to be terminated, you should set src to `null`.

One common use of `sleep` is to create what is known as a ticker. That is an infinite loop that performs some periodic operation.

### Example:

    proc/Weather()
       spawn while(1) //infinite ticker loop
          world << "The sun rises in the east."
          sleep(500)
          world << "The noon day sun rises high in the sky."
          sleep(500)
          world << "The sun sinks low in the west."
          sleep(1000)

Notice how such infinite loops are usually created using `spawn` to prevent the caller from getting locked up. You could call this procedure from `world.New()` to start it rolling.

Note: sleep time is in 1/10s units, not server ticks. If your `world.tick_lag` or `world.fps` value is different from the default, `sleep(1)` still means "sleep for 1/10s". To sleep for exactly `N` ticks, call `sleep(N * world.tick_lag)`.

If the ticker does intensive processing during each iteration, you probably want to run it in the background like this:

    proc/Ticker()
       set background = 1

Calling sleep() with a negative argument (such as sleep(-1)) causes it to do a backlog check. Only if other pending events have become backlogged will it sleep. This is similar to running in the background, but you manually control where the backlog checks are made. The difference between this and sleep(0) is that sleep(0) always sleeps the current procedure for as short a time as possible, whereas sleep(-1) only sleeps the current procedure if other scheduled events have become backlogged. Therefore, sleep(-1) will tend to run the current procedure at a higher priority with fewer interruptions. It is appropriate when there is a single task that needs to be done before anything else can happen, and you just want to make sure that network and user I/O are not terribly lagged in the process.

## sorttext proc

See also:
  > operator
  < operator
  sorttextEx proc

Format:
  sorttext(T1,T2,...)

Args:
  Any number of text strings to sort.

Returns:
  1 if text is ascending
  -1 if text is descending
  0 otherwise

This instruction is NOT sensitive to case. The case sensitive version is sorttextEx().

### Example:

    switch(sorttext("A","B"))
      if(1) world << "ascending"
      if(-1)world << "descending"
      if(0) world << "neither"

This outputs "ascending", since "A" comes before "B" in the alphabet.

## sorttextEx proc

See also:
  > operator
  < operator
  sorttext proc

Format:
  sorttextEx(T1,T2,...)

Args:
  Any number of text strings to sort.

Returns:
  1 if text is ascending
  -1 if text is descending
  0 otherwise.

This instruction is sensitive to case. The case-insensitive version is sorttext().

Note: Uppercase letters are lower in the alphabetical order than lowercase letters.

### Example:

    switch(sorttextEx("a","B"))
      if(1) world << "ascending"
      if(-1)world << "descending"
      if(0) world << "neither"

This outputs, "descending", since "B" comes before "a" in the alphabet.

Note: This proc used to be named `sortText`, like `sorttext` but with a capital T. To avoid confusion it has been renamed, but old code will still compile.

## sound proc

See also:
  sound datum
  vars (sound)
  << output operator
  load_resource proc

Format:
  sound(file,repeat=0,wait,channel,volume)
  (supports named arguments)

Args:
  file: A sound file to play
  repeat: 1 to play sound repeatedly
  wait: 0 to interrupt current sound on channel; 1 to wait in queue
  channel: 0 for any available channel, 1-1024 for specific channel (non-MIDI only)
  volume: 100 for full volume (default), 0 for none, or any value in between

This is used to play a sound file.

The sound file must be a music or sample file. Music files include MIDI (.mid or .midi), and module formats .mod, .it, .s3m, .xm, and .oxm. A sample file used for sound effects can be .wav, .ogg, .raw, .wma, or .aiff.*

The following example plays some sound files. Note that `sound()` is not even necessary when you don't need to set any additional parameters.

### Example:

    usr << 'giggle.wav' // play a giggle once
    usr << sound('gigue.midi',1) // repeat gigue
    usr << sound('boom.wav', volume=50) // play an explosion at half volume

*See Notes under sound support for more information.

## spantext proc

See also:
  findtext proc
  nonspantext proc
  splittext proc

Format:
  spantext(Haystack,Needles,Start=1)

Returns:
  The number of consecutive characters, from the start position, that match the characters in Needles.

Args:
  Haystack: The text string to search.
  Needles: A text string with all the characters that match.
  Start: The text byte position in Haystack in which to begin the search.

This proc is case-sensitive. A common use for this proc is in parsing. spantext("apples, oranges",", ",7) will tell you that, starting at position 7, you need to skip 2 characters to get past any commas or spaces.

If the start position is negative, the position is counted backwards from the end of the string.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `spantext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## spawn proc

See also:
  background setting (proc)
  sleep proc

Format:
  spawn(Delay=0) Statement
  spawn(Delay=0)
  Statement

Args:
  Delay: The amount of time (in 1/10 seconds) before Statement is executed.

Run Statement after a delay. Statement may be a single statement or a code block enclosed in (optional) braces and indented. If delay is negative, the spawned code is executed before continuing in the main code. If it is zero, the spawned code is scheduled to happen right after other existing events that are immediately pending.

### Example:

    spawn(30) storm()
    usr << "Storm clouds are brewing!"

This will display `"Storm clouds are brewing!"` and then call the storm() proc after 3 seconds.

The important feature of spawn() is that the caller does not have to wait around for the spawned code to finish.

Any vars you have defined in the proc itself, including arguments, will be copied between the spawned code and the code that runs right away. This means that if one part modifies one of those vars, the other part will not see that change. Changes made to objects, lists, datums, etc. however will be visible to both code blocks.

Pointers to any vars that belong to the proc will stay with the original proc, not the copy.

## splicetext proc

See also:
  copytext proc
  Splice proc (list)

Format:
  splicetext(Text,Start=1,End=0,Insert="")

Returns:
  Spliced text

Args:
  Text: The text string to splice.
  Start: The text byte position in Text where the splice will begin.
  End: The text byte position in Text immediately following the last character to be cut from the splice. 0 is the end of the string.
  Insert: Text to be inserted.

Cuts out a section of a text string and inserts a different piece of text in its place. This is basically equivalent to `copytext(Text,1,Start) + Insert + copytext(Text,End)`, but faster.

### Example:

    // cuts "nan" from "banana" and replaces it with "laclav"
    // prints "balaclava"
    usr << splicetext("banana", 3, 6, "laclav")

The `Start` and `End` index values can be negative, which count backwards from the end of the string. If the index values are out of range, there will be no error; they will simply be clamped to the beginning or end of the string. If `End` comes before `Start`, the two values are swapped.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `splicetext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## splittext proc

See also:
  findtext proc
  jointext proc
  nonspantext proc
  spantext proc
  Regular expressions

Format:
  splittext(Text,Delimiter,Start=1,End=0,include_delimiters=0)

Returns:
  A list of text strings split by the delimiter given.

Args:
  Text: The text string to search.
  Delimiter: A text string that will be used as the separator between items, OR a regular expression (regex) used to find splits
  Start: The text byte position in Text in which to begin looking for splits.
  End: The text byte position in Text immediately following the last character to look at for splits.
  include_delimiters: True if any delimiters found should be included in the result.

Splits up a text string and returns a list. The delimiter is case-sensitive (unless you use a case-insensitive regular expression), and can be more than one character long.

### Example:

    var/list/items = splittext("apples,oranges,bananas", ",")
    // prints "apples", "oranges", and "bananas" separately
    for(var/item in items)
        usr << item

Where multiple delimiters are next to each other, they're considered to be separating an empty string. Therefore splittext("a,,b,c", ",") would return a list with four elements instead of three. Splitting empty text returns an empty list.

If a regular expression is used as the delimiter, any capturing groups in the expression will be included in the list, in order. (The whole match itself will come first, if include_delimiters is true.) So for instance splitting by regex(",") will not include the comma, but splitting by regex("(,)") will. Groups that were not part of the match will be null.

If the start or end position is negative, the position is counted backwards from the end of the string. Please note that the start and end positions do NOT trim the string; if you want to split a trimmed string, trim it with copytext() and send the result to `splittext()` instead.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `splittext_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## sqrt proc

Format:
  sqrt(A)

Returns:
  The square root of A

Args:
  A: A number.

### Example:

    usr << sqrt(2) // outputs 1.41421

## startup proc

See also:
  params var (world)
  shutdown proc

Format:
  startup(File,Port=0,Options,...)

Args:
  File: The dmb file to run in a new server or null to load the current world.
  Port: The network port to start the new server on. A value of 0 indicates that any available port should be used.
  Options: Any number of the options listed below. Each option should be in an argument by itself. If the option takes a parameter, this can be in the same argument or in the following one.

### The valid options are:

-once
  automatically shuts down the server when all players have logged off.
-close
  Closes the child copy of DreamDaemon after the world it is running shuts down.
-log <logfile>
  sends all server output to the specified file. The path to the file is relative to the world directory (the path containing the world `.dmb` file).
-logself
  is identical to "-log [YourWorldFile].log".
-safe
  runs the server in a special protective mode. The server may only access files in the same directory (or below) as the dmb file and access to the shell() command is disabled. This is the default mode if no security setting is specified and the world is run from a directory by the same name as the dmb file.
-home <path>
  runs with the specified "safe home" directory. Normally, in safe mode the directory containing the world dmb file is the safe home.
-ultrasafe
  like -safe, this prohibits all file access. This is the default if no security mode is specified and the world is not run from a directory with the same name.
-trusted
  allows full access to files on the computer and to the shell() command. Note that this does not bypass the normal security of the operating system. For example, in the UNIX operating system, all of the usual access restrictions apply. This mode merely removes BYOND's built-in safety checks.
-params <paramtext>
  this is for passing user-defined parameters to the world. Multiple parameters may be packed into a single argument or -params may be used several times. In either case, the parameters are all loaded into world.params when the world starts up. The parameter format is "name1=value1&name2=value2&...".
-quiet
  disables the server's normal output indicating the BYOND version number and network port.
-nologdates
  disables automatic date/time output in the log.
-CGI
  runs the world as a CGI program (to be executed by a web server). A /client object is automatically created for the user and any output sent to the associated mob gets returned to the user's web browser. This option is normally specified in the compile-time setting: world.executor, which is automatically initialized for you if you include `html/CGI.dm` from the html library.
-suid <path>
  runs the world as the owner of the specified directory or path. This only works if DreamDaemon is running as root on operating systems where there even is such a thing.
-suidself
  runs the world as the owner of the world dmb file. This only works if DreamDaemon is running as root on operating systems where there even is such a thing.
-cd <path>
  runs with the specified working directory. Normally, the directory containing the world dmb file is used.
-port P
  sets the network port to P. The port may also be specified as a positional argument (following the .dmb name).
-ports <list>
  restricts the range of ports that DreamDaemon and any child worlds may use. The syntax of list is a comma separated list of ports or ranges of ports. Example: `-ports 1234,1236,1240-1250`.
-ip <address>
  sets the IP address of the server. This will only work for an IP address the system recognizes as one it can use for hosting. Accepts numerical addresses only.
-webclient
  Enables the webclient, overriding default behavior.
-nowebclient
  Disables the webclient, overriding default behavior.
-verbose
  Runtime errors will continue outputting details after a certain number of errors has been reached. Without this option, the number of errors that provide detailed info (such as call stack) is limited. Use this option with caution as it could fill up a log file quickly if a problem occurs.

Returns:
  The address of the new server in the form ip:port.

## stat proc

See also:
  Stat proc (atom)
  Stat proc (client)
  statpanel proc
  Info control (skin)

Format:
  stat(Name,Value)

Args:
  Name: the name of the stat line
  Value: the data to be displayed

This is used in a Stat() proc to send a stat line to usr, the person looking at an object. A stat line has an optional name part which must be unique for each stat line (or successive calls will replace previous ones).

The stat line gets appended to the current stat panel. The current panel may be changed by using statpanel().

If no name is specified and the value is a list, this is the same as calling stat on each item in the list. This can be used (in conjunction with statpanel) to create an inventory panel or something similar.

### Example:

    mob/Stat()
       stat("description",src.desc)
       if(src == usr) stat(src.contents)

This example displays the mob's description and inventory all in one panel. The code ensures that only the mob may see his own inventory, but you don't have to worry about that unless you change client.statobj to something other than one's own mob.

## statpanel proc

See also:
  Stat proc (atom)
  Stat proc (client)
  stat proc
  Info control (skin)

Format:
  statpanel(Panel,Name,Value)

Args:
  Panel: the name of the stat panel
  Name: the name of the stat line
  Value: the data to be displayed

Returns:
  If called with just a Panel argument, 1 is returned if the player is looking at the panel and 0 is returned if not. This may be useful to avoid the needless overhead of generating output to a panel that is not visible.

This is used in a Stat() proc to change the default panel (for subsequent stat lines) or to send one line to the specified panel. Name and Value are both optional. If neither is specified, this simply changes the default panel. Otherwise, the default panel is unchanged and a stat line is appended to Panel.

### Example:

    mob/Stat()
       stat("description",src.desc)
       if(src == usr) statpanel("inventory",src.contents)

This example displays the mob's description in one panel and inventory in another. Only the mob may see his own inventory, but you don't have to worry about that unless you change client.statobj to something other than one's own mob.

## step proc

See also:
  get_step proc
  walk proc
  step_size var (movable atom)
  vector

Format:
  step(Ref,Dir,Speed=0)
  step(Ref,Vector)

Returns:
  1 on success; 0 otherwise

Args:
  Ref: A mob or obj.
  Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.
  Vector: A 2D vector to move by, in pixels.

Move Ref in the direction Dir.

The vector version of this proc takes a 2D vector and tries to move by that amount of pixels.

## step_away proc

See also:
  get_step_away proc
  walk_away proc
  step_size var (movable atom)

Format:
  step_away(Ref,Trg,Max=5,Speed=0)

Returns:
  1 on success; 0 otherwise.

Args:
  Ref: A mob or obj.
  Trg: An object on the map.
  Max: The maximum distance between Ref and Targ before movement halts.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref on a path away from location Trg, taking obstacles into account. If Ref is farther than Max steps from Trg, no action will be taken.

## step_rand proc

See also:
  get_step_rand proc
  walk_rand proc
  step_size var (movable atom)

Format:
  step_rand(Ref,Speed=0)

Returns:
  1 on success; 0 otherwise.

Args:
  Ref: A mob or obj.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref randomly.

## step_to proc

See also:
  get_step_to proc
  get_steps_to proc
  walk_to proc
  step_size var (movable atom)

Format:
  step_to(Ref,Trg,Min=0,Speed=0)

Returns:
  1 on success; 0 otherwise.

Args:
  Ref: A mob or obj.
  Trg: An object on the map.
  Min: The minimum distance between Ref and Trg before movement halts.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref on a path to the location Trg, taking obstacles into account. If Ref is within Min steps of Trg, no action will be taken. This is also the case if the target is too far away (more than twice world.view steps).

## step_towards proc

See also:
  get_step_towards proc
  walk_towards proc
  step_size var (movable atom)

Format:
  step_towards(Ref,Trg,Speed)

Returns:
  1 on success; 0 otherwise.

Args:
  Ref: A mob or obj.
  Trg: An object on the map.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref in the direction of the location Trg.

## switch proc

See also:
  if proc
  #pragma syntax directive

Format:

switch(E)
  if(A1,A2,...) Statement1
  if(B1,B2,...) Statement1
  else Statement3

The "switch" instruction is a compact notation for a lengthy "else-if" chain. The expression E is compared to the values A1, A2, B1, B2, etc. When a match is found, the following statement (or code block) is executed. An optional "else" statement is run if no match is found. Once a matching switch condition is found, no further conditions will be tested.

The values A1, A2, etc. must be constants. As a convenience, a range of values may be specified in the form: A1 to An.

The switch instruction is MUCH more efficient than a lengthy "else-if" chain, because the expression E is evaluated only once. The conditional values may be any constant expression, such as a number or text string.

### Example:

    switch (2)
      if(1)       world << "ONE"
      if(4)       world << "FOUR"
      if(2,3)     world << "TWO or THREE"
      if(5 to 10) world << "FIVE to TEN"
      else        world << "not ONE to TEN"

This outputs:

    TWO or THREE

Note: Currently the compiler does not throw a warning or error if there is a conflict between two different `if` blocks in a `switch`, e.g. when you define `if(1 to 10)` and `if(5 to 20)` which overlap from 5 to 10. If two different blocks could handle a given value, the choice of which block takes over is not defined.

### C-like syntax

Using the `#pragma syntax` directive you can change `switch()` to be more like other languages such as C. This replaces the if/else instructions with `case value` and `default` with a trailing colon. If you don't use the `break` statement at the end of a block, it will fall through to the next block.

### Example:

    // make this syntax change temporary
    #pragma push
    #pragma syntax C switch

    mob/proc/Greeting(friend)
        switch(roll(6))
            case 4:
                friend << "I'm [name]. \..."
                // fall through to cases 1 and 2
            case 1,2:
                friend << "Hi!"
                break
            case 3:
                friend << "Hello there!"
            default:
                friend << "Yo."
                break

    #pragma pop

Multiple cases can be put together with either commas between the values, or separate `case` statements. The `A to B` syntax is still allowed also.

## tan proc

See also:
  arctan proc
  cos proc
  sin proc
  turn proc

Format:
  tan(X)

Returns:
  The tangent of X, where X is in degrees.

### Example:

    mob/verb/test()
       usr << tan(0)  // 0
       usr << tan(45) // 1
       usr << tan(90) // infinity (or close enough)

## text proc

See also:
  << operator
  macros (text)

Format:
  text(FormatText,Args)

Returns:
  The text with macros arguments substituted.

Args:
  FormatText: a text string possibly containing text macros.
  Args: a set of arguments that corresponds to the number of empty embedded expressions in FormatText.

Complicated or lengthy embedded expressions in a text string can sometimes make the string difficult to read. In this case, one can use trailing arguments. The position in which the expression should be substituted should be marked with [] and the expression should then be passed as an argument after the text string.

### Example:

    usr << text("You are [] leagues from home.",sqrt(usr.x**2 + usr.y**2))

## text2ascii proc

See also:
  ascii2text proc
  entities (text)
  Unicode

Format:
  text2ascii(T,pos=1)

Args:
  T: A text string.
  pos: The byte position in T to use, starting at 1.

Returns:
  A number representing the character's ASCII or Unicode code.

ASCII codes are numerical values corresponding to keyboard and special characters. Among other things, they are used to represent many symbols in HTML. This proc converts a text string to its corresponding ascii representation.

### Example:

    world << text2ascii("A")  // = 65
    world << text2ascii("HAPPY",2)  // = 65

With Unicode, things may get more complicated. DM stores text with UTF-8 encoding, so at this position there might be several bytes strung together to make a single character. The value of `pos` is in bytes, not characters. When the return value is 128 (0x80) or higher, multiple bytes are used for the charcter. In that case the next character position is not `pos + 1` like it is for regular text, but you can use `pos + length(ascii2text(result))` instead. Or, you can determine the byte count from this table:

Character code | Size in bytes
--- | ---
0 - 0x7F | 1
0x80 - 0x7FF | 2
0x800 - 0xFFFF | 3
0x10000 - 0x10FFFF | 4

Alternatively, you can use `test2ascii_char()` to work with character positions instead of bytes, at a performance cost.

## text2file proc

See also:
  file2text proc
  shell proc

Format:
  text2file(Text,File)

Args:
  Text: text to be added to file
  File: file to be appended to

Returns:
  1 on success; 0 otherwise.

Appends text to a file. If the file does not exist, one will be created.

This can be useful when interacting with external applications that read output from a text file. For example, you might have an external program that mimics conversation:

### Example:

    mob/oracle/verb/tell(T as text)
      text2file(T,"oracle.in")
      shell("oracle < oracle.in > oracle.out")
      usr << file2text("oracle.out")

## text2num proc

See also:
  istext proc
  num2text proc

Format:
  text2num(T)
  text2num(T, radix)

Args:
  T: A text string.
  radix: The radix/base of the number, e.g. 16 for hexadecimal

Returns:
  A number.

If T is a text string for a number, return the number. Any non-numeric text following the initial portion will be ignored. If there is no initial numeric portion, the result is null.

### Example:

    var/number = text2num("123")  // = 123

The optional radix, which defaults to 10, can be any integer from 2 to 36.

## text2path proc

See also:
  ispath proc

Format:
  text2path(T)

Args:
  T: A text string.

Returns:
  a type path or null.

### Example:

    var/myturf = text2path("/turf/[src.color]")
    if(myturf)
      src.loc = locate(myturf)

T is changed from a text string to the equivalent type path, or null if there is no such type.

## throw statement

See also:
  try statement
  Error proc (world)
  EXCEPTION proc
  exception

Format:
  throw Value

Args:
  Value: Any value, which will be sent to catch() if present.

This keyword throws an exception, which will stop executing the current proc and go to the most recent catch block if one is present. The catch block will receive the thrown value. If there is no try/catch in use, the exception will be passed to `world.Error()` (if present), then the current proc will end and control will return to the caller.

### Example:

    try
      if(!src.ready) throw EXCEPTION("Not ready")
      DoSomething()
    catch(var/e)
      world.log << "Exception: [e]"

You can use the `EXCEPTION` macro to create a new `/exception` datum, which contains a value or message as well as the file and line number where the exception was created. The thrown value does not have to be an `/exception` datum; you can throw anything, even null.

## time2text proc

See also:
  realtime var (world)
  timeofday var (world)
  timezone var (world)
  timezone var (client)

Format:
  time2text(timestamp,format,timezone)

Args:
  timestamp: a time value as obtained from world.realtime or world.timeofday
  format: a text string describing the output format.
  timezone: optional offset, in hours, from UTC

Returns:
  a text string containing the date and time in the specified format.

A time value (UTC) is converted to text representing the time. The world's local time is used, unless you specify a `timezone` argument which will add an offset to UTC.

The default format is "DDD MMM DD hh:mm:ss YYYY", which produces results such as "Wed, May 23 15:41:13 2001". As you can see, the fields in the format text are replaced by components of the date and time. The following list contains all of the recognized fields. Anything else in the format string is inserted directly into the output.

YYYY
  year (2001, 2002, ...)
YY
  year (01, 02, ...)
Month
  January, February, ...
MMM
  Jan, Feb, ...
MM
  number of the month (01, 02, ...)
Day
  Monday, Tuesday, ...
DDD
  Mon, Tue, ...
DD
  day of the month
hh
  hour (00, 01, ... 23)
mm
  minute
ss
  second

Because world.timeofday is in a range of 0 to 864000, values in this range are treated as a time for the current date. This way time2text() can return accurate results for world.timeofday. Any other values are interpreted as coming from world.realtime and will have the right time and date.

## trimtext proc

See also:
  copytext proc

Format:
  trimtext(Text)

Returns:
  Text with whitespace trimmed from both ends

Args:
  Text: The text string to trim.

Trims whitespace from both ends of a text string.

All Unicode whitespace characters are counted, whether they can cause a break or not.

## trunc proc

See also:
  fract proc
  floor proc
  ceil proc
  round proc
  sign proc

Format:
  trunc(A)

Returns:
  truncated A

Args:
  A: A number, pixloc, or vector.

Returns the integer part of the number A. That is, this rounds toward 0 to an integer.

### Example:

    usr << trunc(1.45) // outputs 1

    usr << trunc(-1.45) // outputs -1

## try and catch statements

See also:
  Error proc (world)
  throw statement
  EXCEPTION proc
  exception

The try and catch keywords are used for error handling. Any code that runs inside of a try block will, if an error happens or the throw keyword is used, stop executing and jump to the matching catch block. (This is also true of indirect proc calls. If you call a proc from inside a try block, any errors in that proc will be sent to the catch.)

For every try there must be a catch, even if it does nothing. The catch block takes an optional value that can receive the error.

### Example:

    var/a = 2
    try
      a += "Hello"  // will throw a type mismatch error
    catch(var/exception/e)
      // file and line info is available if you enable debugging
      world.log << "[e] on [e.file]:[e.line]"
    world << "a is [a]"

Because the value in the catch keyword is optional, you can simply use the catch keyword alone. It is also not necessary to include any code under the catch keyword, if the error is meant to be ignored. (However, it is not usually a good idea to ignore errors.)

The throw keyword is used if you want to throw an error deliberately. When you use throw, the error thrown does not have to be an /exception datum, but can be anything you like.

## turn proc

See also:
  Turn proc (icon)
  dir var (atom)
  Turn proc (vector)

Format:
  turn(Dir, Angle)

Args:
  Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST.
  Angle: An angle in degrees (counterclockwise rotation).

Returns:
  The rotated direction.

This proc can also be applied to an icon, a matrix, or a vector.

### Example:

    var/dir
    dir = turn(NORTH, 90)  // dir = west
    dir = turn(dir, -90)   // dir = north
    dir = turn(dir, 45)    // dir = northwest

Only multiples of 45 are allowed for angles. If an invalid angle is used, it will be treated as the closest multiple of 45 to 0.

If the supplied Dir is invalid, such as 0, or something like UP or DOWN, the result is a random direction unless the angle is also 0.

## turn proc (applied to an icon)

See also:
  turn proc
  icon

Format:
  turn(Icon, Angle)

Returns:
  The rotated icon.

Args:
  Icon: an icon to rotate
  Angle: An angle in degrees (clockwise rotation).

### Example:

    mob/verb/drink()
       //this effect is very confusing!
       usr.icon = turn(usr.icon,90)
       usr << "Woah!  That stuff is powerful!"
       sleep(200)
       usr.icon = turn(usr.icon,-90)

An icon that is not square will not be turned.

If the icon is an /icon datum, a new datum will be created as the result.

## turn proc (applied to a matrix)

See also:
  turn proc
  matrix

Format:
  turn(Matrix, Angle)

Returns:
  A new matrix which has been rotated.

Args:
  Matrix: a matrix to rotate
  Angle: An angle in degrees (clockwise rotation).

### Example:

    mob/verb/drink()
       //this effect is very confusing!
       usr.transform = turn(usr.transform, 90)
       usr << "Woah!  That stuff is powerful!"
       sleep(200)
       usr.transform = null

## turn proc (applied to a vector)

See also:
  vector
  vector proc
  Turn proc (vector)

Format:
  turn(vector/A, angle)
  turn(vector/A, vector/B)

Returns:
  A new rotated vector.

Args:
  A: The vector to rotate.
  angle: An angle to turn a vector counter-clockwise in 2D.
  B: A vector to rotate around (left-hand rule).

All angles are in degrees.

When the argument is an angle, the result is a copy of vector A, rotated in 2 dimensions counter-clockwise.

When the argument is a vector, the result is rotated in 3 dimensions around vector B using the left-hand rule (thumb pointed in the direction of B, rotation following curled fingers). The angle of rotation is the length of B, in degrees.

## typesof proc

See also:
  istype proc
  locate proc

Format:
  typesof(Type1,Type2,...)

Returns:
  A list of all types that are derived from the specified "base" types, including the base types themselves.

Args:
  The "base" types.

### Example:

    obj/fruit
      apple
      peach
      mango
    var/list/fruit_types = typesof(/obj/fruit)

In this example, fruit_types is initialized to contain /obj/fruit, /obj/fruit/apple, /obj/fruit/peach, and /obj/fruit/mango.

This procedure can also be used to list procs and verbs.

### Example:

    mob/admin_commands/verb
       shutdown_world()
          world.Del()
       reboot_world()
          world.Reboot()

    //for testing
    mob/verb/add_admin()
       verbs += typesof(/mob/admin_commands/verb)
    mob/verb/remove_admin()
       verbs -= typesof(/mob/admin_commands/verb)

## uppertext proc

See also:
  lowertext proc

Format:
  uppertext(T)

Returns:
  A capitalized text string.

Args:
  T: A text string.

Capitalize all of the characters of T.

### Example:

    U = uppertext("hi there") // = "HI THERE"

## url_decode proc

See also:
  Topic proc (client)
  url_encode proc

Format:
  url_decode(UrlText)

Args:
  UrlText: text to be "unescaped"

Returns:
  unescaped text

Most non-alphanumeric characters are converted to another format in a URL. To send these characters literally, they must be "escaped".

The `url_decode()` instruction takes a text string containing such escaped symbols and turns them into their literal counterparts. Usually this is done for you automatically in `Topic()`. The more useful function is `url_encode()` which does the reverse.

## url_encode proc

See also:
  url_decode proc

Format:
  url_encode(PlainText, format=0)

Args:
  PlainText: text to be URL "escaped"
  format: 0 to treat PlainText as a query string, 1 to treat it as a full URL

Returns:
  escaped text

Special characters such as spaces are not used literally in URLs. If you want to ensure that an entire text string is sent literally, you can "escape" those characters. For example, a double quote (ASCII 34) is produced by the code `%22`, where 22 is hexadecimal for 34.

The `url_encode()` instruction does this for you automatically. Using `format=1` will treat the URL as already encoded and only re-encode characters that don't belong in the result. Otherwise PlainText is treated as part of a query string; in this case spaces are converted to `+` instead of `%20`, and most characters are escaped.

### Example:

    mob/verb/Private(M as mob in players, T as text)
       if(!client || !M || !M.client || !T) return
       usr << "\[To <a href='?msg=[url_encode(M.key)]'>[M.name]</a>\] [T]"
       M << "\[From <a href='?msg=[url_encode(key)]'>[name]</a>\] [T]"

## values_cut_over proc

See also:
  list associations
  values_cut_under proc

Format:
  values_cut_over(Alist, Max, inclusive=0)

Returns:
  Number of items removed

Args:
  Alist: An associative list or alist
  Max: The maximum number allowed
  inclusive: Also cut items whose value equals Max

Removes all items from the list whose associated values are greater than Max, not numbers, or NaN.

If the optional `inclusive` argument is true, items with associated values equal to Max are removed also.

### Example:

    var/list/stuff = list("a"=1, "b"=2, "c"=-4)
    values_cut_over(stuff, 0)
    for(var/k,v in stuff)
        usr << "[k] = [v]"
    // prints:
    // c = -4

This is a convenience proc for games trying to eke out high performance.

If Alist is not an associative list, nothing happens.

## values_cut_under proc

See also:
  list associations
  values_cut_over proc

Format:
  values_cut_under(Alist, Min, inclusive=0)

Returns:
  Number of items removed

Args:
  Alist: An associative list or alist
  Min: The maximum number allowed
  inclusive: Also cut items whose value equals Min

Removes all items from the list whose associated values are less than Min, not numbers, or NaN.

If the optional `inclusive` argument is true, items with associated values equal to Min are removed also.

### Example:

    var/list/stuff = list("a"=1, "b"=2, "c"=-4)
    values_cut_under(stuff, 0)
    for(var/k,v in stuff)
        usr << "[k] = [v]"
    // prints:
    // a = 1
    // b = 2

This is a convenience proc for games trying to eke out high performance.

If Alist is not an associative list, nothing happens.

## values_dot proc

See also:
  list associations
  values_sum proc
  values_product proc
  values_cut_over proc
  values_cut_under proc
  alist proc

Format:
  values_dot(A, B)

Returns:
  The dot product of all associated numbers in A and B

Args:
  A, B: An associative list or alist

Returns the dot product of two associative lists. If the same item exists in both lists, the associated values are multiplied together as numbers. All of those multiplications are added together to form the dot product. This is similar to vector dot products.

### Example:

    var/list/first = list("a"=1, "b"=2, "c"=3)
    var/list/second = list("b"=4, "c"=5, "d"=6)
    // first["a"] * second["a"] = 1 * 0 = 0
    // first["b"] * second["b"] = 2 * 4 = 8
    // first["c"] * second["c"] = 3 * 5 = 15
    // first["d"] * second["d"] = 0 * 6 = 0
    // total is 23
    usr << values_dot(first, second)  // outputs 23

This is a convenience proc for games trying to eke out high performance.

## values_product proc

See also:
  list associations
  values_sum proc
  values_dot proc
  values_cut_over proc
  values_cut_under proc
  alist proc

Format:
  values_product(Alist)

Returns:
  The product of all associated numbers in Alist, or 1 if no numbers were found

Args:
  Alist: An associative list or alist

Returns the product of all associated values in this list that are numbers. Other values, including vectors, are not multiplied.

### Example:

    var/list/stuff = list("foo" = 3, "bar" = -4, "banana" = 5)
    usr << values_product(stuff)  // outputs -60

This is a convenience proc for games trying to eke out high performance.

If Alist is not an associative list or no numbers were found among the associated values, the result is 1.

## values_sum proc

See also:
  list associations
  values_product proc
  values_dot proc
  values_cut_over proc
  values_cut_under proc
  alist proc

Format:
  values_sum(Alist)

Returns:
  The sum of all associated numbers in Alist

Args:
  Alist: An associative list or alist

Returns the sum of all associated values in this list that are numbers. Other values, including vectors, are not summed.

### Example:

    var/list/weights = list(/obj/crate = 12, /obj/vase = 1)
    usr << values_sum(weights)  // outputs 13

This is a convenience proc for games trying to eke out high performance.

If Alist is not an associative list, the result is 0.

## vars (procs)

See also:
  procs

Built-in proc vars:

proc/var
  .
  args
  callee
  caller
  src
  usr

## . var (proc)

See also:
  return statement
  vars (procs)

This is the default return value. If a proc exits without calling return or if no arguments are specified the value of `.` will be returned. The default value of `.` is null.

### Example:

    mob/Login()
      . = ..()
      view() << "[src] logs in."

## args list var (proc)

See also:
  list

This is a list of the arguments passed to the proc or verb.

### Example:

    proc/add()
      var {cur; tot}
      for(cur in args)
        tot += cur
      return tot

Here, `add()` may be called with any number of arguments, each accessed through the `args` list.

## callee var (proc)

See also:
  callee
  caller var (proc)

Returns a callee object representing the current running proc. This is seldom as useful as the `caller` var, but is available if it's needed.

## caller var (proc)

See also:
  callee
  callee var (proc)

Returns a callee object representing the current proc's caller, which can be used to access information like the proc name, line number (if compiled with debug information), arguments, and more.

The main purpose of this is to make it possible to trace the call stack when handling errors.

### Example:

    world/Error(err)
        world.log << "Error [err]:"
        for(var/callee/p = caller, p, p = p.caller)
            world.log << "  [p.type] (src=[p.src], usr=[p.usr])"
            if(p.file) world.log << "    at [p.file]:[p.line]"

## global var (proc)

See also:
  src var (proc)

This is not really a variable but is used to force treatment of the following variable or proc as global. This may be necessary if a local or src-level variable has the same name.

### Example:

    var/myvar = "global"
    mob
      verb/test()
        var/myvar = "local"
        usr << myvar
        usr << global.myvar

This example outputs "local" and then "global".

## src var (proc)

See also:
  usr var (proc)
  procs
  verbs

This is a variable equal to the object containing the proc or verb. It is defined to have the same type as that object.

### Example:

    obj/bread
      verb/eat()
        world << "[usr] eats [src]"

If a player named "Bob" calls "eat bread", the output will be "Bob eats the bread."

Note that `src` has no meaning for global procs, derived from `/proc`, unless they are invoked as verbs (by being attached to a verb list).

## usr var (proc)

See also:
  src var (proc)
  verbs
  Topic proc (client)
  range proc
  view proc
  alert proc
  input proc

This is a mob variable (var/mob/usr) containing the mob of the player who executed the current verb, or whose action ultimately called the current proc.

### Example:

    obj/bread
      verb/eat()
        world << "[usr] eats [src]"

If a player named "Bob" calls "eat bread", the output will be "Bob eats the bread."

Essentially, `usr` is an implicit parameter that is passed to every proc or verb. Each procedure inherits the value from its caller. While it can simplify your code in some situations, it can also lead to subtle problems if you are assuming that `usr` is automatically assigned the value of `src` when you call a verb programmatically. It is not.

The only time `usr` is assigned for you is when a player executes a verb, clicks something with the mouse, clicks a link (see Topic), or any other such action.

Note: A good rule of thumb is to never put usr in a proc, only verbs. Typically `usr` in a proc is an unsafe programming practice. If `src` would not be the correct choice, it is better to send another argument to your proc with the information it needs.

Certain built-in procs such as atom/Click() are called automatically by a client counterpart like client/Click(); usually atom/Stat() is called by client/Stat(); and so on. It is mostly safe to apply `usr` as directed in those situations, because these procs are pseudo-verbs. It is mostly not safe to apply `usr` in a movement proc such as Move() or Enter(), because objs and non-player mobs may move autonomously without setting `usr`.

Although `usr` is often set in mob/Login() when a client first connects, you should not assume it is valid if `Login()` is called any other way. Common cases occur when creating a new character, loading a player's mob from a savefile; or explicitly when setting a mob's key or changing the value of client.mob. It is safest to use `src` in `mob/Login()`, which is always correct, rather than `usr`.

`usr` is the default point of reference for several procs like view() and range(), because of their common use in verbs. It is also the default recipient for input() and alert() messages. When using these in procs, be aware of that so you can change the default reference value to something more appropriate.

## vector proc

See also:
  vector
  pixloc

Format:
  vector(x,y)
  vector(x,y,z)
  vector(String)
  vector(List)
  vector(Vector)
  vector(Pixloc)

Returns:
  A new vector.

Args:
  x,y,z: Components of the new vector.
  String: A text string to parse as a vector, where the delimiter between numbers can be a comma or x.
  List: A numeric list to copy as a vector.
  Vector: A vector to copy.
  Vector: A pixloc to copy as a vector.

Creates a vector.

## view proc

See also:
  << output operator
  hearers
  oview proc
  range proc
  see_in_dark var (mob)
  see_infrared var (mob)
  see_invisible var (mob)
  sight var (mob)
  view var (client)
  view var (world)
  viewers

Format:
  view(Dist=5,Center=usr)

Returns:
  A list of visible objects within Dist tiles of Center.

Args:
  Dist: A number.
  Center: An object on the map.

A Dist of 0 includes Center, the contents of Center (normally usr.contents), its location (normally the turf a mob is standing on), and any other contents of that location. A value of 1 extends the region to the neighboring squares on the map and so on. Both arguments are optional and may be passed in any order.

The default range is actually controlled by the size of the map viewport size, which is configured with `world.view`. Since the default value of that variable is 5, the default range is also 5. You may use any valid view size, so an explicit view size such as "11x17" is also valid.

### Example:

    view() << "to all in sight of [usr]"
    view(src) << "to all in sight of [src]"
    view(1,src.loc) << "to all within reach of [src]"

Be aware of the following distinctions:

    view(usr)         //objects that usr can see
    view(usr.loc)     //objects visible from usr's position
    view(usr.client)  //objects visible to player

In many cases, the three different statements could produce the same result, but they are not identical in general. For example, the first statement takes into account the visual capabilities of usr, which might include such things as the ability to see in the dark or to see invisible objects.

The second statement, since it is from a non-mob would just do a plain visibility calculation with no special visual capabilities. In many cases, you would want to use viewers() or hearers() instead.

The third statement produces a list of visible objects as the player sees things, which might be different than how the mob sees things if `client.eye` and `client.mob` are different.

## viewers

See also:
  hearers
  oviewers
  view proc

Format:
  viewers(Depth=world.view,Center=usr)

This is just like `view()`, but it is a list of mobs that can see the center object, rather than a list of objects visible to the center object.

## walk proc

See also:
  get_step proc
  step proc
  step_size var (movable atom)

Format:
  walk(Ref,Dir,Lag=0,Speed=0)
  walk(Ref,Vector,Lag=0)

Args:
  Ref: A mob or obj.
  Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, or 0 to halt.
  Lag: Delay in world ticks between movement.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.
  Vector: 2D vector to move by, in pixels.

Move Ref in the direction Dir continuously. Each step will be preceded by Lag time of inactivity.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.

The vector version of this proc will make a copy of the vector, so changing the vector afterward won't have an effect on existing walking.

## walk_away proc

See also:
  get_step_away proc
  step_away proc
  step_size var (movable atom)

Format:
  walk_away(Ref,Trg,Max=5,Lag=0,Speed=0)

Args:
  Ref: A mob or obj.
  Trg: An object on the map.
  Max: The maximum distance between Ref and Targ before movement halts.
  Lag: Delay in world ticks between movement.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Moves Ref on a path away from Trg continuously, taking obstacles into account. Each step will be preceded by Lag time of inactivity. If Ref is farther than Max steps from Trg, no action will be taken.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.

## walk_rand proc

See also:
  get_step_rand proc
  step_rand proc
  step_size var (movable atom)

Format:
  walk_rand(Ref,Lag=0,Speed=0)

Args:
  Ref: A mob or obj.
  Lag: Delay in world ticks between movement.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Moves Ref randomly. Each step will be preceded by Lag time of inactivity.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.

## walk_to proc

See also:
  get_step_to proc
  step_to proc
  step_size var (movable atom)

Format:
  walk_to(Ref,Trg,Min=0,Lag=0,Speed=0)

Args:
  Ref: A mob or obj.
  Trg: An object on the map.
  Min: The minimum distance between Ref and Trg before movement halts.
  Lag: Delay in world ticks between movement.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref on a path to Trg continuously, taking obstacles into account. Each step will be preceded by Lag time of inactivity. If Ref is within Min steps of Trg, no action will be taken. This is also true if the target is too far away (more than twice world.view steps).

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.

## walk_towards proc

See also:
  get_step_towards proc
  step_towards proc
  step_size var (movable atom)

Format:
  walk_towards(Ref,Trg,Lag=0,Speed=0)

Args:
  Ref: A mob or obj.
  Trg: An object on the map.
  Lag: Delay in world ticks between movement.
  Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref in the direction of Trg continuously. Each step will be preceded by Lag time of inactivity.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.

## while proc

See also:
  break statement
  continue statement
  do proc
  for loop proc

Format:
  while(E) Statement

If E is true (non-zero) execute Statement. Continue testing E and doing the while block until E becomes false (zero).

Statement may be a block of code or a single statement.

### Example:

    var/i = 3
    while(i)
      world << i--

This outputs:

    3
    2
    1

## winclone proc

See also:
  winexists proc
  winget proc
  winset proc
  winshow proc
  User interface skins

Format:
  winclone(player, window_name, clone_name)

Args:
  player: A mob or client.
  window_name: The name of a window, pane, menu, or macro set in the world's skin file.
  clone_name: The name of the new window, pane, menu, or macro set to create.

Creates a clone of a window, pane, menu, or macro set that exists in the world's skin file. The original object as it exists in the skin file (not its current state) is used as a template to build the clone. The clone will exist only for the player you choose.

### Example:

    winset(usr, "templatewindow", "clonedwindow")

If a window is not visible by default, it will have to be shown with `winset()` or `winshow()`. A pane may be shown by using it in a Child or Tab control. Menus or macros must be assigned to a window with `winset()` before they will work.

If window_name is "window", "pane", "menu", or "macro", and the skin file does not have a control of that name already, the proc will create a new control of that type from scratch.

### Example:

    winclone(usr, "menu", "newmenu")
    winset(usr, "newmenu_file", "parent=newmenu;name=File")
    winset(usr, "newmenu_quit", "parent=newmenu_file;name=Quit;command=.quit")

A new window is invisible by default. For windows and panes, you should give them a size with `winset()` before adding any controls so you can set their anchors properly.

### Example:

    // Create the pane
    winclone(usr, "pane", "newpane")
    // Give it a size so we can figure out where to put controls
    winset(usr, "newpane", "size=100x100")
    // Add controls
    winset(usr, "newpane_label", \
           "parent=newpane;pos=0,0;size=100x100;anchor1=0,0;anchor2=100,100")
    // Put the pane in a child control where it can be seen
    winset(usr, "a_child", "left=newpane")
    usr << output("New label", "newpane_label")

Once a clone is created, it can be deleted via a `winset()` call:

### Example:

    winset(usr, "clonedwindow", "parent=none")

## winexists proc

See also:
  winclone proc
  winget proc
  winset proc
  winshow proc
  User interface skins
  type parameter (skin)

Format:
  winexists(player, control_id)

Args:
  player: A mob or client.
  control_id: The unique ID of a control in the player's skin.

Tells if a control exists and if so, what type it is. The return value is an empty string if the control does not exist, but otherwise it is the type of control.

This proc will not tell you if a control has been defined in the skin file but is not in use yet.

Because the client must be contacted to get this information, winexists() will sleep the current proc.

## winget proc

See also:
  winexists proc
  winset proc
  User interface skins
  parameters (skin)

Format:
  winget(player, control_id, params)

Args:
  player: A mob or client.
  control_id: The unique ID of a control in the player's skin.
  params: The name of a parameter to read, or a semicolon-separated list of parameters

Retrieves info from a player about the current state of their skin. If `control_id` and `params` are each just a single value, then the return value will be a simple string with the value of that parameter. If `control_id` or `params` is a semicolon-separated list like the kind used in `list2params()`, then the result will be in a similar format, and can be converted to a list form using `params2list()`.

The `control_id` can be a window name, or in a `"[window].[control]"` format, or just the control's ID itself as long as it is unique. Another valid form is `":[type]"` which selects the default control of that type, e.g. `":map"` for the main map. As mentioned above, you can retrieve info on more than one control at once by separating them with semicolons, like `"button1;button2"`.

### Example:

    usr << "mainwindow.is-visible = [winget(usr, "mainwindow", "is-visible")]"
    usr << "\nOther params:"
    usr << winget(usr, "mainwindow", "pos;is-maximized")
    usr << "\nButtons:"
    usr << winget(usr, "button1;button2", "is-checked")

This outputs:

    mainwindow.is-visible = true

    Other params:
    pos=0x0;is-maximized=true

    Buttons:
    button1.is-checked=true;button2.is-checked=false

If the returned result is actual text for any parameters, the single quote or double quote characters may be escaped with a backslash. An actual backslash will also be escaped with a backslash.

You can also use a special wildcard format to retrieve info about all the controls in a window, menu, or macro set. If control_id is `"mainwindow.*"` for instance, then any control that is part of `mainwindow`—and `mainwindow` itself—is included in the result if it has the parameter(s) you're looking for. Use `params2list()` to interpret the result.

Note: Because the client must be contacted to get this information, `winget()` will sleep the current proc.

### Special wingets

Calling `winget()` with a blank or null `control_id` can return some values that belong to the client as a whole, not to specific controls. They can also be used for embedded wingets.

focus
  The full ID of the control, if any, that currently has keyboard focus.
windows
  The IDs of all windows, separated by semicolons.
panes
  The IDs of all panes, separated by semicolons.
menus
  The IDs of all menus, separated by semicolons.
macros
  The IDs of all macro sets, separated by semicolons.
sound
  True if sounds are enabled.
hwmode
  True if the map displays in hardware rendering mode.
url
  The URL the client is connected to in `IP:port` form. The port is 0 if connected to a local .dmb file, and either an empty string or null is returned if Dream Seeker is not connected at all.
num-lock
  True if Num Lock is on.
caps-lock
  True if Caps Lock is on.
scroll-lock
  True if Scroll Lock is on.
dpi
  Application DPI setting: 1 is normal, 1.25 is +25%, etc.
screen-pos
  Top left of main monitor's application area.
screen-size
  Size of main monitor's application area.

## winset proc

See also:
  winclone proc
  winexists proc
  winget proc
  winshow proc
  User interface skins
  parameters (skin)

Format:
  winset(player, control_id, params)

Args:
  player: A mob or client.
  control_id: The unique ID of a control in the player's skin.
  params: A text string with parameters to set, in the format returned by `list2params()`; OR an associative list.

Sets parameters for a player's skin. The parameter list can be created by making a list and using `list2params()`, or it can be done manually by just using a string like `"is-visible=true;text-color=#f00"`. You can also just use a list directly, which will be passed to `list2params()` internally.

The `control_id` can be a window name, or in a `"[window].[control]"` format, or just the control ID as long as it is unique. In some special cases it can also be null. Another valid form is `":[type]"` which selects the default control of that type, e.g. `":map"` for the main map.

If you want to use a text string that may include spaces, surround the string with double quotes and escape them using a backslash, e.g. `"text=\"This is some text.\""`. Backslashes can also be used by preceding them with another backslash. For filenames, use single quotes around the file. Sometimes escapement may need to go several levels deep; for example to set up an input control with a default say command, you will need to escape it twice:

> Desired command: `say "`
> Escaped form with quotes: `"say \""`
> Final form: `\"say \\\"\"`

> `winset(usr, "mainwindow.input", "command=\"say \\\"\"")`

You can set more than one control's parameters at once by leaving the `control_id` argument null, and including the control as part of the parameter list:

    winset(usr, null,\
      "mainwindow.output.background-color=#ffffff;mainwindow.input.background-color=#ffffff")

### Special winsets

Some "global" winset options will let you change things that affect the client as a whole, not just specific controls.

#### reset

You can reset the skin to its beginning state, removing all runtime-created controls and windows, by calling `winset(player, null, "reset=true")`.

#### command

Another use for `winset()` is to send commands to the client that normally can only run from there, like `.profile` or `.quit`. To do this, leave the `control_id` argument null, and just use a parameter called "command":

    obj/quitbutton
        name = "Quit"
        icon = 'buttons.dmi'
        icon_state = "quit"

        Click()
            winset(usr, null, list("command"=".quit"))

Because many characters need to be specially encoded for winsets, it's best to either use the list format of `winset()` which handles that encoding for you. If you want to use the string form, like `winset(usr, null, "command=XYZ")`, then you should use url_encode() to encode your command.

#### browser-options

The "browser-options" global parameter lets you enable or disable certain browser functionality. This can be a comma-separated list, or you can precede an option with `+` or `-` to enable or disable it specifically.

Option | Default | Description
--- | --- | ---
find | ❌ | Ctrl+F can open the built-in Find dialog.
devtools | ❌ | F12 can open a devtools window, which is useful for debugging scripts.
refresh | ❌ | Ctrl+R or F5 can refresh the page.
zoom | ❌ | Ctrl with the + or - keys can zoom the browser, and Ctrl+0 can reset it.
byondstorage | ❌ | Enables byondStorage access.

### Example:

    mob/Login()
        ..()
        winset(usr, null, "browser-options=devtools,find")

If you plan to use the `+` or `-` modifiers, you should either use the list format of `winset()` or use url_encode() to encode the list of options.

Browser options are shared across all browser controls.

## winshow proc

See also:
  winclone proc
  winget proc
  winset proc
  User interface skins
  is-visible parameter (skin)

Format:
  winshow(player, window, show=1)

Args:
  player: A mob or client.
  window: The name of a window in the player's skin.
  show: Use a nonzero value to show the window, zero to hide it.

Shows or hides a window in the player's skin. This is a shortcut, equivalent to setting `is-visible` via `winset()`.

## regex datum

See also:
  Regular expressions
  regex procs
  regex vars
  regex proc
  REGEX_QUOTE proc
  findtext proc
  splittext proc
  stddef.dm file

The /regex datum holds a regular expression that can be used for searching and/or replacing text. Rather than searching for a specific piece of text, a regular expression is a pattern to search for. This can include things like wildcards. See Regular expressions for more information.

A new regular expression can be created with regex() or new/regex().

## regex procs

See also:
  regex datum
  regex vars
  regex proc

regex/proc
  New
  Find
  Replace

## Find proc (regex)

See also:
  Regular expressions
  regex datum
  Replace proc (regex)
  regex vars
  regex proc
  findtext proc

Format:
  Find(haystack, Start=1, End=0)

Returns:
  The position of the matched text, or 0 if no match was found.

Args:
  haystack: The text to be searched
  Start: The start position (in bytes) to search; defaults to 1, or to src.next if this is a global pattern
  End: The position of the byte after the end of the search; 0 is the end. The actual match is allowed to extend past End.

Finds the regular expression pattern within the "haystack" text. The following vars are set by the match:

- text: The text that was searched.
- index: The index where the match was found (same as the return value)
- match: The actual matched text
- group: If the expression contains capturing groups with the ( ) parentheses operator, this is a list that holds the text found in those groups. group[1] is the first group, and so on.
- next: If the "g" flag was used to create thie expression, this is the next index to begin searching.

In a global expression (using the "g" flag), Find() can be called repeatedly on the same piece of text and the Start position will be advanced automatically unless you specify it.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `Find_char()` to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

## New proc (regex)

See also:
  Regular expressions
  regex datum
  regex proc

Format:
  regex(pattern, flags)
  regex(Regex)

Args:
  pattern: The pattern string to search for
  flags: (optional) A text string containing any combination of modifier flags
  Regex: an existing /regex datum to copy

Calling new/regex() is the same as calling regex(). It will create a new /regex datum.

## Replace proc (regex)

See also:
  Regular expressions
  regex datum
  Find proc (regex)
  regex vars
  regex proc
  replacetext proc

Format:
  Replace(haystack, replacement, Start=1, End=0)

Returns:
  The original haystack string with the first match replaced. If using the "g" flag, all matches are replaced.

Args:
  haystack: The text to be searched
  replacement: A piece of text, OR a proc, that will be used to replace the match
  Start: The start position (in bytes) to search; defaults to 1, or to src.next if this is a global pattern
  End: The position of the byte after the end of the search; 0 is the end. The actual match is allowed to extend past End.

Finds the regular expression pattern within the "haystack" text, and replaces the match with the given replacement value.

In a non-global expression (not using the "g" flag), the values of src.index and src.next are set as they would be in a global Find(). See the Find() proc for more info.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use `Replace_char()` to work with character counts instead of bytes. See the Unicode section for more information.

### Replacing with text

If the replacement value is text, the $ character is treated as special. If you want to use the actual dollar sign, it must be escaped with a second dollar sign. Otherwise, the $ character is one of these special values:

Replacement | Value
--- | ---
$1 through $9 | `$1`tt> is whatever was in the first parentheses group, `$2` is the second, and so on.
$` | The text that came before the match
$' | The text that came after the match
$0 or $& | The whole match itself

### Replacing with a proc

If replacing matches with a proc, then the proc will be called with the match as its first argument, and any capturing groups as the following arguments. Whatever the proc returns will be used as the replacement text in place of the match.

### Example

    var/regex/vowels = new("[aeiou]", "i")
    // match any word of 2 letters or more
    var/regex/piglatin = new("\\b(\\l)(\\l+)\\b", "ig")

    // group1 is the first letter, and group2 is everything else
    proc/word2piglatin(match, group1, group2)
    	// If the word starts with a vowel, just add "ay"
        if(vowels.Find(group1)) return "[match]ay"
        // If the word was capitalized, capitalize the replacement
        if(group1 == uppertext(group1))
            group1 = lowertext(group1)
            group2 = uppertext(copytext(group2,1,2)) + lowertext(copytext(group2,2))
        return "[group2][group1]ay"

    mob/verb/PigSay(msg as text)
        msg = html_encode(msg)
        world << piglatin.Replace(msg, /proc/word2piglatin)

## regex vars

See also:
  regex datum
  regex procs
  regex proc

regex/var
  flags
  group
  index
  match
  name
  next
  text

## flags var (regex)

See also:
  Regular expressions
  regex datum
  name var (regex)

The flags that were used to create this regular expression. Changing this value after the datum is created will not change how the expression behaves.

## group var (regex)

See also:
  regex datum
  Find proc (regex)
  index var (regex)
  match var (regex)

After a call to Find(), if this regular expression had any parentheses groups, whatever text was matched in those groups is stored here in a list.

### Example

    var/regex/R = new("B(.)(.)(.)D")
    R.Find("BYOND")     // find this pattern in "BYOND"

The result of the example is that R.group is list("Y","O","N").

## index var (regex)

See also:
  regex datum
  Find proc (regex)
  Replace proc (regex)
  match var (regex)
  next var (regex)

After a call to Find(), this var contains the index where the match was found.

Replace() on a non-global pattern will also store the index of the match here.

## match var (regex)

See also:
  regex datum
  Find proc (regex)
  group var (regex)
  index var (regex)

After a call to Find(), this var contains the text that was matched.

## name var (regex)

See also:
  regex datum
  flags var (regex)

The pattern that was used to create this regular expression. Changing this value after the datum is created will not change how the expression behaves.

## next var (regex)

See also:
  regex datum
  Find proc (regex)
  Replace proc (regex)
  index var (regex)
  match var (regex)

If this is a global pattern (using the "g" flag), then after a call to Find() this var contains the index where next Find() should begin.

Replace() on a non-global pattern will also store the index of the next place to begin a search here. The position to search will be based on the replaced text, which is stored in the text var.

## text var (regex)

See also:
  regex datum
  Find proc (regex)
  index var (regex)
  match var (regex)
  next var (regex)

If this is a global pattern (using the "g" flag), then after a call to Find() this var contains the text that was searched. If that same text is searched again, the next var is the default starting position.

Replace() on a non-global pattern will store the text after replacement here.

## savefile

See also:
  >> operator (savefile)
  << operator (savefile)
  Export proc (client)
  New proc (client)
  procs (savefile)
  vars (savefile)
  tmp vars
  issaved proc
  Read proc (datum)
  Write proc (datum)

A database file in DM is called a "savefile". All of the contents of a savefile reside in a single file. The contents of the file are stored in database directories. These should not be confused with real directories in the external file system. The database directories are all contained inside the one file.

Each database directory contains a list of sub-directories and a buffer in which data may be written. The absolute path to a directory has the following format: "/Dir1/Dir2/...". The current directory may be set by assigning its absolute path name to `savefile.cd`. A relative path (one that doesn't begin with "/") may also be used, in which case the new path starts at the current directory. The path "." stands for the current directory, ".." for its parent, "../.." for its parent's parent, etc.

A savefile may be created with `new/savefile(name)`. The optional name argument may be an external file name (existing or to be created) in double quotes or a file from the resource cache in single quotes. Of course, a variable containing either of these types of values may also be used. If no name is specified, a temporary file will be created, which will be destroyed when the savefile is no longer in use. If a resource cache is specified, a temporary file will be created and the contents of the cached file will be copied into it. Changes will therefore only be temporary.

## operators (savefile)

Built-in savefile operators:

savefile/operator
  <<
  >>

## >> operator (savefile)

See also:
  >> input operator
  << operator (savefile)
  Read proc (datum)

Format:
  F >> Var
  F["Path"] >> Var

Reads a value from a buffer into a variable. If Path is not specified, the current buffer will be used. Otherwise, the buffer at the specified path will be accessed. Whenever the current directory is set, reading starts at the beginning of that buffer (replacing any previous contents). For this reason, when the Path parameter is given, the first value in the specified buffer is always read. If there is no data in the buffer or the end of the buffer has been reached, null is returned.

If the value read is a previously written object, its own directory will be opened and the object's Read proc will be called to load any data that was written in the object's Write proc.

If the value read is a savefile (ie a savefile inside of a savefile), it is treated a little differently. Instead of returning a savefile object, it returns data cached in the world's rsc file. This is to give you control over what file this data is copied into before it is opened as a savefile. If you want to just open it up in a temporary file, do something like this:

    obj
       var
          savefile/myfile
       Read()
          . = ..()   //do the normal stuff
          if(myfile) //load data into a temporary file and create savefile object
             myfile = new/savefile(myfile)

## << operator (savefile)

See also:
  >> operator (savefile)
  << output operator
  Write proc (datum)

Format:
  F << Val
  F["Path"] << Val

Writes Val to a buffer. If Path is not specified, the current buffer will be used. Otherwise, the buffer at the specified path will be written to. Whenever the current directory is set, writing starts at the beginning of that buffer (replacing any previous contents). For this reason, when the Path parameter is given, the specified buffer is always overwritten.

If Val is an object, a separate directory will be created for the object and the object's Write proc will be called. In addition to data that may be written by the Write() proc, the type of the object is stored in a buffer called "type". In the case of turfs, the location of the turf is also recorded so that it can be recreated at the same position. All other objects must be repositioned after the object is recreated (like in the object's Read() proc).

Single operations that write multiple values (such as saving an object) are handled somewhat specially to avoid two references to the same object creating duplicate entries in the savefile. After the object being referenced is written once, successive references to the same object will be saved simply as references rather than as full objects. If this was not done, two references to the same object would be read back in as two separate objects. This also avoids infinite loops that would result when objects contain references back to themselves.

## procs (savefile)

savefile/proc
  ExportText
  Flush
  ImportText
  Lock
  Unlock
  New

## ExportText proc (savefile)

See also:
  ImportText proc (savefile)

Format:
  savefile.ExportText(path=cd,file)

Args:
  path: the path to export
  file: optional file to write to

Converts all or part of a savefile to a human readable text format, similar in syntax to DM. If no file is specified, the savefile text is returned as a text string instead of being written to a file.

The following example shows how to export and later import a savefile. The user's mob is written into a directory with the same name as their ckey and the result is written to a text file.

### Example:

    mob/verb/write()
       var/savefile/F = new()
       var/txtfile = file("players/[ckey].txt")

       F[ckey] << usr

       fdel(txtfile)
       F.ExportText("/",txtfile)

       usr << "Your savefile looks like this:"
       usr << "<pre>[html_encode(file2text(txtfile))]</pre>"

    mob/verb/read()
       var/savefile/F = new()
       var/txtfile = file("players/[ckey].txt")

       F.ImportText("/",txtfile)
       F[ckey] >> usr

## Flush proc (savefile)

Format:
  savefile.Flush()

Flushes any pending write operations for this savefile.

## ImportText proc (savefile)

See also:
  ExportText proc (savefile)

Format:
  savefile.ImportText(path=cd,source)

Args:
  path: the path at which to write the imported data
  source: a file or text string to import

Reads a text file or string and writes it into a savefile. See ExportText for an example.

If `source` is an ordinary string, it will be treated as savefile contents to be parsed. If it's a `file()` reference, it will be treated as a filename and the file's contents will be loaded.

## Lock proc (savefile)

See also:
  New proc (savefile)
  Unlock proc (savefile)

Format:
  Lock(timeout)

Args:
  timeout: seconds to wait; -1 for no timeout

Returns:
  1 on success; 0 on failure

In order to modify a savefile, exclusive access to the file must be guaranteed, so that other processes reading or writing to the file do not experience data corruption. This is known as "locking" the file. While the file is locked, only the world that obtained the lock may access it.

Normally, you do not need to worry about this, because a lock is automatically obtained upon the first attempt to write to the file. In a CGI application, where many instances of the program might be running simultaneously, the normal locking, which just tries once and crashes the proc on failure, would not be ideal.

Explicitly calling Lock() allows you to specify a timeout and it also allows you to handle the case in which no lock could be obtained. If you want it to wait indefinitely, use -1. Just be careful if there are several files read by multiple processes that it is not possible for deadlock to occur.

Obtaining a lock will fail if the file is locked by another world or if it is even open by any other world.

If you are using Lock(), then you probably also want to specify a timeout when you open the savefile, since that too can fail due to the file being locked by another process.

## New proc (savefile)

See also:
  Lock proc (savefile)
  Unlock proc (savefile)

Format:
  New(filename,timeout)

Args:
  filename: name of file or empty for temporary file
  timeout: seconds to wait; -1 for no timeout

You call this via new/savefile(filename,timeout). The timeout is used to determine how long to wait if the file is locked. Normally (timeout=0), if the file is locked, the proc crashes with a runtime error. If you specify a timeout, then it will keep trying to open the file and if this fails, it will simply return with savefile.name being empty (ie a false value).

If the first argument is an entry in the world's rsc cache, the data will be copied into a temporary file and accessed from there. Changes to this, and any other temporary file, are not saved. When you close the file, it simply gets deleted.

## Unlock proc (savefile)

See also:
  Lock proc (savefile)
  New proc (savefile)

Format:
  Unlock()

Exclusive locks are automatically released when the savefile is closed, but if you want to keep reading the file and allow other processes to do the same, then you can explicitly unlock it.

Note that this does not allow other processes to lock the file. It only allows them to read from it. As long as the file is open by more than one process, no lock may be obtained.

## vars (savefile)

savefile vars:

savefile/var
  byond_build
  byond_version
  cd
  dir
  eof
  name

## byond_build var (savefile)

See also:
  savefile
  byond_version var (savefile)
  byond_version var (world)
  byond_build var (world)

Default value:
  0

Sometimes when transitioning between BYOND versions you'll want to keep a savefile in a condition where it can be read by older versions. The `byond_version` var tells it to avoid using newer savefile features (unless forced to) above a certain build number. (The build number changes more often than the BYOND version number.) A value of 0 means not to worry about it.

This can be changed on a per-savefile basis so that you can use newer features in some files and avoid changing others. For instance, character saves might want to go on using older features for a while, but for saving parts of the map you might prefer to allow newer features to be used.

The default savefile compatibility version can be set at compile-time:

### Example:

    savefile/byond_build = 1600  // do not use savefile features from BYOND build 1601 onward

## byond_version var (savefile)

See also:
  savefile
  byond_build var (savefile)
  byond_version var (world)
  byond_build var (world)

Default value:
  0

Sometimes when transitioning between BYOND versions you'll want to keep a savefile in a condition where it can be read by older versions. The `byond_version` var tells it to avoid using newer savefile features (unless forced to) above a certain version number. A value of 0 means not to worry about it.

This can be changed on a per-savefile basis so that you can use newer features in some files and avoid changing others. For instance, character saves might want to go on using older features for a while, but for saving parts of the map you might prefer to allow newer features to be used.

The default savefile compatibility version can be set at compile-time:

### Example:

    savefile/byond_version = 514  // do not use savefile features from BYOND 515 onward

Note: By default, worlds compiled before BYOND 515 will set this value to 514.

## cd var (savefile)

See also:
  savefile

This is the path name of the current directory. Setting it causes the current directory to change. (We are talking about the current database directory inside the savefile. It is not a real directory on the filesystem.) It is perfectly legal to change to a non-existent directory. This new directory will not be saved to disk unless its buffer (or one of its children) is modified, however.

### Example:

    var/savefile/F = new()  // temporary file

    F.cd = "/MyDir/Icon"
    F.cd = ".."    // change to /MyDir
    F.cd = "Icon"  // change to /MyDir/Icon

## dir list var (savefile)

See also:
  list
  savefile

The name of each child directory of the current data directory is stored in the list savefile.dir. New directories may be created with savefile.dir.Add() and removed with savefile.dir.Remove(). To test for the existence of a directory, use savefile.dir.Find(). (Note that these are database directories inside the savefile—not real directories on the filesystem.)

The order of directories is not necessarily preserved, so do not assume, for example, that newer directories will be at the end of the list.

## eof var (savefile)

If there is more data to read in the current buffer, eof is 0; otherwise it is 1. Setting eof to 1 moves to the end of the buffer and 0 moves to the beginning. Setting it to -1 deletes the current buffer.

## name var (savefile)

See also:
  savefile

The external "real" filename is stored in file.name. It is initialized when creating a new file. If none is specified, a temporary file with a random name will be created.

### Example:

    var/savefile/F1
    var/savefile/F2

    F1 = new()         // create a temp file
    F2 = new("myfile") // open "myfile"

    world << "F1.name = [F1]"
    world << "F2.name = [F2]"

## sound datum

See also:
  vars (sound)
  sound proc
  stddef.dm file
  load_resource proc

A `/sound` datum is created by the `sound()` proc or by `new/sound()`. It can be used to change the way a sound file will play. When you're ready to play the sound, just send it to a player like so:

    var/sound/S = sound('bubbles.wav')
    usr << S

The sound file can be supplied as a list of choices, in which case the client will play the first compatible sound in the list.

## vars (sound)

Built-in sound vars:

sound/var
  file
  repeat
  wait
  channel
  volume
  frequency
  len
  offset
  pan
  params
  pitch
  priority
  status
  x, y, z
  falloff
  environment
  echo
  atom
  transform

## file var (sound)

See also:
  sound proc
  vars (sound)
  SoundQuery proc (client)

This is the file that will be played when the sound is sent to a player.

If this value is a list of files rather than a single file, the client will play the first compatible sound in the list. This can be useful for developing webclient games, where .ogg is preferred by most browsers for audio, but .mp3 is needed for others.

This var may be filled in by the `SoundQuery` proc.

## repeat var (sound)

See also:
  sound proc
  vars (sound)
  SoundQuery proc (client)

Default value:
  0 (do not repeat)

Set to 1 to repeat the sound indefinitely once it begins playing, 2 to repeat it forwards and backwards.

This var may be filled in by the `SoundQuery` proc.

## wait var (sound)

See also:
  sound proc
  vars (sound)
  SoundQuery proc (client)

Default value:
  0 (do not wait)

Set to 1 to wait for other sounds in this channel to finish before playing this one.

The `SoundQuery` proc fills in this value with the total duration of sounds that are queued to be played on this channel.

## channel var (sound)

See also:
  sound proc
  status var (sound)
  vars (sound)
  SoundQuery proc (client)

Default value:
  0 (any channel)

For sound effects, set to 1 through 1024 to choose a specific sound channel. For values of 0 or less, any available channel will be chosen. If you play a null sound (no file) on channel 0, the settings for the datum will affect all channels.

If you want to make any changes to your sound later on via the `SOUND_UPDATE` status flag, you must specify a channel for it.

This var may be filled in by the `SoundQuery` proc, but only for sounds that had a specified channel to begin with.

Note: If you don't specify a channel to play a sound, the client will choose a channel automatically but it will not conflict with any specific channels you choose for other sounds later. This means if you play some sounds with channel 0 but then later want to play something on channel 1, you don't have to worry about channel 1 being taken.

## volume var (sound)

See also:
  sound proc
  vars (sound)

Default value:
  100 (full volume)

Set to a percentage from 0 to 100 of the sound's full volume. It will play at that volume when it is sent to a player.

## frequency var (sound)

See also:
  vars (sound)
  pitch var (sound)

Default value:
  0

Any value from -100 to 100 will play this sound at a multiple of its normal frequency. Set to 2 to play at double speed, for example, or -1 to play backwards. A value of 0 or 1 will play the sound at its normal frequency.

Set to a specific frequency (in Hz) outside of the -100 to 100 range to change the playback rate of the sound. A negative value is also allowed. The value 0 means that the sound should be played as-is. This value will take effect when the sound is sent to a player.

CD-quality sound is sampled at 44.1 KHz, which is a value of 44100. Other common sample rates for .wav files are 8000, 11025, and 22050. (11025 is usually a good quality for most sound effects without making file size too large.) If you know the file's sample rate, doubling the value will play it at a higher pitch and twice as fast; halving it will play it at a lower pitch and twice as slow.

To make a sound play at a different speed but keep its pitch intact, set `frequency` to the speed multiple you want (e.g., 1.2 for 20% faster) and set `pitch` to the inverse (e.g., 1/1.2).

## offset var (sound)

See also:
  vars (sound)
  status var (sound)
  SoundQuery proc (client)

Can be used to set a starting time, in seconds, for a sound. It can also alter the current time index when using the `SOUND_UPDATE` flag.

This value is also set by the `SoundQuery` proc and represents the current time index of a sound playing on the client.

## len var (sound)

See also:
  vars (sound)
  SoundQuery proc (client)

This value is set by the `SoundQuery` proc and represents the length, in seconds, of a sound playing on the client. Frequency is taken into into consideration, so a higher frequency means the sound takes a shorter time to play and therefore has a shorter length.

Other uses for this var may be considered in the future.

## pan var (sound)

See also:
  vars (sound)

Default value:
  0

Alter the panning of a sound. -100 is full left, 100 is full right, and 0 is at the center. This value will take effect when the sound is sent to a player.

For music, `pan` can range from -100 (no pan separation) to 0 (full separation).

## params var (sound)

See also:
  vars (sound)

Default value:
  null

Used to set client skin information related to this sound. This can be set to an associative list or a parameter string such as you would get from list2params().

These are the parameters currently defined:

on-end
  Plays when the sound ends or is stopped.
on-preempt
  Plays when the sound is preempted by another sound. If this isn't present, `on-end` still applies if the sound is preempted.

### Example:

    mob/proc/PlayIntro()
        var/sound/S = sound('intro.ogg')
        S.params = list("on-end" = ".intro-ended")
        src << S

    mob/verb/_Intro_Ended()
        set name = ".intro-ended"
        src << "The intro has concluded."

## pitch var (sound)

See also:
  vars (sound)

  frequency var (sound)
  Default value:
    0

  Can be used to shift the pitch of a sound up or down. This works similarly to frequency except that it doesn't impact playback speed.

  The value of this var should be a multiple relative to 1, so for instance to go up a full octave, the value would be 2; to go down an octave, use 0.5.

  Note: The filter that handles pitch shifting only goes from 0.5 to 2. The player will stack up to three filters if it has to, so the range is really from 0.125 to 8. You will however hear much poorer quality at more extreme values.

  To make a sound play at a different speed but keep its pitch intact, set `frequency` to the speed multiple you want (e.g., 1.2 for 20% faster) and set `pitch` to the inverse (e.g., 1/1.2).

  ### Example:

      client
          var/sound/music // music currently playing

          proc/PlayMusic(music)
              music = new(music)
              music.channel = 100
              src << music

          proc/UpTempo(amount = 0.1)  // 10% faster
              if(!music) return
              music.frequency = (music.frequency || 1) + amount
              music.pitch = 1 / music.frequency
              music.status |= SOUND_UPDATE
              src << music

  ## priority var (sound)

  See also:
  vars (sound)
  Default value:
    0

  Sounds with higher priority may steal channels from sounds of lower priority. The maximum value is 255. 0 is the lowest.

  ## status var (sound)

  See also:
  vars (sound)
  SoundQuery proc (client)
  Default value:
    0

  Alter the way the sound is heard by affecting several different on/off values which combine as bit flags.

      SOUND_MUTE      // do not play the sound
      SOUND_PAUSED    // pause sound
      SOUND_STREAM    // create as a stream
      SOUND_UPDATE    // update a playing sound

  Use the `|` operator to combine these values. The setting you choose will take effect when the sound is sent to a player.

  `SOUND_MUTE | SOUND_UPDATE` will mute a sound, but it will continue to play. It can be unmuted while still playing by resending it with `status=SOUND_UPDATE`.

  `SOUND_PAUSED | SOUND_UPDATE` will pause a sound. It can be restarted from its current position by resending it with `status=SOUND_UPDATE`.

  `SOUND_STREAM` will create this sound as a stream. Streams take less memory, but can not play multiple times at once, nor can they play in reverse. This flag is only valid the first time that a sound is played in a particular mode (normal vs. 3D). Changing the flag later will not change the stream status of the sound in that mode.

  `SOUND_UPDATE` updates the settings for the sound currently playing on the specified channel. If this flag is not set or no channel is specified, the sound will start again from the beginning.

  Some of the flags for this value may be filled in by the `SoundQuery` proc.

  ## x, y, and z vars (sound)

  See also:
  vars (sound)
  atom var (sound)
  transform var (sound)
  falloff var (sound)
  Default value:
    all 0

  Set to different values to give your sound a 3D effect which will be applied when it is played. Positive values for `x` will sound as if they come from the right, positive `y` sounds like it is above the player's head, and positive `z` sounds like it is directly ahead. The effect of 3D sound depends on the player's computer's sound card, and is greatly enhanced when wearing headphones.

  Depending on the value of `falloff`, the settings for the location of the sound can also affect its volume. Once the distance passes the value of `falloff`, the volume will diminish.

  If these values are all set to 0, you should set `environment` if you want to treat it as a 3D sound. Otherwise BYOND will assume this is meant to be a non-3D sound such as music or the interface.

  If the atom var is set to an atom that's visible on the map (that is, if it's close enough to the center of view to be sent by the server), its relative x and y coordinates are fed through the transform matrix, if present, and added to the x,y,z coordinates. This way, a sound's 3D position can change in real time. A sound is considered 3D if the `atom` var is set, even if the base x,y,z coordinates are all 0.

  ## falloff var (sound)

  See also:
  vars (sound)
  x, y, z vars (sound)
  atom var (sound)
  transform var (sound)
  Default value:
    1

  Within the falloff distance a 3D sound stays at the constant loudest volume possible. Outside of this distance it attenuates at a rate determined by the falloff.

  Higher values will make sounds fade out more slowly as they get farther away. The distance of a sound is set by `x`, `y`, and `z`.

  ## environment var (sound)

  See also:
  vars (sound)
  x, y, z vars (sound)
  atom var (sound)
  echo var (sound)
  Default value:
    -1

  Changes the environmental reverb for all 3D sounds until another environment is specified. Only 3D sounds react to the environment. Please see the EAX2 documentation at http://developer.creative.com/ for detailed information about these settings.

  This value may be a number which selects a preset, or a list to choose settings manually. The default value (-1) specifies no change in environment. A numeric value from 0 to 25 specifies a set of reverb presets for the environment. The environment presets are:

  0. generic
  1. padded cell
  2. room
  3. bathroom
  4. livingroom
  5. stoneroom
  6. auditorium
  7. concert hall
  8. cave
  9. arena
  10. hangar
  11. carpeted hallway
  12. hallway
  13. stone corridor
  14. alley
  15. forest
  16. city
  17. mountains
  18. quarry
  19. plain
  20. parking lot
  21. sewer pipe
  22. underwater
  23. drugged
  24. dizzy
  25. psychotic

  As of BYOND 515, setting environment to a negative number below -1 will turn the environment off. The generic environment is not the same as off.

  A 23-element list represents a custom environment with the following reverbration settings. A null or non-numeric value for any setting will select its default.

  1 EnvSize (1.0 to 100.0) default = 7.5
    environment size in meters
  2 EnvDiffusion (0.0 to 1.0) default = 1.0
    environment diffusion
  3 Room (-10000 to 0) default = -1000
    room effect level (at mid frequencies)
  4 RoomHF (-10000 to 0) default = -100
    relative room effect level at high frequencies
  5 RoomLF (-10000 to 0) default = 0
    relative room effect level at low frequencies
  6 DecayTime (0.1 to 20.0) default = 1.49
    reverberation decay time at mid frequencies
  7 DecayHFRatio (0.1 to 2.0) default = 0.83
    high-frequency to mid-frequency decay time ratio
  8 DecayLFRatio (0.1 to 2.0) default = 1.0
    low-frequency to mid-frequency decay time ratio
  9 Reflections (-10000 to 1000) default = -2602
    early reflections level relative to room effect
  10 ReflectionsDelay (0.0 to 0.3) default = 0.007
    initial reflection delay time
  11 Reverb (-10000 to 2000) default = 200
    late reverberation level relative to room effect
  12 ReverbDelay (0.0 to 0.1) default = 0.011
    late reverberation delay time relative to initial reflection
  13 EchoTime (0.075 to 0.250) default = 0.25
    echo time
  14 EchoDepth (0.0 to 1.0) default = 0.0
    echo depth
  15 ModulationTime (0.04 to 4.0) default = 0.25
    modulation time
  16 ModulationDepth (0.0 to 1.0) default = 0.0
    modulation depth
  17 AirAbsorptionHF (-100 to 0.0) default = -5.0
    change in level per meter at high frequencies
  18 HFReference (1000.0 to 20000) default = 5000.0
    reference high frequency (hz)
  19 LFReference (20.0 to 1000.0) default = 250.0
    reference low frequency (hz)
  20 RoomRolloffFactor (0.0 to 10.0) default = 0.0
    like rolloffscale in System::set3DSettings but for reverb room size effect
  21 Diffusion (0.0 to 100.0) default = 100.0
    Value that controls the echo density in the late reverberation decay.
  22 Density (0.0 to 100.0) default = 100.0
    Value that controls the modal density in the late reverberation decay
  23 Flags default = 63
    Bit flags that modify the behavior of above properties
    1 - 'EnvSize' affects reverberation decay time
    2 - 'EnvSize' affects reflection level
    4 - 'EnvSize' affects initial reflection delay time
    8 - 'EnvSize' affects reflections level
    16 - 'EnvSize' affects late reverberation delay time
    32 - AirAbsorptionHF affects DecayHFRatio
    64 - 'EnvSize' affects echo time
    128 - 'EnvSize' affects modulation time

  ## echo var (sound)

  See also:
  vars (sound)
  x, y, z vars (sound)
  atom var (sound)
  environment var (sound)
  Default value:
    null

  If set to an 18-element list, this value customizes reverbration settings for this sound only. A null or non-numeric value for any setting will select its default. Please see the EAX2 documentation at http://developer.creative.com/ for indepth information about these settings.

  Here's a rundown of some of the terms: Direct refers to the amount of effect when the sound is on a direct path to the listener. Obstruction is when an object is blocking the direct path but there are other ways for the sound to reach the listener. Occlusion means the sound is on the other side of a wall, and mostly blocked. Exclusion means the sound is on the other side of a wall, but a doorway or window is allowing it to pass through to the listener. You can use a little of each of these effects to increase realism.

  1 Direct (-10,000 to 1,000) default = 0
    direct path level (at low and mid frequencies)
  2 DirectHF (-10,000 to 0) default = 0
    relative direct path level at high frequencies
  3 Room (-10,000 to 1,000) default = 0
    room effect level (at low and mid frequencies)
  4 Room HF (-10,000 to 0) default = 0
    relative room effect level at high frequencies
  5 Obstruction (-10,000 to 0) default = 0
    main obstruction control (attenuation at high frequencies)
  6 ObstructionLFRatio (0.0 to 1.0) default = 0.0
    obstruction low-frequency level re. main control
  7 Occlusion (-10,000 to 0) default = 0
    main occlusion control (attenuation at high frequencies)
  8 OcclusionLFRatio (0.0 to 1.0) default = 0.25
    occlusion low-frequency level re. main control
  9 OcclusionRoomRatio (0.0 to 10.0) default = 1.5
    relative occlusion control for room effect
  10 OcclusionDirectRatio (0.0 to 10.0) default = 1.0
    relative occlusion control for direct path
  11 Exclusion (-10,000 to 0) default = 0
    main exlusion control (attenuation at high frequencies)
  12 ExclusionLFRatio (0.0 to 1.0) default = 1.0
    exclusion low-frequency level re. main control
  13 OutsideVolumeHF (-10,000 to 0) default = 0
    outside sound cone level at high frequencies
  14 DopplerFactor (0.0 to 10.0) default = 0.0
    like DS3D flDopplerFactor but per source
  15 RolloffFactor (0.0 to 10.0) default = 0.0
    like DS3D flRolloffFactor but per source
  16 RoomRolloffFactor (0.0 to 10.0) default = 0.0
    like DS3D flRolloffFactor but for room effect
  17 AirAbsorptionFactor (0.0 to 10.0) default = 1.0
    multiplies AirAbsorptionHF member of environment reverb properties.
  18 Flags default = 7
    Bit flags that modify the behavior of properties
    1 - Automatic setting of 'Direct' due to distance from listener
    2 - Automatic setting of 'Room' due to distance from listener
    4 - Automatic setting of 'RoomHF' due to distance from listener

  ## atom var (sound)

  See also:
  vars (sound)
  x, y, and z vars (sound)
  transform var (sound)
  falloff var (sound)
  Default value:
    null

  Links this sound to an atom, whose position relative to the vitual eye (center of view), in tiles, is transformed and added to the 3D x,y,z coordinates. As you move relative to the atom, the sound's apparent position in 3D space will change without the server needing to update this sound manually.

  This is usually used in conjunction with the transform var, which converts the 2D x,y offset into 3D coordinates. This can scale or rotate the 2D coordinates however you need.

  Note: The atom must remain "in range", meaning the server has to think it's close enough within visual range to send updates to the client, for the sound to be heard.

  ## transform var (sound)

  See also:
  vars (sound)
  atom var (sound)
  x, y, and z vars (sound)
  falloff var (sound)
  Default value:
    null (same as `list(1,0,0, 0,1,0, 0,0,0))

  A 3x3 matrix for converting the 2D position of an atom, relative to the center of view, into 3D sound coordinates. (This value is meaningless if you don't link the sound to an atom via the atom var.) The transformed vector is added to the sound's x,y,z values to get a 3D position.

  The value of `transform` should be a list with 9 elements, in row-major order. The default list is `list(1,0,0, 0,1,0, 0,0,0)`. If you use a list shorter than 9 elements, the defaults will be filled in for you.

      list(xx,xy,xz, yx,yy,yz, cx,cy,cz)

                |xx xy xz|
      [x y 1] x |yx yy yz| = [x' y' z']
                |cx cy cz|

  In easier-to-understand terms, this is how the result is calculated:

      new_x = x * xx + y * yx + cx
      new_y = x * xy + y * yy + cy
      new_z = x * xz + y * yz + cz

  It is helpful to think of each row in the matrix as what each component of the original vector will become. The first row of the matrix is the output x,y,z you'll get for an input x of 1.

  ### Example:

      obj/fire
          proc/HearMe(mob/player)
              var/sound/S = new('fire.ogg', channel=10, repeat=1)
              S.atom = src
              S.transform = list(1,0,0, 0,sqrt(0.5),sqrt(0.5), 0,0,0)
              player << S

  The transform in this example rotates the fire's position by 45° forward, so positive y values get split between y and z. This gives the player the impression that an object higher up on their screen is both forward of and above them, as if they're looking down at the map from a 45° angle.

  ## turf

  See also:
  atom
  procs (turf)
  vars (turf)
  Map

  Turfs cover the surface of the map. They are derived from `/turf` which derives from `/atom`.

  This example defines the turf prototype `/turf/floor` and `/turf/wall`.

  ### Example:

      turf
        floor
          desc = "A wood plank floor."
        wall
          desc = "A stone wall."
          density = 1

  Turfs cannot be moved. They can only be created or destroyed by changing `world.maxx`, `world.maxy`, or `world.maxz`. When you create a new turf with `new()`, it always replaces the old one.

  ### Example:

      // replace old_turf with a wall
      var/turf/wall/T = new(old_turf)

  ## procs (turf)

  Built-in turf procs:

  turf/proc
  Click
  Cross proc
  Crossed proc
  DblClick
  Del
  Enter
  Entered
  Exit
  Exited
  MouseDown
  MouseDrag
  MouseDrop
  MouseEntered
  MouseExited
  MouseMove
  MouseUp
  MouseWheel
  New
  Read
  Stat
  Topic
  Write
  Uncross proc
  Uncrossed proc

  ## vars (turf)

  Built-in turf vars:

  turf/var
  alpha
  appearance
  appearance_flags
  blend_mode
  color
  contents
  density
  desc
  dir
  filters
  gender
  icon
  icon_state
  icon_w
  icon_z
  invisibility
  underlays
  overlays
  loc
  layer
  luminosity
  mouse_over_pointer
  mouse_drag_pointer
  mouse_drop_pointer
  mouse_drop_zone var
  mouse_opacity var
  name
  opacity
  parent_type
  pixel_x
  pixel_y
  pixel_w
  pixel_z
  pixloc
  plane
  render_source
  render_target
  suffix
  tag
  text
  transform
  type
  vars
  verbs
  vis_contents
  vis_flags
  vis_locs
  x
  y
  z

  ## parent_type var (turf)

  See also:
  parent_type var

  The default parent_type of /turf is /atom.

  ## vars

  See also:
  path operators
  vars (atom)
  vars (client)
  vars (datum)
  vars (mob)

  Variables are derived from var.

  Variable Declaration Format:
    var/Type/Name = Value
    var Type/Name = Value

  Value defaults to null.

  The hard-coded types are:
    datum
(ancestor of all objects)
  atom (all mappable objects)
  atom/movable (objs and mobs)
  obj
  mob
  turf
  area
  savefile
  client
  list
  world
  Type modifiers:
    global
    const
    tmp
    final

  User types may be derived from anything except for `/world`, `/list`, `/client`, and `/savefile`.

  ## const vars

  See also:
    vars

  The const type modifier defines a constant value. This may be useful for centralizing the location of a value that is used repeatedly so that it can be easily configured. It has the advantage over #define macros of obeying the normal scope rules for variables. This means, for example, that a const variable declared inside a proc will not conflict with other variables declared elsewhere.

  ### Example:

      mob
          var/const/max_items = 100

          Enter(O)
              if(src.contents.len >= src.max_items)
                  return 0
              return ..()

  This example defines an upper limit on the number of items a mob may carry.

  ## final vars

  See also:
    vars
  const vars
  global vars
  tmp vars

  The final type modifier indicates that a variable should not be overridden by a subtype or another compile-time assignment statement.

  This modifier also applies to procs. A final proc may not be overridden.

  ## global vars

  See also:
    vars

  The global type modifier makes a var permanent and shared. This means only one copy of the var is maintained. Otherwise, separate copies of the var are maintained for each instance containing the var (be it a proc, mob, obj, etc.)

  ### Example:

      mob/proc/Counter()
        var/global/count
        src << "Count = [++count]"

  This example increases the count each time the proc is called. If count were not declared global, the displayed count would be 1 every time.

  ## tmp vars

  See also:
    savefile
  vars

  The tmp type modifier indicates that an object variable should not be automatically written to the save file. This could mean that the variable is transient—that is, it is calculated at run-time and need not be saved. It could also indicated that the designer will handle saving of that variable specially and wishes to bypass the automated routine.

  It is especially important to use tmp when you have references to external objects that should not be saved along with the object. For example, suppose players have a leader variable which indicates who or what they are following. You would not necessarily want the leader to be saved in the player's savefile. Therefore, you would need to use `tmp` when defining the variable.

  ### Example:

      mob
         var/tmp
            leader
         verb
            follow(mob/M)
               leader = M

  The following built-in variables are defined as tmp vars:
    type
    parent_type
    vars
    verbs
    group
    loc
    locs
    vis_locs
    x
    y
    z
    ckey
    bound_x
    bound_y
    bound_width
    bound_height
    mouse_over_pointer
    mouse_drag_pointer
    mouse_drop_pointer

  ## vector

  See also:
    vector proc
  procs (vector)
  vars (vector)
  pixloc
  operators
  matrix

  A primitive value representing a numeric vector in 2 or 3 dimensions. That is, a 2D vector has x and y components, and a 3D vector has x, y, and z components.

  Vectors are primarily useful for physics and distance calculations.

  Vectors can be treated as a list for purposes of using the indexing `[]` operator, or a for loop. The `len` var is the number of components in the list, just like a regular list.

  Vectors support most math operations. Multiplication and division can be done with either a single number or a vector; the latter will act piecewise on each component, just like addition and subtraction do.

  When doing math on two vectors of different dimensions, the result will use the highest dimensionality. E.g., adding a 2D and 3D vector produces a 3D vector.

  Other supported procs for vectors include:

  min()
  max()
  clamp()
  round()
  floor()
  ceil()
  trunc()
  fract()

  ## procs (vector)

  See also:
    vector
  vector proc
  vars (vector)

  Built-in vector procs:

  vector/proc
    Cross
    Dot
    Interpolate
    Normalize
    Turn

  ## Cross proc (vector)

  See also:
    vector
  vector proc
  vars (vector)
  Format:
    A.Cross(vector/B)
  Returns:
    The cross product of the two vectors, which is another vector.

  This proc treats both vectors as 3D.

  The cross product of two 3D vectors is a third vector that is orthogonal to them both. The length is the product of the length of both vectors and the sine of the angle between them.

  The cross product depends on the order of the two vectors. If you switch their order, you get the negative result.

  Note: Rounding errors can mean that if you divide out the length of the two original vectors, the value you get for a sine can potentially be outside of the valid range of -1 to 1. Use `clamp()` if you need to pass the sine to `arcsin()`, so you can be sure it stays in range.

  ## Dot proc (vector)

  See also:
    vector
  vector proc
  vars (vector)
  Format:
    A.Dot(B)
  Args:
    B: The other vector.
  Returns:
    The dot product of the two vectors.

  The dot product of two vectors is determined by multiplying each component in the first vector by its matching component in the second, and adding those multiples together. For instance in a 2D vector, the dot product of A and B is:

      dot = A.x * B.x + A.y * B.y

  The dot product is equal to the product of the magnitude of the two vectors and the cosine of the angle between them.

      dot = A.size * B.size * cos(angle)

  Note: Rounding errors in the math can affect this result. For instance, if you take the dot product of two unit vectors pointing the same direction, you would expect a result of 1, since the angle between them is 0. But due to small rounding errors, you can get a value just over 1. Therefore an expression like `arccos(V1.Dot(V2))` can give a not-a-number value when you expected 0. To combat this, use `clamp()` to clamp the cosine between -1 and 1, as in `arccos(clamp(V1.Dot(V2), -1, 1))`.

  ## Interpolate proc (vector)

  See also:
    vector
  vector proc
  Format:
    A.Interpolate(B, t)
  Args:
    B: The other vector to interpolate with.
    t: The interpolation factor: from 0 (A) to 1 (B). Usually this is a value between 0 and 1.
  Returns:
    A new vector interpolated between A and B.

  Returns the equivalent of `A + (B-A) * t`.

  There is special handling for a case of `t=1` to avoid rounding errors.

  ## Normalize proc (vector)

  See also:
    vector
  vector proc
  size var (vector)
  Format:
    V.Normalize()
  Returns:
    The same vector, after normalizing it to a unit vector.

  Modifies the vector to make it a unit vector. This is the same as setting its `size` var to 1.

  A degenerate vector such as 0,0,0 cannot be normalized; it will be unchanged by this call.

  ## Turn proc (vector)

  See also:
    turn proc (applied to a vector)
  vector
  vector proc
  vars (vector)
  Format:
    A.Turn(angle)
    A.Turn(B)
  Args:
    angle: An angle to turn a vector clockwise in 2D.
    B: A vector to rotate around (right-hand rule).
  Returns:
    The vector A, after rotating it.

  This proc modifies the source vector. For legacy reasons, it rotates in the opposite direction of the built-in `turn()` proc.

  All angles are in degrees.

  When the argument is an angle, the source vector A is rotated in 2 dimensions clockwise.

  When the argument is a vector, the source vector A is rotated in 3 dimensions around vector B using the right-hand rule (thumb pointed in the direction of B, rotation following curled fingers). The angle of rotation is the length of B, in degrees.

  ## vars (vector)

  See also:
    vector
  vector proc
  procs (vector)

  Built-in vector vars:

  vector/var
    len
    size
    x
    y
    z

  ## len var (vector)

  See also:
    length proc
  vector
  vars (vector)

  The dimensionality (number of components) of this vector. Can be 2 or 3. This value can be changed.

  Most math operations on a vector will expand the result to the same dimension as the largest operand.

  ## size var (vector)

  See also:
    vector
  vars (vector)

  The magnitude of this vector. Magnitude is the square root of the summed-up squares of all its components. For instance in 3D:

  size = x*x + y*y + z*z

  `V.size` is the same as `sqrt(V.Dot(V))`.

  This value can be set at runtime, so setting `size = 1` will normalize the vector.

  If the size is already 0, as in the case of a degenerate vector like 0,0, then changing this value will have no effect.

  ## x var (vector)

  See also:
    vector
  vars (vector)

  The x component of this vector.

  ## y var (vector)

  See also:
    vector
  vars (vector)

  The y component of this vector.

  ## z var (vector)

  See also:
    vector
  vars (vector)

  The z component of this vector.

  ## verbs

  See also:
    arguments (verb)
  settings (verb)
  vars (verbs)
  src var (proc)
  usr var (proc)

  Verbs may be attached to mobs, objs, turfs, and areas. Players can then use them as commands if they have access to the source.

  Verbs are fundamentally the same "type" as procs, so their vars are the same.

  ### Example:

      mob/verb/poof()
        world << "POOF!"

  Whenever a player in the world types the command "poof", this verb will be invoked.

  In addition to the normal access control (see the verb src setting) verbs can be dynamically added and removed from objects. One way to do this is to use new() with the following syntax:

      new verb_path(Destination,Name,Desc)

  The Destination specifies the object to receive the verb. Name and Desc optionally specify a new name and description for the verb.

  ### Example:

      mob/DM/verb/kill(mob/M)
        del(M)

      mob/DM/verb/give_kill_verb(mob/M)
        new/mob/DM/verb/kill(M)

  This example defines two verbs (accessible to mobs of type /mob/DM). One verb kills other mobs. The other adds the kill verb to another mob (giving the second mob the ability to kill).

  In some situations, the ability to dynamically change an object's verb list is quite useful, but most of the time it is far more convenient to do the same thing by manipulating objects rather than verbs directly. For example, the previous example can be handled by having an object with the kill verb attached it it. Then players have greater versatility in manipulating the verb by simply moving the object around.

  ### Example:

      obj/scroll/kill/verb/kill(mob/M)
        set src = usr.contents //implicit src
        del(M)

  The use of an implicit verb source in this example gives the user access to the kill verb without having to specify the source scroll as long as the scroll exists in the user's inventory. In other words, the player types "kill rat" rather than "kill kill rat".

  ## arguments (verb)

  See also:
    argument expanding
  command_text (client)
  arglist proc
  args var (verb)

  The parameters to a verb are referred to as arguments. For verbs, the input type and possible value list may also be specified.

  The possible input types are:

      text          // a quoted text string
      password      // un-echoed text (for use with input() only)
      message       // multi-line text
      command_text  // raw command text from the rest of the input line
      num           // a number
      icon          // an icon file from the user's computer
      sound         // a sound file from the user's computer
      file          // any type of file from the user's computer
      key           // a key from the user's BYOND key file
      color         // a color (see rgb proc)
      null          // indicates that the argument is optional

      mob
      obj
      turf
      area
      anything

  These can be combined with the '|' operator. The first group are called constant input types because they turn on various types of literal values that the user can type in (like a number or a text string). The second group work in conjunction with a list of objects or values. They are called input type filters because they may be used to filter out certain types of values from the list. For example a mob or an obj within sight would be specified as follows:

      myverb(M as mob|obj in view()) {...}

  A default value may be specified which takes effect in the case of null arguments. For example:

      myverb(M=usr as null|mob|obj in view()) {...}

  In this example, the input type `null` did not have to be used explicitly, because assigning a default value (in this case `usr`) turns it on by default.

  The `anything` input type can be used to combine values in a list with other constant input types. Here, this is done with the `null` input type:

      set_aggression(a="on" as null|anything in list("on","off"))

  For input types containing mob, obj, turf, or area, the possible value list defaults to view().

  If no input type is specified, the variable type will be used to determine whether it is a mob, obj, turf, or area.

  ### Example:

      mob/verb/tell(mob/M,msg as text)
        M << "[usr] tells you, /"[msg]/""

  This example defines a verb with two arguments: a target mob, and some text.

  ## argument expanding

  See also:
    arguments (verb)

  The expression used to to provide a list of possible values for a verb argument may reference the value of arguments prior to the one being expanded. It may even reference the value of the argument being expanded, but this will always be a text string equal to what the user has typed so far.

  In addition, there is a special variable called "expanding" which is only accessible in this context. It is 1 if the user's input is being expanded and 0 if the user's final input is being validated. In certain rare cases, you may wish to tell the difference between these two cases. For example, you could use this to have possible values which do not show up in the expansion lists, but which are accepted when typed in full.

  ### Example:

      mob/verb/test(A in MyProc(A,expanding))
         usr << "You typed: [A]"

      proc/MyProc(A,expanding)
         var/values[] = list("one","two","three")
         if(!expanding) values += "secret"
         return values

  ## settings (verb)

  verb settings: ``

      verb/set
        name
        desc
        category
        hidden
        popup_menu
        instant
        invisibility
        src
        background

  Procs and verbs are the same "type" so these attributes may be set for procs as well; most of them do not have any meaning, however, unless the proc is invoked as a verb (by adding it to a verb list).

  ## category setting (verb)

  See also:
  default_verb_category var (client)
  show_verb_panel var (client)
  Format:
    set category = "Category"
  Args:
    Category: A text string for the category.

  Verbs in the same category are visually grouped together in the verb panels. The default is "", which is displayed in the default panel titled "Commands". You can change that default by setting `client/default_verb_category`.

  To hide a verb from all panels, set the category to null. The verb may still show up in right-click popup menus, so you may want to use the hidden or popup_menu verb properties instead.

  ## desc setting (verb)

  Format:
    set desc = "Description"
  Args:
    Description: A text string containing the help text.

  The desc attribute sets the descriptive help string for the verb. The player may access this by hitting the 'F1' key after entering the command. This will normally produce a list of each argument by type followed by the desc text. If you wish to override the syntax description, put your modified version inside parentheses at the beginning of the desc text.

  ### Example:

      mob/verb/tell(mob/M,T as text)
         set desc = "(target,message) Talk privately to someone."
         M << "[usr] tells you, '[T]"

  This will produce the help text:

      usage: tell target message (Talk privately to someone.)

  If the syntax description had not been supplied, it would have produced:

      usage: tell mob "text" (Talk privately to someone.)

  ## hidden setting (verb)

  See also:
  category setting (verb)
  invisibility setting (verb)
  name setting (verb)
  popup_menu setting (verb)
  Format:
    set hidden = Setting
  Args:
    Setting: 1 for hidden verbs; 0 otherwise.

  A hidden verb is not visible to players (in menus or in expansion lists) but if typed in full can still be accessed.

  An alternate way to hide a verb from the command-line and verb panels is to make "." the first character in the name. The verb will not show up in command-expansion (ie when hitting spacebar) until the "." has been typed. This could be useful for hiding verbs that would otherwise clutter up the verb list, while still making them relatively easy to use. If you think this is a random quirky feature, you are right. To put "." in front of the name, use the name setting.

  ## instant setting (verb)

  See also:
    settings (verb)
  Format:
    set instant = Setting
  Args:
    Setting: 1 for "instant" verbs; 0 otherwise.
  Default value:
    0

  Normally a player can only call one verb per tick, but they can call any number of "instant" verbs in the same tick. This setting is useful for commands called by the game's interface, or for more responsive controls like for instance the use of "combos" in fighting games.

  Verbs with the instant setting can be used on the same tick as a regular verb, but only one regular verb can be used each tick. Instant commands will jump ahead of non-instant commands in the queue.

  Any verbs that are already built-in, such as movement commands, cannot be modified to use this setting. (Some, such as mouse commands, already use it.) You can, however, create replacement verbs of your own for most of them.

  ### Example:

      mob/verb/FastNorth()
        set instant = 1
        usr.Move(get_step(usr,NORTH), NORTH)

  ## invisibility setting (verb)

  See also:
    hidden setting (verb)
  invisibility var (atom)
  sight var (mob)
  Format:
    set invisibility = Setting
  Args:
    Setting: 0 to 100
  Default value:
    same as invisibility of the source object.

  An invisible verb is only accessible to players who can see invisible objects. This is different from a hidden verb which does not clutter up the verb list but which is still accessible when typed in full.

  ## name setting (verb)

  Format:
    set name = "Name"
  Args:
    Name: A text string for the name.

  The name attribute of a verb defaults to the node name. Setting the name attribute explicitly may be necessary if the name includes characters not allowed in node names.

  ## popup_menu setting (verb)

  See also:
  category setting (verb)
  hidden setting (verb)
  invisibility setting (verb)
  Format:
    set popup_menu = Setting
  Args:
    Setting: 1 (default) for showing this verb in the popup menus; 0 otherwise.

  Use this to prevent a verb from showing up in the popup "context" menu when users right-click on objects.

  ## src setting (verb)

  Format:
    set src in List
    set src = List
  Args:
    List: One of view(), oview(), world, world.contents, usr, usr.contents, usr.loc, or usr.group

  With the first format, if src is in List for a particular player, then that player will have access to the proc. The player must explicitly specify the name of the source on the command line.

  The second format behaves the same, except the source is not read from the command line. If more than one possible source exists, one will be chosen at random.

  When usr or world is specified for the first format, it will be expanded to usr.contents and world.contents respectively.

  The default setting depends on the type of src:

      mob: src = usr
      obj: src in usr // short for usr.contents
      turf: src = view(0)
      area: src = view(0)

  ### Example:

      obj/verb/examine()
        set src in view()
        usr << "You examine [src]."

  ### Example:

      obj/MagicCloak/verb/disappear()
        set src = usr.contents

        usr.invisibility = 1
        view() << "[usr] disappears!"

  ## visibility setting (verb)

  See:
  invisibility setting (verb)

  The function of this variable has been replaced by `invisibility`, which provides a full range of settings.

  ## vars (verbs)

  See:
  vars (procs)

  ## . var (verb)

  See:
  . var (proc)

  ## args list var (verb)

  See:
  args list var (proc)

  ## src var (verb)

  See:
  src var (proc)

  ## usr var (verb)

  See:
  usr var (proc)

  ## world

  See also:
  procs (world)
  vars (world)

  The world node is used to define some global properties for the world. Like the other types, the world has overridable vars and procs. New vars and procs cannot be defined under world though; to make global vars and procs, use /var and /proc instead.

  ## procs (world)

  Built-in world procs:

  world/proc
    AddCredits
  ClearMedal
  Del
  Export
  GetConfig
  GetCredits
  GetMedal
  GetScores
  Import
  IsBanned
  IsSubscribed
  New
  OpenPort
  PayCredits
  Profile
  Reboot
  Repop
  SetConfig
  SetMedal
  SetScores
  Tick
  Topic

  ## AddCredits proc (world)

  See also:
    GetCredits proc (world)
  PayCredits proc (world)
  Format:
    AddCredits(player, credits, note)
  Returns:
    1 if the credits were added successfully, 0 or null otherwise.
  Args:
    player: a mob, client, key, or ckey
    credits: A number of credits to add to the player's account
    note: An optional note (for author purposes) for the credit change

  Adds credits to a player's account. The proc will return 1 if it is successful, or 0 if the attempt failed and should not be tried again. This feature is intended for games that make use of the credit system, and for security all such games must use a hub password.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      mob/proc/QuestCompleted(name, credits)
          src << "Congratulations! You completed the [name] quest and earned [credits] credit\s!"
          world.AddCredits(name, credits, "Quest: [name]")

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## ClearMedal proc (world)

  See also:
    GetMedal proc (world)
  SetMedal proc (world)
  GetScores proc (world)
  SetScores proc (world)
  Format:
    ClearMedal(medal, player)
  Returns:
    1 if the medal was rescinded successfully, 0 or null otherwise.
  Args:
    medal: name of the medal being rescinded
    player: a mob, client, key, or ckey

  Removes a medal from a player. The proc will return 1 if it is successful, or 0 if the medal was not already awarded. If the world already knows this medal was not earned, the hub will not be contacted.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      mob/NPC
         Die(mob/killer)  // assume Die() is a proc all mobs have
            spawn()
               if(ismob(killer) && killer.key)
                  world.ClearMedal("Pacifist", killer)

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## Del proc (world)

  See also:
    Del proc (datum)
  shutdown proc
  Format:
    Del()
  When:
    Called when the world is shutdown.
  Default action:
    Shutdown the world.

  When the world is destroyed, only the Del() proc of the `world` object is called automatically. If you want to delete any other objects, you must do so from within `world/Del()`. Once this procedure returns, any other procedures which may still be executing are immediately aborted and all objects are silently destroyed.

  To prevent accidental hangs during `world/Del()` from preventing shutdown, a timeout is applied to any sleeping operations such as `sleep`, `world.Export()`, and so on. If the total time slept exceeds the timeout, `world/Del()` is aborted. Currently, this timeout is set at 30 seconds.

  ## Error proc (world)

  See also:
    try and catch statements
  throw statement
  exception
  Format:
    Error(exception)
  Args:
    exception: The error that was thrown. If this was a runtime error, the value will be an /exception datum.

  Called when a runtime error happens, or the throw keyword is used, without a try/catch to handle it. The return value is ignored.

  ## Export proc (world)

  See also:
    Export proc (client)
  Import proc (world)
  Topic proc (world)
  link proc
  shutdown proc
  Format:
    Export(Addr,File,Persist,Clients,Method)
  When:
    Call this to send a message to another server. The message may be composed of an optional topic text string (in the address) and an optional file. This will call world.Topic() on the remote server, which may in turn call world.Import() to access the file.
  Args:
    Addr: The address of the recipient server. It should be in the form `byond://server?topic`, unless it's a web request. The topic portion is optional.
    File: The (optional) file to send. This could be a cache file (in single quotes) an external file (in double quotes) or a savefile, or an associative list if sending a `POST` web request.
    Persist: Set to 1 to indicate that the server should keep this connection open, to expedite subsequent calls to the same address. An open connection can be closed at a later time by passing 0 in the Persist field.
    Clients: An optional client, or list of clients, to tell the receiver about.
    Method: The request method for HTTP requests; defaults to `"GET"`. about.
  Default action:
    Send the topic text string and file to the remote server and return the result of calling world.Topic() there. Note that this will cause the caller to sleep while waiting for the necessary data to be transfered.
    or Send a web request via HTTP. This will also cause the caller to sleep while waiting for the request to finish.

  Sends a request to a remote BYOND server that will be handled by its world.Topic() proc, or a web request via HTTP.

  ### Example:

      mob/verb/shout(Msg as text)
        world << Msg
        world.Export("[ShadowWorld]?shout:[Msg]")

  This example defines a verb that will broadcast a message to everyone in this world as well as sending it in the form of topic text to another world whose address is stored in the variable ShadowWorld. This address could be manually set or could be the result of calling startup().

  If the Clients argument is used, it accepts a client that is currently loggedin, a mob belonging to such a client, or a list of any of these. The remote server will receive a list of their keys in world.Topic().

  ### Web requests

  It is also possible to access an HTTP server via `world.Export()`. Simply use an http address such as: `http://www.byond.com`. This returns a list of HTTP header parameters as well as the extra values `"STATUS"` and `"CONTENT"`. The value associated with the `"STATUS"` entry is the HTTP status code returned by the web server (as text). The value associated with the `"CONTENT"` entry is the requested resource, as a file.

  ### Example:

      mob/verb/test()
          var/http[] = world.Export("http://www.byond.com")

          if(!http)
              usr << "Failed to connect."
              return

          usr << "HTTP Header:"
          for(var/V in http)
              usr << "[V] = [http[V]]"
          usr << "\n"

          var/F = http["CONTENT"]
          if(F)
              usr << html_encode(file2text(F))

  Note that the HTTP request is submitted using the GET method by default.

  As of BYOND 516.1664, HTTPS is supported as well, along with other methods such as POST and PUT.

  If sending a POST request, the File argument should be an associative list, representing form data.

  ### Example:

      mob/verb/SendForm(name as text, favoritecolor as color)
          var/list/formdata = list("name"=name, "color"=favoritecolor)

          var/http[] = world.Export("http://mysite.com/myform", formdata, 0, null, "POST")

          if(!http || findtextEx(http["STATUS"],"200") != 1)
              usr << "Failed to send the form."
              return

  ## GetConfig proc (world)

  See also:
    IsBanned proc (world)
  SetConfig proc (world)
  Format:
    GetConfig(config_set,param)
  Returns:
    Value of requested parameter.
  Args:
    config_set: name of the configuration set (see below)
    param: name of the configuration parameter

  This command is for retrieving configuration information that is shared by applications installed on the same system. The configuration data is accessed by specifying the configuration "set" and the parameter within that set. The "sets" defined so far are:

      env       system environment variables (changes are not persistent)
      admin     list of site administrators
      ban       list of banned users or IP addresses
      keyban    list of banned users (deprecated)
      ipban     list of banned addresses (deprecated)

  If no parameter is specified, a list of the names of all available parameters is returned.

  The format of the configuration data itself is currently being defined. It will generally be a sequence of parameters (such as produced by list2params()). For example, each ban entry would have the user's ckey or ckeyEx as the parameter, and might have data such as "reason=jerkish;message=You+jerk!".

  ### Example:

      mob/verb
         ban(key as text)
            world.SetConfig("ban",ckey(key),"reason=fiendish;admin=[ckey]")
         lookban(key as null|text)
            if(key)
               usr << "[key]: [world.GetConfig("ban",key)]"
            else
               var/lst[] = world.GetConfig("ban")
               for(key in lst)
                  usr << "[key]: [world.GetConfig("ban",key)]"

  Ban files store information on a game-specific basis. You will only be able to read and write values that are set for the game you are running (defined by the value of world.hub). It is possible for a host to specify universal bans as well, but these will not be accessible via GetConfig or SetConfig. If you are using "ban" as the config_set, IP addresses are recognized automatically. (See the ban format info below.)

  It is possible, but rarely useful, to specify a configuration "space" of SYSTEM, USER, HOME, or APP. Settings made in the SYSTEM space are shared by all BYOND software on the computer. The USER space is shared by all software owned by the same user. The HOME space is shared by all worlds running with the same safe home directory. The APP space is shared by all software running from the same filesystem directory. By default, the USER space is used, and if that cannot be modified (in safe mode), then HOME is used instead. These distinctions are sometimes important on a UNIX machine, where there are many BYOND sites belonging to different users, but even then, the default behavior is almost always what you want.

  The configuration space is specified inside the configuration set parameter like this:

      world.SetConfig("APP/keyban",...)

  When reading configuration settings, the spaces are always lumped together. In cases of settings with the same name but different values, APP overrides HOME, which overrides USER, which overrides SYSTEM.

  ### Ban Format

  If you want to create or read bans at runtime by using the "ban" config set, these are the main parameters currently used:

  type
    The ban's type, if any. It can be "sticky", "session", or "time", or a combination separated by commas. Session bans expire when the current session is over (world.Reboot() does not affect this).
  reason
    The reason the ban was implemented; this is for the host's or admin's purposes only and is not displayed to the user.
  message
    A message to display to the user.
  keys
    Other keys caught in a sticky ban.
  IP
    Other IP addresses caught in a sticky ban.
  computer_id
    Other computer_id values caught in a sticky ban.
  time
    The number of seconds remaining in the ban. The type parameter must include "time" for this to mean anything. If this parameter is not present when a timed ban is read, it means the ban has expired.

  The old "keyban" and "ipban" config files are now just aliases for "ban".

  ## GetCredits proc (world)

  See also:
    AddCredits proc (world)
  PayCredits proc (world)
  Format:
    GetCredits(player)
  Returns:
    Number of credits if hub contact was successful, null otherwise.
  Args:
    player: a mob, client, key, or ckey

  Retrieves the number of available credits in a player's account. This feature is intended for games that make use of the credit system, and for security all such games must use a hub password.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  The best time to call this proc is before a player does something that would allow them to spend credits, and/or just afterward, so they can see what is left in their account.

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## GetMedal proc (world)

  See also:
    SetMedal proc (world)
  ClearMedal proc (world)
  GetScores proc (world)
  SetScores proc (world)
  Format:
    GetMedal(medal, player)
  Returns:
    1 if the medal has been earned by the player
    0 if the medal has not been earned
    A list of medals in list2params() format if checking all medals
    null if the hub cannot be contacted
  Args:
    medal: name of the medal being checked
    player: a mob, client, key, or ckey

  Checks to see if a medal has been awarded to the player in question. If the medal has been awarded, the return value is 1. If not, 0.

  You can also use GetMedal() to read a list of all medals a player has earned for the hub entry, by leaving the medal argument blank. If you also leave the player argument blank, you will get a list of all medals available to the hub entry. In both cases the result can be parsed with params2list().

  This proc will return null if there was no way to reach the hub or otherwise verify the medal's status. Use isnull() to check for a null value.

  Whenever possible, GetMedal() will avoid contacting the hub by using the information it was given when the user logged in. If contacting the hub is required, the proc may take a few moments to return a result. It is a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      turf/medal_door
        density = 1
        icon_state = "closed"
        var/medal = "Dragon slayer"

        verb/Knock()
          usr << "<b>Guard:</b> Just checking your credentials...."
          var/hasmedal = world.GetMedal(medal, usr)
          if(hasmedal)
            usr << "<b>Guard:</b> Go right in."
            icon_state = "open"
            density = 0
          else if(!isnull(hasmedal))
            usr << "<b>Guard:</b> Sorry, no admittance without a <b>[medal]</b> badge."
          else
            usr << "<b>Guard:</b> Sorry, I lost the paperwork. Try again later."

  You can add an optional hub path argument if you want to look at a medal for a different hub entry.

  ## GetScores proc (world)

  See also:
    SetScores proc (world)
  GetMedal proc (world)
  SetMedal proc (world)
  ClearMedal proc (world)
  Formats:
    GetScores(key, fields)
    GetScores(count, field)
    GetScores(count, skip, field)
  Returns:
    A parameter list of scores for a given entry. Use params2list() to interpret the results.
  Args:
    key: the name of the player, character, etc. for which scores have been set
    fields: The data fields to retrieve
    count: The number of top score records to look at
    skip: The number of top score records to skip over

  Retrieves information about scores that is kept on the BYOND hub.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  ### GetScores(key, fields)

  In this form, you can get information about individual scores. This is the most common way to use GetScores().

  The key is an arbitrary text value. Usually a player's key is a good choice, but you can also use the name of their character, or anything else you like, as long as it is unique. The key is case-insensitive.

  Scores and stats use data fields, which might be things like "Score", "Level", "Class", etc. To retrieve all the fields associated with a key, leave the fields argument blank. To retrieve only certain fields, you can send a separated list like "Score;Level" which is in the same format returned by list2params().

  If you leave the key argument blank, you will get a complete list of keys that have scores and stats associated with them.

  ### Example 1:

      mob/var/scores_found
      mob/var/score = 0

      mob/Login()
        ..()
        spawn()
          var/scores = world.GetScores(key)
          scores_found = !isnull(scores)
          if(scores)
            var/list/params = params2list(scores)
            if(params["Score"])
              score = text2num(params["Score"])
              src << "You have [score] point\s!"

  ### GetScores(count, field)
  and GetScores(count, skip, field)

  In this form, the proc gets a list of the top scores for a certain field, and gives you the keys and scores in order. To get the top 10 players by level, for instance, you would use GetScores(10,"level"). This returns a parameter list with the top keys and scores, so it might be in a form like "Bob=100;Anita=80;David=20;Charlie=5".

  The count and skip arguments are always numbers, not text. The count is the number of scores to retrieve, and skip is the number to skip over to get to them. So count=10 and skip=0 is the top 10, while count=10 and skip=5 is #6 through #15. If you leave out skip, it's a 0.

  The way you set up your hub entry is how the top scores are determined. If you told the hub that the "score" field is always sorted from highest number to lowest, then that's what you'll get. If "birthplace" is set up to use an alphabetical order, that's the order that GetScores() will use. If a field cannot be sorted, this form of GetScores() will return an empty text string.

  If you don't specify a field, your hub entry may have a default field to use. For instance if your hub page displays "Score", then "Level", then the "Score" field is the default.

  ### Example 2:

      mob/var/scores_found

      mob/Login()
        ..()
        spawn()
          var/top_scores = world.GetScores(10, "Booty")
          scores_found = !isnull(scores)
          if(scores)
            var/list/params = params2list(scores)
            src << "<b>Top Buccaneers:</b>"
            for(var/i=1, i<params.len, ++i)
              var/player = params[i]
              var/loot = params[player]
              src << "[i]\th place: [player] with [loot] doubloon\s"
            if(params.len && params[1] == key)
              src << "Ye be master of the seas! Take thy well-earned hat."
              icon_state = "Commodore"

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## Import proc (world)

  See also:
    Export proc (world)
  Import proc (client)
  Topic proc (world)
  fcopy proc
  Format:
    Import()
  Returns:
    The file sent by the remote server. The file will be downloaded to the local server's resource cache. Note that this will cause the caller to sleep while waiting for the necessary data to be transfered.
  When:
    Call this inside world.Topic() if you are expecting a file from the remote server.

  ### Example:

      //sending the file
      mob/proc/Export(Addr)
        var/savefile/F = new()
        F.Write(src)
        world.Export(Addr,F)

      //receiving the file
      world/Topic()
        var/savefile/F = new(world.Import())
        F.Read() //read the mob

  This example defines a mob proc called Export() which writes the mob to a savefile and sends it to another server (specified by Addr). The remote server opens it as a savefile and creates the mob (if the same mob type is defined on both servers and mob.Read() is compatible with the sending server's mob.Write()).

  Note that another method of transferring player mobs is to use the key savefile (accessed by client.Export() and client.Import()). Direct server to server communication on the other hand could transfer data (like non-players) without the need for player involvement at all.

  Savefiles are the most common type of file to transfer, but world.Import() simply returns a reference to an item in the world's .rsc file, which could be any type of file. This particular example demonstrates how to open such a file as a temporary savefile. (It gets dumped from the cache into a separate temporary file, which is then opened as a savefile.) Other types of files would be handled differently. For example, you could use fcopy() to dump the cached item to its own separate file.

  ## IsBanned proc (world)

  See also:
    GetConfig proc (world)
  params2list proc
  address var (client)
  computer_id var (client)
  connection var (client)
  hub var (world)
  Format:
    IsBanned(key,address,computer_id,type)
  Returns:
    True value if user is banned from this world. This may be a list, in which case special meaning is attributed to certain list elements as described below.
  Args:
    key: BYOND key of the user.
    address: current IP address of the user.
    computer_id: current computer_id of the user if known.
    type: type of connection if known (see client.connection)

  By default, this procedure checks the "ban" configuration file. If an entry is found for the current world (based on the value of world.hub), the parameter text is converted into a list (using params2list()), and the result is returned. Otherwise, null is returned.

  A ban that applies to all worlds on the host's computer will not call IsBanned(). The connection will simply be denied.

  This procedure is called internally whenever a new user connects (before client/New() is called). If the result is true, access is denied. If you want to ban a user but still allow them to log in (perhaps with reduced functionality), you can put "Login=1" in the parameter text. If you want to display an explanation to the user about why they are banned, you can also put "message=X" in the parameter text, where X is the message to display to the user. A reason for the ban can be added with a "reason=X" field. Of course, you can also override IsBanned() and insert these values directly into the list that is returned.

  ## Example

      world/IsBanned(key,address)
         . = ..()            //check the ban lists
         if(istype(., /list))
            .["Login"] = 1   //allow banned user to login

  When you ban people from paging you, this also causes them to be added to the keyban list. Even if they are already connected, IsBanned() will be re-evaluated and acted upon at that time. When you remove pager ban, they are removed from keyban as well.

  Additional data elements may be added to the ban list in the future. The current definition includes just the following items:

  Login
    true if banned user should be allowed to log in
  reason
    text string describing the reason or origin of the ban. For example, when people are banned from the pager, they are added to the "keyban" list with reason = "pager ban". This text is internal information only and is not displayed to the banned user.
  message
    text string explaining to the user why they were banned and possibly what they should do to be forgiven.

  Since the data in the "ban" file is in application/x-www-form-urlencoded format, it is probably not desirable to edit the file by hand. No built-in facilities for editing the file have been provided (aside from automatic addition of pager bans), but an interface could be created, using GetConfig and SetConfig to read and write the data. Extra features could also be added such as automatic inference of key associations by IP address.

  ## IsSubscribed proc (world)

  Format:
    IsSubscribed(player)
    IsSubscribed(player, "BYOND") (to check BYOND Membership)
  Returns:
    Number of days left in subscription, -1 for a lifetime subscriber, or null if hub contact failed
  Args:
    player: a mob, client, key, or ckey

  Checks a player for their subscription status to this game. This is a simpler alternative to `client.CheckPassport()`, which is deprecated, and also allows you to check even when the player has gone offline.

  This proc will return null if contacting the hub was required, but there was no way to reach the hub. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      mob/verb/JoinClub()
          if(!world.IsSubscribed(src))
              src << "Sorry, the club is only for subscribers."
          else
              // go to the turf with the tag "clubhouse"
              loc = locate("clubhouse")
              src << "Welcome to the clubhouse!"

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## New proc (world)

  Format:
  New()
  When:
  Called after the world is initially loaded. The only procs preceding this one would be in the initialization of global variables and objects on the map.
  Default action:
  None.

  ## OpenPort proc (world)
See also:
  port var (world)
  visibility var (world)
  See also:
    OpenPort(port=0)
  Args:
    port: the network port to open
  Returns:
    1 on success; 0 on failure

  This causes the world to be hosted on the specified network port. A value of 0 or "any" requests that any available port be used. The value "none" causes the port to be closed so that no new connections are possible.

  This proc may be overridden. If it is, calling ..() is necessary to open the port. If ..() is not called, it will not open.

  ### Example:

      world/OpenPort(port)
        // only allow subscribers to host
        if(host_is_subscribed)
          return ..()

  The "ports" configuration option in cfg/byond.txt can be used to control what ports worlds may open. The -ports command-line option may also be used. See startup for the syntax.

  ## PayCredits proc (world)

  See also:
    AddCredits proc (world)
  GetCredits proc (world)
  Format:
    PayCredits(player, credits, note)
  Returns:
    1 if the credits were spent successfully, 0 or null otherwise.
  Args:
    player: a mob, client, key, or ckey
    credits: A number of credits to deduct from the player's account
    note: An optional note (for author purposes) for the credit change

  Removes credits from a player's account, if they have enough. The proc will return 1 if it is successful, or 0 if the attempt failed (usually because the player doesn't have enough credits). This feature is intended for games that make use of the credit system, and for security all such games must use a hub password.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is often a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      mob/proc/ItemShop()
          var/items = list("Get credits!", "Magic sword"=10, "Skeleton key"=50)
          var/choices[0]
          var/item,price
          for(item in items)
              price = items[item]
              choices["[item]: [price] credit\s"] = item

          var/credits = world.GetCredits(key)
          if(isnull(credits))
              src << "Sorry, the item shop isn't available right now."
              return

          var/choice = input(src,\
            "You have [credits] credit\s. What would you like to purchase?",\
            "Item Shop")\
            as null|anything in choices
          if(!choice) return  // cancel

          if(choice == "Get credits")
              src << link("http://www.byond.com/games/Author/MyGame/credits")
              return

          item = choices[choice]
          price = items[item]
          if(!price) return

          src << "Contacting item shop..."
          var/result = world.PayCredits(name, price, "Item shop: [item]")

          if(isnull(result))
              src << "Sorry, the item shop isn't available right now."
          else if(!result)
              src << "You need [price-credits] more credit\s to buy [item]."
          else
              src << "You bought \a [item]!"

              // Now give the user the item and save their character
              // These procs are for you to define
              src.AddEquipment(item)
              src.SaveCharacter()

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## Profile proc (world)

  Format:
    Profile(command, format)
    Profile(command, type, format)
  Returns:
    Profilng data or null
  Args:
    command: A numerical value that says whether to start, stop, refresh, etc.
    type: A type of profile to use, other than proc profiling.
    format: Optional format for output data

  Interacts with the built-in server profiler without requiring the host to do so via Dream Daemon, or an authorized player via Dream Seeker.

  The `command` value is built from bitflags, so it can combine any of these three values via the `|` operator:

  PROFILE_STOP
    Stop profiling. Not using this flag will start/continue profiling.
  PROFILE_CLEAR
    Clear all profile data. This will also cause the proc to return null.
  PROFILE_AVERAGE
    Any output data should use average times instead of total times.

  These additional values are also defined for convenience:

  PROFILE_START
    Start/continue profiling but don't clear any existing data.
  PROFILE_REFRESH
    Currently this is the same as `PROFILE_START.
  PROFILE_RESTART
    Start profiling and clear existing data.

  ### Profiling procs

  By default, data will be returned as a list. The first six values are the column names: `"name"`, `"self"`, `"total"`, `"real"`, `"over"`, and `"calls"`, corresponding to the columns in the profiler. These are followed by the profile data for each proc, with the data being in the same column order. E.g. the next six items represent the first proc in the profile.

  The optional `format` argument however can be used to return the data in other formats. Currently the only accepted value is `"json"`, which will output the same data in JSON format.

  ### SendMaps profile

  Using `"sendmaps"` in the `type` argument will profile the routines used to send map informaiton to players. Unlike the proc profiling this only has three data columns: `"name"`, `"value"`, and `"calls"`. The value column might be a time or number value, depending on what's being measured.

  The JSON format will include a `unit` property data that is not a raw number, such as a time value.

  ## Reboot proc (world)

  Format:
  Reboot(reason)
  Args:
  reason: the reason `Reboot() was called:
  0 or null: Called by game code
  1: By host (Ctrl+R in Dream Seeker)
  2: By world.Topic()
  - 3: By SIGUSR1 in UNIX
  Default action:

  Reload the world from scratch. Any connected players will automatically relogin. This would be useful if you needed to recompile the world after changing some code.

  In a UNIX environment, you can cause a running server to reboot by sending it the signal SIGUSR1.

  If you override this proc, you must call ..() if you want the reboot to complete normally.

  For reboots initiated by Dream Seeker, usr will be the mob belonging to the player who sent the command.

  ## Repop proc (world)

  Format:
  Repop()
  Default action:
  Reload the obj and mob instances defined in the world map. This "repopulates" a world to its initial state. Only objects that were destroyed will be recreated.

  ## SetConfig proc (world)
See also:
  GetConfig proc (world)
  Format:
    SetConfig(config_set,param,value)
  Args:
    config_set: name of the configuration set (see below)
    param: name of the configuration parameter
    value: data to store (or null to delete this entry)

  This command is for storing configuration information that is shared by applications installed on the same system. The configuration data is accessed by specifying the configuration "set" and the parameter within that set.

  For more information, see GetConfig.

  ## SetMedal proc (world)

  See also:
    GetMedal proc (world)
  ClearMedal proc (world)
  GetScores proc (world)
  SetScores proc (world)
  Format:
    SetMedal(medal, player)
  Returns:
    1 if the medal was awarded successfully, 0 or null otherwise.
  Args:
    medal: name of the medal being awarded
    player: a mob, client, key, or ckey

  Awards a medal to a player. The proc will return 1 if it is successful, or 0 if the medal was already awarded. If the world already knows this medal was earned before, the hub will not be contacted.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      mob/monster/dragon
         Die(mob/killer)  // assume Die() is a proc all mobs have
            spawn()
               if(ismob(killer) && killer.key)
                  world.SetMedal("Dragon slayer", killer)

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## SetScores proc (world)

  See also:
    GetScores proc (world)
  GetMedal proc (world)
  SetMedal proc (world)
  ClearMedal proc (world)
  Format:
    SetScores(key, fields)
  Returns:
    The key, if the scores were successfully updated; null otherwise.
  Args:
    key: the name of the player, character, etc. for which scores should be set
    fields: The data fields to set

  Updates scores that are kept on the BYOND hub.

  The key is an arbitrary text value. Usually a player's key is a good choice, but you can also use the name of their character, or anything else you like, as long as it is unique. The key is case-insensitive.

  Scores and stats use data fields, which might be things like "Score", "Level", "Class", etc. Use list2params() to set the fields that you want to change. Fields that you do not include in the list will not be changed. A field with a blank value will be deleted.

  Sending an empty text string for the fields will erase the scores for that key.

  This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

  ### Example:

      var/params

      // Change the Score and Pet fields
      params = list("Score"=123, "Pet"="Dog")
      world.SetScores("Tom", list2params(params))

      // Delete the Pet field
      params = list("Pet"="")
      world.SetScores("Tom", list2params(params))

      // Delete Tom's scores entirely
      world.SetScores("Tom", "")

  Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.

  ## Tick proc (world)

  See also:
    cpu var (world)
  map_cpu var (world)
  tick_usage var (world)
  Format:
    Tick()
  When:
    Called during the server tick, after sleeping procs and queued commands, just before map information is sent to the clients.
  Default action:
    None.

  This proc allows you to do any updates just before map info is sent out. One possible use for this is to run a movement loop, or sync up any user interface input that might have arrived and deal with it all at once.

  ### Example:

      world/Tick()
          for(var/client/C)
              if(C.mob?.move_dir)
                  try
                      step(C.mob, move_dir)
                  catch
                      // empty catch, just so a failed step won't break the loop

  Note: The tick will not wait if this proc sleeps. It effectively has set waitfor=0 already built in. It's a good idea not to sleep in this proc or any of its callees at all, since it will keep getting called every tick.

  ## Topic proc (world)

  See also:
    Del proc (world)
  Export proc (world)
  Import proc (client)
  Import proc (world)
  Reboot proc (world)
  Format:
    Topic(T,Addr,Master,Keys)
  When:
    Called when a message is received from another server by using world.Export(). If a file is expected, world.Import() may be called to get it. The return value of Topic() will be passed back to the remote server.
  Args:
    T: The topic text string specified by the remote server (everything following ? in the URL).
    Addr: The address of the remote server.
    Master: 1 if remote server is the server which started this one.
    Keys: List of keys belonging to users who are logged in on the remote server
  Default action:
    The topic "ping" returns a true value (number of players plus one), which may be useful for telling if a server is alive. The topics "Reboot" and "Del" will call world.Reboot() and world.Del() respectively if the message was sent by the master server.

  ### Example:

      world/Topic(T)
        if(findtext(T,"shout:") == 1)
          world << copytext(T,7)

  This example allows other servers to send this server topic text of the form "shout:msg" and will broadcast the message to all the players in this world.

  The Keys argument is either null, or a list of user keys. Any keys in the list are logged in to the remote server.

  Always validate the input in `Topic()` calls to make sure it's correct and the query you're recieving is legitimate.

  ## vars (world)

  Built-in world vars:

  world/var
    address
  area
  byond_build
  byond_version
  cache_lifespan
  contents
  cpu
  executor
  fps
  game_state
  host
  hub
  hub_password
  icon_size
  internet_address
  log
  loop_checks
  map_format
  map_cpu
  maxx
  maxy
  maxz
  mob
  movement_mode
  name
  params
  port
  process
  realtime
  reachable
  sleep_offline
  status
  system_type
  tick_lag
  tick_usage
  time
  timeofday
  timezone
  turf
  url
  vars
  version
  view
  visibility

  ## address var (world)

  See also:
    port var (world)
  url var (world)
  internet_address var (world)

  This is the network address of the machine hosting the world. If it cannot be determined, it will be null.

  The full network address of the world may be formed by concatenating the world address and port: "byond://[address]:[port]".

  In CGI mode, this is the web address of the world.

  This is the local address only. If the world is hosted via a router, the external IP address may be different. Use `internet_address` to find the external address, if available.

  ## area var (world)

  Default value:
    /area.

  This is the default area type to be placed on the map wherever no area is specified. A value of 0 turns off the default area.

  ## byond_build var (world)

  See also:
  DM_VERSION macro
  byond_version var (world)
  byond_version var (client)
  byond_build var (savefile)
  byond_version var (savefile)

  This is the build number (minor version) of BYOND being run by this server. Typically this is not useful information, but it can come in handy when diagnosing issues reported by players when hosting with a beta build.

  ## byond_version var (world)

  See also:
    DM_VERSION macro
  byond_build var (world)
  system_type var (world)
  byond_version var (client)
  byond_build var (savefile)
  byond_version var (savefile)

  This is the version of BYOND at run-time. A game designed to work around known bugs in older versions could use this to adapt its behavior accordingly.

  ## cache_lifespan var (world)

  See also:
    cache
  Default value:
    30 (days)

  Number of days items that are not in use will be saved in the resource cache (.rsc file). Files uploaded by players are stored in the world's .rsc file for future use. If the file is not used for the specified amount of time, it will be removed to save space.

  Setting this value to 0 causes items to be saved for the current session only. This is used by the CGI library, because web browsers cannot make use of server-side caches when uploading files anyway.

  This value must be a whole number.

  ## contents list var (world)

  See also:
    list
  Default value:
    List of all areas, turfs, mobs, and objs initially in the world.

  This is a list of every object in the world. Objects in this list are in no particular order.

  ### Example:

      proc/ListAreas(mob/M)
        var/area/A
        M << "Areas:"
        for (A in world.contents)
          M << A

  This example displays a list of every area in existence. As a convenient short-hand, one may simply write for(A) or for(A in world) instead of the full for(A in world.contents).

  ## cpu var (world)

  See also:
    map_cpu var (world)
  tick_lag var (world)
  tick_usage var (world)
  Tick proc (world)

  This is the percentage of a server tick that the server spends processing running procs and the work of sending map information to players. A value of 0 would indicate very little cpu usage. A value of 100 would indicate full cpu usage, which could mean that the server cannot complete all the necessary computations during a tick to finish in time for the next tick. In this case, timed events (such as sleep) may take longer than requested.

  When deciding on a value for tick_lag, one could use this value to determine if the CPU is fast enough to tick at a higher rate.

  The `map_cpu` var is a subset of this, measuring only time used for sending map information.

  ## executor var (world)

  See also:
    startup proc
  Format:
    executor = "/usr/local/byond/bin/DreamDaemon [params]"

  This option is for direct execution of `.dmb` files in UNIX. The most common use is for writing CGI programs that are executed by the web server.

  The first parameter in the executor text string is the path to DreamDaemon. The one listed above is the standard UNIX location.

  Optional parameters may follow. The most common are -CGI and -logself.

  ### Example:

      world/executor = "/usr/local/byond/bin/DreamDaemon -CGI -logself"

  This example creates a CGI program to be executed by a web server. It puts its error output in the file `projname.log`.

  All of this is configured for you when you include `html/CGI.dm` from the html library.

  ## fps var (world)

  See also:
    tick_lag var (world)
  fps var (client)
  Pixel movement
  Default value:
    10

  The value of `world.fps` defines the speed of the world in frames (server ticks) per second. By default this is 10 fps, which is a good speed if all objects move in full tiles. Higher values yield smoother results, but at a cost to performance. Timing of many events may be limited by the system clock, so `fps` values beyond 40 or 50 may cause unwanted effects like jitter even for projects that are not very demanding in terms of performance.

  For projects making use of pixel movement, higher `fps` is usually desired. 40 seems to be a good value for general use, but in worlds that have a large number of players, you may wish to lower the value and give players a higher `step_size` per tick instead.

  This var exists for convenience; it is calculated by `10 / world.tick_lag`. The value of `world.tick_lag` is actually more accurate, but it is easier to think of world speed in terms of frames per second. The actual tick rate has a resolution of 1 ms.

  When reading `world.fps`, the result is always given as a whole number to gloss over rounding error.

  If you set `client.tick_lag` or `client.fps` to a value other than 0, you can make the client tick at a different (usually faster) rate.

  ## game_state var (world)

  See also:
    name var (world)
  status var (world)
  visibility var (world)
  Default value:
    0

  At runtime, this value may be changed to let the BYOND hub know about certain changes in the game's status. An example for using this value is if the number of players in the game gets too high and most new logins are rejected, you can set game_state to 1 to let the hub know this server is full.

  The following values are accepted:

  0
    Normal status
  1
    Server is full

  Note that this value does not affect how your world actually reacts to new players logging in. It is only used by the hub and website.

  ## host var (world)

  See also:
    game_state var (world)
  name var (world)
  status var (world)
  visibility var (world)
  Default value:
    null

  If the information is made available by the pager, this will provide the key of the world's host. If the host is not known, this value will be either null or an empty string.

  ## hub var (world)

  See also:
    hub_password var (world)
  name var (world)
  status var (world)
  game_state var (world)
  version var (world)
  visibility var (world)
  Default value:
    null

  This is a registered BYOND hub path. The default value of null is for unregistered games. Registered games (don't worry, it's free!) have their own hub page showing a brief description of the game, the author, an optional installation package, and links to online games. The hub path is a string of the form "YourName.GameName" and can be found in your hub console.

  Even unregistered games show up in the hub when they are live (that is online with people connected). It just doesn't show any of the extra info like a description, and there is no way for people to find out about it when nobody is logged in.

  If you do not want your game to show up in the hub (like while you are in the initial stages of development), just compile with `visibility=0`. Either that, or turn off your pager or your BYOND locator when you are connected to it.

  You (or the players) might also wish to turn off the notice of a live game in the hub when there is no longer any room for new players or if it is too late in the game for new people to join. At such times, you can simply set the visibility to 0.

  ### Example:

      world
         hub = "Dan.PipeStock"   //registered hub path

      mob/verb/start_game()
         world.visibility = 0
         //...

  If you configure your hub page to require a hub password, you must also specify `world.hub_password`.

  ## hub_password var (world)

  See also:
    hub var (world)
  visibility var (world)
  Default value:
    null

  If `world.hub` is set, any live session of the game will be attached to the specified BYOND Hub page. Under the default settings, any game can set `world.hub` and attach itself to any BYOND Hub page.

  To beef up security, you can set a hub password in your hub's configuration page via the BYOND website. This will ensure that only authorized copies of your game can attach themselves to your hub page when live. Then simply copy that password into your code as `world.hub_password` so that your game's live broadcast will be accepted by the hub.

  ### Example:

      world
         hub = "Dan.PipeStock"   //registered hub path
         hub_password = "UPAggnJaeXmSBoKK"   //password for live game authentication

  Note that for security reasons, reading this variable at runtime will return a hashed version of the value that was set.

  ## icon_size var (world)

  See also:
    map_format var (world)
  step_size var (movable atoms)
  Gliding
  Pixel movement
  Default value:
    32

  This is the tile size that will be used as a default for icons in the world. It can be set to a single number that represents both the width and height, or you can use a format like "[width]x[height]" (such as "16x48") to specify width and height separately.

  This value affects several calculations, including icon operations and gliding between turfs.

  Note: If you do not use a square icon size and you are using a topdown map format, you may experience display issues if setting `client.dir` to `EAST` or `WEST`. A non-square tile with a topdown map format will also interfere with pixel movement. For this reason, square sizes are recommended when using any topdown-view map format.

  ## internet_address var (world)

  See also:
    port var (world)
  url var (world)
  address var (world)

  This is the network address of the machine hosting the world, as it is seen by the outside network (from the Internet) and the hub. If it cannot be determined, it will be null.

  The full network address of the world may be formed by concatenating the world address and port: "byond://[address]:[port]".

  This var exists because `world.address` may not be accurate if the world is hosted on a machine behind a router using NAT. The value returned by `internet_address` can be given to other players who wish to log in.

  ## log var (world)

  See also:
    file proc
  startup proc

  Sending output to world.log may be useful for debugging purposes. The output goes to the same place run-time proc errors are displayed.

  ### Example:

      if(1+1 != 2)
        world.log << "Uh oh."

  You can assign world.log to a file name or file() object to redirect output to that file. (There is also a command-line option to Dream Daemon that does this.)

  ### Example:

      world.log = file("mylog.txt")

  ## loop_checks var (world)

  Default value:
    1

  Setting this to 0 disables the very long loop protection. By default, loops in the code which undergo a very large number of iterations or recursions are aborted (by crashing the proc). This prevents the proc from locking up the server for too long.

  You may need to disable this feature if your code has some very long loops in it. Before doing that, make sure it's not infinitely long! Your program will utterly crash if it runs out of system stack space, which can happen in a very deep or infinite recursion.

  Note: The compiler will now generate a warning when you disable `loop_checks`. It is not advisable to disable the check unless you're trying to debug something, since you can cause the server to hang. Generally if you have a loop so long it can cause the regular loop checks to freak out, you need to make a change to the loop behavior anyway.

  ## map_format var (world)

  See also:
  icon_size var (world)
  view var (world)
  view var (client)
  screen_loc var (movable atoms)
  Topdown maps
  Isometric maps
  Side-view maps
  Big icons
  Tiled icons
  Understanding the renderer
  Default value:
    TOPDOWN_MAP
  Possible values:
    TOPDOWN_MAP
    ISOMETRIC_MAP
    SIDE_MAP
    TILED_ICON_MAP

  This value says how the world will display maps. In a normal overhead tiled map the value is `TOPDOWN_MAP` for the top-down format. For older games that predate this feature, the value is `TILED_ICON_MAP`.

  If you use a map format other than top-down, the HUD will still use a tile format like it would in top-down display. HUD objects are not projected into whatever map_format you use and they are not affected by changing client.dir. The size of the HUD is rounded up to the nearest number of full screen tiles; the size of each tile is defined by world.icon_size.

  ### Top-down format

  (See more at Topdown maps.)

  This is the default map format. Icons are drawn in a tile form and viewed from overhead. In this layout, the layer assigned to each atom is very important. The number of tiles shown is set by client.view or world.view.

  Because this format is familiar and easy to understand, it is the default setting. Most of the vars related to maps and atoms are designed and documented with this format in mind.

  ### Tiled icon format

  (See more at Tiled icons.) In BYOND 4.0 a new feature was introduced for using "big" icons, bigger than the standard tile size, by splitting them up into states like "0,0", "1,0", and so on. This functionality is no longer needed since BYOND now has the ability to display icons in their natural size. Some games that were designed before this, however, may still need to make use of this splitting feature that breaks icons into smaller tile-sized pieces. When an icon is broken into chunks, each state in the icon is given a thumbail version of the full image, and then new states are added to show each chunk. For instance if world.icon_size is the default 32×32, and the icon is 64×64, then the "door" state would become a thumbnail of the full door image while "door 0,0" (the lower left corner), "door 1,0", "door 0,1", and "door 1,1" were created to show each smaller section of the image. If the default "" state is broken into chunks, those chunks are just named "0,0" and so on without a space.

  This format is deprecated. It exists to support older games and allow them to be compiled without causing them to break, until they can be redesigned for one of the newer formats.

  ### Isometric format

  (See more at Isometric maps.)

  If map_format is set to `ISOMETRIC_MAP`, the map is displayed in isometric form. Isometric tiles are displayed in a foreshortened diagonal perspective, where the "north" direction actually displays as northeast on the player's screen, and "east" shows up as southeast. The value of `client.view` or `world.view` is used to calculate the minimum number of tiles to display, and extra tiles to each side will be shown to fill in the corners.

  In an isometric map, the tile width set in world.icon_size is the most important factor. This should be a multiple of 4 for best results. The minimum tile height is half that value, and any extra height is used to show vertical structures that "stick up" off the map surface. When you draw an isometric tile icon, start with a flattened diamond shape at the bottom that is only half as high as it is wide.

  Isometric maps behave differently during drawing than top-down maps. In isometric, tiles that are nearer to the viewer's perspective are drawn in front of tiles farther back, regardless of layer. Layers only count within an individual tile. This means that if you want to have a vertical structure "stick up" to partially hide something behind it, the icon sticking up should always be on a tile forward from the one being partly covered. E.g. if you have a wall taking up part of your tile, it needs to be at the "back" end of the tile to properly hide anything on the tiles behind it.

  The `pixel_x` and `pixel_y` values, `step_x` and `step_y` values, and the gliding that happens when moving between tiles, are based on the width set by `world.icon_size`. If you set `world.icon_size="64x128"` to show tall buildings, only the 64 matters for pixel offsets. Use `pixel_w` and `pixel_z` to adjust the position of atoms (or the client) horizontally or vertically without respect to `client.dir` or the map format.

  Note: Offsets for x and y also affect the layering order used to draw the icons. Any object with a pixel offset onto another tile is considered part of whichever tile is closer.

  If you use an icon wider than one tile, the "footprint" of the isometric icon (the actual map tiles it takes up) will always be a square. That is, if your normal tile size is 64 and you want to show a 128x128 icon, the icon is two tiles wide and so it will take up a 2×2-tile area on the map. The height of a big icon is irrelevant--any excess height beyond width/2 is used to show vertical features. To draw this icon properly, other tiles on that same ground will be moved behind it in the drawing order.

  One important warning about using big icons in isometric mode is that you should only do this with dense atoms. If part of a big mob icon covers the same tile as a tall building for instance, the tall building is moved back and it could be partially covered by other turfs that are actually behind it. A mob walking onto a very large non-dense turf icon would experience similar irregularities.

  ### Side-view format

  (See more at Side-view maps.)

  The `SIDE_MAP` format is like a cross between `TOPDOWN_MAP` and `ISOMETRIC_MAP`. It looks very similar to a top-down view but it is intended for more of a 3/4 perspective, where tiles lower on the screen are considered closer to the viewer. Because this impacts the way layers work, most of the layering behavior is the same as with isometric.

  In a 3/4 perspective the tiles are often foreshortened, so pixel offsets are adjusted to account for this. For example, you may set `world.icon_size` to `"32x24"`, but the tile is considered to be a perfect square if you look at it from the top down. Because the width is 32 pixels, the virtual height is also 32, so if you use pixel_y=32 the atom will appear one tile further back than it normally is. (This adjustment doesn't affect screen objects or `pixel_w`/`pixel_z`.)

  Changing `client.dir` preserves the same tile size regardless of orientation.

  ## map_cpu var (world)

  See also:
    cpu var (world)
  tick_lag var (world)
  tick_usage var (world)
  Tick proc (world)

  This is the percentage of a server tick that the server spends processing information about the map to send to players. A value of 0 would indicate very little cpu usage. A value of 100 would indicate full cpu usage, which means that the server cannot complete all the necessary computations during a tick to finish in time for the next tick. In this case, timed events (such as sleep) may take longer than requested.

  ## maxx var (world)

  See also:
    area var (world)
  maxy var (world)
  maxz var (world)
  turf var (world)
  Map
  Default value:
    0

  The world map is a three-dimensional block of turfs with coordinates ranging from (1,1,1) to (maxx,maxy,maxz). If set at compile time, it provides a lower bound and will be increased as needed by the map files.

  The default value is 0, indicating no map. If any of the map dimensions are set to non-zero values at compile time, the others will default to 1.

  New territory created by increasing the map boundaries is filled in with the default turf and area (world.turf, and world.area).

  ## maxy var (world)

  See also:
    area var (world)
  maxx var (world)
  maxz var (world)
  turf var (world)
  Default value:
    0

  The world map is a three-dimensional block of turfs with coordinates ranging from (1,1,1) to (maxx,maxy,maxz). If set at compile time, it provides a lower bound and will be increased as needed by the map files.

  The default value is 0, indicating no map. If any of the map dimensions are set to non-zero values at compile time, the others will default to 1.

  New territory created by increasing the map boundaries is filled in with the default turf and area (world.turf, and world.area).

  ## maxz var (world)

  See also:
    area var (world)
  maxx var (world)
  maxy var (world)
  turf var (world)
  Default value:
    0

  The world map is a three-dimensional block of turfs with coordinates ranging from (1,1,1) to (maxx,maxy,maxz). If set at compile time, it provides a lower bound and will be increased as needed by the map files.

  The default value is 0, indicating no map. If any of the map dimensions are set to non-zero values at compile time, the others will default to 1.

  New territory created by increasing the map boundaries is filled in with the default turf and area (world.turf, and world.area).

  ## mob var (world)

  See also:
    New proc (client)
  Default value:
    /mob.

  When a player connects to the world, the world is searched for a mob with the player's key. If one is found, the player is connected to that mob. If none is found, a new mob of type world.mob is created and the player is connected to this new mob.

  The default value is /mob. Setting world.mob to 0 prevents the creation of default mobs.

  ### Example:

      world
        mob = /mob/newbie

      mob/newbie
        Login()
          src << "Welcome, [name]."
          ..()

  This example will connect new players to mobs of type /mob/newbie. They are welcomed when they connect.

  ## movement_mode var (world)

  See also:
    appearance_flags var (atom)
  Enter proc (atom)
  Exit proc (atom)
  Cross proc (atom)
  Uncross proc (atom)
  Pixel movement
  Gliding
  Possible values:
    `LEGACY_MOVEMENT_MODE`: Old BYOND behavior regarding pixel movement and turf contents (see below)
    `TILE_MOVEMENT_MODE`: All atoms are locked to the tile grid
    `PIXEL_MOVEMENT_MODE`: All movable atoms can use pixel movement unless otherwise specified (see below), but legacy behavior for turf contents is ignored
  Default value:
    LEGACY_MOVEMENT_MODE

  Controls how movement works on the map.

  `TILE_MOVEMENT_MODE` allows you to easily discard any and all pixel movement, so if step_x or step_y coordinates or unexpected atom bounds were loaded from a savefile, for instance, they would be eliminated. If you use any other movement mode, you can give an atom the TILE_MOVER flag and it will behave as if it were in this mode, while other atoms are free to do their own thing.

  `LEGACY_MOVEMENT_MODE` exists to distinguish between old and new movement behavior. In older versions of BYOND before pixel movement, turfs took their contents into consideration by default in Enter() and Exit(). This doesn't really make sense for newer games, so in any other movement mode the turf behavior will ignore its contents. mob.Cross() is also affected, since it would return 0 by default in legacy mode when both mobs were dense; now by default it checks `mob.group`.

  ## name var (world)

  Default value:
    The <world> part of the <world>.dmb file.

  This is the name of the world.

  ### Example:

      world
        name = "The Void"

  ## params var (world)

  See also:
  list associations
  params2list proc
  startup proc
  Default value:
    null

  This is a list of parameters passed to the world from the command-line -params option when the server was started. The parameter text is passed through params2list() to generate the world.params list.

  ### Example:

      world/New()
         var/p
         if(params.len) world.log << "Command-line parameters:"
         for(p in params)
            world.log << "[p] = [params[p]]"

  This example displays the value of each parameter.

  ## port var (world)

  See also:
    OpenPort proc (world)
  address var (world)
  reachable var (world)
  visibility var (world)

  This is the network port of the world. If the world does not have an open network port, this is 0.

  ## process var (world)

  See also:
    byond_version var (world)
  system_type var (world)
  shell proc

  This read-only variable indicates the ID of the server's process on the system running it. The result is a number, unless for some unexpected reason the number won't fit in a `num` type, in which case it will be text. (In practice it should always be a number.)

  ## realtime var (world)

  See also:
    time var (world)
  timeofday var (world)
  time2text proc

  This is the time (in 1/10 seconds) since 00:00:00 GMT, January 1, 2000 (also known as the BYOND era).

  Because this is a large number, BYOND's number system isn't capable of enough precision to deliver the exact number of 1/10 second ticks. It usually rounds off to the nearest several seconds. For more accurate readings use `world.timeofday`.

  ## reachable var (world)

  See also:
    port var (world)
  OpenPort proc (world)

  Returns 1 if the world is currently hosted and the port can be reached by players (as determined by the BYOND hub), 0 if not.

  If the port is not reachable, there may be a brief period during which the hub is still attempting to make contact; during that time the port is assumed to be reachable. Currently, the reachability test times out and fails after 30 seconds.

  ## sleep_offline var (world)

  Default value:
    0

  Setting this to 1 causes the world to be suspended when there are no players, even if you have sleeping procs waiting to happen. The default value is 0, which means the server will only sleep if there are no players and no procs waiting to happen. The main purpose of the variable is to save the cpu from doing work when there is nobody around to appreciate it. On the other hand, that doesn't give the poor NPC's a break from the nasty humans.

  ## status var (world)

  See also:
  hub var (world)
  game_state var (world)
  visibility var (world)

  This is a short text string used in BYOND hub to describe the state of a game in progress. For example, you might want to indicate if new players will be able to actively play, or whether they would have to join as spectators.

  ### Example:

      world
         status = "accepting players"
      mob/verb/start_game()
         world.status = "accepting spectators"
         //...

  ## system_type var (world)

  See also:
    byond_version var (world)
  process var (world)
  shell proc

  This variable indicates the operating system type at run-time. It will be one of the following constants:

  - MS_WINDOWS
  - UNIX

  ## tick_lag var (world)

  See also:
    fps var (world)
  tick_lag var (client)
  tick_usage var (world)
  sleep proc
  Default value:
    1

  This is the smallest unit of time (one server tick) measured in 1/10 seconds. The duration of events that take some finite amount of time (like sleep) will be rounded to a whole number of ticks.

  Players are limited to one command (including movements) per server tick, so this value can be used to adjust the responsiveness of the game. If the network is too slow to keep up with players, their commands will get queued up, which can be annoying when trying to move. In this case, tick_lag should be increased so that the stored up movement commands are discarded. On the other hand, if you have a very fast network, you may wish to decrease tick_lag to speed up the response time to player commands.

  Often it is more convenient to set world.fps instead of world.tick_lag, since fps (frames per second) is an easier way to think of server ticks. world.tick_lag is 10 / world.fps and vice-versa, so a tick_lag of 0.25 is equal to 40 fps.

  If you set client.tick_lag or client.fps to a value other than 0, you can make the client tick at a different (usually faster) rate.

  ## tick_usage var (world)

  See also:
    cpu var (world)
  tick_lag var (world)
  Tick proc (world)

  This is the approximate percentage of the server tick that has been used already. A value under 100 means there's time to do more calculations, which can include any pending procs that are still waiting to run on this tick. When the value is over 100, the tick is running long and your world will experience lag.

  Keep in mind that sending maps to clients is the last thing that happens during a tick, except for handling any events such as player commands that might arrive before the next tick begins. Therefore in a verb, `tick_usage` might have a higher value than you would expect to see in a proc that loops and sleeps.

  ## time var (world)

  See also:
    realtime var (world)
  tick_lag var (world)

  This gives the amount of time (in 1/10 seconds) that the world has been running. In actual fact, it is the number of server ticks that have passed multiplied by world.tick_lag. Therefore if the server sleeps (when no players are connected) this time is not counted. Also, if the server runs overtime during a tick (because procs take longer than tick_lag to finish) this still only counts as one tick. This value is therefore a measure of "game time" rather than real time.

  ## timeofday var (world)

  See also:
    realtime var (world)
  time var (world)
  time2text proc

  This is the time (in 1/10 seconds) since 00:00:00 GMT today. It is basically identical to `world.realtime` but doesn't include any information about the date. This is a much smaller number; hence it is more accurate.

  ## timezone var (world)

  See also:
    realtime var (world)
  timeofday var (world)
  timezone var (client)
  time2text proc

  This is the time offset from UTC, in hours, for the world's time zone. It can be used in the `time2text()` proc, although it is the default time zone for that proc.

  ## turf var (world)

  Default value:
    /turf.

  This is the default turf type to be placed on the map wherever no turf is specified. A value of 0 turns off the default turf.

  ## url var (world)

  See also:
  address var (world)

  This is the full network address of the world. (For example, byond://dan.byond.com:6005.)

  ## version var (world)

  See also:
  hub var (world)
  Default value:
    0

  If you are distributing your game to players, you can use this variable to automatically notify them of new releases. To do so, you will first need to set `world.hub to the hub path of your game. You can then advertise the current version by configuring that value in your hub console.

  When players boot up an outdated version of your game (as indicated by comparing `world.version` with the version advertised by BYOND hub), they will be notified of the new release.

  ## view var (world)

  See also:
  lazy_eye var (client)
  show_map var (client)
  view proc
  view var (client)
  Default value:
    5
  Possible values:
    -1 to 34 or "WIDTHxHEIGHT"

  This is the default map viewport range. The default value of 5 produces an 11x11 viewport. A value of -1 turns off the map display altogether. The client may automatically scale down icons in order to conveniently fit the map on the player's screen.

  For non-square views, you can assign this to a text string of the form "WIDTHxHEIGHT". For example, "11x11" is equivalent to a view depth of 5, but you could make it wider like this: "13x11".

  This setting also affects the default range of the `view()`, `oview()`, `range()`, and `orange()` procedures.

  If the entire map is small enough to fit on one screen (arbitrarily defined to be 21x21 or less), the default `view` is automatically adjusted to fit the map. In this case, `client.lazy_eye` is also automatically turned on by default, since you probably don't want the map to scroll around.

  ## visibility var (world)

  See also:
    OpenPort proc (world)
  hub var (world)
  Default value:
    1 (visible)

  This controls whether the world advertises itself in the BYOND Hub when it has an open network port for accepting players. The visibility of the world still depends on whether any of the connected players has their location reporter turned on, and that in turn relies on the pager being turned on.

  ## Special notes

  This section of the reference should help explain some concepts that may be harder to understand or that can use more clarification.

  Language features
    Numbers
  Regular expressions
  Unicode
Icons
  Big icons
  Tiled icons
Map formats
  Topdown maps
  Isometric maps
  Side-view maps
Movement
  Gliding
  Pixel movement
Display
  Understanding the renderer
  HUD / screen objects
  Color matrix
  Filter effects
  Particle effects
    Color gradient
    Generators
  Projection matrix
  BACKGROUND_LAYER
  EFFECTS_LAYER
  TOPDOWN_LAYER

  ## BACKGROUND_LAYER

  See also:
    layer var (atom)
  plane var (atom)
  map_format var (world)
  EFFECTS_LAYER
  TOPDOWN_LAYER
  stddef.dm file
  Understanding the renderer

  This is mostly no longer needed. A negative value for plane is the preferred way to do show objects in the background. It can still be used however when you want to rearrange objects in the same plane when using PLANE_MASTER for visual effects.

  `BACKGROUND_LAYER` is a special high value that can be added to the regular layer of any atom.

  The purpose of this value is to make an atom appear below any regular atoms, even if they share the same plane. In an isometric map for instance, HUD objects will always appear above the map, but makeing a HUD object appear behind the map was basically impossible without this feature until `plane` was implemented.

  When using this special layer, it should be added to the layer an atom normally uses. For instance an obj should have a layer of `BACKGROUND_LAYER + OBJ_LAYER`.

  This can be mixed with `TOPDOWN_LAYER` and `EFFECTS_LAYER`, but it will take precedence over both. Anything with `BACKGROUND_LAYER` will always appear below anything without it on the same plane.

  Images or overlays with `FLOAT_LAYER` can be left alone. They will automatically have the same layer as whatever atom they are attached to.

  ## Big icons

  See also:
    icon
  procs (icon)
  Blend proc (icon)
  map_format var (world)
  icon_size var (world)
  Tiled icons
  Isometric maps
  Side-view maps

  BYOND allows you to use icons that are not the same size as the tile size defined in world.icon_size. These icons can be manipulated with the /icon datum using their raw, native size, and shown on the map in full size. To use the old behavior where an atom can display only an icon of the normal tile size, use the TILED_ICON_MAP value for map_format instead.

  When you use an icon of non-standard size on an atom, the icon is "anchored" to the southwest corner of the atom. If you are using a top-down view (world.map_format=TOPDOWN_MAP), the icon will appear to spread out further to the east and north. In an isometric map (world.map_format=ISOMETRIC_MAP), the icon will cover additional tiles north and east as well. The "footprint" of an isometric icon--the actual map tiles it covers--is always square, so if your tile size is 64x64 and you use a 128x64 icon, the 128-pixel width means the icon will cover a 2x2 section of map tiles.

  It is important to remember that using a big icon is a visual effect only. It will not affect how the atom bumps into other atoms or vice-versa.

  Big icons will affect layering--the order in which icons are drawn. In general, because a big icon is covering more than one tile of the map, it will try to draw above any other tiles in that space that are on the same layer. This way, you can set a turf to use a big icon without having to change the turfs to the north and east. If an atom has a big icon, any overlays and underlays attached to it will be pulled forward as well, so they will draw in front of anything on their same layer. In isometric mode this is about the same, except that the layer isn't that important--anything in the way will just be moved back behind the big icon.

  Note: Big overlays will not "pull forward" on their own. If the main atom uses a single-tile icon, a big overlay attached to it will not try to draw in front of other icons on the same layer. This is so that name labels, health bar overlays, etc. will not cause any odd behavior. To be safe, you should always specify a layer when adding an overlay.

  In isometric mode, layering is affected by the "distance" between the atom and the viewer, so putting a regular-sized icon and part of a big icon on the same tile could cause layering oddities. Tiles that are covered by a big icon will tend to be drawn behind the big icon as mentioned above. For this reason, any atoms whose icons cover more than one tile (the extra height of an isometric icon doesn't count) should always be dense, and you should block movement onto any tile covered by them.

  When manipulating icons with the /icon datum, you can still use Blend() to combine icons of different sizes. By default, the icons will be lined up at their southwest corners. You can change the position at which the second icon is blended.

  ## Color gradient

  See also:
    gradient proc
  color var (atom)
  Particle effects
  Color space

  A color gradient is a special list that defines a range of colors that you can smoothly interpolate between. A simple example is a gradient from red to white:

  ### Example:

      list("red", "white")
      // OR
      list(0, "red", 1, "white")

  Applying a number like 0.2 to this gradient would give you a color that's 20% of the way from red to white. More complex gradients however are also possible.

  The format of a gradient is a list that contains a number (the position along the gradient, from 0 to 1 unless you use values outside that range) followed by a color. You can have as complex a gradient as you like. If you reuse the same number twice in a row, the gradient will have a sudden color change at that point.

  It is also possible to skip numbers or colors, and they will be filled in automatically with the previous number or color. The exceptions are at the beginning and ends of the list; at the end of the gradient, the last color is assigned a number 1 by default, and the first is assigned 0. If you skip colors at the beginning, they will be filled in with the first color you use.

  Include "loop" anywhere in the list to make this a looped gradient. If you don't, any numbers outside the gradient's range will be clamped to that range. E.g., in a normal gradient ranging from 0 to 1, a number of 1.2 is interpreted as 1 without a loop and 0.2 with a loop.

  Here are some more examples:

  ### Example:

      // color wheel; ranges 0 to 6 and loops
      list(0, "#f00", 1, "#ff0", 2, "#0f0", 3, "#0ff", 4, "#00f", 5, "#f0f", 6, "#f00", "loop")

      // 10% each red, yellow, green, blue, with a 20% transition zone between each
      // notice no color follows 0.4 or 0.7, so the previous color is used
      list(0.1, "#f00", 0.3, "#ff0", 0.4, 0.6, "#008000", 0.7, 0.9, "#00f")

      // green and black stripes
      list(0.5, "#008000", 0.5, "#000000", "loop")

  You can also include "space" in the list, and give it an associated value that describes the color space this gradient uses to interpolate between colors. For instance, `"space"=COLORSPACE_HSL` will use HSL interpolation instead of the default RGB. See Color space for more information.

  ### Example:

      // color wheel with a different color space
      list(0, "#f00", 3, "#0ff", 6, "#f00", "loop", "space"=COLORSPACE_HSLA)

  Currently, color gradients are only used by particle effects and the `gradient` proc. With particles, if you use a gradient the particle's color is given as a number, and that number is used to look up its real color from the gradient. The number can change over time, thus changing the particle's color.

  ## Color matrix

  See also:
    color var (atom)
  color var (client)
  MapColors proc (icon)

  A color matrix is used to transform colors, in the same way that a matrix represented by the `/matrix` datum is used to transform 2D coordinates. A transformation matrix is 3x3, of which only 6 values are needed because the last column is always the same. A color matrix, because it transforms four different numbers instead of two, is 5x5.

                      |rr rg rb ra 0|
                      |gr gg gb ga 0|
      [r g b a 255] x |br bg bb ba 0| = [r' g' b' a' 255]
                      |ar ag ab aa 0|
                      |cr cg cb ca 1|

  In that formula, values like `rg` mean "red to green", meaning that's the ratio of red in of green out. (The "c" is for "constant".) In an identity matrix, which just produces the original color, the values `rr`, `gg`, `bb`, and `aa` are all 1 and everything else is 0.

  In easier-to-understand terms, this is how the result is calculated:

      new_red   = red * rr + green * gr + blue * br + alpha * ar + 255 * cr
      new_green = red * rg + green * gg + blue * bg + alpha * ag + 255 * cg
      new_blue  = red * rb + green * gb + blue * bb + alpha * ab + 255 * cb
      new_alpha = red * ra + green * ga + blue * ba + alpha * aa + 255 * ca

  It is helpful to think of each row in the matrix as what each component of the original color will become. The first row of the matrix is the rgba value you'll get for each unit of red; the second is what each green becomes, and so on.

  Because the fifth column of the matrix is always the same, only 20 of the values need to be provided. You can use a color matrix with atom.color or client.color in any of the following ways:

  RGB-only (9 to 12 values)
    list(rr,rg,rb, gr,gg,gb, br,bg,bb, cr,cg,cb)
  RGBA (16 to 20 values)
    list(rr,rg,rb,ra, gr,gg,gb,ga, br,bg,bb,ba, ar,ag,ab,aa, cr,cg,cb,ca)
  Row-by-row (3 to 5 `rgb()` values, or null to use the default row)
    list(red_row, green_row, blue_row, alpha_row, constant_row)

  Reading a color var that has been set to a matrix will return the full 20-item list, where every 4 items represent a row in the matrix (without the fifth column).

  In the `MapColors()` icon proc, the values are sent as arguments, not as a list.

  ### Other color spaces

  The color filter allows the use of other color spaces for a matrix. In those other color spaces, the matrix calculations work the same but instead of red, green, and blue, they'll be whatever values that color space uses. For instance an HSL color matrix uses hue in place of red, saturation in place of green, and luminance in place of blue. (Alpha is always alpha.)

  The way that works internally is that the shader will convert a color from RGB to the color space used by the matrix, then apply the matrix, then convert back to RGB.

  ## EFFECTS_LAYER

  See also:
    layer var (atom)
  plane var (atom)
  map_format var (world)
  BACKGROUND_LAYER
  TOPDOWN_LAYER
  stddef.dm file
  Understanding the renderer

  This is mostly no longer needed. A negative value for plane is the preferred way to do show objects in the background. It can still be used however when you want to rearrange objects in the same plane when using PLANE_MASTER for visual effects.

  `EFFECTS_LAYER` is a special high value that can be added to the regular layer of any atom.

  The purpose of this value is to make an atom appear above any regular atoms. For instance, in an isometric map if you want to display a character's name below them, it does not make much sense to have nearer objects cover up that name, so you can tell the name overlay to use `EFFECTS_LAYER + MOB_LAYER` and it will show up on top of all the normal icons on the map. This has been somewhat obviated by `plane` but may still be useful in some cases.

  When using this special layer, it should be added to the layer an atom normally uses. For instance an obj should have a layer of `EFFECTS_LAYER + OBJ_LAYER`.

  This can be mixed with `TOPDOWN_LAYER`, in non-topdown map formats. Anything in `TOPDOWN_LAYER` will display on top of `EFFECTS_LAYER`, and `TOPDOWN_LAYER + EFFECTS_LAYER` will be above both.

  This can also be mixed with `BACKGROUND_LAYER`, which takes priority over everything else.

  Images or overlays with `FLOAT_LAYER` can be left alone. They will automatically have the same layer as whatever atom they are attached to.

  ## Filter effects

  See also:
    filters var (atom)
  appearance_flags var (atom)
  filter proc
  animate proc
  Understanding the renderer

  Filters are a way of adding special effects to an icon, or a group of icons (see `KEEP_TOGETHER` in appearance_flags), by post-processing the image. A filter object describes a specific form of image processing, like for instance a blur or a drop shadow. Filters can be added or removed at will, and can even be animated.

  A filter is created by using the filter proc like so:

      // halo effect
      mob.filters += filter(type="drop_shadow", x=0, y=0,\
                            size=5, offset=2, color=rgb(255,255,170))

  These are the filters currently supported:

  - Alpha mask
  - Angular blur
  - Bloom
  - Color matrix
  - Displacement map
  - Drop shadow
  - Gaussian blur
  - Layering (composite)
  - Motion blur
  - Outline
  - Radial blur
  - Rays
  - Ripple
  - Wave

  ## Alpha mask filter

  See also:
    icon var (atom)
  render_target var (atom)
  Format:
    filter(type="alpha", ...)
  Args:
    x: Horizontal offset of mask (defaults to 0)
    y: Vertical offset of mask (defaults to 0)
    icon: Icon to use as a mask
    render_source: `render_target` to use as a mask
    flags: Defaults to 0; use see below for other flags

  Uses an icon or render target as a mask over this image. Every pixel that is transparent in either the image or the mask, is transparent in the result.

  The `x` and `y` values can move the mask from its normal position. By default, the mask is centered over the center of the image.

  The `MASK_INVERSE` flag will invert the alpha mask so that opaque areas in the mask become transparent, and vice-versa. There is also a `MASK_SWAP` flag which treats the source image as the mask and vice-versa, which might be useful for some effects.

  Note: Unlike many other filters, this filter is taken into account for mouse-hit purposes.

  ## Angular blur filter

  See also:
    Gaussian blur (filters)
  Radial blur (filters)
  Motion blur (filters)
  Format:
    filter(type="angular_blur", ...)
  Args:
    x: Horizontal center of effect, in pixels, relative to image center
    y: Vertical center of effect, in pixels, relative to image center
    size: Amount of blur (defaults to 1)
    offset: Pixel radius before blurring occurs

  Blurs the image by a certain amount in a circular formation, as if the image is spinning. The size of the blur can roughly be thought of in "degrees" worth of blur. As the distance from the center increases, the blur becomes more noticeable since the same amount of angular motion has to travel farther along a circle.

  Typically this blur is used with an entire plane, but it could be used to give a sense of motion blur to a spinning object.

  Note: Large blurs will look worse toward the edges due to limited sampling. Loss of accuracy will appear where `size` × distance is greater than about 300. You can increase accuracy by breaking up large sizes into multiple filter passes with differing sizes. The blur used is Gaussian, so combining blur sizes A and B will give a total size of sqrt(A2+B2).

  The `offset` parameter, if used, is effectively subtracted from the pixel distance to the center. Pixels within that radius won't blur. Anything outside that radius will act as if it's `offset` pixels closer to the center.

  ## Bloom filter

  See also:
    Gaussian blur (filters)
  Drop shadow (filters)
  Format:
    filter(type="bloom", ...)
  Args:
    threshold: Color threshold for bloom
    size: Blur radius of bloom effect (see Gaussian blur)
    offset: Growth/outline radius of bloom effect before blur
    alpha: Opacity of effect (default is 255, max opacity)

  Post-processing effect that makes bright colors look like they're a strong light source, spreading their light additively to other nearby pixels. This is a complex effect that involves multiple shader passes. For both performance and visual reasons, it is usually best applied to an entire plane rather than to individual objects.

  The color `threshold` determines which pixels this effect applies to. If any of the red, green, or blue components of the pixel are greater than the same component for the threshold, that pixel will bloom. The blooming pixels then have their colors spread outward to create a glow that gets added to the original image.

  The `offset` and `size` parameters are used to control the glow effect. They work the same as they do in the drop shadow filter: `offset` causes the light to grow outwards, and a blur of `size` is then applied to soften it. Often just using a blur alone will produce a pleasing effect. By playing with these two values you can make the bloom effect appear differently.

  The `alpha` value is applied to any light contributions from bloomed pixels that get added to the original image, so values lower than 255 can make the effect less pronounced. This can be very useful if you choose to animate the filter.

  ## Gaussian blur filter

  See also:
    Motion blur (filters)
  Radial blur (filters)
  Angular blur (filters)
  Drop shadow (filters)
  Format:
    filter(type="blur", ...)
  Args:
    size: Amount of blur (defaults to 1)

  Blurs the image by a certain amount. The size of the blur can roughly be thought of in "pixels" worth of blur.

  Note: Large blurs will result in reduced performance. The highest size that can be handled easily in this filter is 6. Higher sizes require multiple passes, although the filter will "cheat" and use low-quality passes for much higher sizes.

  ## Color matrix filter

  See also:
    color var (atom)
  Color matrix
  Color space
  Format:
    filter(type="color", ...)
  Args:
    color: A color matrix
    space: Value indicating color space: defaults to `FILTER_COLOR_RGB`

  Applies a color matrix to this image. Unlike with the atom.color var, you can apply color conversions other than the regular RGBA color space, depending on the value of `space`. See Color space for more information.

  ## Displacement map filter

  See also:
    Alpha mask (filters)
  icon var (atom)
  render_target var (atom)
  Format:
    filter(type="displace", ...)
  Args:
    x: Horizontal offset of map (defaults to 0)
    y: Vertical offset of map (defaults to 0)
    size: Maximum distortion, in pixels
    icon: Icon to use as a displacement map
    render_source: `render_target` to use as a displacement map
    flags: Defaults to 0; use see below for other flags

  Uses an icon or render target as a template for various warping effects on the main image. Think of displacement as "pulling" a pixel from an offset location.

  In the displacement map, pixels that have a higher red component will make the image appear to warp to the left, lower reds warp it to the right, and gray (r=128) will cause no horizontal warping. The green component affects the vertical: higher to warp upward, lower to warp downward. Transparent pixels in the displacement map will have no effect.

  This can be used for very complex distortion, unlike other distortion filters such as wave and ripple that are confined to specific equations.

  The optional `FILTER_OVERLAY` flag is supported for the `flags` argument, which will overlay the displaced image onto the original.

  ## Drop shadow filter

  See also:
    Gaussian blur (filters)
  Outline (filters)
  Format:
    filter(type="drop_shadow", ...)
  Args:
    x: Shadow horizontal offset (defaults to 1)
    y: Shadow horizontal offset (defaults to -1)
    size: Blur amount (defaults to 1; negative values create inset shadows)
    offset: Size increase before blur (defaults to 0)
    color: Shadow color (defaults to 50% transparent black)

  Applies a drop shadow to this image. This is a combination of multiple filters, since it will apply an outline if `offset` is included, a Gaussian blur to the shadow, and will underlay the shadow beneath the image.

  You can also think of this filter as an outer glow.

  If you use a `size` less than 0, the shadow will appear inside the image instead. This would be an inset shadow, or inner glow.

  ## Layering (composite) filter

  See also:
    icon var (atom)
  render_target var (atom)
  Format:
    filter(type="layer", ...)
  Args:
    x: Horizontal offset of second image (defaults to 0)
    y: Vertical offset of second image (defaults to 0)
    icon: Icon to use as a second image
    render_source: `render_target` to use as a second image
    flags: `FILTER_OVERLAY` (default) or `FILTER_UNDERLAY`
    color: Color or color matrix to apply to second image
    transform: Transform to apply to second image
    blend_mode: Blend mode to apply to the top image

  Composites another image over or under this image. Using the `FILTER_OVERLAY` flag, which is the default, puts the second image on top of what's already here. `FILTER_UNDERLAY` puts it underneath.

  The `x` and `y` values can move the mask from its normal position. By default, the second image is centered over the center of the first.

  The `color`, `transform`, and `blend_mode` vars are available for convenience. Because the bottom image is drawn over a blank background, `blend_mode` is always applied to the top image. All of the other vars apply to the second image being drawn.

  Note: Transforms use default bilinear scaling, since PIXEL_SCALE is not available here.

  Note: Like most other filters, this filter is not taken into account for mouse-hit purposes. Any layered icons will be strictly visual.

  ## Motion blur filter

  See also:
    filters var (atom)
  Gaussian blur (filters)
  Format:
    filter(type="motion_blur", ...)
  Args:
    x: Blur vector on the X axis (defaults to 0)
    y: Blur vector on the Y axis (defaults to 0)

  Applies Gaussian blur in one direction only. The amount and direction are both specified by `x` and `y`. The size of the blur is equal to `sqrt(x*x + y*y)`.

  See Gaussian blur for more information.

  ## Outline filter

  See also:
    Drop shadow (filters)
  Format:
    filter(type="outline", ...)
  Args:
    size: Width in pixels (defaults to 1)
    color: Outline color (defaults to black)
    flags: Defaults to 0 (see below)

  Applies an outline to this image.

  At larger sizes, the outline is less accurate and will take more passes to produce. Performance and appearance are best at sizes close to 1 or less.

  `flags` can be a combination of the following values:

  0
    Ordinary outline
  OUTLINE_SHARP
    Avoid antialiasing in the outline
  OUTLINE_SQUARE
    Extend the outline sharply from corner pixels; for a box this will maintain a box shape without rounded corners

  ## Radial blur filter

  See also:
    Gaussian blur (filters)
  Angular blur (filters)
  Motion blur (filters)
  Format:
    filter(type="radial_blur", ...)
  Args:
    x: Horizontal center of effect, in pixels, relative to image center
    y: Vertical center of effect, in pixels, relative to image center
    size: Amount of blur per pixel of distance (defaults to 0.01)
    offset: Pixel radius before blurring occurs

  Blurs the image by a certain amount outward from the center, as if the image is zooming in or out. As the distance from the center increases, the amount of blurring increases, and near the center the blur is hardly visible at all. The `size` value is smaller by default for this filter than it is for other filters, since it's typically used with an entire plane where the distance from the center can easily be several hundred pixels.

  Typically this blur is used with an entire plane.

  Note: Large blurs will look worse toward the edges due to limited sampling. Loss of accuracy will begin when `size` × distance is greather than 6. You can increase accuracy by breaking up large sizes into multiple filter passes. The blur used is Gaussian, so combining blur sizes A and B will give a total size of sqrt(A2+B2).

  The `offset` parameter, if used, is effectively subtracted from the pixel distance to the center. Pixels within that radius won't blur. Anything outside that radius will act as if it's `offset` pixels closer to the center.

  ## Rays filter

  Format:
    filter(type="rays", ...)
  Args:
    x: Horiztonal position of ray center, relative to image center (defaults to 0)
    y: Vertical position of ray center, relative to image center (defaults to 0)
    size: Maximum length of rays (defaults to 1/2 tile width)
    color: Ray color (defaults to white)
    offset: "Time" offset of rays (defaults to 0, repeats after 1000)
    density: Higher values mean more, narrower rays (defaults to 10, must be whole number)
    threshold: Low-end cutoff for ray strength (defaults to 0.5, can be 0 to 1)
    factor: How much ray strength is related to ray length (defaults to 0, can be 0 to 1)
    flags: Defaults to `FILTER_OVERLAY | FILTER_UNDERLAY (see below)

  Draws random rays that radiate outward from a center point. (That point may be outside of the image.) As they move outward, their alpha value diminishes linearly. These are meant to be animated. The `offset` value determines the "time", where every jump of +1 can be a very different set of rays, and every 1000 units this filter will repeat.

  The `threshold` value can be thought of as a way of culling lower-strength rays. Ray strength is anywhere from 0 to 1 at any given angle, but values below `threshold` may as well be 0. Values above that are re-scaled into a range of 0 to 1.

  The `factor` parameter allows you to tie the ray's length to its strength. At 0, the length of every ray is the same. At 1, the length ranges from 0 to `size`. Generally speaking, the higher `factor` is, the more the rays will appear to move outward as they strengthen and inward as they weaken.

  Ray `color` can be provided as a matrix. Only the diagonal values of the color matrix will be used, but using a matrix will allow you to set values outside of the normal color range.

  `flags` can have the following values:

  0
    The rays are drawn alone, erasing the existing image (useful for some effects).
  FILTER_OVERLAY
    The rays are overlaid on top of the existing image.
  FILTER_UNDERLAY
    The rays are drawn underneath the existing image.
  FILTER_OVERLAY | FILTER_UNDERLAY
    Default. For plane masters, this will use the `FILTER_OVERLAY behavior and draw the rays over the plane, and for all other images it will default to `FILTER_UNDERLAY to draw the rays beneath them.

  ## Ripple filter

  See also:
  Wave (filters)
  Format:
    filter(type="ripple", ...)
  Args:
    x: Horiztonal position of ripple center, relative to image center (defaults to 0)
    y: Vertical position of ripple center, relative to image center (defaults to 0)
    size: Maximum distortion in pixels (defaults to 1)
    repeat: Wave period, in pixels (defaults to 2)
    radius: Outer radius of ripple, in pixels (defaults to 0)
    falloff: How quickly ripples lose strength away from the outer edge (defaults to 1)
    flags: Defaults to 0; use `WAVE_BOUNDED to keep distortion within the image

  Applies a ripple distortion effect to this image.

  This filter is meant to be animated. A good animation will typically start at a `radius` of 0 and animate to a larger value, with `size` decreasing to 0.

  The `falloff` parameter can be tweaked to your liking. A value of 1 should look reasonably like ripples in water, with the inner ripples losing strength. A value of 0 will cause no reduction in strength.

  The equation governing the ripple distortion is size × sin(2πr') ÷ (2.5 × falloff × r'2 + 1), where r' = (radius - distance) ÷ repeat.

  Up to 10 ripples can be stacked together in a single pass of the filter, as long as they have the same `repeat`, `falloff`, and `flags` values. (See the wave filter for the `WAVE_BOUNDED` flag.)

  ## Wave filter

  See also:
  Ripple (filters)
  Format:
    filter(type="wave", ...)
  Args:
    x: Horiztonal direction and period of wave
    y: Vertical direction and period of wave
    size: Maximum distortion in pixels (defaults to 1)
    offset: Phase of wave, in periods (e.g., 0 to 1)
    flags: Defaults to 0; see below for other flags

  Applies a wave distortion effect to this image.

  The `x` and `y` parameters specify both the direction and period of the wave; the period is `sqrt(x*x + y*y)`.

  This filter is meant to be animated, from whatever `offset` you want to `offset+1`, and then repeating. With multiple waves, you can produce a very convincing water effect.

  ### Example

      #define WAVE_COUNT 7
      atom/proc/WaterEffect()
          var/start = filters.len
          var/X,Y,rsq,i,f
          for(i=1, i<=WAVE_COUNT, ++i)
              // choose a wave with a random direction and a period between 10 and 30 pixels
              do
                  X = 60*rand() - 30
                  Y = 60*rand() - 30
                  rsq = X*X + Y*Y
              while(rsq<100 || rsq>900)   // keep trying if we don't like the numbers
              // keep distortion (size) small, from 0.5 to 3 pixels
              // choose a random phase (offset)
              filters += filter(type="wave", x=X, y=Y, size=rand()*2.5+0.5, offset=rand())
          for(i=1, i<=WAVE_COUNT, ++i)
              // animate phase of each wave from its original phase to phase-1 and then reset;
              // this moves the wave forward in the X,Y direction
              f = filters[start+i]
              animate(f, offset=f:offset, time=0, loop=-1, flags=ANIMATION_PARALLEL)
              animate(offset=f:offset-1, time=rand()*20+10)

  The equation governing the wave distortion is size × sin(2π(d - offset)), where d is the number of wave periods' distance from the center along the x, y direction.

  The `WAVE_SIDEWAYS` flag will cause the distortion to be transverse (perpendicular) to the wave instead of in the same direction as the wave. The `WAVE_BOUNDED` flag limits the distortion to the confines of this image, instead of lettings its pixels spill out a little further from the distortion (and likewise, transparent pixels spill inward).

  Up to 10 waves can be stacked together in a single pass of the filter, as long as they have the same `WAVE_BOUNDED` flags.

  ## Generators

  See also:
  Particle effects
  generator proc
  color var (atom)
  Color matrix

  A generator is an object that can produce a random number, vector (list of 3 numbers), color (as a text string), or color matrix (list of 20 numbers) in a specified range according to rules you set down. It is used primarily for particle effects, since it can run on the client.

  There are several types of generators:

  - Numbers: Generate a random real number.
  - Vectors: Generate a random vector.
  - Shapes: Generate a random vector within a specific shaped region.
  - Colors: Generate a random color or color matrix.

  Generators can also be chained together with math operators and some procs. The second value can be a regular value instead of a generator, so for instance you can multiply a vector by 2, or by a matrix to transform it.

  Operators | Action
  --- | ---
  + - * / | Arithmetic operators. You can multiply a 3D vector by a color matrix (where red,green,blue in the matrix correspond to x,y,z) to do a 3D transform, or by a 2D matrix for a 2D transform.
  - (unary) | Negate the value, same as multiplying by -1.
  turn(), generator.Turn() | Rotate a vector clockwise in the XY plane.

  ## Gliding

  See also:
    Pixel movement
  animate_movement var (movable atom)
  appearance_flags var (atom)
  glide_size var (movable atom)
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  step_size var (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)
  movement_mode var (world)
  fps var (client)

  Gliding is a "glitz" effect applied by BYOND to cover up the visual sins of tile-based movement, by making objects and the map appear to move smoothly from one tile to another instead of immediately jumping. It is also available to smooth over small jumps in pixel movement that might occur, for instance if the client FPS is set higher than the server's.

  To control the gliding speed of an atom, set `glide_size` to the value of your choice. If this is not set, the client will attempt to adjust the speed manually. `glide_size` is measured in server ticks, so if `client.fps` is set to a value greater than `world.fps`, it will be scaled appropriately.

  Whether an object glides or jumps is based on how far it moves relative to its `step_size` value, which by default is a full tile width. If the movement goes too far past `step_size` in the X or Y directions, it's no longer a glide.

  The `animate_movement` var can be used to control the way in which an object glides, or suppress gliding altogether.

  By using the `LONG_GLIDE` flag in `appearance_flags`, a diagonal glide will take just as long as a cardinal-direction glide by moving a fullt `glide_size` pixels in the dominant X or Y direction. Otherwise, gliding tries to move by that many pixels in strict Euclidean distance (a straight line) and diagonal glides take longer.

  In LEGACY_MOVEMENT_MODE, gliding is turned off if you set any of the bound or step vars for an atom to a non-default value. The only gliding that occurs in this case is when client.fps is higher than world.fps. All other movement modes base gliding on an atom's `glide_size` value.

  ## HUD / screen objects

  See also:
    screen_loc var (movable atoms)
  screen var (client)
  view var (client)
  map_format var (world)
  icon_size var (world)
  layer var (atom)
  image objects

  HUD stands for Heads-Up Display, and refers to any atoms that appear on the screen but don't move when the player moves. These are also called screen objects. Any movable atom can be added to the HUD by setting its `screen_loc` var, and adding it to `client.screen` for each user who is supposed to see it. This can be used to display a character's vital stats, scores, etc.

  If you want to have something like a health meter or name attached to a moving atom, use overlays or `/image` objects instead. An `/image` object is similar to a screen object in that it can be shown to only certain players instead of being shown to everyone.

  The size of the screen depends on `client.view` (or `world.view`), `world.map_format`, and `world.icon_size`. In a normal topdown map format, `client.view` is the same as the screen size; in other map formats the screen might be a different size.

  The `screen_loc` var can be set to a value like `"1,1"` (the southwest tile of the screen), `"4,NORTH"` (fourth tile from the west, along the north side of the screen), `"SOUTHEAST"`, and so on. You can also include pixel offsets, percentages, and specify two corners to tile an icon repeatedly from one end to the other. See screen_loc for more details.

  `screen_loc` can also be used to stretch the bounds of the HUD. A value of `"0,0"` will cause the atom to appear to the southwest of the southwest-most tile on the visible map, outside of the regular map bounds. Using HUDs in this way, you can provide a nice decorative "frame" for your map.

  More complex

  You can use HUDs in other map controls as well, by preceding screen_loc with the name of the map you will use followed by a colon. For instance, `screen_loc="map2:1,1"` will show an icon in the southwest corner of the `map2` control. The actual size of a secondary HUD is based on how far out the icons in it extend in any direction. If you have one icon at `"map2:1,1"` and another at `"map2:4,3"`, then that HUD will be four tiles wide and three high.

  ## Isometric maps

  See also:
    map_format var (world)
  icon_size var (world)
  dir var (client)
  pixel_w var (atom)
  pixel_z var (atom)
  screen_loc var (movable atoms)
  Big icons
  Side-view maps
  Topdown maps
  HUD
  BACKGROUND_LAYER
  EFFECTS_LAYER
  TOPDOWN_LAYER

  Isometric projection is a form of pseudo-3D in which the 2D icons used by BYOND can be arranged in a way to give the appearance of three dimensions. If you look at a map top-down, each tile on the map is a square. The map is rotated 45° clockwise and then tilted at an angle (30°) so that each square now looks like a foreshortened diamond from the viewer's perspective. What was once north now points to the northeast end of the viewer's screen; what was once east now points southeast to the viewer. Tiles that are more to the south or east are "nearer" to the viewer, and tiles that are north or west are "farther". The actual direction the map faces can be changed by using `client.dir`.

  It is important to remember that this is an illusion of 3D, not real 3D.

  To use isometric mapping, set `world.map_format` to `ISOMETRIC_MAP`. You should set `world.icon_size` so the tile width is a multiple of 4 pixels. The width of the tile is highly important. The height of your tiles should be at least half that value. BYOND uses a 2:1 isometric format, meaning that the diamond base of each tile is half as high as its width. For example if you have a 64x64 tile size, every diamond in the map will be 64 pixels wide by 32 high, and you have an extra 32 pixels at the top of your icon for vertical projections like buildings. If you set the tile size to 64x80, the base is still a 64x32 diamond and you have 48 pixels left over for vertical structures.

  In this mode `pixel_x` and `pixel_y` will offset icons along the "ground". To adjust horizontal and vertical positions, use the `pixel_w` and `pixel_z` vars.

  ### Layers

  The `layer` var behaves differently in isometric mode. Because some tiles are nearer to the viewer than others, the tiles that are farther back need to be drawn first so they are behind any tiles that should go in front of them. So in isometric mode, the back row of tiles (a diagonal line of them) is drawn first, followed by the next row forward, and so on. The `layer` var only matters when icons overlap each other in the "physical" space, like an obj sitting on a turf.

  When pixel or step offsets, or gliding, place an object on multiple turfs, it is drawn on top of the nearer turf (assuming its layer is higher).

  Using icons wider than the regular tile size can have an impact on layering as well. See Big icons for more information.

  Because of the order in which icons are drawn, you may want to limit the ability of an atom to cut diagonally around corners. While moving northeast behind a dense wall, for instance, a mob might temporarily appear in front of the wall because its pixel offsets (from gliding) temporarily put it on the same tile as the wall. If you do not want to limit corner-cutting, a simple workaround for this case is to give the wall a higher layer than the mob.

  Screen objects (in `client.screen`) are always drawn on top of all isometric tiles, as is the case in other map modes as well.

  Since it may be desirable in some games to use a topdown map for some situations (like a special battle map), you can add `TOPDOWN_LAYER` to any atom's layer—e.g., `TOPDOWN_LAYER+TURF_LAYER`—to make it appear in topdown mode. Topdown and isometric tiles really aren't meant to be mixed, but if they do mix you'll see topdown tiles always display above isometric tiles, just like screen objects do. The best way to use this is to apply `TOPDOWN_LAYER` to every tile in a certain part of the map that the players can't walk to.

  If you want to use an overlay that should not be covered by other "nearer" icons on the map, such as a name or health meter, you can add `EFFECTS_LAYER` to the overlay's layer. Icons with `EFFECTS_LAYER` will draw above regular icons. Then objects with `TOPDOWN_LAYER` will draw on top of everything else. However, be aware that `EFFECTS_LAYER` has largely been superseded by the `plane` var.

  ### Screen size

  In this mode, `world.view` or `client.view` is used to define the minimum number of map tiles you will see, not the screen/HUD size which is calculated from client.view. Extra map tiles are shown to fill out the screen size. HUD objects use screen coordinates, so 1,1 is still the lower left.

  The actual HUD size is always a full number of tiles, whose size is defined by `world.icon_size`. If you have a tile size of `64x64`, and `world.view=6` (a 13x13 map), a full 13x13 diamond of map tiles will be shown. The width of this diamond is 13 tiles. The height is only half that, plus whatever vertical space is needed to show the icons in that area. Then everything is rounded up to a full tile size, so the result is a 13x7-tile screen. This is the formula you need if you want to calculate the screen size:

      pixel_width = round(icon_width * (view_width + view_height) / 2)
      pixel_height = round(icon_width * (view_width + view_height - 2) / 4) + icon_height

      screen_width = round((pixel_width + icon_width - 1) / icon_width)
      screen_height = round((pixel_height + icon_height - 1) / icon_height)

  If you use `TOPDOWN_LAYER`, any topdown sections of the map will be limited to this same view.

  ## Numbers

  In DM, all numbers are stored in floating point format. Specifically, single-precision (32-bit) floating point. This is important to know if you think you will be working with large numbers or decimal values a lot, because the accuracy of the numbers is limited.

  32-bit floating point numbers can represent integers from -16777216 to 16777216 (224). Non-integer values can get about as small as 2-126 and as large as 2127.

  Floating point numbers do not handle most decimal values precisely. For instance, 0.1 is not exactly 0.1, because floating point numbers are stored in a binary format and in binary, 1/10 is a fraction that repeats forever—the same way 1/3 repeats as 0.33333... in decimal numbers. It ends up being rounded off, either a little higher or a littler lower than its true value. This means that the following loop won't work like you might expect:

  ### Example:

      for(i = 0, i < 100, i += 0.1)
          world << i

  You might expect that code to loop exactly 1000 times, with `i` going from 0 up to 99.9 before stopping. The truth is more complicated, because 0.1 stored in floating point is actually greater than the exact value of 0.1. Other values might be more or less than their exact numbers, and as you add these numbers together repeatedly you'll introduce more and more rounding error.

  Even more insidious, if you add 0.1 a bunch of times starting from 0, and then subtract it out again the same number of times, the result you get may not be 0. This is counterintuitive, because you might expect rounding errors to reverse themselves in the same order they crept in. Unfortunately it doesn't work that way.

  You can correct for rounding error somewhat by using the `round proc to adjust the loop var each time, although for performance reasons it might be preferable to find another alternative.

      for(i = 0, i < 100, i = round(i + 0.1, 0.1))
          world << i

  Only fractions whose denominators are powers of 2 are immune to this rounding error, so 0.5 is in fact stored as an exact value.

  Another place floating point may lose accuracy is when you try to add numbers of very different sizes. For instance as stated above, the upper limit for accurate integers is 16777216. If you try to use a number such as 100 million it will only be approximate, so adding 1 to that number won't actually change it because the 1 is so much smaller, it will be gobbled up by rounding error.

  Also for the same reasons stated above, division will cost you accuracy. Again you can divide by powers of 2 easily enough, and you can divide an integer by any of its factors (like dividing 9 by 3) without a problem, but a fraction like 1/3 will repeat forever so it gets rounded to as much precision as floating point can manage.

  In decimal, floating point numbers have at least six decimal digits of precision. Since they're actually stored in binary, their true precision is exactly 24 bits.

  ## Particle effects

  See also:
  particles (movable atom var)
  Generators
  generator proc
  Projection matrix
  .add-particles (client command)
  stddef.dm file

  A particle set is a special effect, whose computations are handled entirely on the client, that spawns and tracks multiple pixels or icons with a temporary lifespan. Examples of this might be confetti, sparks, rocket exhaust, or rain or snow. Particles are rendered on a special surface and that gets attached to an obj or a mob like an overlay.

  Particles can exist in 3 dimensions instead of the usual 2, so a particle's position, velocity, and other values may have a z coordinate. To make use of this z coordinate, you can use a projection matrix. (The value of the z coordinate must be between -100 and 100 after projection. Otherwise it's not guaranteed the particle will be displayed.)

  To create a particle set, use `new` to create a new `/particles` datum, and then you can set the datum's vars. The vars can be set to constant values, or generator functions that will allow the client to choose from a range of values when spawning those particles. (The easiest way to handle this is to create your own type that inherits from `/particles`, and set up the parameters you'll want at compile-time.)

  After the datum is created, it can be assigned to an obj or mob using their `particles` var. The particles will appear on the map wherever that obj or mob appears.

  ### Example:

      particles/snow
          width = 500     // 500 x 500 image to cover a moderately sized map
          height = 500
          count = 2500    // 2500 particles
          spawning = 12    // 12 new particles per 0.1s
          bound1 = vector(-1000, -300, -1000)   // end particles at Y=-300
          lifespan = 600  // live for 60s max
          fade = 50       // fade out over the last 5s if still on screen
          // spawn within a certain x,y,z space
          position = generator("box", vector(-300,250,0), vector(300,300,50))
          // control how the snow falls
          gravity = vector(0, -1)
          friction = 0.3  // shed 30% of velocity and drift every 0.1s
          drift = generator("sphere", 0, 2)
      obj/snow
          screen_loc = "CENTER"
          particles = new/particles/snow

      mob
          proc/CreateSnow()
              client?.screen += new/obj/snow

  These are the vars that can be used in a particle set. "Tick" refers to a BYOND standard tick of 0.1s.

  Particle vars that affect the entire set (generators are not allowed for these)
  Var | Type | Description
  --- | --- | ---
  width | num | Size of particle image in pixels
  height
  count | num | Maximum particle count
  spawning | num | Number of particles to spawn per tick (can be fractional)
  bound1 | vector | Minimum particle position in x,y,z space; defaults to list(-1000,-1000,-1000)
  bound2 | vector | Maximum particle position in x,y,z space; defaults to list(1000,1000,1000)
  gravity | vector | Constant acceleration applied to all particles in this set (pixels per squared tick)
  gradient | color gradient

Color gradient used, if any
transform matrix Transform done to all particles, if any (can be higher than 2D)
Vars that apply when a particle spawns
lifespan num Maximum life of the particle, in ticks
fade num Fade-out time at end of lifespan, in ticks
fadein num Fade-in time, in ticks
icon icon Icon to use, if any; no icon means this particle will be a dot
Can be assigned a weighted list of icon files, to choose an icon at random
icon_state text Icon state to use, if any
Can be assigned a weighted list of strings, to choose an icon at random
color num or color Particle color (not a color matrix); can be a number if a gradient is used
color_change num Color change per tick; only applies if gradient is used
position num x,y,z position, from center in pixels
velocity num x,y,z velocity, in pixels
scale vector (2D)Scale applied to icon, if used; defaults to list(1,1)
grow num Change in scale per tick; defaults to list(0,0)
rotation num Angle of rotation (clockwise); applies only if using an icon
spin num Change in rotation per tick
friction num Amount of velocity to shed (0 to 1) per tick, also applied to acceleration from drift
Vars that are evalulated every tick
drift vector Added acceleration every tick; e.g. a circle or sphere generator can be applied to produce snow or ember effects

The `icon` and `icon_state` values are special in that they can't be assigned a generator, but they can be assigned a constant icon or string, respectively, or a list of possible values to choose from like so:

    icon = list('confetti.dmi'=5, 'coin.dmi'=1)

The list used can either be a simple list, or it can contain weights as shown above.

Changing a var on a particle datum will make changes to future particles. For instance, you can set the datum's `spawning` var to 0 to make it stop creating new particles. (Note: If you are changing a vector or color matrix, such as `gravity`, you need to assign a new value. You can't for instance set `particles.gravity[2] = 0` because it won't do anything to update the particle stream.)

The same particle datum can be assigned to more than one movable atom. However the particles displayed by each atom will be different.

### The `.add-particles` command

If you want to spawn particles at specific times, you can use the client `.add-particles` command. From the server, you can run this command via winset().

### Example:

    // spawn 100 particles for src's particle set right now
    winset(player, null, list(command=".add-particles \ref[src] 100"))

## Pixel movement

See also:
  Bounding boxes
  bound_x var (movable atom)
  bound_y var (movable atom)
  bound_width var (movable atom)
  bound_height var (movable atom)
  icon_w var (atom)
  icon_z var (atom)
  Speed and position
  step_size var (movable atom)
  step_x var (movable atom)
  step_y var (movable atom)
  locs list var (movable atom)
  contents list var (atom)
  fps var (world)
  Movement
  Move proc (movable atom)
  Cross proc (atom)
  Crossed proc (atom)
  Uncross proc (atom)
  Uncrossed proc (atom)
  movement_mode var (world)
  appearance_flags var (atom)
  Other topics
  bounds proc
  bounds_dist proc
  Gliding

Pixel movement is a concept that allows atoms to escape the constraints of BYOND's historically tile-based movement, and move in smaller steps. In the past this had to be done with soft code, but that was sometimes inconvenient and it did not perform as well in projects with many objects moving.

The key to understanding pixel movement is to use the bound and step vars. You use the bound family of vars to define a bounding box for a movable atom, instead of just making it one full tile in size. The step vars can give it a movement speed and offset it from the corner of the tile it's standing on.

- bound_x: The left edge of the bounding box
- bound_y: The bottom edge of the bounding box
- bound_width: Width of the bounding box
- bound_height: Height of the bounding box
- step_size: default movement speed
- step_x: x offset from the corner of loc
- step_y: y offset from the corner of loc

Those are for movable atoms only; they do not apply to turfs.

If world.movement_mode is set to `TILED_MOVEMENT_MODE`, all movable atoms must be aligned to the tile grid: their step_x/y/size values must be multiples of the icon size, and their bounds must also land on tile boundaries although the atom can be bigger than one tile. In other movement modes you can specify that only specific atoms use this behavior, by giving them the TILE_MOVER appearance flag.

### Bounding boxes

As an example, if your players' mobs have icons that only cover the center 24×24 pixels of a regular 32×32 icon, then you would set the mobs' bound_x and bound_y to 4--because there are 4 pixels unused to the left and bottom--and bound_width and bound_height to 24.

The mob's physical location on the map depends on four things: Its loc, its step_x/y values, its bound_x/y values, and its bound_width/height. The lower left corner of the bounding box, relative to the turf the mob is actually standing on, begins at step_x+bound_x on the left and step_y+bound_y on the bottom.

The physical position of the bounding box is not affected by the pixel_x/y/z vars. Those are still strictly visual offsets.

The turfs the mob is covering can be read from the read-only locs var. The mob will also appear in the contents of those turfs.

Note: This means if an atom is in a turf's contents, its loc is not necessarily that turf. The contents list is made to include "overhangers" from another tile for ease of use.

### Movement

All of the step and walk procs have been upgraded to take an additional argument, which is the speed at which the atom should move. If that argument is left out, the atom's own step_size is used by default. The step_size determines how fast the step_x and step_y values will change when moving.

Move() has two new arguments that handle the position change gracefully. These are the step_x and step_y values for the target location.

Pixel movement changes the behavior of the Move() proc, because a lot of things are possible that were not possible when BYOND only supported moving one tile at a time. For starters, a Move() is either a "slide" or a "jump" depending on the distance. A slide is when the move can be stopped partway; a jump is strictly pass/fail. Anything greater than one tile and the mover's regular step_size is considered a jump. Changing z levels is also a jump, as is moving to/from a non-turf.

If step_x and step_y aren't within a good range, the new loc and the step_x/y values may be changed so that the southwest corner of the mover's bounding box is standing on its actual loc, or as close to it as possible.

Enter() and Exit() can be called for several turfs and/or areas, not just one at a time. It is also possible for them not to be called at all, if the moving atom moves within a turf but doesn't cross a new turf boundary. Enter() and Exit() are only called when first attempting to enter or fully exit. The behavior of these procs depends on world.movement_mode; in legacy mode, they look at some of the contents of the turfs as well as the turfs themselves, to preserve behavior found in older BYOND versions.

Cross() and Uncross() are the equivalent of Enter() and Exit() but apply to objects the mover will either overlap or stop overlapping. (For turfs, Enter() and Exit() call these procs by default, since the mover is both stepping into and onto a turf.) Likewise Crossed() and Uncrossed() are the equivalents of Entered() and Exited().

If an atom is sliding, its movement can be halted if it encounters an obstacle partway along its route. Bump() will still be called for any obstacles the atom runs into, but Move() will return the number of pixels moved (the most in any direction). When sliding at a speed so fast that the distance is bigger than the atom itself, the move will be split up into several smaller slides to avoid skipping over any obstacles.

Gliding, which is used to show smooth movement between atoms in tile movement, is mostly not used in pixel movement. It only applies when the client uses a higher fps than the server.

### Pixel procs

The bounds() and obounds() procs have been added to grab a list of atoms within a given bounding box. That box can be relative to an atom, or in absolute coordinates.

bounds_dist() tells the distance between two atoms, in pixels. If it is positive, that is the minimum distance the atoms would have to traverse to be touching. At 0, they are touching but not in collision. A negative value means the two atoms are in collision.

## Projection matrix

See also:
  Particle effects
  transform var (atom)
  matrix
  Color matrix

Note: Currently this feature applies only to particle effects, using the `transform` var.

Normally icons in BYOND can only be transformed in 2D, using a simple 3x3 matrix. This is represented by the `/matrix` object, which cuts off the last column because it isn't used. However particles can have coordinates in x, y, and z, and the whole particle set can be given a transformation matrix that handles all three dimensions.

### Simple 2D transforms

The easiest transformation for particles is a simple 2D one, which you can do by setting the particle datum's `transform` var to a `/matrix` object.

              a d 0
    x y 1  *  b e 0  =  x' y' 1
              c f 1

When an x,y point is multiplied by the matrix, it becomes the new point x',y'. This is equivalent to:

    x' = a*x + b*y + c
    y' = d*x + e*y + f

This is called an affine transform because all the operations are "linear" in math terms. (That is, every term in the formula above has a single variable, not raised to a higher power than 1.)

### 3x4 matrix (x,y,z with translation)

3D affine transforms of this type are also affine transformations. There is no special object for this so a list is used (see below).

                xx xy xz 0
    x y z 1  *  yx yy yz 0  =  x' y' z' 1
                zx zy zz 0
                cx cy cz 1

The way to read the vars above is that the first letter says what input component is being transformed (x,y,z, or c for "constant"), and the second letter is the output component.

    x' = xx*x + yx*y + zx*z + cx
    y' = xy*x + yy*y + zy*z + cy
    z' = xz*x + yz*y + zz*z + cz

To use this kind of matrix, you can cut off the 4th column and provide the values in a list form, in row-major order:

    list(xx,xy,xz, yx,yy,yz, zx,zy,zz, cx,cy,cz)

Note the 4th row is also optional.

### 4x4 matrix (x,y,z,w with projection)

This is the most interesting matrix, since if you use all 4 columns you're actually altering an "axis" called w. This isn't a real axis, but is just a number that the resulting vector will be divided by.

                xx xy xz xw
    x y z 1  *  yx yy yz yw  =  x'w' y'w' z'w' w'
                zx zy zz zw
                wx wy wz ww

    w' = xw*x + yw*y + zw*z + ww
    x' = (xx*x + yx*y + zx*z + wx) / w'
    y' = (xy*x + yy*y + zy*z + wy) / w'
    z' = (xz*x + yz*y + zz*z + wz) / w'

In a regular affine transform, w always stays at 1. In projection you can think of w as a distance from the "camera". 1 is where objects are their "normal" size. If you make the z value affect w' by setting zw, you basically make an object look smaller at higher z values.

This is a simple projection matrix where x,y,z are left untouched, but there's a projection effect. The "D" value is how far away the "camera" is from z=0, so a point at z=D looks like it's twice as far away.

    1  0  0  0
    0  1  0  0
    0  0  1  1/D
    0  0  0  1

This 4x4 matrix is handled as a list just like the 3x4 affine matrix:

    list(xx,xy,xz,xw, yx,yy,yz,yw, zx,zy,zz,zw, wx,wy,wz,ww)

## Regular expressions

See also:
  regex datum

  regex proc
  findtext proc
  replacetext proc
  splittext proc
  REGEX_QUOTE proc

  Regular expressions are patterns that can be searched for within a text string, instead of searching for an exact match to a known piece of text. They are much more versatile for find and replace operations, and therefore useful for parsing, filtering, etc.

  Some example regular expressions are:

  Pattern | Code | Meaning
  --- | --- | ---
  B.*D | regex("B.*D") | Find `B, followed by any number of characters (including none), followed by a `D.
  [0-3] | regex(@"[0-3]") | Find any digit from 0 to 3
  foo|bar | regex("foo|bar","i") | Find `foo or `bar, case-insensitive
  \d+ | regex(@"\d+","g") | Find all sequences of digits

  These are some of the patterns you can use. If you want to use any of the operators as an actual character, it must be escaped with a backslash.

  It is highly recommended that you use raw strings like `@"..."` for your regular expression patterns, because with a regular DM string you have to escape all backslash `\` and open bracket `[` characters, which will make your regular expression much harder for you to read. It's easier to write `@"[\d]\n"` than `"\[\\d]\\n"`.

  Pattern | Matches
  --- | ---
  a|b | a or b
  . | Any character (except a line break)
  ^ | Beginning of text; or line if `m flag is used
  $ | End of text; or line if `m flag is used
  \A | Beginning of text
  \Z | End of text
  [chars] | Any character between the brackets. Ranges can be specified with a hyphen, like 0-9. Character classes like `\d and `\s can also be used (see below).
  [^chars] | Any character NOT matching the ones between the brackets.
  \b | Word break
  \B | Word non-break
  (pattern) | Capturing group: the pattern must match, and its contents will be captured in the group list.
  (?:pattern) | Non-capturing group: Match the pattern, but do not capture its contents.
  \1 through \9 | Backreference; `\N is whatever was captured in the Nth capturing group.
  Modifiers
  Modifiers are "greedy" by default, looking for the longest match possible. When following a word, they only apply to the last character.
  a* | Match a zero or more times
  a+ | Match a one or more times
  a? | Match a zero or one time
  a{n} | Match a, exactly n times
  a{n,} | Match a, n or more times
  a{n,m} | Match a, n to m times
  modifier? | Make the previous modifier non-greedy (match as little as possible)
  Escape codes and character classes
  \xNN | Escape code for a single character, where NN is its hexadecimal ASCII value
  \uNNNN | Escape code for a single 16-bit Unicode character, where NNNN is its hexadecimal value
  \UNNNNNN | Escape code for a single 21-bit Unicode character, where NNNNNN is its hexadecimal value
  \d | Any digit 0 through 9
  \D | Any character except a digit or line break
  \l | Any letter A through Z, case-insensitive
  \L | Any character except a letter or line break
  \w | Any identifier character: digits, letters, or underscore
  \W | Any character except an identifier character or line break
  \s | Any space character
  \S | Any character except a space or line break
  Assertions
  (?=pattern) | Look-ahead: Require this pattern to come next, but don't include it in the match
  (?!pattern) | Look-ahead: Require this pattern NOT to come next
  (?<=pattern) | Look-behind: Require this pattern to come before, but don't include it in the match (must be a fixed byte length)
  (?<!pattern) | Look-behind: Require this pattern NOT to come before (must be a fixed byte length)

  The optional flags can be any combination of these:

  Flag | Meaning
  --- | ---
  i | Case-insensitive matching
  g | Global: In Find() subsequent calls will start where this left off, and in Replace() all matches are replaced.
  m | Multi-line: ^ and $ refer to the beginning and end of a line, respectively.

  After calling `Find()` on a `/regex` datum, the datum's `group` var will contain a list—if applicable—of any sub-patterns found with the `()` parentheses operator. For instance, searching the string `"123"` for `1(\d)(\d)` will match `"123"`, and the `group` var will be `list("2","3")`. Groups can also be used in replacement expressions; see the Replace() proc for more details.

  ## Understanding the renderer

  To get the most out of BYOND's visual effects, it helps to understand how the map is displayed.

  Every atom has an appearance

  that holds all of its visual info (and sometimes a little non-visual info). This appearance has to be turned into sprites in order to be rendered.

  Although many atoms need little more than a simple icon and icon_state and produce only a single sprite, some are more complex with overlays, underlays, maptext, etc. Also there may be image objects and visual contents involved, although they're not part of the atom's appearance.

  For a simple `icon` and `icon_state`, just one sprite is generated. The client looks up the icon it's given. Then it looks up an icon state, which may be influenced by whether the atom is moving or not since you can have moving and non-moving icon states. Then it determines which direction to draw and which frame of the icon's animation (if any) to use.

  So with several simple icons, and not worrying about layers for now, a list of sprites lays out like this:

  Atom #1
  Atom #2
  ⋮
  Atom #N

  ### Overlays and underlays

  Now let's consider what happens when an appearance has overlays.

  Underlay #1
  ⋮
  Underlay #N
  Main icon
  Overlay #1
  ⋮
  Overlay #N

  The underlays list is processed first, then overlays. These lists contain appearances themselves, rather than actual atoms. This means that overlays are recursive: an overlay can have overlays itself. To picture how that works, just replace one of the overlays above with another list.

  Underlay #1
  Underlay #2
  Main icon
  Underlays of overlay #1
  Overlay #1 icon
  Overlays of overlay #1
  Overlay #2

  ### Image objects and visual contents

  Any atom can have an image object attached, which can be shown to only specific players. Most atoms, and image objects, can have visual contents that display other atoms as if they're overlays.

  Underlays
  Main icon
  Overlays
  Image objects
  Visual contents

  As you see this is very similar to overlays. Just like overlays, image objects and visual contents have appearances of their own (and may also have their own images or visual contents), so this may be recursive as they add new overlays, etc.

  A couple of things to keep in mind:

  - If an image object uses the override
var, it will replace the main appearance's icon and overlays, although it won't replace other images or visual contents.
- An object in visual contents can use vis_flags to set `VIS_UNDERLAY` and move itself before the parent's underlays.

### Maptext and particles

Any appearance may have maptext attached. That maptext draws above the icon but is grouped with it. That grouping will be discussed further below.

Particle effects also get grouped with the main icon in a similar way to maptext.

For simplicity, from this point forward the diagram will just treat underlays, overlays, image objects, and visual contents as overlays.

Main icon
Maptext
Particles
Overlays

### Color, transform, and filters

An appearance's color and alpha vars (from here forwarded they'll just be referred to by `color`) and transform are inherited by any overlays, which also includes images and visual contents. You can avoid that inheritance by giving those overlays special appearance_flags: `RESET_COLOR`, `RESET_ALPHA`, and `RESET_TRANSFORM`.

The appearance's filters are only applied to the main icon.

Main icon
Maptext
Main `color`, `transform`, and `filters` apply
Overlays
`color` and `transform` are inherited from Main
`filters` are not inherited from Main

When `color` and `transform` are inherited, they "stack". The inherited color and transform values are applied after those of the overlays.

### `KEEP_TOGETHER` and `KEEP_APART`

There are times it's desirable for an appearance and all its overlays to be treated as a single unit so any colors or filters can be applied all at once. One simple example is if the appearance has an `alpha` of 128 to make it translucent, you probably want to draw the whole atom faded instead of drawing each sprite faded, one on top of the other.

By using the `KEEP_TOGETHER` value in appearance_flags (called KT for short), an appearance will group all of its underlays and overlays together. If this is an atom with image objects and visual contents, those will be grouped with it as well.

KT group
Main `color`, `transform`, and `filters` apply
Main icon
Maptext
Overlays

With `KEEP_TOGETHER` all of these sprites are rendered to a temporary drawing surface, and then the main appearance's `color`, `transform`, and `filters` are all applied to the combined drawing. This comes with a trade-off, since you can no longer use flags such as `RESET_COLOR` to opt out of inheritance.

If an overlay doesn't want to be part of a KT group, it can use the `KEEP_APART` flag (KA for short). If there are multiple nested KT groups, KA will only escape the innermost group.

If an overlay inside a KT group has a different plane than the group's owner, it will be separated as if it defined `KEEP_APART`, except it can escape multiple nested groups.

### Layers and planes

Any appearance can have a layer or plane, and these influence how it gets sorted. (There's also a concept called a "sub-plane" that's influenced by whether an atom is a HUD/screen object or special layers like BACKGROUND_LAYER.)

If a sprite is created with `FLOAT_LAYER` (any negative value counts as a floating layer) its layer has to be resolved, or "unfloated". The main sprite for an atom can never float; it has to have a real layer. Its overlays and underlays with floating layers will reorder themselves in numerical order, then look for the next closest sprites in the rendering list that has a non-negative layer.

A similar process happens with `FLOAT_PLANE`. Planes can have negative values but `FLOAT_PLANE` and the values close to it are special. Sprites with floating planes have to resolve those as well.

Once all atoms that will appear on the map are assembled into a rendering list of sprites, the order in which they're rendered on the map is determined in this order:

1. The `plane` var matters most.
2. Subplane is counted next. E.g., HUD objects render above non-HUD objects.
3. Depending on world.map_format, `layer` or physical position determine the drawing order from here.
4. After everything else has been checked, the order the sprites were generated in is the final tie-breaker.

In a typical topdown map, `layer` is basically all that matters after the plane and subplane are taken into account. There is a legacy concept called micro-layers that helps break ties between sprites with the same layer; for instance if an atom is moving it's usually desirable to draw it above other atoms with the same layer; this applies only to topdown maps.

### Plane masters

Sometimes it's helpful to group multiple sprites on one plane as if the plane itself were a KT group. For this, appearance_flags has a value called `PLANE_MASTER`. An object with this flag will act as a "parent" for everything else on the plane. All other sprites on the plane will be grouped together and rendered on a temporary drawing surface, and then the plane master's `color`, `transform`, and `filters` will be applied.

A plane master does not, however, get an icon or maptext of its own; they're simply ignored. It can have overlays added to the group.

### Advanced topics

There are other topics not covered in this article, such as render targets and special map formats. Any details on how those features impact rendering are discussed in their own articles.

## Side-view maps

See also:
  map_format var (world)
  icon_size var (world)
  dir var (client)
  pixel_w var (atom)
  pixel_z var (atom)
  screen_loc var (movable atoms)
  Big icons
  Isometric maps
  Topdown maps
  HUD
  BACKGROUND_LAYER
  EFFECTS_LAYER
  TOPDOWN_LAYER

The side-view map format is used for 3/4 perspective, where the map is basically similar to a top-down view but is usually foreshortened. Just like with isometric projection, tiles that are closer to the bottom of the screen are considered to be closer to the viewer. This is a form of pseudo-3D in which the 2D icons used by BYOND can be arranged in a way to give the appearance of three dimensions.

It is important to remember that this is an illusion of 3D, not real 3D.

The `layer` var behaves much the same way it does in `ISOMETRIC_MAP` mode.See isometric maps for more information.

When using this mode you may want to use a foreshortened `world.icon_size`, like a 32x24 format instead of 32x32 for example, and use taller icons for any vertical structures like walls or buildings. If you set `world.icon_size` to use foreshortening, then `pixel_y` (or `pixel_x`, depending on the orientation of client.dir) will be adjusted for you; the same applies to `step_x` and `step_y`. For example, with `world.icon_size` set to `"64x32"`, the physical tile—what you would see if you were to look at it straight down from above— is considered to be 64x64, so you would need `pixel_y=64` or `step_y=64` to offset by a whole tile. This adjustment does not apply to screen objects, `pixel_w`, or `pixel_z`.

## Tiled icons

See also:
  icon

  procs (icon)
  map_format var (world)
  icon_size var (world)
  Big icons

  In BYOND 3.0, any file like a large .bmp would be treated like a regular icon that had been broken up into several tile-sized icon states. All tiles then were 32x32 pixels. An image that was 100x100 would therefore take at least 4x4 tiles to display. The icon was padded to the right and the top with blank space to become an even multiple of 32x32, and then broken up into sections. The lower left section was given an icon_state of `"0,0"`, the next to the right was `"1,0"`, and so on, up to the upper right which was `"3,3"`. Another icon state, a 32x32 thumbnail of the big image, was also included.

  BYOND 4.0 expanded on this concept by allowing icons to be defined that had individual graphics bigger than 32x32, and it would break each one up into tiles just like 3.0 did. If an icon had a state called `"open"` then it might break down into `"open 0,0"`, `"open 1,0"`, and so on, while the actual `"open"` state would be a thumbnail image. To show the whole image, you would have to have a separate atom or overlay for each individual tile.

  In newer versions, breaking big icons into tiles is no longer done by default. Instead, icons are shown and manipulated in their native size. To use the old method of breaking icons into tiles, set `world.map_format` to `TILED_ICON_MAP`. This is the default for all projects compiled before version 455.

  When using tiled icons, there are some important things to note:

  - You need to use extra atoms or overlays to show any icon bigger than a single tile, where each atom/overlay shows an individual tile-sized piece of the big icon.
  - The icon_state names of each tile are always the original name followed by a space, followed by x,y tile coordinates such as 0,0 or 2,1, so the northeast corner of `"flag" might for instance be `"flag 3,2". If the original icon_state had no name, the space is left out and only the x,y coordinates are used.
  - Every icon's size is a multiple of world.icon_size. If an icon of an incompatible size is used, it will be padded to the nearest full tile size.
  - `Crop() and `Scale() always pad their results to the nearest full tile size.
  - `icon.Insert() can insert a single-tile icon into a multi-tiled big icon using the appropriate icon_state; e.g., inserting into `"door 0,0" will replace the southwest corner of the `"door" state.
  - Using the `icon() proc, you can extract a single tile from a multi-tiled big icon.

  This example shows a big icon being applied to an atom in tiled mode, as overlays:

  ### Example:

      // icon is 3 tiles wide by 2 high
      icon_state = "0,0"

      // A temporary object used for the overlays
      var/obj/O = new
      O.icon = icon
      O.layer = FLOAT_LAYER

      for(var/tile_y=0, tile_y<2, ++tile_y)
         for(var/tile_x=0, tile_x<3, ++tile_x)
            if(tile_x && tile_y)
               O.pixel_x = tile_x * 32
               O.pixel_y = tile_y * 32
               O.icon_state = "[tile_x],[tile_y]"
               overlays += O

  ## Topdown maps

  See also:
  map_format var (world)
  icon_size var (world)
  dir var (client)
  layer var (atom)
  plane var (atom)
  screen_loc var (movable atoms)
  Big icons
  HUD
  Isometric maps
  Side-view maps
  Understanding the renderer

  By default, BYOND displays all maps in top-down format, so `world.map_format` is set to `TOPDOWN_MAP` unless you say otherwise. This view means players are looking down on the map, and "north" corresponds to the top of their screen. (This can be changed by setting `client.dir`.)

  A related map_format, used by older games, is `TILED_ICON_MAP`. This is also topdown but it handles icons differently.

  In this form, the `layer` var behaves exactly as you would expect: Icons with a lower layer are drawn beneath icons with a higher layer. The only exception is when you use big icons, which will be drawn above any other icons on the same layer. Also an atom's underlays will be drawn behind it unless their layer is changed, and its overlays will draw in front of it unless otherwise stated.

  Topdown mode also guarantees that `world.view` or `client.view` will set the exact screen size used by the HUD, except for HUD objects that appear outside of the normal bounds.

  Screen objects (also called the HUD) cannot be intermixed with topdown icons. They will appear on top of other icons, unless using a lower plane or a special layer like `BACKGROUND_LAYER`.

  ## TOPDOWN_LAYER

  See also:
  layer var (atom)
  map_format var (world)
  BACKGROUND_LAYER
  EFFECTS_LAYER
  stddef.dm file

  TOPDOWN_LAYER is a special high value that can be added to the regular layer of any atom. This is only available when using a non-topdown world.map_format, such as isometric mapping.

  The purpose of this value is to make an atom appear as if it belongs in a top-down map, when using a map_format other than TOPDOWN_MAP or TILED_ICON_MAP. This can be handy for title screens, or for special battle maps or the inside of a building in an RPG.

  When using this special layer, it should be added to the layer an atom normally uses. For instance a turf should have a layer of TOPDOWN_LAYER + TURF_LAYER. Usually you will want one part of the map to have TOPDOWN_LAYER, and for players to be unable to walk to there from the regular map. Mixing topdown icons and icons in the normal map_format in view of each other could look very strange. For safety's sake, the easiest thing to do is to keep them on separate z layers.

  This can be mixed with EFFECTS_LAYER. Anything in TOPDOWN_LAYER will display on top of EFFECTS_LAYER, and TOPDOWN_LAYER + EFFECTS_LAYER will be above both.

  This can also be mixed with BACKGROUND_LAYER, which takes priority over everything else.

  Images or overlays with FLOAT_LAYER can be left alone. They will automatically have the same layer as whatever atom they are attached to.

  ## Unicode

  See also:
  text

  BYOND was originally written to handle 8-bit ("ANSI") characters only. However as time has marched on, Unicode has become ubiquitous for supporting multiple languages, special characters, and emojis. To adapt to this, BYOND now supports Unicode.

  When ANSI was king, every character was exactly one byte in width, because the only valid characters were between 1 and 255. (And technically, BYOND reserved 255 for its own use.) Now, BYOND uses an encoding called UTF-8 to store characters that can't fit in one byte.

  UTF-8 breaks up characters with codes of 128 or higher into multiple bytes, like so:

  Character code | Size in bytes
  --- | ---
  0 - 0x7F | 1
  0x80 - 0x7FF | 2
  0x800 - 0xFFFF | 3
  0x10000 - 0x10FFFF | 4

  ### Text handling

  Importantly, BYOND's text procs are based on the byte position, not the character position which may be lower. In other words, `length("abcdéfg")` is greater than 7; it's 8, because `é` takes up 2 bytes in UTF-8. That also means `f` is at position 7, not position 6.

  Why do the text procs work with byte position instead of character position? Because ultimately, it's faster. Going by character position would require counting every byte in a string (at least when it uses UTF-8) until the right character position was found. This would be detrimental to performance in most cases.

  For the most part, this distinction should be fairly invisible to you. Most code isn't going to encounter problems, but if you do a lot of text processing you should be aware of it.

  In particular, text2ascii() returns the Unicode value at a specific position, which may cover several bytes. If you loop through a string calling this proc for each character, you'll have to make adjustments for cases when multiple bytes have been read.

  The read-only `[]` index operator also uses byte positions.

  If you read a byte or cut text at an inappropriate point, any broken characters resulting from the cut will be turned into the Unicode replacement character � which is 0xFFFD.

  ### `_char` procs

  Most of the text handling procs have slower `_char` versions (e.g., `copytext_char`) that use character positions instead of byte positions.

  These should be used sparingly if at all; whenever it's possible to use byte positions, you should. When you do use a `_char` version of a proc, prefer using `-offset` instead of `length_char(text)-offset` for positions near the end of the string. Most text procs allow negative position values that count backwards from the end, and counting a small number of characters backward is faster than counting a lot of characters going forward.

  ### Old code

  Code written in ANSI will be up-converted to UTF-8 by Dream Maker, based on your current locale when the code is loaded.

  ## User interface skins

  See also:
  winset proc
  winget proc
  output proc
  winclone proc
  winexists proc
  winshow proc
  controls
  parameters
  macros (skin)
  Client commands

  BYOND games used to have very limited interface options, all effectively sharing the same layout. In BYOND 4.0, skins were introduced, allowing developers more control over the layout.

  A skin consists of macro sets for keyboard/gamepad input, menus, and windows and/or panes. All of these are considered controls that a game can interact with via winset(), winget(), output(), and a few other procs.

  About the simplest possible skin is a single window with a single map control, and a single macro set.

  ## Client commands

  Several commands can be executed on the client that are not verbs, but instructions for Dream Seeker. Some of these commands have detailed syntax described in their own reference entries.

  .winset
  Sets skin parameters, and includes special syntax for conditional actions.
.output
  Sends output to a control.
.options
  Shows the Options & Messages box.
.reboot
  Reboots the world, when Dream Seeker is also acting as a server.
.reconnect
  Reconnects to the same world.
.host
  Opens hosting options box, when Dream Seeker is also acting as a server.
.profile
  Opens the profiler. On a remote connection you may not have access to profile server procs, but you can look at the client and network profilers.
.screenshot
  Saves a screenshot of the map. If there's more than one map control, the default map is used.
.screenshot auto
  Saves a screenshot of the map, but does not prompt for a filename. The file will be saved in the client's user directory in BYOND/screenshots.
.gamepad-mapping
  Opens the gamepad mapping dialog. Helpful if the user's gamepad is not supported or not configured to their liking.
.command
  Prompts the user to enter a command, which can be one of these commands as well.
.sound
  Play, stop, or update sound.
.add-particles
  Adds a batch of particles to a particle set.
.configure option value
  Toggle certain Dream Seeker config options, such as `.configure graphics-hwmode on`. The only supported options you can use are `graphics-hwmode`, `sound`, and `delay` which is an old mechanism for dynamically adapting to network delay. (Usually the `delay` is reset to 0.)
.quit
  Closes Dream Seeker.

Client commands have a special syntax that allows you to query information from the skin and include it directly in the command, as if you had called winget(). Embedded expressions look like `[[expression]]` in your command text. Some commands have built-in data that gets filled in via `[[*]]`. See embedded winget for more information.

## .add-particles (client command)

See also:
  Particle effects

  Client commands
  Format:
    .add-particles object count

  Immediately spawns a batch of particles for a known particle set.

  The object parameter is a reference string for the object that holds the particles.

  A negative count is allowed, which will absorb some ordinary particle spawns.

      .add-particles [0x200004f] 50

  If the object isn't known to the client, nothing will happen.

  ## .output (client command)

  See also:
  output proc
  Client commands
  Format:
    .output control text

  Sends output to a control. The text does not need quotes, but any backslashes, newlines, and tabs should be escaped with a backslash. This works similarly to the `output() proc. If text is omitted, the control is cleared.

  Here is an example of using a map control's on-status event to set a label rather than using the window's own statusbar.

      .output statuslabel [[* as escaped]]

  ## .sound (client command)

  See also:
  sound proc
  sound datum
  Client commands
  Format:
    .sound file options
    .sound none options

  Plays, stops, or modifies a sound. This command can be used for instance to play a click sound when using mouse macros, for instance, without waiting for the server to initiate the sound which would introduce a small delay.

      .sound 'click.ogg'

  The file can be `none` or `-` when updating or stopping a sound. Any options should be separated by spaces; most are in a `name=value` format, as seen below.

  Supported options are:

  update
    This action is updating a channel rather than playing a new sound. It corresponds to the SOUND_UPDATE
status flag.
channel=N
  Specifies a channel.
volume=N
  Sets the volume.
mute
mute=T
  Mutes the sound; the `update` option is implied.
pause
pause=T
  Pauses the sound; the `update` option is implied.
wait
  The new sound will queue up in the specified channel, and play after the current sound is done.
repeat
repeat=T
repeat=once/infinite/rewind
  Specifies whether, and how, the sound repeats.
falloff=N
  Sets the falloff value for 3D sound.
x=N
y=N
z=N
  Sets the x, y, or z value for 3D sound.
atom=ref
  Sets the atom for atom-linked 3D sound. The reference is in a format such as `[0x200001b]` without quotes (see ref() proc).
transform=list
  Sets the transform value for 3D sound. The list is up to 9 numbers, separated by commas without spaces.

*T represents a true/false value. True values include `true`, `on`, or 1. False would be `false`, `off`, or 0.

## .winset (client command)

See also:
  winset proc
  Client commands

Format:
  .winset "[control.param=value;...]"

Sets skin parameters like the `winset()` proc. You can set more than one parameter by separating them with semicolons.

This command also allows you to use conditional expressions, like so:

    condition ? choice1 : choice2

The condition is the same as any other parameter you might use in `.winset`, but instead of setting the parameter, it checks to see if it's true. If so, then the parameters in `choice1` will be set. Otherwise, the parameters in `choice2` are set. This example makes the window background red if bigbutton is checked.

    .winset "bigbutton.is-checked=true ? window.background-color=#ff0000 : window.background-color=none"

If you want to look for values that don't match instead of values that do, use `!=` instead of `=` in the condition.

    .winset "bigbutton.is-checked!=false ? window.background-color=#f00 : window.background-color=none"

The `choice2` item is optional.

    .winset "bigbutton.is-checked=true ? window.background-color=#f00"

Because it's often useful to do more than one thing at a time, `choice1` and `choice2` don't have to be just one parameter. You can use multiple parameters, but they are separated with a space instead of a semicolon. (A semicolon indicates the conditional expression is over.)

    .winset "bigbutton.is-checked=true ? window.text-color=#fff window.background-color=#f00 : window.text-color=none window.background-color=none"

## Embedded Winget

See also:
  Client commands

Commands that are initiated by the skin (like button.command, map.on-show, etc.) have a special syntax that allows you to include information that would normally require a winget call. By including `[[something]]` in the command, the double-bracketed text will be replaced by the result of running a winget on that parameter.

A value of `[[id.parameter]]` will run a winget on the control with the given ID. Just using `[[parameter]]` will run a winget for the control that initiated this command. You can also use `parent` in place of the ID to do something with the parent of the control, or `parent.id` for access to a sibling control. Position and size parameters can be further broken down by appending `.x` or `.y` to get at the numbers directly.

Several commands already support some special cases like `[[*]]` or `[[width]]` or such, where the special-case values are relevant to the command. An example is that in `on-size` the value of `[[*]]` is a size value. The Any macro, gamepad macros, and mouse macros, also support this syntax; see macros for more info.

You can choose how embedded wingets get formatted by following the value with `as` and a type, such as `[[window.size as string]]`. There are several types you can use, and different types of parameters get formatted differently:

arg
  Value is formatted as if it's an argument on a command line. Numbers are left alone; booleans are 0 or 1; size and position have their X and Y values separated by a space; pretty much everything else is DM-escaped and enclosed in quotes.
escaped
  DM-escape the value as if it's in a quoted string but do not include the quotes. Size and position values both use `,` to separate their X and Y values.
string
  Value is formatted as a DM-escaped string with surrounding quotes.
params
  Format value for a URL-encoded parameter list (see list2params), escaping characters as needed.
json
  JSON formatting. Numbers are left unchanged; size or position values are turned into objects with x and y items; boolean values are `true` or `false`.
json-dm
  JSON formatting, but DM-escaped so it can be included in a quoted string. Quotes are not included.
raw
  Does not change the value's text representation in any way; assumes it's already formatted correctly for the purpose. This is similar to `as arg` but does no escaping and no quotes.

The `arg` type is the default, unless the `[[`...`]]` expression has double quotes on both sides, in which case `escaped` is the default.

## controls (skin)

Control types:
  Bar

: A progress bar or slider
  Browser: A browser
  Button: A pushbutton or toggle button
  Child: A container holding one or two panes, with a movable splitter
  Grid: For table-like or list-like output
  Info: Classic BYOND statpanel
  Input: Command input or other user-entered text
  Label: Non-interactive text label
  Main: A window or pane that holds other controls
  Macro: A keyboard/gamepad/mouse macro
  Map: The game map display
  Menu: An item in a drop-down menu
  Output: Text output
  Tab: A tab control holding multiple panes, showing one at a time
  Parameters common to all controls:
    id
  is-disabled
  parent
  saved-params
  type
Positionable controls only (not Macro or Menu):
  anchor1, anchor2
  background-color
  border
  drop-zone
  flash
  focus
  font-family
  font-size
  font-style
  inner-mouse-pos
  is-visible
  is-transparent
  mouse-pos
  on-size
  outer-mouse-pos
  pos
  right-click
  size
  text-color

  ### Creating/Destroying at runtime

  Controls can be created or deleted at runtime. (Only controls you created during runtime may be deleted.) To create a control, call winset() using the id of the new control, and the parameter list should include type, parent, and probably also pos, size, and any anchors.

  To delete the control again, set its `parent` to a blank value.

  Menu items and macros work similarly, except they have no positional info. For those, the name parameter is important when you create them, and you will either need command or (for macros) map-to to do anything with them.

  ## bar control (skin)

  A progress bar or interactive slider. This can be made to use several different orientations. Its `value` can be read or set as a percentage from 0 to 100.

  Bar-specific parameters:
    angle1, angle2
  bar-color
  dir
  is-slider
  on-change
  value
  width

  ## browser control (skin)

  A browser panel integrated into the skin.

  Browser-specific parameters:
    auto-format
  inner-background-color
  on-hide
  on-show
  show-history
  show-url
  use-title

  Browsers are capable of displaying HTML documents, and can also interact with the skin.

  ### Browsers and popups

  A longstanding behavior of BYOND is the ability to create a new browser window by sending an extra argument to the browse() proc. Since the advent of skins in BYOND 4.0, this behavior was kept. When you create a new browser popup, the window name you specify for the popup is used for the name of a new window control, and within that window there will be a new browser control simply called `browser`.

  If you want to interact with the new browser, its full "decorated" id is `windowname.browser`.

  ### Running JavaScript from DM

  Sending output() to a browser will send a document to display there, but if you follow the browser's control name with a colon and a function name, you can call a JavaScript function in the document displayed within that browser.

  ### Example:

      var/list/info = list("name"="fridge", "power"=12)
      // send {"name":"fridge","power":12} to a JavaScript function
      usr << output(url_encode(json_encode(info)), "mybrowser:myJSfunction")

  The text that you send as output will be parsed like URL parameters, where mutliple arguments to the function are separated by `&` or `;`, which is why url_encode() is wrapped around the json_encode() call in this example.

  ### More browser options

  These topics cover more advanced uses of the browser control.

  BYOND object (JavaScript)
    Shortcuts for client interaction
  winset and winget (JavaScript)
    Interact with the skin via JavaScript
  byondStorage (browser control)
    Provides persistent storage options for small data

  ## BYOND object (JavaScript)

  See also:
    browser control (skin)

  The BYOND object is a built-in shortcut for interacting with the client via JavaScript in a browser control. When the object is created, a custom `byond-ready` event is dispatched to both the document and the window.

  The object contains the following methods:

  ### BYOND.winset(id, params)

  Performs a winset, where `id` is the ID of the control to change (or null for global settings), and `params` is an object with parameter,value pairs such as `{"text-color": "red"}`. Parameters can use camelCase, where a capital letter indicates where a hyphen would normally go, e.g. `"textColor"` and `"text-color"` are the same.

  ### Example:

      // uncheck a button from JavaScript
      BYOND.winset("inventory_button", {isChecked: false});

  ### BYOND.winget(id, props)

  Sends a winget, where `id` is the ID of the control to retrieve (or null for global settings), and `props` is a single property or an array of properties to retrieve. As with `winset`, camelCase is allowed, but the result will not use camelCase.

  Returns a Promise object, so this call can be used with the `await` keyword or followed by `then()`. The result inside the promise is an object with parameter,value pairs, such as `{"background-color": {value: "#ff0000", red: 255, green: 0, blue: 0, isDefault: false}}`.

  ### Example:

      // get a button's status JavaScript
      let buttonData = await BYOND.winget("inventory_button", "isChecked");
      if(buttonData["is-checked"]) {
          alert("The button is checked!");
      }

  ### BYOND.command(command)

  Initiates a client command. This is basically just a shortcut for using `winset` to run a command.

  ### Example:

      // play a sound
      BYOND.command(".sound 'ding.ogg'");

  ### BYOND.topic(params)

  Sends a topic string to client.Topic(), where `params` is an object with parameter,value pairs. This will automatically url_encode the params object into a topic string.

  ## byondStorage (browser control)

  See also:
    browser control (skin)
  winset proc

  A replacement for `localStorage` that can be used to hold information for reuse in later sessions of the same game. (This must be enabled via `browser-options` with the `winset()` proc.)

  There are three actual storage objects you can use:

  hubStorage | Stores info that can be shared for all games falling under this same hub entry

. (This will not be available without a hub path.)
serverStorage Stores info that can be shared for all games with the same hub path using this same server address.
domainStorage Same as serverStorage, but ignores the connection port.

Interacting with these storage objects is done in JavaScript, the same way you would use `localStorage` or `sessionStorage`.

Note: Technically `localStorage` does work, but because of the way BYOND handles browser controls it acts more like `sessionStorage` in practice.

## winset and winget (JavaScript)

See also:
  browser control (skin)
  BYOND object (JavaScript)
  winset proc
  winget proc

Browser controls can interact with the skin via JavaScript, by setting `window.location` to a special URL.

### Winset

`byond://winset?id=[control ID]&[property]=[value]&...`

This works like an ordinary winset() call from the server. If `id` is omitted, it's the same as a winset with a null ID. You can also leave the `id` blank if you use "fully decorated" property names such as `mybutton.is-checked` instead of just `is-checked`.

Any text you use other than letters, numbers, hyphens, commas, and periods should be encoded via the `encodeURIComponent()` function in JavaScript.

### Winget

`byond://winget?callback=[callback function]&id=[control ID/list]&property=[property/list]`

In this winget, the IDs and properties you want can be separated by commas if you want to retrieve more than one. The winget operation works via a callback function you must define in JavaScript. The callback is given just one argument, a JavaScript object with all of the properties you requested. For example, this URL:

    byond://winget?callback=wgcb&id=button1&property=is-checked,size,background-color

...might send this to the callback function `wgcb`:

    {
        "is-checked": true,
        "size": {
            "x": 60,
            "y": 20
        },
        "background-color": {
            "value": "none",
            "isDefault": true,
            "red": 236,
            "green": 233,
            "blue": 216,
            "alpha": 255,
            "css": "#ece9d8"
        }
    }

The property names will be in the same format you would expect from winget(), so when you're looking at multiple elements' properties, you'll get the full names in `id.property` format. The values are always sent back in a convenient form for JavaScript to work with; in the case of size, position, and color these will always be objects.

An optional `control` parameter for the winget call can be used if you want to send data to a callback in a different browser control.

## button control (skin)

A button that can be pressed to run a command, or possibly toggled.

Button-specific parameters:
  button-type
  command
  group
  image
  is-checked
  is-flat
  text

## child control (skin)

A container that can hold one or two panes. If it holds two panes, a splitter may appear between them. This control can therefore be used to subdivide a window or pane into smaller units.

Child-specific parameters:
  is-vert

  left, top
  lock
  right, bottom
  show-splitter
  splitter

  ## grid control (skin)

  A grid that contains multiple cells that can show various kinds of output data.

  Grid-specific parameters:
  cell-span
  cells
  current-cell
  enable-http-images
  highlight-color
  is-list
  line-color
  link-color
  show-lines
  show-names
  small-icons
  style
  visited-color

  Sending output to a grid looks like this:

  ### Example:

      // output to column 3, row 2
      winset(usr, "thegrid", "current-cell=3,2")
      usr << output("Text", "thegrid")

      // or even easier:
      usr << output("Text", "thegrid:3,2")

      // when is-list is true:
      usr << output("5th item", "thegrid:5")

  You can output an atom to the grid, which can be clicked, dragged, etc. However, you should make sure that atom is not temporary and will persist until you no longer need it, or else the server may recycle it and the object in the cell will either disappear or be impossible to interact with anymore.

  There are some limitations to output in grid controls:

  - Only one character style (font, color, bold, etc.) may appear within a single cell.
  - A cell is either a link, or not.
  - One image is allowed per cell.
  - A cell can hold an object (atom), sent to it via the `output() proc
, which can be clicked, dragged, etc.; it will not act as a link.
- The same margin is used all around the cell, not different margins for left, right, top, bottom.
- There will always be a 1-pixel space for grid lines, whether they're shown or not.

## info control (skin)

The classic BYOND statpanel, which contains both stat and verb tabs. This is technically a 3-column grid with a variable number of rows.

Info-specific parameters:
  allow-html
  has-stats
  has-verbs
  highlight-color
  multi-line
  on-hide
  on-show
  on-tab
  prefix-color
  suffix-color
  tab-background-color
  tab-font-family, tab-font-size, tab-font-style
  tab-text-color

Output to a statpanel is done via the stat() and statpanel() procs, during mob/Stat().

The same limitations that apply to grid output apply here.

Info controls can now be split so that one displays stats and another handles verbs.

## input control (skin)

A text box into which the user can type. By default this is used for sending client commands, but it can be used for other purposes as well.

Input-specific parameters:
  command

  is-password
  multi-line
  no-command
  on-blur
  on-focus
  text

  Note that when in "standard" mode of accepting user commands, built-in verbs like `.click`, or local commands like `.winset`, are not accepted when typed in. This kind of command can still be entered manually through the Client menu of the Options & Messages window.

  ## label control (skin)

  A text label that appears on the skin.

  Label-specific parameters:
  align
  allow-html
  image
  image-mode
  keep-aspect
  text
  text-wrap

  ## macro control (skin)

  A keyboard/gamepad/mouse macro

  , usually designed to run a command. The control is a means of interacting with the macro as an object, allowing some of its properties to be changed at runtime.
  Macro-specific parameters:
    command
  map-to
  name
  pass-through

  ## main control (skin)

  A container for other controls. The Main control takes two forms: a window or a pane.

  A window exists independently and can be moved around on the screen. A pane has to be used within another container control such as a Child or Tab control.

  Main-specific parameters:
    icon
  image
  image-mode
  inner-pos
  inner-size
  is-pane
  keep-aspect
  outer-pos
  outer-size
  title
  on-status
Windows only:
  alpha
  can-close
  can-minimize
  can-resize
  is-fullscreen
  is-maximized
  is-minimized
  macro
  menu
  on-close
  screen-pos
  screen-size
  statusbar
  titlebar
  transparent-color
Panes only:
  can-scroll

  The font parameters have no impact on a window's statusbar or titlebar; those are drawn by the operating system.

  ## map control (skin)

  A map that will display icons from the game.

  Map-specific parameters:
    icon-size
  letterbox
  on-hide
  on-show
  style
  text-mode
  view-size
  zoom
  zoom-mode

  ## menu control (skin)

  A menu item, that when activate will run a command.

  Menu-specific parameters:
    can-check
  command
  group
  index
  is-checked
  name

  ## output control (skin)

  Displays text output.

  Output-specific parameters:
    enable-http-images
  image
  legacy-size
  link-color
  max-lines
  style
  visited-color

  ## tab control (skin)

  A tab control, where each tab holds a different pane.

  Tab-specific parameters:
    current-tab
  multi-line
  on-tab
  tabs

  ## macros (skin)

  Macros are used to convert keyboard and gamepad events into actions. There are two ways this works: A macro can run a command, or in some cases (such as gamepad controls) it can be used to remap one control to another.

  A collection of macros is called a macro set, and the window currently in use defines which macro set will be used via its macro parameter.

  Macros can be changed at runtime. If a macro does not have an id, you can refer to it by its key combination (name). If you have a macro set named `macro1` and have a `Ctrl+E` macro for instance, you could use winset() with `"macro1.Ctrl+E"`. See the Macro control for information on which parameters you can change with `winset()`.

  The `name` of the macro is actually the full key combination as it would appear in the macro editor, like `CTRL+E`, `Space+REP`, or `Alt+Shift+F1`. This is not case-specific and it doesn't matter where you put modifiers like `CTRL+`, `SHIFT+`, etc.

  ### The Any macro

  Oftentimes it's desirable to keep track of key presses yourself rather than have a hundred different macros defined. BYOND makes this possible via the `Any` and `Any+UP` macros, which respond to any key or gamepad button. `UP` is the only allowed modifier for this macro, since other modifier keys are handled by this same macro.

  Typically, you will want to use set instant=1 on the verbs that will be tied to the Any macro, so that keyboard input doesn't queue up and lag behind.

  In the command that goes with this macro, `[[*]]` will be replaced with the name of the key or gamepad button that was pressed/released. (See embedded winget for more details on the `[[...]]` format.)

  ### Mapping

  The map-to parameter is used by mappings, which are like macros but are used to convert gamepad inputs easily and quickly to keyboard inputs. E.g., `GamepadLeft` can map to `West` which is the left arrow key. A set of default mappings will be added automatically at runtime if you don't include any gamepad mapping in your project.

  ### Gamepads

  BYOND will support up to four gamepads, and breaks up their input into the following categories:

  - Buttons: Buttons on the controller that are either pressed or not pressed.
  - Directions: Directions pressed on the D-pad, which act like buttons. Diagonals are also included.
  - D-pad: The D-pad itself, which can be used to read a dir
  number.
  - Analog: The analog sticks (BYOND supports left and right).

  See the list of available macros below for information on how to harness these inputs.

  To let a user configure their gamepad, you need to call the client-side `.gamepad-mapping` command. Or, if they have access to the Options & Messages window and Dream Seeker's default menus, they can reach it from there. However it's a good idea to make this easy for them to find. Several common gamepads are already known by BYOND.

  There is also the `GamepadRaw` macro, which is similar to `Any` in some ways and will avoid doing any processing (e.g. checking for dead zones on the analog sticks) so you can handle all input yourself. `GamepadRaw` does not rely on BYOND's controller configuration, so it will not, for instance, know that button 0 should be `GamepadFace1`. See below for more information on how to use this macro.

  ### Mouse macros

  You can add macros (not local player-defined ones) for any of the mouse input commands, thereby bypassing the normal mouse verbs. This can be helpful for designing custom setups where you don't want to have to parse the normal parameter string that provides most of the info, and instead want to provide data directly to the verb. You will want `set instant=1` on any such verb.

  Mouse macro commands use the `[[...]]` syntax to embed values, just like embedded wingets. These are the values you can include in a mouse macro:

  Embedded keyword | Meaning
  --- | ---
  `action | Name of the mouse action (e.g. MouseDown, MouseMove, etc.).
  `src | Object the mouse is touching, or dragging/dropping.
  `loc | Turf or statpanel that `src is over; in a drag-drop you should split this into `src.loc and `over.loc.
  `button | Mouse button used for this action, if any: `left, `middle, or `right.
  `drag | Mouse button currently used for dragging.
  `buttons | Mouse buttons currently down or involved in this action, separated by commas.
  `keys | Modifier keys currently held (`shift, `ctrl, `alt), separated by commas.
  `over | Object the mouse is over in a drag/drop operation.
  `id | Control ID; in a drag-drop you should split this into `src.id and `over.id.
  `icon | The icon offset (starting from 1,1 at the lower left) where the mouse action occurred.*
  `tile | The tile where the mouse action occurred, if relevant.*
  `vis | Pixel coordinates relative to the icon's position on screen (same as `icon but without taking transform into account).*
  `screen_loc | The regular `screen_loc cordinate string.*
  `screen | `screen_loc coordinates but entirely in pixels starting at 0,0 from lower left.*
  `screen_tile | `screen_loc coordinates but only the tile number starting at 1,1.*
  `screen_offset | `screen_loc coordinates but only the pixel offset from the tile, starting at 0,0.*
  `delta | Wheel changes in a mouse wheel command.*
  `left, `right, `middle | 1 if this button is down or involved in this action, 0 otherwise
  `shift, `ctrl, `alt | 1 if this modifier key is held, 0 otherwise
  `link | 1 if the mouse is over a maptext link, 0 otherwise
  `cell | Grid cell involved in a mouse action. In a drag/drop action, `src.cell is the dragging cell and `over.cell is the drop cell.
  `drag-cell | Alias for `src.cell.
  `drop-cell | Alias for `over.cell.
  `params | Parameter list that would be sent with the default mouse command.
  * Coordinate values are comma-separated, but you can follow them with `.x or `.y to get the individual X and Y numbers.

  An example mouse macro command might look like this:

  >     my-mousedown-verb [[src]] [[button]] "keys=[[keys as params]];drag=[[drag as params]]"

  And the verb to go with it looks like this:

      client
          // "in src" is the same as "in usr.client" here
          verb/my_mousedown_verb(object as anything in src, button as text, params as text)

  In the example, the `src` value is a reference such as you would get with the `ref()` proc. It can be used as a verb argument directly and won't be enclosed by quotes by default. The `button` value is a string and the default formatting will put quotes around it. The `keys` and `drag` values were given the `as params` format specifier so they would behave as part of a parameter list.

  In drag/drop actions, you can precede any value with `src` or `over` if there may be different information for the dragged object and the mouseover object/location. This also applies to things like `keys`, which by default will be the currently held keys but you can use `src.keys` to refer to the values from when the drag began.

  ### Available macros

  This is a list of all keys and gamepad events that can be used in macros.

  Macro modifiers are part of the macro name, and control the conditions in which the macro will fire.
  Modifier | Meaning
  --- | ---
  `SHIFT+ | This macro only counts if either Shift key is pressed.
  `CTRL+ | This macro only counts if either Ctrl key is pressed.
  `ALT+ | This macro only counts if either Alt key is pressed.
  `+REP | If a key/button is held down, this macro repeats.
  `+UP | This macro fires when the key/button is released.
  Keyboard keys are the garden-variety macros. (This list is abridged to exclude keys probably no one has.)
  Key | Description
  `A - `Z | Letter key
  `0 - `9 | Number key
  `Numpad0 - `Numpad9 | Numpad numbers
  `North | Up arrow
  `South | Down arrow
  `East | Right arrow
  `West | Left arrow
  `Northwest | Home key
  `Southwest | End key
  `Northeast | Page Up key
  `Southeast | Page Down key
  `Center | Center key (numpad)
  `Return | Enter / Return key
  `Escape | Esc key
  `Tab | Tab key
  `Space | Space bar
  `Back | Backspace key
  `Insert | Ins key
  `Delete | Del key
  `Pause | Pause key
  `Snapshot | Snapshot / Print Screen key
  `LWin | Left Windows key
  `RWin | Right Windows key
  `Apps | Apps key
  `Multiply | Multiply key
  `Add | Add key
  `Subtract | Subtract key
  `Divide | Divide / Slash key
  `Separator | Separator / Backslash key
  `Shift | Shift key (when not used as a modifier)
  `Ctrl | Ctrl key (when not used as a modifier)
  `Alt | Alt key (when not used as a modifier)
  `VolumeMute | Mute key
  `VolumeUp | Volume up key
  `VolumeDown | Volume down key
  `MediaPlayPause | Play/pause media key
  `MediaStop | Stop media key
  `MediaNext | Next track key
  `MediaPrev | Previous track key
  Special macros
  `Any | A special macro that can run a command on press/release of any key or gamepad button. `UP is the only modifier allowed. In the command, `[[*]] is replaced with the key/button name.*
  `GamepadRaw* | Captures raw input from a gamepad, without regard to the adjustments done by the Gamepad Setup dialog. In the command, `[[id]] is replaced by the name of the button or axis changed ("Button0" through "Button15" and "Axis0" through "Axis11"), `[[value]] is replaced with the value of the button or axis, and `[[*]] is equivalent to `[[id]] [[value]].
  * If no gamepad mappings are included in a game's interface, the default mappings are used instead, which will map the Dpad buttons to the arrow keys. This will cause the Any macro to register both a gamepad directional button and the mapped key on the same press. If you plan on using macros to capture gamepad input, you may wish instead to map any one of the directional buttons to "None", which will override the default gamepad mappings completely.
  Gamepad buttons† can use another gamepad button as a modifier (but not CTRL, SHIFT, ALT), and can be mapped to one or two keyboard keys or mouse buttons.
  Button | Description
  `GamepadFace1 | A (Xbox), X (PS), bottom of diamond
  `GamepadFace2 | B (Xbox), Circle (PS), right of diamond
  `GamepadFace3 | X (Xbox), Square (PS), left of diamond
  `GamepadFace4 | Y (Xbox), Triangle (PS), top of diamond
  `GamepadL1 | Left top shoulder
  `GamepadR1 | Right top shoulder
  `GamepadL2 | Left bottom shoulder
  `GamepadR2 | Right bottom shoulder
  `GamepadSelect | Select / Back
  `GamepadStart | Start / Forward
  `GamepadL3 | Left analog click
  `GamepadR3 | Right analog click
  Directional buttons: only one can pressed at a time, and the diagonal buttons are virtual.
  `GamepadUp | Up button
  `GamepadDown | Down button
  `GamepadLeft | Left button
  `GamepadRight | Right button
  `GamepadUpLeft | Up+left virtual button
  `GamepadUpRight | Up+right virtual button
  `GamepadDownLeft | Down+left virtual button
  `GamepadDownRight | Down+right virtual button
  Gamepad analog sticks† can have commands and/or map to `GamepadDir, `GamepadDir4, or `Mouse. They can use a gamepad button as a modifier. In a command, `[[x]] and `[[y]] are replaced by coordinates, and `[[*]] is replaced by both with a comma for separation.
  `GamepadLeftAnalog | Left analog stick
  `GamepadRightAnalog | Left analog stick
  Gamepad Dpads†‡ can have commands or are used as mapping targets for analog sticks. A gamepad button can be used as a modifier. In a command, `[[*]] is replaced by a direction number, which can be 0.
  `GamepadDir | Dpad, converted to one of the eight standard directions.
  `GamepadDir4 | Dpad, converted to a cardinal direction.
  † All of the gamepad macros defined above apply to the first gamepad. BYOND can now support up to four gamepads, and you can replace Gamepad in the names above with Gamepad2, Gamepad3, or Gamepad4 to access them. Each gamepad also has its own raw macro (i.e., Gamepad2Raw). ‡ If you use a Dpad macro like GamepadDir as a `map-to target, you don't have to specify gamepad 2-4 in map-to; the mapping will automatically know that when Gamepad2LeftAnalog is mapped to GamepadDir, it means Gamepad2Dir.
  Mouse macros can have commands but not be used as mapping targets.
  `MouseDown | Mouse button pressed (replaces MouseDown verb)
  `MouseUp | Mouse button released (replaces MouseUp verb)
  `MouseClick | A click action has occurred (replaces Click verb)
  `MouseDblClick | A double-click action has occurred (replaces DblClick verb)
  `MouseOver | Mouse has moved over a new icon or entered/exited a control (replaces MouseEntered and MouseExited verbs)
  `MouseMove | Mouse has moved to a new pixel of the same icon (replaces MouseMove verb)
  `MouseDrag | Mouse has begin dragging or is over a new drop target (replaces MouseDrag verb)
  `MouseDragMove | Mouse is dragging and is over a new pixel of the same drop target (replaces MouseDrag verb in situations where MouseMove would apply)
  `MouseDrop | Mouse drag has been released over a target (replaces MouseDrop verb)
  `MouseWheel | A wheel movement has occurred (replaces MouseWheel verb)
  Mouse targets can only be used as mapping targets for another macro.
  `Mouse | The mouse cursor, mappable by a gamepad analog stick.
  `MouseLeftButton | Left button, mappable by a gamepad button.
  `MouseRightButton | Right button, mappable by a gamepad button.
  `MouseMiddleButton | Middle button, mappable by a gamepad button.

  ## parameters (skin)

  Controls can be interacted with via winset() and winget() to change or read various parameters.

  Parameters come in a few different formats:

  - Boolean: `true or `false
  - Numeric: any number, sometimes allowing decimal or negative numbers
  - String: text
  - Position: x`,y
  - Size: width `x height
  - Enumerated: one of several text choices, sometimes accepting numbers or true/false values as shortcuts

  The list of all controls which shows which parameters are universal, and each individual control type lists additional parameters that apply to that type specifically.

  Note: In any parameter's "Applies to" section, "all" refers to positionable controls only, not Macro or Menu controls. Macro and Menu will be listed separately if supported.

  ## align parameter (skin)

  See also:
  allow-html parameter
  Applies to:
    Label
  Possible values:
    center
    left
    right
    top
    bottom
    top-left
    top-right
    bottom-left
    bottom-right
  Default value:
    center

  Default alignment of text/image, both horizontal and vertical.

  A BYOND direction flag like `WEST` may be assigned to this parameter, or 0 for center alignment.

  ## allow-html parameter (skin)

  Applies to:
    Label
  Info
  Format:
    true/false
  Default value:
    false

  Info control: Allow HTML tags to be used in stat() info. The same limitations apply as to the Grid control.

  Label control: Currently, the label control will not actually use the HTML; it will simply strip it out. Full support may appear in a later version.

  ## alpha parameter (skin)

  See also:
    transparent-color parameter
  Applies to:
    Main (window only)
  Format:
    number
  Default value:
    255

  Opacity of the window, from 0 (invisible) to 255 (opaque).

  ## anchor1, anchor2 parameters (skin)

  See also:
    pos parameter
  size parameter
  Applies to:
    All (except Main)
  Format:
    none
    x,y
  Default value:
    none

  Anchors the control within the window or pane. If the anchor is not `none`, it is expressed as pecentages of the container's width and height. For example, an anchor of 100,100 means that the X and Y position are tied to the lower right of the container, and 50,0 is tied to the top center.

  Setting only `anchor1` will control the position of the control but won't affect its size.

  Setting `anchor2` as well will allow you to stretch the control as the container's size changes. You can think of this `anchor1` controlling the top left corner, and `anchor2` the bottom right corner.

  ## angle1, angle2 parameters (skin)

  See also:
    dir parameter
  width parameter
  Applies to:
    Bar
  Format:
    number
  Default value:
    `angle1`: 0
    `angle2`: 180

  The angle of the bar control's arc when its dir is `clockwise` or `counterclockwise`. Angles are measured clockwise from due north, so 0 is north, 90 is east, and so on. `angle1` is the beginning of the arc, and `angle2` is the end.

  ## auto-format parameter (skin)

  Applies to:
    Browser
  Format:
    true/false
  Default value:
    false (was once true in old versions)

  This parameter only existed to inject compatibility scripts into very old versions of the embedded browser. It is no longer used.

  ## background-color parameter (skin)

  See also:
    text-color parameter
  tab-background-color parameter
  Applies to:
    All
  Format:
    #rrggbb
    none

  The control's background color. The exact way this applies depends on the control.

  ## bar-color parameter (skin)

  See also:
    background-color parameter
  is-transparent parameter
  Applies to:
    Bar
  Format:
    #rrggbb
    none

  The color of the bar or slider.

  ## border parameter (skin)

  Applies to:
    All
  Possible values:
    none
    line
    sunken
  Default value:
    none

  Border type around the control or window. May not work the same in all controls.

  ## button-type parameter (skin)

  See also:
    group parameter
  is-checked parameter
  Applies to:
    Button
  Possible values:
    pushbutton: press once
    pushbox: press to toggle
    checkbox: press to toggle, and displays a checkmark if checked
    radio: press to check, and other buttons with the same `group` will be unchecked
  Default value:
    pushbutton

  Changes the type of button.

  ## can-check parameter (skin)

  See also:
    group parameter
  is-checked parameter
  Applies to:
    Menu
  Format:
    true/false
  Default value:
    false

  If true, this menu item is toggled like a checkbox or radio button when clicked.

  ## can-close parameter (skin)

  See also:
    on-close parameter
  can-resize parameter
  titlebar parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    true

  Allow the window to be closed, and also shows a system menu for the window.

  ## can-minimize parameter (skin)

  See also:
    can-resize parameter
  titlebar parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    true

  Allow the window to be minimized.

  ## can-resize parameter (skin)

  See also:
    on-size parameter
  can-minimize parameter
  titlebar parameter
  is-fullscreen parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    true

  Allow the window to be resized or maximized.

  If `is-fullscreen` is true, `can-resize` is ignored, so this value represents the state of the window when `is-fullscreen` is turned off again.

  ## can-scroll parameter (skin)

  See also:
    on-size parameter
  size parameter
  Applies to:
    Main (pane only)
  Possible values:
    none
    horizontal
    vertical
    both
  Default value:
    none

  Allow this pane to retain its horizontal and/or vertical size and show scrollbars if necessary, instead of shrinking to fit the container.

  ## command parameter (skin)

  See also:
    Client commands
  Applies to:
    Button
    Input
    Macro
    Menu
  Format:
    string

  Command executed when this control is activated.

  For the Input control, whatever the user types in follows this command. If your command starts with an exclamation point `!`, everything after the `!` is shown as a default prompt that may be cleared by the user.

  ## cell-span parameter (skin)

  See also:
    cells parameter
  Applies to:
    Grid
  Format:
    columns,rows
  Default value:
    1x1

  The span of the current grid cell; it can be merged with cells to the right and down. If `is-list` is true, this setting is ignored. This setting is only available at runtime.

  ## cells parameter (skin)

  See also:
    cell-span parameter
  current-cell parameter
  is-list parameter
  Applies to:
    Grid
  Format:
    columns,rows
    items
  Default value:
    0x0

  The number of columns and rows in the grid. Using -1 for either columns or rows will leave that value unchanged.

  If is-list is true, this value can be set to a single number.

  ## current-cell parameter (skin)

  See also:
    cell-span parameter
  cells parameter
  is-list parameter
  Applies to:
    Grid
  Format:
    columns,rows
    items
  Default value:
    0x0

  The active cell. Any output sent to the grid, that is not sent to a specific cell, will go into this cell.

  If is-list is true, this value can be set to a single number.

  ## current-tab parameter (skin)

  See also:
    on-tab parameter
  tabs parameter
  Applies to:
    Tab
  Format:
    string

  The name of the pane in the active/default tab. If set to a pane that is not currently in this tab control, the pane by that name will be added as another tab.

  ## dir parameter (skin)

  See also:
    value parameter
  angle1, angle2 parameters
  width parameter
  Applies to:
    Bar
  Possible values:
    north
    south
    east
    west
    clockwise
    counterclockwise
  Default value:
    east

  The direction/orientation of the bar. As the value increases the bar will move further in this direction.

  Shorthand values like `cw` and `ccw` can be used, or also numerical BYOND directions.

  ## dpi parameter (skin)

  See also:
    id parameter
  winget proc
  Applies to:
    Main
    Global
  Format:
    number
  Default value:
    1

  Read-only and unlisted parameter that returns the DPI scaling factor. A value of 1 indicates 100%. This is currently system-wide for the whole application and won't vary by window, but is implemented for windows in case future scaling changes allow them to differ.

  This is also a special global parameter. Calling winget() with no `id` and `dpi` as the parameter will return the system DPI scaling.

  Note: The DPI scale is currently set at the time Dream Seeker starts, and does not change after that.

  ## drop-zone parameter (skin)

  See also:
    mouse handling
  Applies to:
    All
  Format:
    true/false
  Default value:
    `true` for Grid, Info, Map
    `false` for everything else

  True if dragged objects may be dropped here. Default is true for Map, Info, and Grid controls, false for others. When in use, this will be the value of the `over_control` argument in MouseDrop() if you drop an atom here.

  Grids can also add `drag-cell` and `drop-cell` to mouse proc parameters. The mouse procs' `src_location` and `over_location` arguments are in the form `"[column],[row]"` (or `"[item"]` if is-list is true) when dragging to/from a grid cell.

  In Info controls, `src_location` and `over_location` in mouse procs will be the name of the statpanel tab.

  ## enable-http-images parameter (skin)

  See also:
    small-icons parameter
  style parameter
  Applies to:
    Grid
    Output
  Format:
    true/false
  Default value:
    false

  Allows images to be pulled from the Web when using the `<img>` tag; otherwise only locally stored images can be shown.

  ## flash parameter (skin)

  Applies to:
    Main
  (window only)
  Format:
    number
  Default value:
    0

  Set to a positive number to make the window flash that many times, -1 to flash forever, and 0 to stop flashing.

  ## focus parameter (skin)

  See also:
    id parameter
  winget proc
  Applies to:
    All
    Global
  Format:
    true/false
  Default value:
    false

  This parameter is true if this control currently has focus.

  This is also a special read-only global parameter. Calling winget() with no `id` and `focus` as the parameter will return the id of the currently focused control, if any.

  ## font-family parameter (skin)

  See also:
    font-size parameter
  font-style parameter
  tab-font-family, tab-font-size, tab-font-style parameters
  Applies to:
    All
  Format:
    string

  Leave blank to use the default font. This can be used for CSS-style fallback fonts, e.g. "Arial,Helvetica".

  You can include fonts in your resource file, making them available to the client, like so:

      var/list/extra_resources = list(\
          'myfont.ttf',
          'myfont_bold.ttf')

  ## font-size parameter (skin)

  See also:
    font-family parameter
  font-style parameter
  tab-font-family, tab-font-size, tab-font-style parameters
  Applies to:
    All
  Format:
    number
  Default value:
    0

  Point size of the font, or leave at 0 for the default size.

  The Output control behaves differently for legacy reasons, unless legacy-size is false.

  ## font-style parameter (skin)

  See also:
    font-family parameter
  font-size parameter
  tab-font-family, tab-font-size, tab-font-style parameters
  Applies to:
    All
  Possible values:
    bold
    italic
    underline
    strike
  Default value:
    empty

  Sets the font style. Any combination of the above values may be used, or none of them. Multiple values may be separated by spaces or commas.

  ## group parameter (skin)

  See also:
    button-type parameter
  can-check parameter
  is-checked parameter
  Applies to:
    Button
    Menu
  Format:
    string

  Used for "radio" buttons and menu items, where only one of them in the same group may be checked at a time. This value is a text string, or may be left empty.

  Buttons in different windows/panes, or menu items in another menu/submenu, are always treated as a different group.

  ## has-stats parameter (skin)

  See also:
    has-verbs parameter
  Applies to:
    Info
  Format:
    true/false
  Default value:
    true

  True if this info control contains the statpanels created via stat() and statpanel().

  Only one info control can have statpanels.

  ## has-verbs parameter (skin)

  See also:
    has-stats parameter
  Applies to:
    Info
  Format:
    true/false
  Default value:
    true

  True if this info control contains the verbs used in the game.

  Currently only one info control can have verbs.

  ## highlight-color parameter (skin)

  See also:
    text-color parameter
  background-color parameter
  Applies to:
    Grid
    Info
  Format:
    #rrggbb
    none
  Default value:
    #00ff00

  The color used to highlight moused-over statpanel items or verbs. In grids, this color is used when hovering over objects or links.

  ## icon parameter (skin)

  See also:
    title parameter
  titlebar parameter
  Applies to:
    Main
  Format:
    'file'
  Default value:
    empty

  Custom icon used for the window. If no icon is specified, the Dream Seeker icon is used by windows by default.

  If this control is a pane, its icon will appear on the tab if the pane is inside a tab control. Lack of an icon will mean no icon appears in the tab.

  Note: The Windows `.ico` format is not used. Only image formats BYOND can already use are supported.

  ## icon-size parameter (skin)

  See also:
    zoom parameter
  zoom-mode parameter
  Applies to:
    Map
  Format:
    number
  Default value:
    0

  Size, in pixels, of icons on the map. A size of 0 stretches to fit available space.

  This parameter has been deprecated. Use zoom instead.

  ## id parameter (skin)

  See also:
    parent parameter
  type parameter
  Applies to:
    All
  Format:
    string

  The name of this control. Read-only.

  If this is a Main control, the name should always be unique. For others, it is usually still a good idea to use a unique name, but they can be referenced by window.id at runtime.

  You can use a colon in front of the type to refer to the default control of a certain type, if one exists, e.g. `:map` is the default map.

  ## image parameter (skin)

  See also:
    image-mode parameter
  keep-aspect parameter
  Applies to:
    Button
    Label
    Main
    Output
  Format:
    'file'

  A background image to show in this control.

  In the Output control this image is always tiled.

  Note: Icons displayed in the output control will not show the background image underneath their transparent parts, but will instead show the background color.

  For Label and Main, use image-mode to control how the image is displayed.

  ## image-mode parameter (skin)

  See also:
    image parameter
  keep-aspect parameter
  Applies to:
    Label
    Main
  Possible values:
    center
    stretch
    tile
  Default value:
    center

  Determines how the background image is displayed.

  ## index parameter (skin)

  Applies to:
    Menu
  Format:
    number
  Default value:
    1000

  Moves the menu item to the Nth position among its siblings. 0 or less is no change. Write-only.

  ## inner-background-color parameter (skin)

  See also:
    background-color parameter
  Applies to:
    Browser
  Format:
    #rrggbb
    none (defaults to white)
    transparent

  The background color of the browser portion of the control. This does not apply to the area outside of the browser itself, such as the URL bar or the navigation buttons if they appear.

  Due to technical limitations, partial transparency is not supported. To use partial transparency, you should set this parameter to transparent and then modify the document within the browser to have a translucent background or opacity less than 1.

  ## inner-mouse-pos / mouse-pos parameter (skin)

  See also:
    outer-mouse-pos parameter
  pos parameter
  Applies to:
    All
  Format:
    x,y

  Read-only.

  Reads the position of the mouse cursor relative to the upper left corner of this control, not including the control's borders.

  `mouse-pos` is an alias for `inner-mouse-pos`.

  This parameter is "unlisted" and must be explicitly queried. It won't appear when sending `*` as the parameter in winget().

  ## inner-pos parameter (skin)

  See also:
    pos parameter
  outer-pos parameter
  inner-size parameter
  outer-size parameter
  Applies to:
    Main
  Format:
    x,y

  Read-only.

  Reads the position where the window's interior contents begin (i.e., not counting titlebar, statusbar, borders, etc.), relative to its `outer-pos`.

  ## inner-size parameter (skin)

  See also:
    size parameter
  outer-size parameter
  inner-pos parameter
  Applies to:
    Main
  Format:
    widthxheight

  Read-only.

  If the control is a window, this refers to its current interior size: i.e., not counting titlebar, statusbar, borders, etc. If it's maximized, this will be the true size of the window interior, as opposed to `size` which is the interior size once this window is no longer maximized.

  If this control is a pane and can-scroll is true, this is the size of the display area not including the scrollbars.

  ## is-checked parameter (skin)

  See also:
    button-type parameter
  can-check parameter
  group parameter
  Applies to:
    Button
    Menu
  Format:
    true/false
  Default value:
    false

  True if the button or menu item is checked. Menu items can set this even if can-check is false.

  ## is-default parameter (skin)

  See also:
    id parameter
  parent parameter
  type parameter
  Applies to:
    All
  Format:
    true/false
  Default value:
    false

  Specifies that this is a default control. This should be true for your main window, and for your primary map, info, output, input, and browser controls.

  The default control of a given type can be referenced in winset() and other skin-related procs by the name `":type"`, e.g. `":map"`.

  Changing this value at runtime should be avoided, especially for windows. Results may be unpredictable.

  ## is-disabled parameter (skin)

  See also:
    is-checked parameter
  is-visible parameter
  Applies to:
    All
    Macro
    Menu
  Format:
    true/false
  Default value:
    false

  Disables the control, menu item, or macro.

  ## is-flat parameter (skin)

  See also:
    button-type parameter
  Applies to:
    Button
  Format:
    true/false
  Default value:
    false

  Gives this button a flat appearance instead of pseudo-3D highlights.

  ## is-fullscreen parameter (skin)

  See also:
    can-resize parameter
  titlebar parameter
  is-maximized parameter
  is-minimized parameter
  size parameter
  outer-size parameter
  screen-pos parameter
  screen-size parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    false

  True if the window should be in fullscreen mode. This suppresses `can-resize`, `titlebar`, `is-maximized`, and `is-minimized`. They will continue to return the values that would apply if fullscreen mode were turned off.

  ## is-list parameter (skin)

  See also:
    cells parameter
  current-cell parameter
  Applies to:
    Grid
  Format:
    true/false
  Default value:
    false

  True if the grid is used for a flexible list of items; the number of columns and rows may change to fit them.

  ## is-maximized parameter (skin)

  See also:
    can-resize parameter
  is-minimized parameter
  is-fullscreen parameter
  size parameter
  outer-size parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    false

  True if the window is maximized.

  If `is-fullscreen` is true, this value represents the state of the window when `is-fullscreen` is turned off again.

  ## is-minimized parameter (skin)

  See also:
    can-resize parameter
  is-maximized parameter
  is-fullscreen parameter
  size parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    false

  True if the window is minimized.

  If `is-fullscreen` is true, this value represents the state of the window when `is-fullscreen` is turned off again.

  ## is-pane parameter (skin)

  See also:
    id parameter
  Child control
  Tab control
  Applies to:
    Main
  Format:
    true/false
  Default value:
    false

  True if this is a pane that will be used in other container controls, instead of an independent window. Read-only.

  ## is-password parameter (skin)

  See also:
    command parameter
  multi-line parameter
  no-command parameter
  Applies to:
    Input
  Format:
    true/false
  Default value:
    false

  Hide text with asterisks. Copy to clipboard is not available in this mode, but the text parameter can still read the control's contents.

  Note: For obvious reasons, you should never use the same password in a game that you would use anywhere else.

  ## is-slider parameter (skin)

  See also:
    value parameter
  Applies to:
    Bar
  Format:
    true/false
  Default value:
    false

  Make this an adjustable slider capable of being changed by the user, instead of a progress bar.

  ## is-transparent parameter (skin)

  Applies to:
    All
  Format:
    true/false
  Default value:
    false

  Make this control transparent.

  Transparency support is extremely limited. Only some controls can actually use it, and only when on top of certain other controls.

  Bars and labels handle transparency reasonably well, when not on top of other controls (or only on top of other conrols of these types).

  ## is-vert parameter (skin)

  See also:
    left parameter
  right parameter
  show-splitter parameter
  splitter parameter
  Applies to:
    Child
  Format:
    true/false
  Default value:
    false

  The splitter between the two panes in this control is vertical.

  ## is-visible parameter (skin)

  See also:
    is-disabled parameter
  Applies to:
    All
  Format:
    true/false
  Default value:
    true

  True if this control can be seen. The main window should usually be made visible.

  ## keep-aspect parameter (skin)

  See also:
    image parameter
  image-mode parameter
  Applies to:
    Label
    Main
  Format:
    true/false
  Default value:
    false

  If stretching a background image, preserve its aspect ratio.

  ## left, top parameters (skin)

  See also:
    right parameter
  is-vert parameter
  show-splitter parameter
  splitter parameter
  Applies to:
    Child
  Format:
    string
    none
  Default value:
    none

  The id of the left/top pane in this control. The parameter names `left` and `top` can be used interchangeably.

  ## legacy-size parameter (skin)

  See also:
    font-size parameter
  Applies to:
    Output
  Format:
    true/false
  Default value:
    true

  When true, font sizes are scaled slightly larger for readability, which is legacy (and default) BYOND behavior. Set to false for exact font sizing.

  ## letterbox parameter (skin)

  See also:
    view-size parameter
  zoom parameter
  zoom-mode parameter
  Applies to:
    Map
  Format:
    true/false
  Default value:
    true

  If map auto-scales its icons (zoom is 0), make sure the entire map fits, and fill excess space with the background color.

  If `letterbox` is not enabled, auto-zoom will fill all available space, and any excess will be cut off.

  ## line-color parameter (skin)

  See also:
    background-color parameter
  show-lines parameter
  Applies to:
    Grid
  Format:
    #rrggbb
    none
  Default value:
    #c0c0c0

  The color of grid lines.

  ## link-color parameter (skin)

  See also:
    text-color parameter
  visited-color parameter
  Applies to:
    Grid
    Output
  Format:
    #rrggbb
    none
  Default value:
    #0000ff

  The color used for links. In some controls visited links may have a different color.

  ## lock parameter (skin)

  See also:
    left parameter
  right parameter
  is-vert parameter
  show-splitter parameter
  splitter parameter
  Applies to:
    Child
  Possible values:
    left
    right
    none
  Default value:
    none

  Allows one pane to "lock" the splitter so if this Child control is resized, the splitter will stay put on that side.

  ## macro parameter (skin)

  See also:
    Keyboard/gamepad macros
  menu parameter
  id parameter
  Applies to:
    Main (window only)
  Format:
    string

  The id of the macro set this window will use, if any, when it's active.

  ## map-to parameter (skin)

  See also:
    macros (skin)
  command parameter
  id parameter
  name parameter
  Applies to:
    Macro
  Format:
    string

  The macro name (e.g., "SOUTH") of a key combo, Dpad, mouse button, etc. that this macro maps to.

  ## max-lines parameter (skin)

  Applies to:
    Output
  Format:
    number
  Default value:
    1000

  Maximum number of lines before the control drops old text to make room for more. 0 is no limit.

  An overflow of 5% is allowed, to reduce flicker.

  ## menu parameter (skin)

  See also:
    macro parameter
  id parameter
  Applies to:
    Main (window only)
  Format:
    string

  The id of the menu this window will use, if any, when it's active.

  ## multi-line parameter (skin)

  Applies to:
    Info
  Input
  Tab
  Format:
    true/false
  Default value:
    `false`: Input control
    `true`: Info and Tab controls

  Input control: Create a multi-line input control. Read-only for this control.

  Info and Tab controls: Show tabs in multiple rows if there are too many to fit in a single row.

  ## name parameter (skin)

  See also:
    macros (skin)
  id parameter
  Applies to:
    Macro
    Menu
  Format:
    string

  Macro control: The key/gamepad combination such as `R+REP`, `CTRL+Northwest`, `GamepadLeft`.

  Menu control: This is the menu item label. A tab character can be used between the name and a keyboard shortcut, like "Help\tF1". (Keyboard shortcuts must be implemented as macros in order to work. This is just a label.) A blank name shows just a separator.

  ## no-command parameter (skin)

  See also:
    command parameter
  is-password parameter
  multi-line parameter
  Applies to:
    Input
  Format:
    true/false
  Default value:
    false

  True if this input control is for typing only; hitting Enter will not run a command.

  ## on-blur parameter (skin)

  See also:
    focus parameter
  on-focus parameter
  Applies to:
    Input
  Format:
    string

  Command executed when the control loses focus.

  ## on-close parameter (skin)

  See also:
    can-close parameter
  on-size parameter
  Applies to:
    Main (window only)
  Format:
    string

  Command executed when the window is closed.

  ## on-change parameter (skin)

  See also:
    value parameter
  Applies to:
    Bar
  Format:
    string

  Command executed when the value of the bar/slider is changed. If you drag the slider around, the command will not run until you let go.

  If you include `[[*]]` in the command, it will be replaced by the control's new `value`. (See embedded winget for more details on the `[[...]]` format.)

  ## on-focus parameter (skin)

  See also:
    focus parameter
  on-blur parameter
  Applies to:
    Input
  Format:
    string

  Command executed when the control gains focus.

  ## on-hide parameter (skin)

  See also:
    on-show parameter
  Applies to:
    Browser
    Info
    Map
  Format:
    string

  Commandexecuted when this control is hidden by the game. Must be the default control for the game to show/hide it.

  Currently not editable in Dream Maker.

  ## on-show parameter (skin)

  See also:
    on-hide parameter
  Applies to:
    Browser
    Info
    Map
  Format:
    string

  Command executed when this control is shown by the game. Must be the default control for the game to show/hide it.

  Currently not editable in Dream Maker.

  ## on-size parameter (skin)

  See also:
    size parameter
  Applies to:
    All
  Format:
    string

  Command executed when this control is resized. If you are dragging a window edge or splitter, the command won't run until you finish.

  No command will be sent in response to size or splitter changes made by winset().

  If you include `[[*]]` in the command, it will be replaced by the control's new size. Likewise, `[[width]]` will be replaced with the width and `[[height]]` with the height. (See embedded winget for more details on the `[[...]]` format.)

  ## on-status parameter (skin)

  See also:
    statusbar parameter
  Applies to:
    Main
  Format:
    string

  Command executed when the text that would go in the statusbar is changed. This applies even if this control is a pane and not a window, or is a window without a statusbar. It applies to all panes and windows that directly or indirectly contain whatever control generated the statusbar text (e.g., a map).

  If you include `[[*]]` in the command, it will be replaced by the new text. (See embedded winget for more details on the `[[...]]` format.)

  `[[from]]` can be used to reference the control (if any) that generated the next text. You can also use expressions like `[[from.type]]`, `[[from.parent.pos.x]]`, etc.

  ## on-tab parameter (skin)

  See also:
    current-tab parameter
  tabs parameter
  Applies to:
    Info
    Tab
  Format:
    string

  Command executed when the current tab is changed.

  If you include `[[*]]` in the command, it will be replaced by the new tab's id. (See embedded winget for more details on the `[[...]]` format.)

  ## outer-mouse-pos parameter (skin)

  See also:
    outer-mouse-pos parameter
  pos parameter
  Applies to:
    All
  Format:
    x,y

  Read-only.

  Reads the position of the mouse cursor relative to the upper left corner of this control, including the control's borders.

  This parameter is "unlisted" and must be explicitly queried. It won't appear when sending `*` as the parameter in winget().

  ## outer-pos parameter (skin)

  See also:
    pos parameter
  outer-size parameter
  inner-pos parameter
  Applies to:
    Main
  Format:
    x,y

  Read-only.

  Reads the control's current exterior position including titlebar, statusbar, borders, etc. If the window is not minimized or maximized, this is identical to `pos`.

  ## outer-size parameter (skin)

  See also:
    size parameter
  inner-size parameter
  Applies to:
    Main
  Format:
    widthxheight

  Read-only.

  If the control is a window, this refers to its current exterior size including titlebar, statusbar, borders, etc. If the window is maximized, this is the maximized size.

  If this control is a pane and can-scroll is true, this is the size of the display area including the scrollbars.

  ## parent parameter (skin)

  See also:
    id parameter
  type parameter
  name parameter
  Applies to:
    All
    Macro
    Menu
  Format:
    string

  The id of this control's parent. Write-only, used when creating a new control at runtime or deleting a control that was created this way.

  ## pass-through parameter (skin)

  See also:
    macros (skin)
  Applies to:
    Macro
  Format:
    true/false
  Default value:
    false

  Sends default action for this input after the user macro. Currently this applies only to mouse macros.

  An example of this is if you want to override MouseDown with new functionality in your own verb, but still handle default mouse processing.

  ## pos parameter (skin)

  See also:
    anchor1, anchor2 parameters
  size parameter
  Applies to:
    All
  Format:
    x,y
    none
  Default value:
    x,y
    none

  Position of this control's upper left corner, relative to its container. (Not applicable to panes.)

  ## prefix-color parameter (skin)

  See also:
    text-color parameter
  suffix-color parameter
  Applies to:
    Info
  Format:
    #rrggbb
    none
  Default value:
    none

  The color used for the prefix/header column of statpanel displays. No color means the default text-color will be used.

  In BYOND 3.0, this color was red.

  ## right, bottom parameters (skin)

  See also:
    left parameter
  is-vert parameter
  show-splitter parameter
  splitter parameter
  Applies to:
    Child
  Format:
    string
    none
  Default value:
    none

  The id of the right/bottom pane in this control. The parameter names `top` and `bottom` can be used interchangeably.

  ## right-click parameter (skin)

  See also:
    mouse handling
  popup_menu setting (verb)
  drop-zone parameter
  Applies to:
    All
  Format:
    true/false
  Default value:
    false

  True if this control should allow right-clicks to behave like any other click instead of opening up popup menus or similar special behavior.

  ## saved-params parameter (skin)

  Applies to:
    All
  Format:
    string
  Default value:
    varies

  A semicolon-separated list of parameters that get saved with this control. This is often used for things a user might set, like zoom level for a map.

  Currently not editable in Dream Maker.

  ## screen-pos parameter (skin)

  See also:
    pos parameter
  outer-pos parameter
  Applies to:
    Main
    Global
  Format:
    x,y

  Read-only.

  For windows, this is the upper left corner of the nearest monitor's area.

  This is also a special read-only global parameter, which returns the position for the main monitor.

  ## screen-size parameter (skin)

  See also:
    size parameter
  outer-size parameter
  Applies to:
    Main
    Global
  Format:
    widthxheight

  Read-only.

  For windows, this is the size of the nearest monitor's area (minus taskbar).

  This is also a special read-only global parameter, which returns the size (minus taskbar) for the main monitor.

  ## size parameter (skin)

  See also:
    pos parameter
  anchor1, anchor2 parameters
  on-size parameter
  inner-size parameter
  outer-size parameter
  Applies to:
    All
  Format:
    widthxheight

  The size of this control.

  Setting 0 for width or height uses up any available space right/downward.

  If the control is a window, this refers to its interior size when not maximized or minimized. That is, it does not count borders, titlebar, menu, or statusbar, and if the window is minimized/maximized, this refers to the window's normal size when it is restored. See the inner-size and outer-size params for comparison.

  If this control is a pane and can-scroll is true, `size` refers to the total scrollable size of the pane, NOT the smaller size displayed. In this case, `outer-size` and `inner-size` refer to the display area with and without scrollbars, respectively.

  ## show-history parameter (skin)

  See also:
    show-url parameter
  use-title parameter
  Applies to:
    Browser
  Format:
    true/false
  Default value:
    false

  Show forward/back navigation buttons.

  ## show-lines parameter (skin)

  See also:
    line-color parameter
  Applies to:
    Grid
  Possible values:
    none
    horizontal
    vertical
    both
  Default value:
    both

  Determines which grid lines to display.

  ## show-names parameter (skin)

  See also:
    name var (atom)
  small-icons parameter
  Applies to:
    Grid
  Format:
    true/false
  Default value:
    true

  When atoms are output to the grid, show the atom's name next to its icon.

  If the atom has no icon and `show-names` is false, the grid cell will be blank.

  ## show-splitter parameter (skin)

  See also:
    left parameter
  right parameter
  is-vert parameter
  splitter parameter
  Applies to:
    Child
  Format:
    true/false
  Default value:
    true

  Show a splitter if both the left and right (or top and bottom) panes are in use. The splitter can be dragged to resize the panes.

  ## show-url parameter (skin)

  See also:
    show-history parameter
  use-title parameter
  Applies to:
    Browser
  Format:
    true/false
  Default value:
    false

  Shows an address bar for this browser control.

  ## small-icons parameter (skin)

  See also:
    show-names parameter
  Applies to:
    Grid
  Format:
    true/false
  Default value:
    false

  When output(object,grid) is sent, show smaller icons in this control instead of larger ones.

  ## splitter parameter (skin)

  See also:
    left parameter
  right parameter
  is-vert parameter
  show-splitter parameter
  Applies to:
    Child
  Format:
    number (0 to 100)
  Default value:
    50

  Position of the splitter when two panes are in use, whether show-splitter is true or not. This value is a percentage. Specifically, it is the percentage of the available width/height that is given to the left/top pane.

  ## suffix-color parameter (skin)

  See also:
    text-color parameter
  prefix-color parameter
  Applies to:
    Info
  Format:
    #rrggbb
    none
  Default value:
    none

  The color used for the suffix column of statpanel displays. No color means the default text-color will be used.

  In BYOND 3.0, this color was blue.

  ## statusbar parameter (skin)

  See also:
    titlebar parameter
  on-status parameter
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    true

  Shows a status bar at the bottom of the window. This will show the name of an atom when you hover over it with the mouse.

  ## stretch parameter (skin)

  See also:
    image parameter
  image-mode parameter
  Applies to:
    Label
  Format:
    true/false
  Default value:
    false

  Stretch the background image.

  Deprecated; use image-mode instead.

  ## style parameter (skin)

  Applies to:
    Grid
  Map
  Output
  Format:
    string

  Custom stylesheet used for the control. Changes made at runtime will usually not impact any existing text.

  For Map controls, this affects any maptext drawn, and changes to the style should appear on the next refresh.

  ## tab-background-color parameter (skin)

  See also:
    background-color parameter
  tab-text-color parameter
  tab-font-family, tab-font-size, tab-font-style parameters
  Applies to:
    Info
  Format:
    #rrggbb
    none
  Default value:
    none

  Affects the background color for tabs. The regular background-color is used for the content area.

  ## tab-font-family, tab-font-size, tab-font-style parameters (skin)

  See also:
    font-family parameter
  font-size parameter
  font-style parameter
  tab-text-color parameter
  tab-background-color parameter
  Applies to:
    Info

  Affects the font for tabs. The regular versions of these without the `tab-` prefix are used for the content area.

  ## tab-text-color parameter (skin)

  See also:
    text-color parameter
  tab-background-color parameter
  tab-font-family, tab-font-size, tab-font-style parameters
  Applies to:
    Info
  Format:
    #rrggbb
    none
  Default value:
    none

  Affects the text color for tabs. The regular text-color is used for the content area.

  ## tabs parameter (skin)

  See also:
    current-tab parameter
  id parameter
  multi-line parameter
  Applies to:
    Tab
  Format:
    string

  A comma-separated list of id values for the panes included as tabs in this control.

  When setting this value, you can put `+` in front of the list to add tabs to the existing control, without affecting current tabs. You can likewise use `-` in front of the list to remove tabs.

  Note: When using this with winset(), remember you will need to escape `+` as `%2B` via url_encode() or list2params().

  ## text parameter (skin)

  See also:
    font-family parameter
  font-size parameter
  font-style parameter
  text-wrap parameter
  Applies to:
    Button
    Input
    Label
  Format:
    string

  Text shown in this control. For Input controls this setting is only available at runtime.

  ## text-color parameter (skin)

  See also:
    background-color parameter
  font-family parameter
  font-size parameter
  font-style parameter
  Applies to:
    All
  Format:
    #rrggbb
    none

  The control's foreground text color.

  ## text-mode parameter (skin)

  See also:
    zoom parameter
  zoom-mode parameter
  Applies to:
    Map
  Format:
    true/false
  Default value:
    false

  Show text mode even if icons are available. Text mode will be used if no icons are present, regardless of this setting.

  ## text-wrap parameter (skin)

  See also:
    text parameter
  Applies to:
    Label
  Format:
    true/false
  Default value:
    false

  Wrap text that is too long for the width of the label.

  ## title parameter (skin)

  See also:
    name var (world)
  icon parameter
  Applies to:
    Main
  Format:
    string

  The title of this window or pane. For a window, the title will appear in the titlebar if present. For a pane, this will be displayed on the tab if this pane is in a Tab control.

  If this is the default window, world.name takes precedence over the window title.

  ## titlebar parameter (skin)

  See also:
    can-close parameter
  can-minimize parameter
  can-resize parameter
  icon parameter
  title parameter
  use-title parameter
  statusbar parameter
  is-fullscreen parameter
  name var (world)
  Applies to:
    Main (window only)
  Format:
    true/false
  Default value:
    true

  Show a titlebar for this window. This is also required for the close, minimize, and maximize buttons to appear.

  If `is-fullscreen` is true, `titlebar` is ignored, so this value represents the state of the window when `is-fullscreen` is turned off again.

  ## transparent-color parameter (skin)

  See also:
    alpha parameter
  Applies to:
    Main (window only)
  Format:
    #rrggbb
    none
  Default value:
    none

  A color that will be turned into transparency wherever it appears in this window. Overall, this method of transparency comes with many limitations, so it is considered deprecated.

  ## type parameter (skin)

  See also:
    id parameter
  parent parameter
  Applies to:
    All
    Macro
    Menu
  Format:
    string

  The type of this control. Read-only.

  ## use-title parameter (skin)

  See also:
    show-history parameter
  show-url parameter
  title parameter
  titlebar parameter
  Applies to:
    Browser
  Format:
    true/false
  Default value:
    false

  Use the browser's document title to override the title of the window or pane it appears in.

  ## value parameter (skin)

  See also:
    is-slider parameter
  dir parameter
  Applies to:
    Bar
  Format:
    number
  Default value:
    0

  The "fullness" of this bar/slider, as a percentage.

  ## view-size parameter (skin)

  See also:
    letterbox parameter
  zoom parameter
  zoom-mode parameter
  icon_size var (world)
  view var (world)
  view var (client)
  HUD / screen objects
  Applies to:
    Map (window only)
  Format:
    widthxheight

  The size, in pixels, of the map after `zoom` has been applied.

  For instance, if the client view has 10×10 tiles (this includes any extended tiles caused by HUD objects) and `world.icon_size` is 32x32, the map has a native size of 320×320 pixels. If the map has a zoom level of 2, then `view-size` will be 640x640.

  With a `zoom` value of 0, which is the default for most projects, the actual zoom level is automatically determined by the size of the map control, the map's native pixel size as explained above, and the value of the letterbox parameter.

  ## visited-color parameter (skin)

  See also:
    text-color parameter
  link-color parameter
  Applies to:
    Grid
    Output
  Format:
    #rrggbb
    none
  Default value:
    #0000ff

  The color used for visited links.

  ## width parameter (skin)

  See also:
    dir parameter
  is-slider parameter
  Applies to:
    Bar
  Format:
    number
  Default value:
    10

  Width, in pixels, of the bar or slider. A value of 0 uses all available width.

  ## zoom parameter (skin)

  See also:
    letterbox parameter
  view-size parameter
  zoom-mode parameter
  Applies to:
    Map
  Format:
    number
  Default value:
    0

  Zoom factor for icons on the map. 1 means to show the icons at their original size, 2 is 200%, 0.5 is 50%, and so on. A value of 0 stretches to fit available space.

  ## zoom-mode parameter (skin)

  See also:
    letterbox parameter
  view-size parameter
  zoom parameter
  Applies to:
    Map
  Posisble values:
    normal
    distort
    blur
  Default value:
    normal

  Controls the way the map is upscaled.

  normal
  Preserves a pixelated look, but does some blending between adjacent pixels when the zoom factor is not an integer. This is equivalent to upscaling by the next highest integer, then downscaling.
distort
  Uses nearest-neighbor sampling to upscale. This may look odd if the zoom factor is not an integer, since for instance some pixels might scale up to be 2 pixels wide, others 3 pixels wide. Some users prefer it anyway.
blur
  Uses bilinear sampling to upscale. This will cause a blurry appearance if the zoom factor is high, but it may be desired in some cases.

## Appendix

This section contains miscellaneous information that may apply to multiple vars or procs.

  Byondapi
  CSS attributes
  HTML colors
  Color space
  stddef.dm file

## Byondapi

See also:
  call_ext() proc

Byondapi is a set of exported functions from BYOND's core library that can be used by external libraries that you call via the `call_ext()` proc. The purpose is to make interfacing with native code easier, and to allow external access to BYOND's functionality. Before this existed, all external calls had to use text strings to pass data back and forth, which was inefficient for many uses and very limited.

To build your external library with Byondapi, you have to include the `byondapi.h` header file that's included in BYOND's distribution. When compiling in Windows, you'll also need to link with `byondapi.lib`; in Linux, your makefile should link with `byondcore.so` from BYOND's own `bin` directory.

### Simple BYOND types

For simplicity, BYOND defines some basic types and macros in `byondapi.h`. The one most relevant to you is `u4c`, which is an unsigned 4-byte integer. There's also `s4c` which is a signed integer, as well as simple 1-byte and 2-byte ints that use `1c` and `2c` (respectively) insteaed of the `4c` suffix.

### CByondValue struct

The main structure used to pass data back and forth is `CByondValue`. This mimics an internal structure in BYOND that holds values of all sorts: numbers, null, references to strings, references to objects and lists, and so on.

The exact functions used for interfacing with this structure are documented in `byondapi.h`.

The main tricky aspect of working with BYOND data is strings. If you need to get the contents of a string, you'll need to allocate memory for the character data and call `Byond_ToString()` to get a copy of the string. For converting character data to an internal string stored in CByondValue, you'll need to call `ByondValue_SetStr()`.

### Other function calls

There are many function calls available in Byondapi for interacting with the server. These include the ability to read and write vars, call procs, create lists, read and write from lists, and so on.

Most of these procs return boolean values: true if they succeed, false if not. In the event of a failure, you can call `Byond_LastError()` to get the error message.

In any functions that read data from lists or read string data—including `Byond_LastError()`—you need to allocate the required memory for a copy of the string or list items. These functions take a pointer to the buffer that will be filled, and a `u4c` pointer for the buffer size (in items for lists, in bytes for strings). If the return value is false and the length is set to zero, an error occurred. If the return value is false and the length is non-zero, the new length value is the required length of the array; the memory should be allocated and the function called again.

### Example:

    char *errmsg = NULL;
    u4c buflen = 0;
    while(!Byond_LastError(errmsg, &buflen)) {
        free(errmsg);
        errmsg = (char*)malloc(buflen);
        if(!errmsg) break;
    }
    ... // do someting with the error message
    free(errmsg);

The C++ wrappers have a better way of calling `Byond_LastError()` and other functions like it, where you don't need to worry about allocations.

### Reference counting

Objects in BYOND are reference-counted; when an object's count reaches 0 it gets garbage-collected. In Byondapi you can call `ByondValue_IncRef()` and `ByondValue_DecRef()` to increment or decrement the reference count, respectively.

Byondapi maintains its own internal reference count for any object, so you can't decref past the number of references Byondapi holds.

The results you get from calls to Byondapi functions, such as reading a var or getting a return value from a proc call, have already had their reference count increased. That means when you're done using the value, you need to clean it up with `ByondValue_DecRef()` or else you'll have a memory leak.

The value you return from a function called by `call_ext()` should have a reference.

The C++ wrappers take care of most of the reference counting issues for you (see below).

### Threads

BYOND servers handle proc execution and the management of data in a single thread. If your library tries to call any BYOND server functions in a different thread of its own, the call will block until the server thread can handle it.

The special function `Byond_ThreadSync()` will run a callback function on the main thread, avoiding the need to keep syncing over multiple Byondapi calls.

### C++ wrappers

If you want to use the handy C++ wrappers and classes, you can include `byondapi_cpp_wrappers.cpp` and `byondapi_cpp_wrappers.h` in your library.

The `ByondValue` class is a wrapper around `CByondValue` that handles a number of operations for you. You can redefine the `argv` argument of any `call_ext()` functions as an array of `ByondValue` instead of `CByondValue`, but the return value should stay a `CByondValue`.

### Example:

    #include <string>
    #include <byondapi.h>
    #include <byondapi_cpp_wrappers.h>
    #include <string>

    extern "C" BYOND_EXPORT CByondValue merge(int n, ByondValue v[])
    {
        ByondValue result;
        std::string merged, str;
        for(int i=0; i<n; i++) {
            v[i].ToString(str);
            if(str) merged += str;
        }
        result = merged.c_str();   // ByondValue's assignment operator takes care of everything
        return result;
    }

The external function calls like `ByondValue_CallProc()` have C++ wrappers that use the C calls internally, but if an error happens they'll call an error handler. The default error handler does nothing, but you can change it to a a different handler that accepts an error string.

If you define a `CatchingByondExceptions` variable inside of a `try` block, it will automatically change the error handler to one that throws a `ByondExtException`. This replaces the more cumbersome approach of checking if the return value is false and then calling `Byond_LastError()`.

## CSS attributes

DM-CSS is a subset of CSS, and only supports some kinds of selectors and attributes.

The following table lists all supported attributes, and whether they are supported in text output, maptext, and in other controls (labels/etc.) Other controls will often allow only one style for an entire unit of text. A checkbox in "Other" only indicates that some support exists in other controls, but it may vary by the type of control.

Attribute | Output | Maptext | Other | Notes
--- | --- | --- | --- | ---
color | ✔️ | ✔️ | ✔️ | Alpha colors may not be supported in some controls.
background | ✔️ | ✔️ | ✔️ | In most cases, only applies to the entire text body.
background-color | ✔️ | ✔️ |  |
background-image | ✔️ |  |  |
font | ✔️ | ✔️ | ✔️ |
font-family | ✔️ | ✔️ | ✔️ |
font-style | ✔️ | ✔️ | ✔️ |
font-weight | ✔️ | ✔️ | ✔️ |
font-size | ✔️ | ✔️ | ✔️ |
text-decoration | ✔️ | ✔️ | ✔️ | Limited to `underline, `overline, `line-through, `blink, and `none. Support for each of these may vary depending on where they are used.
text-align | ✔️ | ✔️ | ✔️ | `justify is supported in output and maptext.
vertical-align |  | ✔️ | ✔️ | Limited to `top, `middle, and `bottom.
text-indent | ✔️ | ✔️ |  |
margin-left | ✔️ | ✔️ | ✔️ |
margin-right | ✔️ | ✔️ | ✔️ |
margin-top |  |  | ✔️ |
margin-bottom |  |  | ✔️ |
margin | ✔️ | ✔️ | ✔️ |
width | ✔️ | ✔️ |  | Applies only to some elements such as images.
height | ✔️ | ✔️ |  | Applies only to some elements such as images.
line-height | ✔️ | ✔️ |  | Support in output control is limited; line heights less than 1 are not respected. Only unitless numbers, percentages, or em units are allowed.
white-space | ✔️ | ✔️ |  | `normal, `nowrap, `pre, `pre-wrap, `pre-line
text-overflow |  | ✔️ |  | `clip, `ellipsis, or quoted string; maptext defaults to empty string
text-shadow |  | ✔️ |  |
-dm-text-outline |  | ✔️ |  | Custom attribute: Adds an outline to text. Values are in the form: `width color style. The style is either blank, or any combination of the `sharp and `square keywords (see Outline filter

).

These pseudo-classes are allowed in some contexts, but they can only change the text color.

Psuedo-class | Output | Maptext | Other | Notes
--- | --- | --- | --- | ---
:link | ✔️ | ✔️ | ✔️ |
:visited | ✔️ |  |  |
:active |  |  |  | Currently not used, but future support is planned.
:hover |  | ✔️ |  |

## HTML colors

See also:
  rgb proc

Text colors may be specified by name or RGB value. The RGB color format uses hexadecimal numbers, with 2 hex digits each for red, green, and blue. These range from 0 (00 in hex) to 255 (FF in hex). In certain situations BYOND will also honor a fourth pair of digits for alpha.

    #rrggbb
    #rrggbbaa

It is also possible to use 4 bit values by using only one hex digit per color. The full 8 bit color is produced by repeating each digit. For example, `#F00` (red) is the same as `#FF0000`.

The named colors supported by BYOND, and their corresponding RGB values, are listed in the following table:

black | #000000 |
silver | #C0C0C0 |
gray or grey | #808080 |
white | #FFFFFF |
maroon | #800000 |
red | #FF0000 |
purple | #800080 |
fuchsia or magenta | #FF00FF |
green | #00C000 |
lime | #00FF00 |
olive or gold | #808000 |
yellow | #FFFF00 |
navy | #000080 |
blue | #0000FF |
teal | #008080 |
aqua or cyan | #00FFFF |

## Color space

See also:
  rgb proc

  rgb2num proc
  gradient proc
  animate proc
  Color gradient
  Color matrix filter

  There are different ways of interpreting color besides RGB. Several parts of BYOND are capable of using other color spaces.

  ### COLORSPACE_RGB

  The default color space is RGB, where each color is split into red, green, and blue components, as well as an optional alpha. All of these components range from 0 to 255.

  The color yellow for instance is `rgb(255,255,0)` which is red and green mixed together at their maximum brightness, but no blue component.

  ### COLORSPACE_HSV

  HSV stands for hue, saturation, and value.

  - Hue ranges from 0 to 360 on a color wheel, where 0 is red, 60 is yellow, 120 is green, and so on as seen in the image.
  - Saturation is how colorful this color is; it ranges from 0 which means a shade of gray, to 100 which is fully colored.
  - Value is the brightness of the biggest red, green, or blue component, and ranges from 0 to 100. A value of 0 is always black.

  All pure hues such as red (hue=0) have a saturation of 100 and a value of 100. As saturation decreases, the colors turns whiter. Lower values mean darker colors and darker shades of gray.

  In HSV, saturation is less meaningful as value gets closer to 0. Black of course always has a value of 0. With 10 as the value, saturation=100 gives you a very dark color whereas saturation=0 is a 10% shade of gray.

  ### COLORSPACE_HSL

  HSL is a little more intuitive than HSV. Here, value is replaced by luminance, which again ranges from 0 to 100. Luminance is the average of the minimum and maximum values of the red, green, and blue components.

  Black has a luminance of 0; white has a luminance of 100. Pure hues all have a saturation of 100 and luminance of 50. As saturation decreases, the color will approach a grayscale shade of L%.

  Saturation is less meaningful the closer luminance is to 0 or 100. At a luminance of 100, the saturation is totally irrelevant. At 90, high saturation will get you a very light shade of the hue but that isn't very far off from a 90% shade of gray.

  ### COLORSPACE_HCY

  HCY stands for hue, chroma, and the Y is for grayscale luminance. (Again chroma and Y range from 0 to 100.) This color space is based around the apparent brightness of each color according to a rough approximation of human vision.

  Chroma is similar to saturation in that it determines how far from grayscale the color is. As chroma decreases toward 0, the color approaches a grayscale shade of Y%. What's different about HCY color from HSV or HSL is that at chroma=0 and chroma=100 the colors should appear equally bright. Pure red, therefore, has a hue of 0, a chroma of 100, and a Y luminance of only 29.9—roughly what red would look like in black & white with all of the color leached out.

  ## stddef.dm file

  This is a special file that's included in all projects when you compile. It contains various constants, definitions of some built-in datums, and so on.

  You can see the contents of this file by creating a new file in Dream Maker called `stddef.dm. It will automatically be filled with the standard definitions.

  The contents of `stddef.dm may change with new BYOND versions. However an eye is always kept on backwards-compatibility.