Free Hero Mesh

class.doc at [382666e88a]
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.

File class.doc artifact 9a7008d58d part of check-in 382666e88a


This document describes how class definitions are working.


=== Syntax ===

The following kinds of tokens are available:

* Open and closing delimiters: These are ( and ) and no spaces are
required around it. They are used for grouping in many places.

* Plain name: A plain word with no sigil. The set of valid plain names is
fixed, and they are all explained in the rest of this document.

* Number: Can be in decimal, or in hexadecimal with a 0x prefix, or in
octal with a 0o prefix. The "x" or "o" must be in lowercase, but the
hexadecimal digits can be uppercase or lowercase. Decimal numbers may be
optionally preceded by a - or + sign.

* Qualified name: A name with a sigil prefix. See below for the list of
possible sigils and their meanings. In all cases except key names, you can
define your own qualified names.

* String: A string literal with quotation marks around it. A string may
contain escapes, which use a backslash followed by whatever text is being
escaped; see below section for the list of string escapes.

Names can contain the following characters:
  0123456789-+_?.*/
  ABCDEFGHIJKLMNOPQRSTUVWXYZ
  abcdefghijklmnopqrstuvwxyz

Plain and qualified names may also optionally be prefixed by an equal
sign and/or a comma; their purpose is explained later. If you have both,
the equal sign comes first and then the comma.

Name sigils are:
  $  Class
  @  Global variable
  '  Key code
  :  Label
  %  Local variable
  #  User message
  !  User sound
  &  User function
  ^  User flag

Comments are also allowed; these start with a semicolon (outside of a
string literal) and end at the next line break.


=== Escapes ===

\0
  Makes further text black (default).

\1
  Makes further text blue.

\2
  Makes further text green.

\3
  Makes further text cyan.

\4
  Makes further text red.

\5
  Makes further text purple.

\6
  Makes further text yellow.

\7
  Makes further text white.

\b
  Draws a horizontal rule.

\c
  Makes further text centred.

\dDATA\
  Includes inline data in the string. The data is not displayed, but
  can be read by class codes, or used in level titles to provide data
  and delimiters for the auto-generated table of contents. Data items
  are separated by semicolons; each item can be a underscore to mean a
  mark, a number (decimal integers only), or a class name with $ at front.
  (Not fully implemented yet)

\iCLASS:NUMBER\
  Displays a picture. Give the class name (without $ at first) and a
  colon and the zero-based index number of the picture in that class.
  This is then followed by another backslash. The picture may span
  multiple lines; it will automatically move the text to make room.

\l
  Makes further text left aligned (default).

\n
  Line break.

\qX
  Make a "quiz button". Any string containing this command is a "quiz
  string", and there are special behaviours involving quiz strings. The
  X should be replaced by any digit or uppercase letter; that will be
  displayed, and if clicked, it represents that key code.

\xXX
  Hexadecimal escape, where XX is a hexadecimal number from 01 to FF,
  and displays a graphic character with the given PC character code.

\"
  Literal quotation mark.

\\
  Literal backslash.

\Txxxxxx;
  Only valid when using multibyte character encoding. Follow \T by six or
  more hex digits and then a semicolon; this is like the "&T code" but is
  using a backslash instead of a ampersand. (This feature is not fully
  implemented yet.)


=== Preprocessor ===

Free Hero Mesh includes a macro preprocessor, which you may use if wanted.
All preprocessor commands are in braces; that constitutes a preprocessor
token, which may contain other tokens as arguments.

Other preprocessor tokens include the macro separator token, which is
written as a vertical bar, and a macro argument token, which is one or
more backslashes followed by a number from 1 to 255.

For user-defined macros, one argument can be either many tokens inside of
parentheses (the parentheses are part of the argument), a single token, or
a macro separator token (omitted from the expansion) followed by any number
of further tokens to make up the last argument.

Built-in macros include:

{+ <numbers...>}
  Addition. The result is 0 if no arguments are specified.

{- <number> <number>}
  Subtraction.

{* <numbers...>}
  Multiplication. The result is 1 if no arguments are specified.

{/ <number> <number>}
  Division.

{append <string> <tokens...>}
  This works like {define} but adds to an existing definition rather than
  replacing the definition.

{band <numbers...>}
  Bitwise AND. The result is -1 if no arguments are specified.

{bit <numbers...>}
  The numbers are in range 0 to 31 and denote bit positions; the result is
  a number with only those bits set. If there are any numbers out of range
  0 to 31 then the numbers out of range are ignored.

{bnot <number>}
  Bitwise complement.

{bor <numbers...>}
  Bitwise OR. The result is 0 if no arguments are specified.

{bxor <numbers...>}
  Bitwise XOR. The result is 0 if no arguments are specified.

{call <string> <tokens...>}
  Call a macro dynamically.

{cat <tokens...>}
  Makes a string by concatenating several tokens together. Sigils are
  omitted, macro separator tokens are removed, and numbers are converted
  to decimal. Strings are also allowed.

{define <string> <tokens...>}
  Define a macro. The inner tokens are not expanded yet; they will be
  expanded during each use. A macro argument token with a single backslash
  expands to the argument in that position, while a macro argument tokens
  with multiple tokens becomes the token with one less backslash. It is
  permitted to redefine existing macros as well as new ones.

{edit <string> <token>}
  Edit a macro. This changes the first token of the definition of the macro
  (which must not be another macro) to the specified token. The token is
  expanded, and must be a single token once it is expanded; that is what it
  will be replaced with. There is a variant with a number in place of a
  string; this will replace the first token of the argument of the macro
  which is currently being expanded (or the entire token if it starts with
  an opening delimiter).

{include <string>}
  Include text from another file into this one. You cannot use {include}
  inside of another macro or in a macro argument. The file must be in the
  current directory, and its name must contain only letters, digits, dot,
  underscore, and minus signs, and must start with a letter or digit. If
  it is a composite puzzle set, then the name must end with ".include",
  and is looked for first inside of the composite puzzle set; if it is not
  found there then it is looked for in the current directory.

{make <mode> <arg>}
  Make a synthetic token; see the below section about synthetic tokens for
  details. The second argument can be a number, or a direction or key name
  which is treated as a number, or a string. In most cases, a number will
  be converted to a string with its unsigned decimal representation.

{mod <number> <number>}
  Modulo.

{version <number>}
  Expands into nothing. The number must be zero, otherwise it is an error.
  Future versions of Free Hero Mesh may change this.

All arithmetic/bitwise macros also allow their arguments to be directions
and keys, in which case they are treated as the corresponding numbers.

It is possible to implement a tag system in this preprocessor, which makes
it Turing complete. For example:

  {define "skip" {call \2}}
  {define "1" {skip \1|"3"|"3"|"2"|"1"|"H"}}
  {define "2" {skip \1|"3"|"3"|"1"}}
  {define "3" {skip \1|"3"|"3"}}
  {define "H" \1}
  {call "2"|"1"|"1"}

Note: Macro names are entirely independent from token names.


=== Synthetic tokens ===

The possible modes of synthetic tokens are:

 ":"    A label with the specified name.
 "=:"   Go to a label with a specified name.
 ",:"   Subroutine call a label with a specified name.
 "@"    A global variable.
 "=@"   Write a global variable.
 "%"    A local variable.
 "=%"   Write a local variable.
 "#"    A user-defined message.
 "$"    A class.
 "&"    A user-defined function.
 "^"    A user flag (read self, or definition).
 "=^"   A user flag (write self).
 ",^"   A user flag (read object).
 "=,^"  A user flag (write object).
 "'"    A key token; either by number or by name.
 "D"    A direction; only the low 4-bits are used.
 "+"    A number interpreted as decimal.
 "=+"   A number interpreted as binary.
 ",+"   A number interpreted as hexadecimal.
 "=,+"  A number interpreted as octal.
 "C"    A string with a single character of the specified code.
 ",C"   A string with a quiz button of the character with the code.
 "A"    The ASCII code of the first character of the string.

Note that as the argument, you can use {cat} to convert other tokens
to strings if needed.


=== Global definitions ===

These are the global definitions in the class definition file. (All of
these definitions are optional.)

(Animate <limit>)
  Set the limit for logical animations, from 1 to 255. The default is 32.

(Background <number> [<number>])
  Set the background colour, from 0 to 255. The default value is 1. You
  can optionally specify a second number, which is the background colour
  for the inventory; if not specified, uses the same colour for both.

(CodePage <number>)
  Define the code page, from 1 to 8388607. If not specified, then the
  default code page is used.

(Connection <string>)
  Set options for connected movement. The string can include any
  combination of the below letters:
  "t" = Use two HIT/HITBY passes, skipping shove/sharp for first pass.
  "w" = Use the total weight of the group instead of each one separately.

(Control <definitions...>)
  Define the control class. The format is the same like other class
  definitions, except that Image and Abstract are not allowed. An
  object of this class is automatically created when initializing the
  level, at X and Y coordinates both zero, and cannot otherwise be
  created, destroyed, or moved. It still receives broadcast messages
  normally, and can also be addressed specifically.

(CollisionLayers <userflags...>)
  Define user flags as CollisionLayers bits; the first defined flag is
  bit0. Up to 8 flags can be defined in this way.

(Density <numbers...>)
  Define the default Density settings for classes that use the collision
  layers. Each number must be in range 1 to 255, and there cannot be more
  than eight density numbers defined. Their order is the same as the order
  of the user flags in the (CollisionLayers) block.

(InputXY <options...>)
  Enables coordinate input. Currently there are no options, so the options
  must be left blank. See the documentation about the CLICK message for
  more details about coordinate input.

(LevelTable <definitions...>)
  Define the level table. See the section about level table definition
  for details. Can only occur once.

(Misc4 <userflags...>)
  Define user flags as Misc4 bits; the first defined flag is bit0. Up to
  32 flags can be defined in this way.

(Misc5 <userflags...>)
  Define user flags as Misc5 bits; the first defined flag is bit0. Up to
  32 flags can be defined in this way.

(Misc6 <userflags...>)
  Define user flags as Misc6 bits; the first defined flag is bit0. Up to
  32 flags can be defined in this way.

(Misc7 <userflags...>)
  Define user flags as Misc7 bits; the first defined flag is bit0. Up to
  32 flags can be defined in this way.

(Order <orders...>)
  See the section below about order of execution. Normally, order of
  execution (for broadcasts and some other things) is in the reverse order
  of creation; the (Order) block allows you to override this order.

(Synchronize <slot> <length> <speed>)
  Define an animation slot for synchronized animation. The slot number can
  be 0 to 7, the length is the number of images in the sequence, and the
  speed is the number of centiseconds between frames.

(Volume <number>)
  Define the maximum allowed volume for an object to move diagonally
  between two other objects. The default value is 10000.

($<name> <definitions...>)
  Define a class. See the section about class definitions for details.

(@<name> <value>)
  Define a global variable and its initial value.

(@<name> Array <rows> <columns>)
  Define a global variable whose value is a reference to a new array, with
  the specified dimensions. The maximum number of rows is 64, and the
  maximum number of columns is 1024, and the maximum number of cells in
  all arrays in total is 65534. All elements are initialized to zero when
  the level starts.

(<message> <code...>)
  Defines a default message code for all classes which do not specify
  their own code for this message. (It is recommended to not use this
  block, and to use subclassing instead.)

(&<name> <code...>)
  Define a user-defined function. User-defined functions may take any
  number of inputs from the stack and leave any number of outputs on the
  stack, but may not access user-defined local variables. (It may still
  access standard local variables, and all global variables, though.)


=== Class definitions ===

Within a class definition, the following definitions can be used. See also
the section about variables; many of these definitions are used to specify
the initial value for variables of objects of this class.

Outside of code blocks, named constants are not normally interchangeable
with the numbers having the same value.

<class>
  Inherit the specified class, which must have been previously declared as
  an abstract class. Flags and message codes are inherited unless they are
  overridden. Multiple inheritance is not allowed. If inheritance is used,
  it must be specified before any blocks with program instructions, and
  any user-defined variables defined in the superclass are not accessible
  by the code specific to this class; you can define another variable with
  the same name but it will be a new variable with the same name.

<userflag>
  Set a user flag bit in the definition of Misc4, Misc5, Misc6, Misc7, or
  CollisionLayers of this class. You must previously define this user flag
  as a global definition.

Abstract
  Disallows creating objects of this class, but allows other classes to
  subclass this one. The (Image), (DefaultImage), (Help), and (EditorHelp)
  blocks are not allowed in abstract classes.

(Arrivals InPlace)
  This is an abbreviation for (Arrivals 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
  0 0 0 0 0 0 0 0).

(Arrivals <numbers...>)
  Define the Arrivals variable for this class. This is twenty-five numbers
  each of which is either zero or one. They are meant to be on five lines
  of five numbers each, making a 5x5 matrix, where the centre means this
  object's location.

(Bishop <code...>)
  Same as four key dispatch blocks: 'PGUP, 'PGDN, 'HOME, and 'END; the
  corresponding direction will be pushed to the stack before the code
  will be executed.

Bizarro
  Means that objects of this class created using the Create instruction
  will be created in the bizarro world by default. (This has no effect on
  objects placed in the level editor.)

(Climb <number>)
  Define the Climb variable for this class.

(CollisionLayers <numbers...>)
  Define the CollisionLayers variable for this class. The format is the
  same as for Misc4 (see below), but only the low 8-bits are usable.

Compatible
  Sets the Compatible flag for this class. This changes some features for
  compatibility with Hero Mesh, and would not normally be used for new
  puzzle sets made with Free Hero Mesh.

,Compatible
  Sets the Compatible flag for this class, but removes the restriction of
  some variables limited to 16-bits.

Connection
  Sets the Connection flag for this class.

Crush
  Sets the Crush flag for this class.

(DefaultImage <list...>)
  Each entry is either a number of an image in this class, or two
  numbers in parentheses giving a range of images, or () to indicate
  that there are no default images. This specifies which images can
  be used in objects of this class which are initially present on
  the level (placed in the editor). If () is used, then this class
  is not available in the editor. If there is no (DefaultImage) block,
  all images are available. The (Image) block must come before this one.
  The list can also contain the token "mod" followed by a positive number;
  in this case, it will also add any images whose numbers are that many
  more than the ones already specified and will repeat; for example, if
  you write "(DefaultImage 1 mod 5)" then images 1, 6, 11, 16, 21, etc
  are added to the list of default images.

(Density <number>)
  Define the Density variable for this class. If you want the Density to
  be different in the editor, specify the value to use in the editor here,
  and then change the Density value in the INIT block.

(Departures InPlace)
  This is an abbreviation for (Departures 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
  0 0 0 0 0 0 0 0 0).

(Departures <numbers...>)
  Define the Departures variable for this class. The format is the same as
  for the Arrivals variable; see above.

(EditorHelp <strings...>)
  A help message to display in the level editor; normally, this would
  explain what values are expected for Misc1, Misc2, Misc3, and Dir.
  Each string is one line of text.

(Hard <number>)
  Define the hardness of this object on all four sides.

(Hard <pairs...>)
  Define the hardness per direction. Each pair is in parentheses, and is
  a direction (E, N, W, or S) followed by a 16-bit number. If any
  direction is not specified, then the hardness is zero in that direction.

(Height <number>)
  Define the Height variable for this class.

(Help <strings...>)
  A help message for the game player, which would normally explain what
  this object does. Each string is one line of text.

(Help Misc1)
  Similar to (Help) but tells it to display a level string referenced
  by the Misc1 of this object.

(Image <strings...>)
  Specify strings with the names of images. The first string is the
  name of the image numbered 0, next for the image numbered 1, etc.

Input
  Set the Input flag for this class. This causes it to receive a KEY
  message during the input phase of each turn.

Invisible
  Set the Invisible flag for this class.

(Misc4 <numbers...>)
  Specify any combination of numbers and/or bit constants. Defines the
  Misc4 variable of this class to be the bitwise OR of the listed numbers.
  Although this variable may have any value at run time, the definition in
  a class is limited to numbers.

(Misc5 <numbers...>)
  Define the Misc5 variable for this class; see Misc4 above for details.

(Misc6 <numbers...>)
  Define the Misc6 variable for this class; see Misc4 above for details.

(Misc7 <numbers...>)
  Define the Misc7 variable for this class; see Misc4 above for details.

(Others <code...>)
  This block is only allowed in classes with the Input flag. If no key
  dispatch block matches and it is not a key which is implicitly ignored,
  and Arg3 is both zero, then it will execute this block instead.

Player
  Set the Player flag for this class.

(Queen <code...>)
  Combines the effects of the (Rook) and (Bishop) blocks.

Quiz
  If specified, the internal variables of objects of this class cannot
  normally be examined by the player. However, the player can override
  this definition at run time; you cannot rely on it. Class codes cannot
  read the value of this flag.

(Rook <code...>)
  Same as four key dispatch blocks: 'UP, 'LEFT, 'DOWN, and 'RIGHT; the
  corresponding direction will be pushed to the stack before the code
  will be executed.

(Shape <number>)
  Define the shape of this object on all four sides, where 0 means flat,
  1 means slanted to left, 2 means slanted to right, and 3 means slanted
  both left and right.

(Shape <pairs...>)
  Define the shape of this object per side, similar to the (Hard) block.

(Sharp <number>)
  Define the sharpness of this object on all four sides.

(Sharp <pairs...>)
  Define sharpness per direction, as for the (Hard) block.

Shovable
  Set the Shovable variable for this class to 0x55 (meaning it is shovable
  in all four directions).

(Shovable <dir...>)
  Set this object to be shovable in the specified directions, which can be
  any absolute direction.

(Shovable <number>)
  Set the Shovable variable to the specified 8-bit number. (You cannot set
  the initial value of any other bits; they are always clear.)

Stealthy
  Set the Stealthy flag for this class.

(Strength <number>)
  Define the Strength variable for this class.

(SUBS <code...>)
  Make a code block with no entry point. This isn't very useful, but it
  is provided for compatibility with Hero Mesh.

(Temperature <number>)
  Define the Temperature variable for this class.

VisualOnly
  Set the VisualOnly flag for this class.

(Volume <number>)
  Define the Volume variable for this class.

(Weight <number>)
  Define the Weight variable for this class.

(<label> <code...>)
  Make a code block whose entry point is the specified label.

(<message> <code...>)
  Make a code block whose entry point is the specified message.

(<key> <code...>)
  Add a code block for key dispatch. This cannot be combined with a KEY
  message in the same class; it causes the KEY message to be automatically
  defined for this class. If this class has the Input flag and the first
  instruction is not IgnoreKey, then it is entered into an internal list
  of key codes to not ignore. Otherwise, the automatic KEY messages (for
  all classes with them, not only this one) will have the effect of the
  IgnoreKey instruction when an unrecognized key is specified. You can
  still call the KEY message by yourself; Arg1 is the key code, and if
  Arg3 is true then the implicit IgnoreKey will not be executed (although
  any explicit IgnoreKey will still work).


=== Data types ===

The following data types are available:

* Number: A 32-bit integer. Whether it is treated as signed or unsigned
depends on the context. In some cases, it is used as bit field data.

* Class: A class name with a $ prefix.

* Message: A message name. User-defined message names have a # prefix;
standard message names have no prefix.

* Object: A reference to an object. There are no literals of this type.

* String: A string in quotation marks. There are no string manipulation
functions; the only thing that can be done with a string is to display it,
or to compare if one string matches another.

* Sound: A named sound effect. Values of this type cannot be compared with
anything, even other values of the same type. A sound can be either a
built-in sound or user sound.

* Mark: There is only one value of this type; it is used to delimit lists
of values on the stack.

* Array: A reference to an array. You cannot allocate arrays at run time;
the available array memory is fixed at compile time, subject to the global
array definitions.

* Link: A link to another point in the code of some class or global. Where
a link is expected, you can also specify a message to mean that message
block for the Self object (this is not quite the same as sending that
message to itself, though).

Some things are not their own types, and are other uses of numbers:

* Null: A null class or null object is represented as zero.

* Boolean: When a boolean is required as input to some instruction, zero
is false, and most other values (of any type) are true, except for sounds
which cannot be used as booleans at all. When an instruction produces a
boolean value as output, true is one and false is zero.

* Key: A key code for input (not necessarily the same as the physical key
with that label). See the list in the below section.

* Direction: Can be absolute or relative. For absolute directions, zero is
east, and increasing numbers go counterclockwise 45 degrees each, up to
seven for southeast. Relative directions start at eight for forward and
otherwise work similarly (increasing numbers go counterclockwise).


=== Constants ===

The following constants are available. Some of them are numeric constants
and using them pushes numbers to the stack, and they are interchangeable
with the corresponding numbers where instructions are expected.

Absolute directions:
  E = 0
  NE = 1
  N = 2
  NW = 3
  W = 4
  SW = 5
  S = 6
  SE = 7

Relative directions:
  F = 8
  LF = 9
  L = 10
  LB = 11
  B = 12
  RB = 13
  R = 14
  RF = 15

Bit constants:
  bit0 to bit31 = numbers with a single bit set

Animation constants:
  STOP = 0
  ONCE = 1
  LOOP = 2
  OSC = 8
  OSCLOOP = 10

Standard messages:
  ARRIVED
  BEGIN_TURN
  BLOCKED
  CLICK
  COLLIDE
  COLLIDEBY
  COLLIDING
  CONFLICT
  CONNECT
  CREATE
  CREATED
  DEPARTED
  DESTROY
  DESTROYED
  END_TURN
  FLOATED
  HIT
  HITBY
  INIT
  JUMPED
  KEY
  LASTIMAGE
  MOVED
  MOVING
  NEXTWARP
  PLAYERMOVING
  POSTINIT
  SUNK
  WARPED
  XCREATE

Input constants:
  'BACK = 8
  'TAB = 9
  'CENTER = 12
  'ENTER = 13
  'SHIFT = 16
  'CTRL = 17
  'BREAK = 19
  'CAPSLOCK = 20
  'SPACE = 32
  'PGUP = 33
  'PGDN = 34
  'END = 35
  'HOME = 36
  'LEFT = 37
  'UP = 38
  'RIGHT = 39
  'DOWN = 40
  'DELETE = 46
  '0 = 48
  '1 = 49
  '2 = 50
  '3 = 51
  '4 = 52
  '5 = 53
  '6 = 54
  '7 = 55
  '8 = 56
  '9 = 57
  'A = 65
  'B = 66
  'C = 67
  'D = 68
  'E = 69
  'F = 70
  'G = 71
  'H = 72
  'I = 73
  'J = 74
  'K = 75
  'L = 76
  'M = 77
  'N = 78
  'O = 79
  'P = 80
  'Q = 81
  'R = 82
  'S = 83
  'T = 84
  'U = 85
  'V = 86
  'W = 87
  'X = 88
  'Y = 89
  'Z = 90
  'NUMPAD0 = 96
  'NUMPAD1 = 97
  'NUMPAD2 = 98
  'NUMPAD3 = 99
  'NUMPAD4 = 100
  'NUMPAD5 = 101
  'NUMPAD6 = 102
  'NUMPAD7 = 103
  'NUMPAD8 = 104
  'NUMPAD9 = 105
  'MULTIPLY = 106
  'DECIMAL = 110
  'DIVIDE = 111
  'F9 = 120
  'F10 = 121
  'F11 = 122
  'F12 = 123
  'NUMLOCK = 144
  'SCRLOCK = 145
  'SEMICOLON = 186
  'EQUALS = 187
  'COMMA = 188
  'MINUS = 189
  'PERIOD = 190
  'SLASH = 191
  'TILDE = 192
  'OBRACKET = 219
  'BACKSLASH = 220
  'CBRACKET = 221
  'QUOTE = 222

Standard sound constants:
  ANHH
  BANG
  BEDOINGNG
  BEEDEEP
  BOOOM
  BOUNCE
  BRRREEET
  BRRRT
  BUZZER
  BWEEP
  CHEEP
  CHYEW
  DEEP_POP
  DINK
  DOOR
  DRLRLRINK
  DYUPE
  FAROUT
  FFFFTT
  FROG
  GLASS
  GLISSANT
  HAWK
  HEARTBEAT
  JAYAYAYNG
  KEWEL
  KLECK
  KLINKK
  LOCK
  OLDPHONE
  POUR
  POWER
  RATCHET1
  RATCHET2
  RATTLE
  SMALL_POP
  SPLASH
  STEAM
  TAHTASHH
  THMP_thmp
  THWIT
  TICK
  UH_OH
  UNCORK
  UNHH
  VACUUM
  WAHOO
  WHACK
  YEEHAW

Note: Some messages can also be used as sounds. Some sounds might later be
changed to messages (they can still be used as sounds, although a sound
file with that name is not guaranteed to be available).


=== Variables ===

These are the variables which each object has. Some are marked [ro] below
because they are read-only. In all cases, you can put , in front to access
a different object rather than self and = in front to write that variable
(unless it is read-only). You can also access some of these variables also
on classes instead of objects; these are always read-only. The variables
which are available on classes too are marked [c] below.

Some variables list one type, and some list two. If there are two types,
"int16/int32" means any number written to it is truncated to 16-bits in
compatible mode, but the full value is retained in incompatible mode. The
16-bit number is treated as unsigned, so it is zero-extended to 32-bits.
The notation "int16/any" means the same thing, except that the variable
is not limited to numbers; non-numbers are never truncated.

A few variables require a direction on the top of the stack, above the
value if you are writing. These are marked [d] below. These are really
four variables, one for each direction (not counting diagonals).

If you use the comma prefix to refer to another object, the object to
refer to is always below the direction and/or value to write on the stack
(if there are any such values).

In incompatible mode, many "physics" variables are treated as signed.

Most of these variables are state-changing; writing to them is not allowed
on the same turn as IgnoreKey. Exceptions are Distance and KeyCleared.

%xyz : any
  A user-defined variable. This variable cannot be accessed on other
  objects other than this one. You can give it any name with a percentage
  sign at first. User variables are initialized to zero, and need not be
  declared anywhere.

^xyz : bool [c]
  A user-defined flag, which is one bit in Misc4, Misc5, Misc6, Misc7, or
  CollisionLayers. If it is CollisionLayers, then it is read-only; other
  flags are read/write. User defined flags must be defined first (globally)
  before they can be used. Unlike user-defined variables, you can access
  user-defined flags on any object.

Arrivals : int32
  Only the low 25-bits are used. Each bit which is set indicates that it
  cares if other objects arrive around it at that relative location, where
  bit0 is two paces northeast, bit1 is to the west of that, etc, and then
  bit4 two paces northwest of this object, and bit5 starts on the next
  row to the south, etc, and bit12 is this object's location.

Arrived : int32
  When an object arrives in the location where this object cares about
  arrivals (according to the Arrivals variable), the corresponding bits
  are set in the Arrived variable. If this value is nonzero, then it will
  also send a ARRIVED message during the trigger phase. You can write all
  bits of this variable, but only the low 25-bits can be read back; if you
  write a nonzero number with only the high bits set, then it will still
  be triggered but will be read back as zero.

Bizarro : bool [c]
  Set if this object is in the bizarro world. Objects in the bizarro world
  are invisible and intangible, and mostly do not interact with other
  objects. However, they can still be accessed/affected by anything that
  references it directly, it is still possible to broadcast messages to
  them, and they are still affected by most turn-based actions (although
  not the compatible part of the trigger phase). Objects in the bizarro
  world are effectively stealthy as well, so do not cause messages due to
  being moved, created, or destroyed. In some circumstances, attempting
  to change this flag will have no effect.

Busy : bool
  If any object has either the Busy or UserSignal variable set, then the
  player input is blocked, and the turn may continue. Use this to control
  the timing of effects in LASTIMAGE blocks.

Class : class [ro]
  The class of this object.

Climb : int16/int32 [c]
  In order for this object to move, this object's Climb must equal or
  exceed the Height of all objects at the target location, otherwise it
  is prevented from moving.

CollisionLayers : int8 [c] [ro]
  Any set bit means no other object with that same bit set in this field
  may exist at the same location. (There is no effect in bizarro world.)

Compatible : bool [c] [ro]
  The compatibility flag. Class definitions imported from EKS Hero Mesh
  always set this flag; in new puzzle sets it is normally not set.

Connection : bool [c]
  If this flag is set, then moving this object by the use of the Move
  instruction will try to move an entire connected group of objects,
  instead of only one. This changes some of the behaviour and will
  cause additional messages to be sent, too. Deferred movement is not
  possible if this flag is set.

Crush : bool [c]
  If this flag is set, then objects that try to move into it will destroy
  it if it is unable to shove it out of the way. Unlike sharpness checking,
  crushing is checked after shoving instead of before. Crushing is never
  possible if warping occurs.

Density : int16/int32 [c]
  Determines the order that objects are stacked within each cell. When an
  object is moved or created, its Density is compared with the Density of
  the objects already present at that location, in order to insert it into
  the stack of objects there, at the top, bottom, or middle, where lesser
  numbers mean closer to the top, and greater numbers are deeper. If there
  are multiple objects of the same Density, the new one goes above others
  with the same Density. If you change the value of this variable, it will
  automatically float/sink the object if necessary in order to fit it into
  the correct stacking order, sending FLOATED and SUNK messages.

Departed : int32
  This is like Arrived but triggered for departures (as specified by the
  Departures variable) rather than arrivals.

Departures : int32
  This is like Arrivals but for positions where it is triggered by objects
  leaving those locations rather than arriving there.

Destroyed : bool [ro]
  It is set if this object has been successfully destroyed (but not yet
  deleted from memory). You must use the Destroy or Assassinate command
  in order to set this flag; you cannot set it by yourself. Unlike all
  other variables, you can access this variable even for an object that
  does not exist; it returns 1 in that case.

Dir : int3
  The current direction. When it moves (without teleportation), it will
  automatically be set to the direction it moved. You can also set this
  by yourself. Relative directions are relative to this direction. If you
  set this by yourself to a relative direction, then it will automatically
  be set to an absolute direction, based on the previous value.

Distance : int16
  When an object moves (including due to teleportation), the Manhattan
  distance of the movement is added to the Distance variable. This is
  reset to zero at the beginning of each turn.

Done : bool [c]
  This flag is used to determine whether or not to find the object in a
  for/next loop. It automatically clears all Done flags at the beginning
  of each turn and at the entry of each for/next loop, so usually you do
  not need to set this by yourself.

Hard : int16 [c] [d]
  See Sharp.

Height : int16/int32 [c]
  Used to block the movement of other objects; see Climb for details. In
  order for HIT and HITBY messages to work, Height must be positive.

Image : int16
  The index number of the picture to display. The (Image) block in the
  class definition specifies which picture to display for each index
  number, where the first picture is zero. The actual picture being
  displayed may differ if an animation is in progress, and no picture
  will be displayed at all if the Invisible flag is set, although this
  variable still remains available in such circumstances.

Inertia : int16/int32
  This determines how much "left over" Strength an object has to move.
  Normally, when an object tries to move, its Inertia is set to the
  Strength of the object which is moving, and then the Weight of the
  objects moved are deducted from Inertia. Normally you do not need to
  set this value by yourself nor to read it, but you might use it in the
  HIT or HITBY messages to affect how much it can push, or to check the
  Inertia after the movement is complete to see what is left over.

Invisible : bool [c]
  If set, then this object is not displayed on the screen. However, it
  is still present in the level and does everything else that a visible
  object will do.

KeyCleared : bool
  The game engine does nothing with this except to automatically clear it
  between turns, so that you need not do by yourself.

Misc1 : int16/any
  The game engine does not use this variable; use it for your own use. The
  Misc1-Misc3 variables can be defined for each individual object in the
  level editor; normally they are zero. In the level editor, they can only
  be defined as a 16-bit number, a class, a message, or a string; at run
  time they can be set to any value.

Misc2 : int16/any
  The game engine does not use this variable; use it for your own use.

Misc3 : int16/any
  The game engine does not use this variable; use it for your own use.

Misc4 : int16/any [c]
  The game engine does not use this variable; use it for your own use.

Misc5 : int16/any [c]
  The game engine does not use this variable; use it for your own use.

Misc6 : int16/any [c]
  The game engine does not use this variable; use it for your own use.

Misc7 : int16/any [c]
  The game engine does not use this variable; use it for your own use.

Moved : bool
  After a Move instruction successfully moves this object, it will set
  this flag. During the trigger phase, it will send the MOVED message
  to all objects which have moved; you can set or clear this flag by
  yourself if you want to cause it to trigger even though it didn't
  move or to not trigger even though it did move.

Moving : bool
  This flag indicates that a deferred movement is scheduled for this
  object. The direction of movement is specified by the Dir variable.
  This flag is also used for connected movement, for a different purpose.

NextR : any
  This variable is normally zero, but when there is a collision by the
  CollisionLayers, it can be programmed to destroy an object and create
  another one which represents the combination of the two. In this case,
  the NextR variable of the destroyed object points to the new one.

Player : bool [c] [ro]
  If this object is the player. This is used implicitly as the From of
  some messages sent by the game engine, and has a few other purposes.
  (Normally, a level should have exactly one object of such a class,
  although this is not mandatory; any number (including zero) is allowed.)

Shape : int16 [c]
  Defines the shape of the object, which is used when one object tries to
  move into another one that it can't climb over. The low 2-bits are for
  east, next 2-bits for north, next 2-bits for west, and finally the high
  2-bits are for south. Each of these 2-bit values can be 0 for flat (no
  sliding), 1 for slanted to the left, 2 for slanted to the right, and 3
  for slanted both left and right. (Left and right are when "facing" that
  side of the object.)

ShapeDir : int2 [c] [d]
  Allows accessing the individual 2-bit parts of Shape.

Sharp : int16 [c] [d]
  When one object tries to move into another object, the Hard and Sharp
  values for the sides that are touching will be compared. If the Sharp
  value for one is greater than the Hard of the other, then the object
  with insufficient Hardness is destroyed. If the object that is trying
  to move has the Connection flag, it cannot be destroyed due to running
  into something sharp, but may still destroy other things if it is sharp
  enough to do so (whether or not the other thing has a Connection flag).

Shovable : int16 [c]
  Defines what directions the object may be shoved, where bit0 means east,
  bit2 means north, bit4 means west, and bit6 means south. Bit1, bit3,
  bit5, and bit7 can be used for diagonal shoving. Higher bits are used
  for connection movement, if the Connection flag is also set; each bit
  which is set makes it connect to an object in that direction which has
  the same CollisionLayers value, the bit in the Shovable high 8-bits for
  the opposite direction, and the Connection flag. If the Connection flag
  is not set, then you can use the high bits of Shovable for your own use,
  since the game engine will not use them in that case.

Stealthy : bool [c]
  If this flag is set, then the Arrived and Departed variables of other
  objects are not automatically set when this object moves.

Strength : int16/int32 [c]
  When this object's code tries to move this or other objects by the use
  of the Move instruction, the Strength must be greater than or equal to
  the total Weight of all objects being moved, or else it won't move.

Temperature : int16/int32 [c]
  The game engine does not use this variable; use it for your own use.

ThisR : any
  This variable is related to NextR, and setting either variable will also
  affect the other one. If NextR is zero, then this variable points to the
  object itself, and setting this variable to point to itself will cause
  NextR to be set to zero. (They are actually the same variable, but are
  just different ways to access it.)

UserSignal : bool
  This variable has the same effect as Busy; see Busy for details. It is
  still a separate variable though.

UserState : bool [c]
  The game engine does not use this variable; use it for your own use.

VisualOnly : bool [c]
  If set, this object is ignored by most operations, although it can still
  receive messages, and ObjClassAt can still find it. If the Compatible
  flag is also set, then VisualOnly also has the effects of Stealthy.

Volume : int16/int32 [c]
  If an object tries to move diagonally, it will not be able to move if
  the sum of its Volume and the largest Volumes at the orthogonally
  adjacent cells that it is moving between is greater than the limit
  (which is normally 10000, but you can redefine it globally). See the
  documentation about moving objects for further details.

Weight : int16/int32 [c]
  Determines how much Inertia is required to move this object (and is used
  up once it has moved, or if it failed to move it). See Strength.

Xloc : int8 [ro]
  The 1-based X coordinate of this object. To move the object, use any of
  the instructions for movement; it cannot be moved by directly assigning
  the new coordinates to these variables.

Yloc : int8 [ro]
  The 1-based Y coordinate of this object (1 is at the top of the screen).


=== Instructions ===

For some instructions, a comma prefix means to operate on another object,
while the lack of the comma means to operate on itself; for some other
instructions, a comma prefix means to use signed instead of unsigned
arithmetic. An equal sign prefix usually means to write instead of read.

Anywhere an instruction is allowed, it may be one of these instructions, or
it may be a constant value, or reading/writing a variable (see the above
section about variables specific to objects), or a block instruction (see
the next section for block instructions).

Many instructions are state-changing instructions; these instructions are
marked with ** in the summary line. Such instructions are not allowed to be
used on the same turn as the IgnoreKey instruction.

<function>
  Call a user-defined function (the name starts with a ampersand).

<global>  ( -- any )
  Read a global variable.

=<global>  ( any -- ) **
  Write a global variable.

<label>
  Define a label. Labels are local to the current class. (Label names
  always start with a colon.)

=<label>
  Go to a label. (Put the colon after the equal sign; this instruction,
  and the one below, are using a double sigil.)

,<label>
  Call a label as a subroutine; when it returns, comes back to here.

(<attribute> <userflags...>)  ( -- number )
  The attribute must be one of Misc4, Misc5, Misc6, Misc7, or
  CollisionLayers, and may optionally be preceded by a comma. This
  produces the number with all of the specified bits set only. If the
  attribute is preceded by a comma, then it is an error to specify any
  user flags not assigned to that variable, otherwise any user flags
  that do not belong are ignored. Any user flag may optionally be
  preceded by a comma, and may occur multiple times; only the last
  instance of each is used. If the last instance of a flag has a
  comma then that bit is clear, if without a comma then it is set.

(<userflags...>)  ( -- number )
  As above, but you can omit the attribute; it will be implied. All
  flags listed must be the same attribute otherwise it is an error.

.  ( x -- )

+  ( in1 in2 -- out )
  Add two numbers together.

-  ( in1 in2 -- out )
  Subtract in2 from in1.

*  ( in1 in2 -- out )
  Multiply two numbers together.

,*  ( in1 in2 -- out )
  Signed multiply in1 by in2.

/  ( in1 in2 -- out )
  Unsigned divide in1 by in2 producing the quotient.

,/  ( in1 in2 -- out )
  Signed divide in1 by in2 producing the quotient.

/mod  ( in1 in2 -- quotient remainder )
  Like / and mod together.

,/mod  ( in1 in2 -- quotient remainder )
  Like ,/ and ,mod together.

_  ( -- mark )
  Add a mark to the stack.

a?  ( any -- bool )
  True if the value is an array reference, or false if it is any other
  type. Error if it is a sound.

Animate  ( flag start end delay -- ) **
  Start or stop an animation for this object. This also sets the Image
  variable equal to the start value. The flag can be STOP to stop an
  animation, ONCE to play the animation once (and to queue a LASTIMAGE
  event if the animation isn't changed before that happens; note that
  the message is sent even before the animation is actually visible),
  LOOP to play it in a loop, or OSCLOOP for an oscillating loop. The
  delay between frames is in centiseconds; the start and end are the
  image numbers in this class, and may be ascending or descending.

=Animate  ( mode start end delay -- ) **
 Set animation for this object, in a similar but different way than
 Animate does. There is no animation limit if this command is used,
 and this does not set Image.  The mode can be: 0=stop, 1=logical once,
 2=logical/visual once, 3=visual once, 4=visual looped, 5=visual looped
 oscillating, 6=visual synchronized (the delay is now the slot number
 instead), 7=logical once (also set Image). You can add 8 to set the
 initial visible image to the Image variable instead of the start image,
 and you can add 16 to start at half phase.

AnimateDead  ( x y class start end delay -- )
  Create a dead animation, at the specified coordinates. Give the class
  to use the pictures of, and the start and end image number, and the
  delay between frames in centiseconds. This will draw the animation on
  the screen without being associated with any object; this animation is
  purely visual and does not affect the game state. The animation will
  play once and then it will disappear.

=AnimateDead  ( delay -- )
  Define the delay (in centiseconds) for the most recent dead animation.
  If there isn't one, then this command does nothing.

Arg1  ( -- value )
  The first message argument.

=Arg1  ( value -- )
  Allows setting the first message argument. This will last until the
  current message returns, and does not affect further messages sent; it
  allows Arg1 to be used as a mutable local variable.

Arg2  ( -- value )
  The second message argument.

=Arg2  ( value -- )
  Allows setting the second message argument. This will last until the
  current message returns, and does not affect further messages sent; it
  allows Arg2 to be used as a mutable local variable.

Arg3  ( -- value )
  The third message argument. If the message was sent with only two
  arguments, then this value is zero by default.

=Arg3  ( value -- )
  Allows setting the third message argument. This will last until the
  current message returns, and does not affect further messages sent; it
  allows Arg3 to be used as a mutable local variable.

ArrayCell  ( array row column -- array )
  Make a reference to a single cell of an array. The new reference is
  treated as a reference to a 1x1 array, which aliases the original array.
  Coordinates are zero-based.

,ArrayCell  ( array row column -- array )
  Same as ArrayCell but using 1-based coordinates instead.

ArraySlice  ( array start count -- array )
  Make a slice of an array. The new reference aliases the original array.
  Coordinates are zero-based.

Assassinate  ( -- ) **
  Destroy this object without sending any messages. The object is marked
  as destroyed, but its variables are still accessible until the garbage
  collector runs (during the trigger step for compatible objects, and
  during the cleanup step for all objects). Assassination always succeeds,
  so there is no result value to indicate success or not.

,Assassinate  ( obj -- ) **
  Destroy the given object without sending any messages.

band  ( in1 in2 -- out )
  Bitwise AND.

(bit <numbers>)  ( -- number )
  Make a number with only the specified bits set, given numbers 0 to 31.

BizarroSwap  ( x y | obj1 obj2 -- number ) **
  Attempt to exchange either two objects (one in the bizarro world, one
  not) at the same location or all objects at the specified location into
  or out of the bizarro world. If it is successful, then the result is 0.
  If unsuccessful due to CollisionLayers, then the result is the bits in
  the CollisionLayers which are conflicting; if unsuccessful due to any
  other reason then the result will be 256.

bnot  ( in -- out )
  Bitwise NOT.

bor  ( in1 in2 -- out )
  Bitwise OR.

Broadcast  ( class message arg1 arg2 -- count )
  Send a message to all objects of the specified class (or to all objects
  of all classes if the specified class is zero), in the reverse order of
  the creation of the objects. The result value is the number of objects
  of that class.

(Broadcast <class>)  ( message arg1 arg2 -- count )
  An alternative syntax for Broadcast (needed only for compatibility with
  EKS Hero Mesh).

BroadcastAnd  ( class message arg1 arg2 -- bool )
  As Broadcast but the result is 1 if all results are true, or 0 if at
  least one result is zero. If any result is zero, it doesn't send the
  message to the rest.

BroadcastAndEx  ( class message arg1 arg2 arg3 -- bool )
  As BroadcastSum but with three message arguments.

BroadcastEx  ( class message arg1 arg2 arg3 -- count )
  As Broadcast but with three message arguments.

BroadcastList  ( class message arg1 arg2 -- ... )
  As Broadcast but push all results to the stack. If any result is a mark,
  it is not pushed to the stack.

BroadcastListEx  ( class message arg1 arg2 arg3 -- ... )
  As BroadcastList but with three message arguments.

BroadcastSum  ( class message arg1 arg2 -- total )
  As Broadcast but the result is the sum of the return values rather than
  the number of objects. If a return value is a class or object, it is
  treated as 1. Other non-numeric return values are errors.

BroadcastSumEx  ( class message arg1 arg2 arg3 -- total )
  As BroadcastSum but with three message arguments.

bxor  ( in1 in2 -- out )
  Bitwise XOR.

c?  ( any -- bool )
  True if the value is a class, or false if it is any other type. Error if
  it is a sound.

CancelTriggers  ( -- bits ) **
  Cancel all triggers for this object, including Moved, Departed, and
  Arrived. The return value has bit0 set for Moved, bit1 set for Departed,
  and bit2 set for Arrived, according to which triggers have been pending.

,CancelTriggers  ( obj -- bits ) **
  Like CancelTriggers but for a specified object instead of this one.

(case <cases...>)  ( any -- ??? )
  A case block. Read one value from stack; find which case it matches, and
  then push or jump to the result for that case. See the section below
  about case blocks for details.

chain  ( any -- bool )
  If given an object of the same class as the current object, selects that
  object as the current object and continues executing the code with that
  object instead. This new current object is not saved if you return from
  a function or a subroutine call. If it successfully chained, then the
  result is false. If given an object of a different class, an object that
  doesn't exist, or anything other than an object, then it does nothing
  and the result is true.

Chebyshev  ( obj -- number )
  Calculate the Chebyshev distance between this object and the specified
  object. If the specified object is zero, then the result is also zero.

,Chebyshev  ( obj1 obj2 -- number )
  Calculate the Chebyshev distance between thie two specified objects. If
  either specified object is zero, then the result is also zero.

clear  ( mark ... -- )
  Remove everything above the mark including the mark itself.

Coloc  ( obj -- bool )
  True if this object and the specified object are in the same place, or
  false otherwise. Always false if the object is destroyed, or if one
  object is in the bizarro world and the other one isn't.

,Coloc  ( obj1 obj2 -- bool )
  True if the two specified objects are in the same place, or false
  otherwise. Always false if the object is destroyed, or if one object
  is in the bizarro world and the other one isn't.

Connect  ( -- ) **
  Adds this object to the connection list; has no effect if this object
  is already in the connection list or has the Moving, Destroyed, or
  Bizarro flags set, or does not have the Connection flag. This will
  also set the Moving and VisualOnly flag of this object; it will
  automatically clear the Moving flag after it is handled, and will
  restore the old value of VisualOnly. This should not be used outside
  of the CONNECT message.

,Connect  ( obj -- ) **
  Similar to Connect but for a specified object, instead of necessarily
  this object.

Control  ( -- obj )
  Push the control object to the stack. (If no control class is defined,
  then there will be no control object and this will be zero.)

CopyArray  ( src dest -- ) **
  Copy one array to another. It is OK if the two references overlap.

count  ( mark ... -- mark ... count )
  Count how many values are above the mark on the stack.

Create  ( class x y image dir -- obj ) **
  Creates a new object at the specified location, and returns it. The
  result is zero if the class is zero, the coordinates are out of range,
  the object cannot be created due to the CollisionLayers, or if the new
  object is destroyed before its CREATE message returns.

cz?  ( any -- bool )
  True if the value is a class or zero, or false if it is neither a class
  nor zero. Error if it is a sound.

Data  ( string index -- ... )
  Read string data. If the index is a number, it is the zero-based number
  of which data block in the string to read; all of the data in that block
  is pushed to the stack. If there isn't enough data blocks, then nothing
  will be pushed to the stack. If the index is the KEY message, then all
  of the key codes of the quiz buttons in the string are push to stack.

DeferTriggers  ( -- ) **
  Any triggers that would be executed during the current loop of triggers
  is deferred until the next such loop; the Arrived, Departed, and Moved
  variables are updated with the triggers that would have been done so
  that they will be set to be executed during the next trigger loop. If
  the Compatible flag is set then the meaning is a bit different and the
  Arrived, Departed, and Moved variables are unchanged.

,DeferTriggers  ( obj -- ) **
  Like DeferTriggers but for a specified object instead of this one.

DelInventory  ( class image -- ) **
  Delete an item from the inventory; see SetInventory for more details.

Delta  ( in1 in2 -- out )
  Subtracts the smaller input from the larger (unsigned).

Destroy  ( -- value ) **
  Destroy this object. The variables can still be accessed after it is
  destroyed until it is garbage collected. This calls the DESTROY message;
  the return value will be the result of this instruction, and if it is
  false then it is destroyed, and if true then the destruction fails.

,Destroy  ( object -- value ) **
  Destroy the specified object (as Destroy but for any object).

DotProduct  ( array array -- any )
  Compute the dot product of two arrays. Any nonzero number times a class,
  message, or object will shortcut and return that class, message, or
  object; zero can multiply by any value of any type to make zero; a class
  by an object will return that object if the class is correct; an object
  by a message will send that message to that object, and add the return
  value to the running total, or stop and return that value if the return
  value isn't a number.

dup  ( x -- x x )

eq  ( in1 in2 -- bool )
  Test if they are equal. Sounds cannot be compared, but you can compare
  values of any other type. Strings compare as equal if they contain the
  same text. Object references are only equal if they refer to the same
  object; objects which no longer exist still compare correctly. Values
  of two different types are never equal to each other.

eq2  ( in1 in2 in3 in4 -- bool )
  Test if in1 is equal to in3 and in2 is equal to in4. Comparison works
  the same way as the "eq" instruction.

exec  ( link -- )
  Go to a link; does not continue executing from here afterward. If the
  link is zero then it will be the same as ret.

,exec  ( link -- )
  Go to a link and then continue executing from here afterward. If the
  link is zero then this instruction does nothing.

FakeMove  ( dir -- result ) **
  Similar to IntMove but omits many capabilities, including the actual
  movement. This is the same as a function used internally to deal with
  HIT/HITBY for connection movement. If the HIT or HITBY message returns
  a mark, then it is added like using Connect (if the object's flags
  allow it) and then the return value will be 2.

,FakeMove  ( obj dir -- result ) **
  Works like FakeMove but you can specify a different object instead of
  the current one.

FindConnection  ( link -- result ) **
  Find all connected objects to this one, execute the link for all objects
  in the connected group (including this one), and then pushes zero. If
  any of the CONNECT messages return nonzero, then it will stop and then
  the result is that value instead, and won't execute the link at all. If
  this object doesn't have the Connection flag, or its other flags are not
  appropriate, then it just does nothing and the result is zero.

,FindConnection  ( obj link -- result ) **
  Similar to FindConnection but uses a specified object instead of
  necessarily using the current object. If the object is zero then it
  will do nothing and the result is zero.

Finished  ( -- number )
  Returns the value of an internal flag which tells it that the beginning
  and ending phases should be skipped. This is a 8-bit number; zero means
  don't skip them, and any other number means it does. When the game engine
  sets this automatically, it normally sets it to 1, but "-1 FlushClass"
  during the input phase sets it to 255. When you set this value by
  yourself, you can use any 8-bit number.

=Finished  ( number -- )
  Write to the Finished variable. Only the low 8-bits are used. When set to
  nonzero then the beginning and ending phases are skipped (see above), but
  if IgnoreKey is used, then all phases are skipped, regardless of the
  value of this flag.

flip  ( mark ... -- mark ... )
  Reverses everything above the mark on the stack.

FlushClass  ( class -- ) **
  Resets the Arrived, Busy, Departed, Inertia, Moved, and UserSignal flags
  of all objects of the specified class to zero. If the class is -1, then
  all objects are flushed in this way, and during the input phase, it also
  skips the beginning and ending phases if the class is -1.

FlushObj  ( -- ) **
  Resets this object's Arrived, Busy, Departed, Inertia, Moved, UserSignal.

,FlushObj  ( obj -- ) **
  Resets the Arrived, Busy, Departed, Inertia, Moved, and UserSignal flags
  of the specified object only.

From  ( -- obj )
  The object which send the message to this object. In some cases, this
  will be zero instead of a valid object.

ge  ( in1 in2 -- bool )
  Test if first input is greater or equal to second input (unsigned).

,ge  ( in1 in2 -- bool )
  Test if first input is greater or equal to second input (signed).

GetArray  ( array row column -- value )
  Read a value from an array. Coordinates are zero-based.

,GetArray  ( array row column -- value )
  Same as GetArray but using 1-based coordinates instead.

GetInventory  ( class image -- value true | false )
  Read from the inventory, with true if it exists or false if not.

gt  ( in1 in2 -- bool )
  Test if first input is greater than second input (unsigned).

,gt  ( in1 in2 -- bool )
  Test if first input is greater than second input (signed).

HeightAt  ( x y -- height )
  Finds the greatest height among objects at the specified location.

HitMe  ( dir -- bool ) **
  Checks hardness/sharpness and shoving like is done by Move, subject to
  From and Arg3. The direction is a direction relative to From, not to
  Self. The result is 1 if shoving or sharpness is successful, or 0
  otherwise. This will update Arg3, including at least setting the low
  three bits; the new value of Arg3 may then be used as the return value
  from HITBY. It is intended that this instruction is used inside of a
  HITBY block, in case you want to do some of your own processing. The
  Compatible and VisualOnly flags of this object are not checked.

IgnoreKey  ( -- )
  There is no effect outside of the input phase. During the input phase,
  indicates that this input is not part of the solution, so it will not
  be entered into the replay. It is an error to ignore inputs which do
  cause state changes. Pop-up messages are still allowed, and unlike in
  EKS Hero Mesh they will not break replayability; the key to dismiss a
  non-quiz popup is not entered into the replay list, and the key to
  dismiss a quiz popup will be treated as a non-quiz input. IgnoreKey
  also causes the rest of the turn after the input phase to be skipped.

in  ( x mark ... - bool )
  Check if x is equal to any of the values above the mark; equality is
  tested the same as the "eq" instruction.

InitArray  ( array value -- ) **
  Fill all cells of an array with the specified value.

IntMove  ( dir -- bool ) **
  Similar to Move but do not initialize Inertia at all; use the current
  value of Inertia instead.

,IntMove  ( obj dir -- bool ) **
  Similar to ,Move but do not initialize Inertia at all; use the current
  value of Inertia instead.

is  ( x y -- bool )
  Where x is a class or object or zero, and y is a class, check that it
  is an object of that class, is the same class, or is a subclass of the
  class. If y is zero, then it is always true unless x is zero.

JumpTo  ( x y -- bool ) **
  As MoveTo but sends JUMPED message to that object after it has been
  successfully teleported.

,JumpTo  ( obj x y -- bool ) **
  As ,MoveTo but sends JUMPED message to that object after it has been
  successfully teleported.

Key  ( -- number )
  During the input phase, the key input. During other phases, zero. During
  the input phase of coordinate input, this value will be 1.

,Key  ( -- number true | false )
  If the key (as for Key command) is '1 to '9 or 'A to 'Z then it will be
  the corresponding array index (as for %Q) and true, otherwise false.

land  ( in1 in2 -- out )
  Logical AND.

LastR  ( -- obj )
  Follows the NextR chain of this object to other objects, and the result
  is the last object of the chain.

,LastR  ( obj -- obj )
  Similar to LastR but for a specified object instead of this one.

le  ( in1 in2 -- bool )
  Test if first input is less or equal to second input (unsigned).

,le  ( in1 in2 -- bool )
  Test if first input is less or equal to second input (signed).

Level  ( -- number )
  The level code value for this level. The game engine does nothing with
  this value, but you can use it in class codes if you wish. (For puzzle
  sets converted from EKS Hero Mesh, this is the zero-based level number;
  a few badly designed puzzles use it. In Free Hero Mesh, you can set it
  to whatever 16-bit number you wish in the level editor, and then use it
  as an additional parameter for the puzzle.)

lnot  ( in -- out )
  Logical NOT.

Loc  ( -- x y )
  The X and Y coordinates of this object; same as "Xloc Yloc".

,Loc  ( obj -- x y )
  The X and Y coordinates of the specified object; same as "dup ,Xloc
  swap ,Yloc" (but more efficient).

LocateMe  ( -- )
  Makes the current object especially visible. This is meant to help the
  player to notice where the "Hero" object is more easily, but you can use
  it to make other objects noticeable too if that is appropriate.

,LocateMe  ( obj -- )
  Is like LocateMe but for a specified object instead of this one.

lor  ( in1 in2 -- out )
  Logical OR.

LoseLevel  ( -- )
  Ends all execution and results in loss of game.

lsh  ( in shift -- out )
  Left shift. If the shift amount is out of range 0-31, all bits are
  shifted out, and the result is zero.

lt  ( in1 in2 -- bool )
  Test if first input is less than second input (unsigned).

,lt  ( in1 in2 -- bool )
  Test if first input is less than second input (signed).

lxor  ( in1 in2 -- out )
  Logical XOR.

m?  ( any -- bool )
  True if the value is a message, or false if it is any other type. Error
  if it is a sound.

Manhattan  ( obj -- number )
  Calculate the Manhattan distance between this object and the specified
  object. If the specified object is zero, then the result is also zero.

,Manhattan  ( obj1 obj2 -- number )
  Calculate the Manhattan distance between thie two specified objects. If
  either specified object is zero, then the result is also zero.

max  ( in1 in2 -- out )
  Whichever input number is greater (unsigned).

,max  ( in1 in2 -- out )
  Whichever input number is greater (signed).

MaxInventory  ( number -- )
  Results in an error and loss of game if the number of different
  inventory items exceeds the given number, otherwise no effect.

min  ( in1 in2 -- out )
  Whichever input number is lesser (unsigned).

,min  ( in1 in2 -- out )
  Whichever input number is lesser (signed).

mod  ( in1 in2 -- out )
  Unsigned divide in1 by in2 producing the remainder.

,mod  ( in1 in2 -- out )
  Signed divide in1 by in2 producing the remainder.

Morton  ( in -- out )
  Like ,Morton but the first input is always zero.

,Morton  ( in1 in2 -- out )
  Interleave bits of two 16-bit numbers to make a 32-bit number, like the
  mingle operator of INTERCAL. (One use of this is if you have a class
  with images for each combination of E/N/W/S directions and will want
  to convert them to make the appropriate Shovable value.)

Move  ( dir -- bool ) **
  Move this object in the given direction (which may be absolute or
  relative to the current direction). The result will be true if the
  move is successful or false if it failed. See the section about
  movement for details.

,Move  ( obj dir -- bool ) **
  As Move but moves a specified object rather than necessarily this one.

Move+  ( dir -- bool ) **
  Similar to Move but adds Strength to Inertia without resetting Inertia.
  (The reason this exists is for compatibility with a bug in EKS Hero
  Mesh; you probably do not need to use this yourself.)

,Move+  ( obj dir -- bool ) **
  As Move+ but for a specified object.

+Move  ( dir -- bool ) **
  Schedules a deferred move for this object in the specified direction
  (which may be absolute or relative). Some things are checked at this
  time, while other things are checked at the time that the movement will
  be made; its working is different from non-deferred movements. The
  result is true if the move was scheduled or false if it isn't. (Note:
  Do not confuse +Move with Move+; they are unrelated.)

,+Move  ( obj dir -- bool ) **
  As +Move but for a specified object rather than necessarily this one.

-Move  ( dir -- bool ) **
  Cancel a deferred move in the specified direction, and possibly also
  other things that are shoved by it. The result will be true if it was
  scheduled and successfully removed, or false otherwise.

,-Move  ( obj dir -- bool ) **
  As -Move but for a specified object rather than necessarily this one.

MoveNumber  ( -- number )
  The current move number. This is initially zero, and is advanced after
  each input phase (before the beginning phase).

=MoveNumber  ( number -- ) **
  Allows changing the MoveNumber value.

MoveTo  ( x y -- bool ) **
  Teleports this object to the specified coordinates; the MOVING message
  (and PLAYERMOVING if applicable) are sent to check if it is allowed.
  This also updates the Distance variable, and will deal with arrivals and
  departures, and send FLOATED and SUNK messages as appropriate.

,MoveTo  ( obj x y -- bool ) **
  As MoveTo but for a specified object, not necessarily this one.

Msg  ( -- message )
  The current message being processed.

n?  ( any -- bool )
  True if the value is a number, or false if it is any other type. Error
  if it is a sound.

ne  ( in1 in2 -- bool )
  As eq but the result is inverted (like "eq lnot").

neg  ( in -- out )
  Multiply by negative one.

NewX  ( oldx dir -- newx )
  Advance the number in the direction as though it is a X coordinate. If
  the direction is north or south, leaves it alone, but if it is east or
  west then it is increased or decreased by one. The output is never less
  than zero nor exceeding the playfield width by more than one.

NewXY  ( oldx oldy dir -- newx newy )
  NewX and NewY together.

NewY  ( oldy dir -- newy )
  Advance the number in the direction as though it is a Y coordinate.

nin  ( x mark ... - bool )
  Check if x is unequal to any of the values above the mark; this is the
  same as "in lnot".

nip  ( x y -- y )

o?  ( any -- bool )
  True if the value is an object (whether or not it has been garbage
  collected), or false for any other type. Error if it is a sound.

ObjAbove  ( -- obj )
  The object above this one (0 if this one is at the top). "Above" means
  it overlaps this object, not upward on the screen (north).

,ObjAbove  ( obj -- obj )
  The object above the specified object (0 if there isn't any).

ObjBelow  ( -- obj )
  The object below this one (0 if this one is at the bottom). "Below"
  means this object overlaps it, not downward on the screen (south).

,ObjBelow  ( obj -- obj )
  The object below the specified object (0 if there isn't any).

ObjBottomAt  ( x y -- obj )
  Find the object on the bottom at the specified location. The result will
  be zero if that location is vacant or out of range.

ObjClassAt  ( class x y -- obj )
  Find the bottom-most object of the specified class at that location. If
  there is no object of that class, then the result is zero. This function
  will find objects with the VisualOnly flag set as well as clear. You may
  specify zero instead of a class, in which case it finds nothing. Any
  other number, or any other value that isn't a class, is an error.

ObjDir  ( dir -- obj )
  Find the top-most object in the cell one step in the specified direction
  from this object.

,ObjDir  ( obj dir -- obj )
  Find the top-most object in the cell one step in the specified direction
  from the specified object.

ObjLayerAt  ( layers x y -- obj )
  Find an object with the given CollisionLayers bits set at that location.
  If you specify multiple bits, it finds one with any of those bits. (It
  is not possible for there to be more than one such object if you specify
  only one bit. If there are multiple, the bottom-most one is returned.)

ObjMovingTo  ( x y -- ... )
  Push on the stack all objects scheduled to move to the specified X and Y
  coordinates. There may be zero or more such objects; you can add a mark
  to the stack in order to delimit this list (it won't do so automatically,
  since you may be putting multiple lists together).

ObjTopAt  ( x y -- obj )
  Find the object on the top at the specified location. The result will be
  zero if that location is vacant or out of range.

over  ( x y -- x y x )

oz?  ( any -- bool )
  True if the value is an object or zero, or false if it is neither an
  object nor zero. (Even if the object has been garbage collected, it is
  still true.) Error if it is a sound.

pick  ( index -- any )
  Copy a value from the specified index from the top of the stack, where 0
  means the top of the stack, 1 means the one below, etc.

PopUp  ( value -- )
  Displays a popup message. Normally, the value is a string, but it can be
  another type, and it will try to display it. If the text contains any \q
  commands, then dismissing the popup message will send a KEY message to
  the object which created the popup message. If there is already another
  existing popup message, only the first one set up will be displayed, and
  the others will be ignored. IgnoreKey also affects what happens when a
  popup message is dismissed; see IgnoreKey for details.

(PopUp <number>)  ( string args... -- )
  Displays a popup message, like PopUp does. However, this one allows the
  string to contain substitution codes; see the section below about what
  substitution codes are allowed in popup messages. Each substitution code
  consumes some number of arguments, from bottom to top. The number of
  arguments must be 0 to 32.

Quiz  ( -- ) **
  If used after PopUp, makes dismissing the popup message to send a KEY
  message to this object instead of any other one.

,Quiz  ( any -- ) **
  If used after PopUp, makes dismissing the popup message to send a KEY
  message to the specified object instead of any other one. If you specify
  a class, then it will create an object of that class and use that one.
  If you specify a message, then it will send that message to the Control
  object, similar to specifying the Control object itself but will use the
  specified message instead of KEY.

Rel  ( dir -- dir )
  Resolves a relative direction to an absolute direction.

,Rel  ( obj dir -- dir )
  Resolves a relative direction to an absolute direction, using the
  direction of the specified object as the base. If zero is specified
  instead of a valid object, then the result is the same as the input.

Replace  ( class x y image dir -- obj ) **
  Similar to Create, except that it also destroys any objects in the
  target location with any matching CollisionLayers bits, and clears the
  Bizarro flag of the created object. You may also specify an object
  instead of a class; in this case, it moves that object, but otherwise
  acts like above. In the case of an existing object, it will update the
  Image and Dir (which can now be relative) if the movement is successful.

ret  ( -- )
  Exit the current subroutine. If this is a message block, it must either
  leave the stack as it is, or leave it but with one extra value pushed
  which will be the return value from the message call. (This is implied
  at the end of a code block.) For a user defined function call, or a
  subroutine call, these restrictions are not applicable.

retnz  ( z -- ? )
  If true, then works like ret (the value is kept); but if false, then the
  value is discarded and then it continues from here instead.

retz  ( z -- ? )
  If false, then works like ret (the value is kept); but if true, then the
  value is discarded and then it continues from here instead.

rot  ( x y z -- y z x )

-rot  ( x y z -- z x y )

rsh  ( in shift -- out )
  Logical right shift. If the shift amount is out of the range 0-31,
  then all bits are shifted out and the result is zero.

,rsh  ( in shift -- out )
  Arithmetic right shift. If the shift amount is out of the range 0-31,
  then all bits are shifted out; the result will be -1 if the input is
  negative, or 0 otherwise.

rtn  ( -- )
  Same as "ret then".

s?  ( any -- bool )
  True if the value is a string (which may be either a string in the class
  codes or a string in the level), or false if it is any other type. Error
  if it is a sound.

Seek  ( obj -- dir )
  Returns the direction from this object to the specified object. If that
  object is in the same place as this one, returns F. If zero is specified
  then it is an error.

,Seek  ( obj1 obj2 -- dir )
  Returns the direction from obj1 to obj2. If the two objects are in the
  same place, returns F. If either object is zero, then it is an error.

Self  ( -- obj )
  The reference to the current object.

Send  ( message arg1 arg2 -- value )
  Similar to ,Send but this object sends the message to itself.

,Send  ( obj message arg1 arg2 -- value )
  Send a message to the specified object.

SendEx  ( message arg1 arg2 -- value )
  Similar to ,SendEx but this object sends the message to itself.

,SendEx ( obj message arg1 arg2 arg3 -- value )
  Send a message to the specified object.

SetArray  ( array row column value -- ) **
  Write a value to an array. Coordinates are zero-based.

,SetArray  ( array row column value -- ) **
  Same as SetArray but using 1-based coordinates instead.

SetInventory  ( class image value -- ) **
  Sets an inventory item with the specified class and image number to the
  specified value (which must be a number). If there is no inventory item
  with that exact class and image, an inventory item will be added,
  otherwise the existing one is updated to the new value. Inventory values
  are always unsigned 16-bit numbers.

Sound  ( sound interruptflag -- )
  Play a sound; if the interrupt flag is zero then it does not interrupt
  existing sounds but otherwise it does. It is not an error if the values
  of the arguments are not valid.

Super  ( ? -- ? )
  Only allowed in a class which is a subclass of another class. This
  causes the current code to stop being executed and to instead execute
  the code of the class it is inheriting.

,Super  ( ? -- ? )
  Same as Super but return to this code after it is finished.

swap  ( x y -- y x )

SwapWorld  ( -- ) **
  Exchange the entire game with the bizarro world. Sometimes, this might
  fail due to CollisionLayers bits; in this case, it is an error.

Sweep  ( xstart ystart xend yend order msg arg1 arg2 -- )
  Send a message to all objects in the specified rectangle, given its
  corners. The coordinates are treated as signed, so you can safely make
  a surrounding rectangle with a specified radius if wanted. If all of the
  coordinates are out of range and not on opposite sides of the playfield,
  no messages are sent. The order of sending the messages is starting at
  the start coordinates and ending at the end coordinates, regardless of
  which are greater than the others; if the order is true then it does
  vertical movement first and if false then horizontal movement first.

SweepEx  ( xstart ystart xend yend order msg arg1 arg2 arg3 -- )
  Same as Sweep but three message arguments.

Synchronize  ( slot startimage -- ) **
  Start a synchronized animation. Give the slot number of the animation,
  and the starting image number. The length and speed are defined in a
  global definition, and the animation is always a non-oscillating loop.

Target  ( -- bool )
  Check if Arg1 and Arg2 are the coordinates of this object. It is an
  error if either Arg1 or Arg2 are not numbers.

,Target  ( obj -- bool )
  Check if Arg1 and Arg2 are the coordinates of the specified object. It
  is an error if either Arg1 or Arg2 are not numbers.

tmark  ( any -- any true | false )
  If the input is a mark, then it is removed and the result is false.
  Otherwise, the value remains and true is added above it on the stack.

Trace  ( obj arg1 arg2 -- )
  If tracing is enabled, sends the three values and some other information
  on stdout. If tracing is disabled, does nothing. This is intended to be
  used for debugging class codes.

TraceStack  ( -- )
  If tracing is enabled, list the entire operand stack on stdout (including
  items below the current message frame, if any). Items are listed from top
  to bottom, each preceded by the index number.

,TraceStack  ( count -- )
  This is like TraceStack but is limited to specified count.

Trigger  ( obj message -- ) **
  Call a message for a pending trigger for the specified object immediately
  instead of waiting for its turn in the trigger phase. Only has an effect
  if the object does not have the Compatible flag. The message must be
  MOVED, DEPARTED, or ARRIVED; otherwise it is an error. If that trigger is
  pending, it will clear the trigger and send it like it does during the
  trigger phase, setting Arg1 as appropriate, but From is set to the object
  calling it instead of 0, and Arg2 and Arg3 will be inherited from the
  current values of those variables. The return value is ignored. Since the
  trigger is cleared before it is sent, it is safe for objects to call the
  triggers of objects in a loop.

TriggerAt  ( x y message -- ) **
  Works like Trigger on all objects at the specified location, from the
  bottom to the top.

tuck  ( x y -- y x y )

uniq  ( mark ... value -- mark ... value true | mark ... false )
  Check if the top value matches any others in the list above the mark. If
  it doesn't match any, then the value remains and it pushes true; if it
  does match, then the top value is removed and it pushes false instead.

VolumeAt  ( x y -- volume )
  Finds the greatest volume among objects at the specified location.

Walkable  ( x y -- bool )
  Tells if the current object could walk on the specified coordinates,
  according to Height, Climb, and CollisionLayers. This object is not
  counted, even if it is at the specified coordinates. Shoving, hit bits,
  Volume, etc are not checked.

,Walkable  ( obj x y -- bool )
  Similar to Walkable but for a specified object instead of this one. You
  may also specify a class, in which case it uses the default values of
  that class instead of the current values of an object.

WinLevel  ( -- )
  Ends all execution and accepts the input sequence that resulted in the
  current game state as a valid solution. (In other words, the goal of the
  game is to find a sequence of inputs that result in the execution of a
  WinLevel instruction, without causing any errors or executing LoseLevel.)

,WinLevel  ( score -- )
  Same as WinLevel but you can set the score, which is treated as a signed
  number; lower numbers are considered to be a better score. (Currently,
  the score is not used by anything.)

XDir  ( dir -- newx )
  Finds the X coordinate of the cell in the specified direction.

,XDir  ( obj dir -- newx )
  Finds the X coordinate of the cell in the specified direction of the
  specified object.

XStep  ( dir -- result )
  Will be -1 or 0 or +1 depending on the direction; this is the X step
  difference for the specified direction. If it is a relative direction,
  it is relative to the Self object.

,XStep  ( obj dir -- result )
  Similar to XStep but relative directions are relative to the specified
  object, instead of necessarily Self.

XYDir  ( dir -- newx newy )
  Finds the X and Y coordinates of the cell in the given direction.

YDir  ( dir -- newy )
  Finds the Y coordinate of the cell in the given direction.

,YDir  ( obj dir -- newy )
  Finds the Y coordinate of the cell in the specified direction of the
  specified object.

YStep  ( dir -- result )
  Will be -1 or 0 or +1 depending on the direction; this is the Y step
  difference for the specified direction. If it is a relative direction,
  it is relative to the Self object.

,YStep  ( obj dir -- result )
  Similar to YStep but relative directions are relative to the specified
  object, instead of necessarily Self.


=== Block instructions ===

These are block flow controls. They include bodies of other instructions.

and <body> then  ( any -- any )
  Takes a value from the stack. If it is false, leaves it there and skips the
  body, otherwise removes it and executes the body.

begin <body> again  ( -- )
  Executes <body> an unlimited number of times; it will only stop once some
  command inside of the loop jumps out, returns, or results in an error.

begin <body> until  ( -- ) ( bool -- )
  Executes <body>, and then pops one boolean from the stack; if false, then it
  will be repeated, but if true then it stops.

begin <part1> while <part2> repeat  ( -- ) ( bool -- ) ( -- )
  Executes <part1>, and then pops one boolean from the stack; if true, then it
  will execute <part2> and then repeat; if false then it jumps out of the loop
  and does not execute <part2>.

for <body> next  ( upflag x y -- ) **
  It starts by saving the inputs into an internal variable (each class has its
  own such variables, and they are separate for each instance of the word "for"
  in the program, but they will interfere if the same loop is reentrant on the
  same object or other objects of the same class), and then resetting the Done
  flag of all objects at the given (x,y) coordinates. If upflag is false, then
  it starts at the top, and if true, starts at the bottom. At the beginning of
  the <body>, the found object is on the stack; you can then use or store it.
  Once "next" is reached, it finds the next object and goes back.

fork <body1> [else <body2>] then  ( -- )
  Continues executing <body1> as a subroutine; after it finishes then the
  part after "then" is executed in the same subroutine call (there is no
  implicit "ret" before "then"), but the "else" part (if any) is skipped.
  After it returns, then <body2> (if any) is executed, and then it will
  also continue from after "then". (This is not the same as the fork
  function (or any other function) in C.)

if <truepart> [else <falsepart>] then  ( bool -- )
  Takes a boolean value from the stack. If true, then <truepart> is executed;
  otherwise it tries the other parts; "else" means always do this if none of
  the previous parts match.

link <body> [else <body2>] then  ( -- link )
  Skips the body and makes a link to the beginning of the body. If there is
  a else block, then it executes that instead but will be skipped if the
  link to the first body is executed.

mbegin <body> repeat  ( -- any ) ( -- )
  The "mbegin" instruction is a shortcut for "begin tmark while", and it has
  the same behaviour.

or <body> then  ( any -- any )
  Takes a value from the stack. If it is true, leaves it there and skips the
  body, otherwise removes it and executes the body.

Any of the keywords "if", "while", and "until" in the above constructions
can optionally have a comma prefix; if they do, then the value remains on
the top of the stack if it is true, and is only popped if it is zero.


=== Case blocks ===

A case block consists of (case) with the cases listed inside of the () after
the word "case". Each case consists of two tokens inside of their own
parentheses. The first token may be any one of:

* A number or direction (representing a number from 0 to 15); only the low
16-bits of the number will be used

* A class

* A message

* The word "else"; if present, it must be the last one. This is the case if
none of the other cases match. It is optional; if not specified, then the
default is zero or to not jump.

The second token may be any one of:

* A number or direction (representing a number from 0 to 15); this must fit
in 16-bits (unsigned)

* A class

* A message

* A string literal

* A label name (with the colon at first)

All types on the left must be the same as each other, and all types on the
right must be the same as each other, except that zero may be mixed with
other types other than labels.

If the right side is a label, then nothing is pushed to the stack, and it
jumps to the specified label instead. If not, then the result is pushed to
the stack instead.


=== Substitution codes ===

%c
  Display a single character whose code is the low 8-bits of the value.

%C
  The low 3-bits of the argument specifies the colour of the text. If it
  is not a number, then the colour is unchanged.

%d
  Display a signed decimal number.

%i
  Display a picture. Consumes two arguments, being first a class and then
  the image number. If either argument is not valid, displays nothing. The
  picture may take up multiple lines of space; the lines will be moved
  farther apart to make room if necessary.

%Q
  Display a quiz button from 1 to 9 or A to Z, depending on the current
  array index. This is only valid inside of a %[ ... %] block, and it does
  not itself consume any argument.

%R
  Display a roman number.

%s
  Display a string. If the value is not a string, it will display it as
  whatever type it is.

%T
  Only valid if this puzzle set uses MBCS. This is like %c but uses all of
  the bits to make a TRON-32 character code. If the code is less than 256
  then this is the same as %c. (This is not fully implemented or tested.)

%u
  Display a unsigned decimal number.

%x
  Display a unsigned hexadecimal number in lowercase.

%X
  Display a unsigned hexadecimal number in uppercase.

%%
  Display a percentage sign; does not consume an argument.

%(
  Begin a conditional block, of the form "%(true-part%|false-part%)" or
  "%(true-part%)". Consumes one argument; if zero then the false-part is
  used (or nothing, if there is no false-part), or if nonzero then the
  true-part is used. Conditional blocks cannot be nested.

%|
  Else part of a conditional block. See above about conditional blocks.

%)
  End of a conditional block. See above about conditional blocks.

%<
  Unconsume one argument. (Does not produce any output.)

%>
  Skip one argument. (Does not produce any output.)

%[
  Consumes one argument, which must be an array; no further arguments can
  be accessible in this case. If it is not an array then all further output
  is suppressed (even past the end of this block, too). This cannot occur
  more than once. The second dimension is the number of records, and the
  first is the fields within that record; all further data accessed by the
  substitution codes are the data within the array.

%]
  End of an array block; if there are any more records in the array then it
  will access the next record and go back to the beginning of this block.


=== Messages ===

This section describes when the various standard messages are sent to
objects, and what return values are expected. (Do not confuse CREATE with
CREATED, or DESTROY with DESTROYED, or COLLIDE with COLLIDING; they have
different purposes.)

(Some standard messages are in the names.js file but not used; do not use
them in your own code, since their names and meaning may change later. The
ones listed here are (probably) considered stable, and their numeric value
(used in level files) will (probably) remain unchanged.)

ARRIVED
  Sent during the trigger phase if the Arrived value is nonzero. Arg1 is
  the saved Arrived value. The Arrived variable will usually be set
  automatically; see the section about variables.

BEGIN_TURN
  Sent to all objects during the beginning phase (the phase after the
  input phase). From is an object with the Player flag (if there is any),
  Arg1 and Arg2 are the X and Y coordinates of that object, and Arg3 is
  the most recent return value from a KEY message. The beginning phase may
  be suppressed; if it is, then the ending phase is also suppressed.

BLOCKED
  When scheduling deferred movement, if the moving object is blocked by
  another object, then the moving object sends this message to the object
  which is blocking it. From is the object attempting to move, Arg1 and
  Arg2 are that object's coordinates, and Arg3 is 1 for +Move or 0 for
  -Move. Of the return value, bit0 clears the Moving flag (causing the
  move to fail), and bit1 causes it to not send any more BLOCKED messages.

CLICK
  Sent during coordinate input. It is first sent to the control object,
  and then if IgnoreKey is not executed, to each object at the clicked
  coordinates, from top to bottom; it will stop if any one returns nonzero
  or if the object that received this message has moved. Arg1 and Arg2 are
  the X and Y coordinates. Arg3 is zero for the control object, but is the
  return value of the CLICK message from the control object when this
  message is sent to other objects.

COLLIDE
  Received when this object is trying to move into a location where there
  is a collision, so it can't move there. Of the return value, bit0 means
  to prevent the movement (even if the objects are moved out of the way or
  destroyed in order to make room), bit1 means to not send any COLLIDEBY
  messages, and bit2 means to pretend the move attempt was successful even
  if it isn't successful. Even if bit0 is set, that won't prevent sending
  COLLIDEBY messages unless bit1 is also set. Arg1 and Arg2 are the X and
  Y coordinates that it is trying to move to, and Arg3 is the collision
  bits which are conflicting.

COLLIDEBY
  Received when another object is trying to move into the location of this
  object or trying to be created in the same location as this object, if
  there is a collision in the CollisionLayers values of those two objects.
  Of the return value, bit0 means to prevent the movement, bit1 means to
  not send any more COLLIDEBY messages, bit2 means to pretend the movement
  attempt is successful even if it isn't (there is no effect for creating
  objects; this bit is meaningful only for moves), and bit4 means that if
  necessary, it will try to destroy this object to make room. From is the
  object attempting to move here, and Arg1 and Arg2 are its location (if
  attempting to create an object, then From, Arg1, and Arg2 are all zero).
  Arg3 is the class of the object being moved or created. If the return
  value is a class, then it will destroy this one, and if moving also the
  object moving, and attempt to create an object of the specified class
  instead and set the NextR of both old objects to the new one. If the
  return value is an object, it is treated as 1 but creation will return
  the specified object instead of the one which is trying to be created.

COLLIDING
  Called when deferred movement is being performed if the move cannot
  occur due to a collision with some other object. From is the object
  that it is colliding with, Arg1 and Arg2 are its location, and Arg3
  is the type of collision (0 if this object is trying to move into a
  stationary object, 1 if another object is trying to move into this
  stationary object, 2 if two objects are trying to move into the same
  space, or 3 if two or more objects forming a loop are trying to move
  into each other). There is no guarantee that this will only be called
  once; sometimes it will be called multiple times for a single collision
  or for multiple collisions with the same objects. The return value has
  bit0 to allow the move, bit1 to handle sharpness, and bit2 to retry if
  the move fails. The bit16 and higher bits will have the similar effect
  for the other object instead.

CONFLICT
  Called during scheduling of a deferred move if it is already currently
  scheduled to move but in a different direction. Arg1 is the direction
  that it is trying to schedule the move in. If the return value is false
  then the schedule fails; if true, then it succeeds.

CONNECT
  Should use the ,Connect instruction to add additional objects to the
  connection group; it will then send this message to those objects too.
  If the return value is true, then the movement fails, and none of the
  objects in the group will move. The Inertia of this object is set
  automatically before calling this message; it can change the Inertia
  before returning if it wants a different value for Inertia. Arg1 is
  the number of objects in the group previously to this one, Arg2 is the
  direction of movement, and Arg3 is the total Weight so far. If this
  message is sent for FindConnection, then Arg3 is a mark instead, and
  the Inertia is not automatically changed.

CREATE
  Sent when the object is created by the Create instruction. This is done
  after the object is created, but before sending any other messages. The
  From is the object that created it. The return value will be used as the
  Arg3 of the SUNK and CREATED messages it might send if appropriate. From
  is the object which executed the Create instruction to create it, or zero
  if it was sent after a XCREATE message due to objects being replaced
  after a collision.

CREATED
  Sent to all objects whose Arrivals care about objects in the location
  where an object has just been created. From is the newly created object,
  Arg1 and Arg2 are the X and Y coordinates where the object was created,
  and Arg3 is the return value from the CREATE message.

DEPARTED
  Sent during the trigger phase if the Departed value is nonzero. Arg1 is
  the saved Departed value. The Departed variable will usually be set
  automatically; see the section about variables.

DESTROY
  Received when the object is about to be destroyed. Arg3 is the reason:
  0 for the Destroy or ,Destroy instruction, 1 due to this object moving
  into something sharp, 2 due to something sharp moving into this one,
  3 for a conflict with CollisionLayers, 4 for crushing, 5 if it was
  destroyed due to COLLIDEBY returning a class or object to be created
  in its place to substitute for it, or 6 if it was trying to move into
  another place but could not and COLLIDEBY told it to create a different
  object in its place (in which case From is the object that it collided
  with). The return value is false to allow it to be destroyed or true to
  keep the object.

DESTROYED
  Sent to all objects whose Departures care about objects in the location
  where an object has just been destroyed (if its VisualOnly flag isn't
  set). From is the object which has just been destroyed. Arg3 is the
  reason, as for the DESTROY message.

END_TURN
  During the trigger phase, if no objects are busy, then the ending phase
  will be executed next. This message is sent to all objects during the
  ending phase (unless the ending phase has been suppressed). Arg1 is the
  phase number; this is initially zero at the beginning of each turn, but
  after each ending phase completes, this number is incremented. If the
  return value is true, or if this object has Arrived, Busy, Departed,
  Moved, or UserSignal variables set to nonzero, it will not suppress the
  next ending phase. Otherwise, if this is not the case for any of the
  objects checked, it will suppress the ending phase for the rest of this
  turn (although other phases may still work).

FLOATED
  This message is used in three cases. If an object's Density variable is
  changed, then as each pair is being exchanged, it sends the FLOATED
  message to the object which now has less density. From is the object
  which it has been exchanged with. The return value is used as the Arg3
  of the corresponding SUNK message. The other case this is used is when
  an object moves or is created but is not the least dense object at that
  location. In this case, From is the object which has been moved or
  created, Arg3 is the return value of the corresponding SUNK message,
  and the return value is not used. (The FLOATED and SUNK messages have
  nothing to do with floating and sinking in water.)

HIT
  Indicates that this object is trying to move into another one; that
  other object is the From value of the message. Arg1 and Arg2 are the
  X and Y coordinates of that object, and Arg3 is the current hit value
  (see below). The return value is ORed with the hit value to make the
  new hit value.

HITBY
  Indicates that this object was hit by another object that was trying to
  move, where From is the object trying to move, Arg1 and Arg2 are the X
  and Y coordinates of that object, and Arg3 is the current hit value, and
  the return value is ORed with the hit value to make the new hit value.
  The return value may also be an object in order to warp; see the section
  about hit values below, which also explains warping.

INIT
  Sent to all objects when the level is initialized. Objects which are
  created during this time will not receive INIT messages, but they will
  receive POSTINIT messages.

JUMPED
  Sent after a successful teleport by the JumpTo instruction. Arg1 and
  Arg2 are the previous X and Y coordinates, and Arg3 (not From) is the
  object that caused the move.

KEY
  During the input phase, it sends this message either to all objects with
  the Input flag set, or to only the current quiz object if there is one
  (whether or not it has the Input flag). Arg1 is the key code (the Key
  instruction can also be used), Arg2 is the return value of the previous
  KEY message (0 for the first one), and Arg3 is zero for normal input or
  one for a quiz. The return value is passed as Arg2 for the next object.

LASTIMAGE
  Called during the trigger phase if this object has a one-shot logical
  animation whose logical timer has expired. New animations played during
  or after this time will retain any existing visual animation, but the
  new logical animation replaces the old one. However, there is a maximum
  number of animations that may be sequenced together in this way.

MOVED
  Sent during the trigger phase to all objects which have the Moved flag
  set; this flag is cleared before sending the message, so if it moves
  again it will remember that it moved again. It will not send this
  message again during the same trigger phase, even if the Compatible
  flag is set; it will wait until all other objects have been processed
  during the same trigger phase first. Arg3 is the phase number (see the
  description of END_TURN for details). The Moved variable will usually
  be set automatically; see the section about variables for details.

MOVING
  Called when the object is about to be moved (whether due to Move,
  MoveTo, JumpTo, or any other reason). From is the object that caused
  the move, and Arg1 and Arg2 are the target X and Y coordinates. If the
  return value is true, then the move is aborted. From will be zero if
  it is the first pass of checking if it can be moved due to Connection;
  in that case, if all first passes are successful then it will try again
  the second pass with From set to the first object of the group, and
  this second time they will actually be moved.

NEXTWARP
  Sent to the warp object if a warp fails. From is the same as it is for
  HITBY, Arg1 is the direction of movement, and Arg3 is the hit value.
  Return zero to not try again, or an object to try again with a new
  warp object.

PLAYERMOVING
  If an object with the Player flag is about to move, then after the
  MOVING message is sent, PLAYERMOVING is sent to all objects. From is
  the object which is moving, Arg1 and Arg2 are where it will be moved to,
  and Arg3 is the From of the MOVING message. If the return value is true,
  then the move is aborted.

POSTINIT
  After all INIT messages are sent when the level is initialized, then it
  will send POSTINIT to all objects. Objects which are created during this
  time will not receive POSTINIT messages.

SUNK
  This message is used in three cases. If an object's Density variable is
  changed, then as each pair is being exchanged, it sends the SUNK message
  to the object which now has more density. From is the object which it
  has been exchanged with. Arg3 is the return value from the corresponding
  FLOATED message. The other cases this is used is when an object moves or
  is created but is not the least dense object at that location. In this
  case, From is zero, and the return value is not used. For creation, Arg3
  is the return value of the corresponding CREATE message; for movement,
  Arg3 is always zero. (This has nothing to do with sinking in water.)

WARPED
  Sent to an object that has been moved by a warp. From is the warp
  object, Self is the object that has just been moved, and Arg3 is the hit
  value. If the return value is true, then whatever tried to move it
  believes that the move failed.

XCREATE
  This message is received by an object which has been just created due to
  a COLLIDEBY message returning a class. From is the object at the target
  location that a collision with layers occurred (which is now destroyed).
  Arg1 is the class of the attempted creation or object trying to move
  here, Arg2 is the image of the attempted creation or object trying to
  move here, and Arg3 is the object trying to move here (or zero if it was
  trying to create an object). If the return value is zero, then it will
  continue with CREATE, CREATED, SUNK, and FLOATED messages like with a
  usual creation, but if a number other than zero then they are skipped.
  If the return value is an object, then the Create command will return
  the specified object.


=== Hit values ===

This section describes the bits of the return value of the HIT and HITBY
messages; these values are also used as the Arg3 of those messages.

Some descriptions below are marked with an asterisk. If the Compatible
flag is set for the object that returned this value, then all bits with
the asterisk in the below descriptions are masked out (bit15 is only
masked out for Compatible objects for diagonal movement).

(If the Connection flag is set for the object that is moving, then the
Compatible flag is ignored for the purpose of HIT/HITBY bits, but is not
ignored for other purposes.)

bit0
  Do not send the HITBY message to the target object. If the moving object
  has the Connection flag, then this bit is set in Arg3, but this does not
  prevent sending the HITBY message unless the return value also has bit0.

bit1
  Do not destroy either object due to hardness/sharpness or crushing.

bit2
  Do not attempt to shove the target object.

bit3
  Abort the move attempt immediately. Do not send any more HIT or HITBY
  messages, do not check hardness/sharpness, and do nothing else either.
  This bit is also set in Arg3 if the object can't move due to Volume.

bit4
  Do not send the HITBY message to the target object or to any further
  objects at the target location.

bit5
  Do not destroy either object due to hardness/sharpness or crushing, nor
  should any further objects at the target location be destroyed due to
  hardness/sharpness or crushing.

bit6
  Do not attempt to shove the target object, nor attempt to shove any
  other objects at the target location. (If you are using the two pass
  HIT/HITBY for connection movement, then this bit will automatically
  be set during the first pass.)

bit7 *
  Do not attempt sliding. (This bit is always set in Arg3 if it is due
  to Connection, and always prevents sliding in this case.)

bit8
  Abort after sending the HITBY message.

bit9
  Abort after hardness/sharpness checking.

bit10
  Abort after attempting shoving and crushing.

bit11
  Set by the game engine if the move attempt has been restarted due to
  bit15 being set during the previous attempt.

bit12 *
  If the move attempt fails, pretend it was successful, even though the
  object hasn't actually moved. This means that the result of Move will
  be 1 and that the MOVED message will trigger; it does not trigger any
  ARRIVED, DEPARTED, FLOATED, or SUNK, nor does it set Distance. (If the
  moving object has the Connection flag, then this does not stop it from
  moving; it will move anyways if this flag is set.)

bit13 *
  Abort before actually moving the object and before trying sliding.

bit14 *
  Do not set the Moved flag even if successful. (If you are using two pass
  HIT/HITBY for connection movement, then this bit will automatically be
  set in most cases during the first pass.)

bit15 (*)
  Try again after trying shoving (whether or not the shoving is
  successful). If it tries to shove an object and it is successful, then
  it will automatically set this bit and automatically try again.

bit16
  Set by the game engine if it is attempting sliding.

bit17 *
  Do not actually move the object. It still does everything else, but when
  it is time to move the object, just assume it is successful without even
  trying. Things that Move and JumpTo have in common aren't done.

bit18 *
  Do not restart, even if bit15 is set.

bit19
  Set by the game engine if the requested movement is diagonal.

bit20 *
  If set, then when the movement attempt is restarted (due to bit15 set),
  the direction will be reread from the object's Dir variable.

bit21 *
  Allows the object to move regardless of Height. The game engine sets
  this bit if currently the Climb/Height is OK for moving.

bit22 *
  Prevents movement regardless of Height, but may still allow sliding.

bit23 *
  If this bit is set, then do not consider any further objects at the
  new location of the shoved object after successfully shoving, and
  instead restart the movement immediately.

bit24 *
  Allows sliding to the left regardless of Height; the other attributes
  still need to be correct (unless bit26 is set). The game engine sets
  this bit if the Climb/Height is OK for moving.

bit25 *
  Allows sliding to the right regardless of Height; the other attributes
  still need to be correct (unless bit27 is set). The game engine sets
  this bit if the Climb/Height is OK for moving.

bit26 *
  Allows hitting to the left regardless of Shape, Volume, etc. In order
  to actually move when sliding to the left, both bit24 and bit26 must
  be set, and bit7 must be clear.

bit27 *
  Allows hitting to the right regardless of Shape, Volume, etc. In order
  to actually move when sliding to the right, both bit25 and bit27 must
  be set, and bit7 must be clear.

bit28 *
  This bit is set by the game engine if a warp has occurred. See the below
  description of warping. You can also set this bit by yourself, and it
  persists across restarts. If this bit is set, the moving object's
  direction is updated after the movement if it is successful; this will
  also allow the NEXTWARP and WARPED messages to be sent.

bit29 *
  Reserved for future.

bit30
  Available for your own use.

bit31
  Available for your own use.

The return value of HITBY can also be an object instead of a number. In
this case, a warp occurs. The movement is restarted, using the specified
object as the origin of the movement, and that object's direction as the
direction of movement. (This is not allowed if bit0 of Arg3 is set; in
that case, it is an error.)

If the moving object has the Connection flag (and bit0 is set in Arg3),
then the return value of HIT or HITBY may be a mark. In this case, it
makes the object "sticky", adding it to the list of objects to be moved
as a part of the same connection group. (Returning a mark if bit0 of
Arg3 is not set is an error.)


=== Pattern matching ===

Where an instruction is expected, you can have pattern matching. This can
be (<operator> <pattern...>) where the operator can be one of:

P
  Find starting at the current location, with the current object's
  direction. Pushes the found object, or zero if not found.

,P
  Find starting at the specified object's location and direction. Pushes
  the found object, or zero if not found.

=P
  Searches everywhere. Pushes the found object, or zero if not found.

P*
  Like P but push all found objects, or pushes nothing if not found.

,P*
  Like ,P but push all found objects, or pushes nothing if not found.

=P*
  Like =P but push all found objects, or pushes nothing if not found.

Pc
  Like P* but pushes only the number of matches (zero if none are found),
  rather than all of the objects.

,Pc
  Like ,P* but pushes only the number of matches.

=Pc
  Like =P* but pushes only the number of matches.

Inside the pattern, the following commands are allowed (although the
commands that push stuff to the stack should not be used in the patterns
with P* or ,P* or =P*):

<class>
  Match an object of the specified class.

<dir>
  Move in the specified direction. (This does not move any objects; it
  only moves the cursor for pattern matching.) The direction can be
  relative to the current direction (initially the Dir variable of the
  origin object) or absolute.

<function>
  Call a user-defined function, which should be ( obj dir -- result ),
  and Self is the position from which the current matching started.
  The obj is the currently matched object (which may be zero), and the
  dir is the current direction. If the result is a number, then it sets
  the direction; if a object, sets the current object and the current
  location at that object's location; if a mark, the match fails.

<message>
  Send the message to all objects at the current location. From is the
  position from which pattern matching started. Arg1 is the direction.
  Arg2 is the currently matched object (which may be zero). If the
  return value is zero, it continues normally; if one, the match fails;
  if two, it continues without sending more messages at this location;
  if an object, sets the matched object and current location.

<userflag>
  Match an object with the specified flag.

,<userflag>
  Fail if there are any objects having the specified flag here.

+
  Push the matched object to the stack. (For the counting modes, instead
  unconditionally increments the total.)

-
  Push zero to the stack. (For the counting modes, instead unconditionally
  decrements the total.)

*
  Update the current choice point with the location and direction.

/
  Succeeds only if the pattern prior to this command succeeds but the
  pattern after this command (which still has the same state as the
  prior pattern) fails. This should not be used inside of loops and
  should not be used in a (P*) or (,P*) or (=P*) block. If this command
  occurs more than once, then the most recent / that is successfully
  matched determines the return value if the final match fails.

,/
  Undoes the effect of the / command.

_
  Push a mark to the stack.

again
  End a block with begin or if, allowing it to occur more than once; it
  is repeated until it no longer matches. If the first word is begin,
  then it must match at least once; if it is if, then it can match zero
  or more times. The match is greedy; it will match as much as possible.

begin
  Begin a block.

Bishop
  Try four directions (NE, NW, SW, and SE).

Climb
  Fail the match if the origin object cannot climb here.

(Climb <number>)
  Fail the match if the height here is greater than this number.

cut
  Discards the most recent choice point.

Dir
  Set the direction to the origin object's direction.

,Dir
  Set the direction to the matched object's direction.

=Dir
  Change the origin object's direction to the current direction.

=,Dir
  Change the matched object's direction to the current direction.

else
  Delimits alternatives within a block.

Height
  Fail the match if the origin object can climb here.

(Height <number>)
  Fail the match if the height here isn't greater than this number.

if
  Begin a block that can optionally match.

Image
  Match an object with the remembered class and image (if none is
  remembered, use the origin object's class and image).

,Image
  Remember the class and image of the currently matched object.

next
  Unconditionally fail the current attempt and try the next choice.

ObjAbove
  Match the object above the currently matched object.

ObjBelow
  Match the object below the currently matched object.

ObjBottomAt
  Match the object at the bottom of this location.

ObjTopAt
  Match the object at the top of this location.

Queen
  Try all eight directions.

Rook
  Try four directions (E, N, W, and S).

then
  Ends a block started with begin or if.

Trace
  Used for debugging.


=== Order of execution ===

You can specify the order of execution of objects by class by a global
(Order) block. Inside of this block is a list of sub-lists; each sub-list
is delimited by parentheses.

Each sub-list starts with a flag name, which may be a user flag, or Input,
or Player, or Control. This matches only classes that have that flag
(changing that flag at run time has no effect on order of execution). A
sub-list can also start with a class name, in which case only objects of
that class match; if it is an abstract class then any classes that inherit
from it (directly or indirectly) also match.

The remaining elements are optional; if they are present, they are used to
break ties. First, the second item breaks ties if there is one, and then
if there is still a tie then the third item breaks ties, etc. These extra
elements can be one of the following, with or without a comma: Misc1,
Misc2, Misc3, Misc4, Misc5, Misc6, Misc7, Temperature, Density, Xloc, Yloc,
Image. If there is no comma, they are lowest to highest, but a comma
reverses the order to be highest to lowest instead. These values are
treated as signed, and the values after INIT or CREATE message returns is
used. If any of the values is not a number, then it is an error.

Custom criteria are also possible. In this case, any of the items in the
list (other than the first one) can be a user-defined message name (but not
a built-in message). In this case, the message is sent to other objects that
match the first element of the current list to compare them. From is the
object that needs to be inserted into the list (which has just been created
or initialized), and Arg1 and Arg2 are the coordinates of that object. The
return value is negative or positive for the result of the comparison, or
zero if the result is a tie. State-changing effects are not allowed during
the processing of this message.

The order of execution is then first all objects not listed in the (Order)
block, and then for each sub-list in the (Order) block, the objects that
meet that criteria, in that order. (If it meets multiple criteria, only
the first one that meets that criteria is used.)

Objects not listed in the (Order) block are executed in the reverse order
of their creation. The control object is created after all objects placed
in the level editor but before any other objects, while objects placed in
the editor are created in the order by their coordinates (which is not
necessarily the same order they were put in by the author).

Note: If a value used for the criteria changes after the INIT or CREATE
message of that object returns, then it can result in an unstable (but
still fully deterministic) order when new objects are created. For this
reason, you should only use criteria based on values which don't change.


=== Compatibility ===

Compatible objects have the following differences from the default:

* VisualOnly implies Stealthy.

* If the current quiz object is Compatible, the effect of "-1 FlushObj"
is implied at the beginning of the turn (before the input phase), except
that Inertia is not reset.

* Some bits are masked out of the return value from HIT and HITBY.

* Many variables are limited to 16-bits.

* Moving objects is not allowed during LASTIMAGE processing.

* The way that the trigger phase works is different.

* In the ARRIVED and DEPARTED messages, Arg1 is always zero.

* Diagonal shoving is not possible.

* The JumpTo instruction has an additional effect that rarely matters,
having to do with the timing of ARRIVED, DEPARTED, and MOVED messages.


=== Level table definition ===

The following blocks are allowed in a level table definition:

(<label> <code...>)
  Define a data column. The SQL name of the data column will be that of
  the label name, preceded by a underscore, and some characters will be
  stripped out; note that SQL is case-insensitive. (Other implementations
  or ports of Free Hero Mesh might not implement it as a SQL column, or
  at all. For best portability, names should contain only ASCII letters,
  digits, and underscores, and should not start with a digit, and you
  should not define two or more data columns whose names differ only by
  their case. Aggregates are not subject to this restriction, though.)
  The label name must have a colon at front; if a comma is also added
  then numeric values of this column are treated as signed.

(<string> <label> <width> <format> <color>)
  Defines a display column. The <label> is the name of the data column.
  The <width> is a number 1 to 255 or it can be * for fill width; only
  the last column is allowed to be fill width (although it is also OK if
  no columns are fill width). The <format> is a string of exactly one or
  two characters; see the below list of possible formats. The <color> is
  the text colour, and is optional; it can be a number from 1 to 255, or
  it can be a sequence of parenthesized pairs of a number (-127 to +127)
  and colour, to mean use those colour if the value of this column is
  in range. It uses the colour for all values up to and including the
  specified number, so the numbers should be listed in ascending order,
  in order to work. If the last number is 127 then it is also use for all
  higher numbers too. The <string> is the heading; it is not allowed to
  include control characters, nor can it include graphic characters with
  code number less than 32.

(<local> <type> <code...>)
  Defines a aggregate calculation. The <local> is the name of the aggregate
  to be referred by other blocks (which must start with a percentage sign,
  like a local variable does). The <type> is the type of aggregate, which
  can be + (sum of all values), min (least value), or max (greatest value);
  any one with a comma at first means it is a signed aggregate.

The valid formats are:

* "L" or "R" = Left or right aligned text.

* "L*" or "R*" replacing * with any character = Left or right aligned
displaying the specified character repeated as many times as the column
value is.

* "d", "d-", "d+", "x", "x0", "X", "X0", "o", "o0", "u" = Display a number
(right aligned) as signed decimal (d), hexadecimal (x/X), octal (o),
unsigned decimal (u). The ones with "0" will pad by 0 instead of spaces,
and the "d-" and "d+" will display a left aligned sign.

If a numeric format is specified but it is a text value, then it is treated
as "L" instead, unless format is "R*" in which case it is treated as "R".

Valid instructions in this block include:

 Arithmetic:  + - * ,* / ,/ mod ,mod Delta min ,min max ,max neg

 Bitwise:  band bor bxor bnot lsh rsh ,rsh

 Logical:  land lor lxor lnot

 Compare:  eq ne lt ,lt gt ,gt le ,le ge ,ge

 Misc:  Level _ in nin ret if else then c? m? n? . dup Trace

 Object:  Xloc Yloc Class Dir Misc1 Misc2 Misc3 Misc4 Misc5 Misc6 Misc7
   Temperature Density Player Input Bizarro CollisionLayers

Additionally, you can include numbers, strings (see below for their
meaning, which is different from the meaning in class codes), aggregate
names (with % at first), user flags (with ^ at first), class names, and
message names (both built-in messages and user messages are possible).
Accessing values of objects other than the current one is not possible.

The Trace instruction in the (LevelTable) block is not the same as in the
class codes. In this block, it doesn't consume anything from the stack;
instead, if both -t and -v switches are enabled, then it will display data
relating to the level table calculation on stdout, at the time when the
level table is loaded. (If the table is dropped, it will automatically be
reloaded the next time it is accessed.)

If a string is found where an instruction is expected in this block, then
unlike class codes it is not simply pushing the string to the stack.
Instead, if it starts with @ then the rest of it is a literal string, but
otherwise it represents a pattern to match. If the match is successful,
it pushes the matched substring (or sometimes, a number) to the stack,
and then pushes 1; if unsuccessful, only pushes 0. These patterns will
match the title string of the level. Pattern codes are:

  =    Follow by a delimited string; match that string at the current
        position and skip past it, or if it doesn't match, fail.
  /    Follow by a delimited string; match that string at the current or
        any later position (at the first place where it is found), or if
        it doesn't match, fail.
  [    Set beginning of slice.
  ]    Set end of slice.
  (    Set beginning of slice (same as the [ command);
  )    Set end of slice, but use the position just before the matched item
        instead of just after it.
  \n   Skip until a line break or horizontal bar, and past it. If it is
        followed by any more consecutive line breaks without anything else
        in between, skips those ones too.
  \d   Follow by some text and then : and \ or just \ to skip to and find
        the data in the string that has the same text. If it contains a
        question mark then any single character is matched. Between : and \
        you can have usual other matching commands such as [ and ]. It can
        also be ; instead of : optionally.
  +    Follow by one more character, skip past any number of them.
  -    Skip past any number of digits.
  _    Skip past any number of spaces and line breaks.
  <    Rewind back to the beginning.
  >    Skip to the end.
  #    Successful match; the result is a number within the slice, converted
        from a string (parsed as decimal) to a number.
  $    Successful match; the result is the matched slice.
  %    Successful match; the result is the length of the matched slice.
  Z    Trace (if both -t and -v switches are used).

A "delimited string" in this block is delimited by any printable
character on both sides (except a character with code less than 32).

(The above list of pattern codes maybe it isn't explained very well;
hopefully someone else know how to improve it better.)

After the instructions for a % block is executed, there should be only one
or zero items on the stack. If none, then this one is ignored; if there is
one, then it is added to the accumulation. For all three kinds, if only one
value is given it can use that even if it is not a number.

After the instructions for a : block is executed, the possible cases are:

* The stack is empty, or contains only a mark: The result is null.

* The stack contains only a number: The result is that number. It will be
treated as signed or unsigned according to the column type.

* The stack contains one or more items, of which the first (bottom) one is
a string: Concatenates all of them together, which can be strings, numbers
(treated as unsigned), or classes. All formatting codes of strings will be
stripped, so that the result will be a unformatted string.


=== MML sound effects ===

The MML sound effects are similar to ZZT and MegaZeux. It is a string
consisting of the commands listed below (case-insensitive):

A B C D E F G
  Play a note of the current length and octave; notes outside of the range
  of a 88-key piano are not valid, but the quarter tones are possible. It
  can be followed by zero or more of the following signs:
  ! flat
  , half flat
  ' half sharp
  # sharp

X
  Play a silenced rest of the current note length.

W H Q I S T Z
  Set the note length to one of the predefined note lengths, where W means
  a whole note, the other letters are successively half until Z which means
  a sixty-fourth note, which is the shortest possible note.

.
  Multiply note length by 3/2.

0 1 2 3 4 5 6 7
  Set the octave to a specified number. Note that notes lower than A are
  not valid for octave zero.

-
  Low octave.

+
  High octave.

L
  Set note length to a following number of sixty-fourth notes.

N
  Play a note with the following note number, and the current length. The
  note number 0 is the lowest piano note, and then each next key on the
  piano is 2 more than the previous one (odd numbers are used for quarter
  tones that are not on a standard piano). Numbers 190 and higher are used
  for overtone notes; subtract 188 for the overtone number (although note
  that overtone numbers 0 and 1 are not usable).

(Note that this is not the same as standard MML.)