ADDED class.doc Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -0,0 +1,1484 @@ +[TODO: This document is incomplete] + +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 + +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. + +\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. + + +=== 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: + +{+ } + Addition. The result is 0 if no arguments are specified. + +{- } + Subtraction. + +{* } + Multiplication. The result is 1 if no arguments are specified. + +{/ } + Division. + +{band } + Bitwise AND. The result is -1 if no arguments are specified. + +{bit } + The numbers are in range 0 to 31 and denote bit positions; the result is + a number with only those bits set. + +{bnot } + Bitwise complement. + +{bor } + Bitwise OR. The result is 0 if no arguments are specified. + +{bxor } + Bitwise XOR. The result is 0 if no arguments are specified. + +{call } + Call a macro dynamically. + +{cat } + 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 } + 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. + +{include } + Include text from another file into this one. You cannot use {include} + inside of another macro or in a macro argument. + +{mod } + Modulo. + +{version } + Expands into nothing. The number must be zero, otherwise it is an error. + Future versions of Free Hero Mesh may change this. + +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. + + +=== Global definitions === + +These are the global definitions in the class definition file. + +(Animate ) + Set the limit for logical animations, from 1 to 255. The default is 32. + +(Background ) + Set the background colour, from 0 to 255. The default value is 1. + +(Synchronize ) + 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 ) + Define the maximum allowed volume for an object to move diagonally + between two other objects. The default value is 10000. + +($ ) + Define a class. See the section about class definitions for details. + +(@ ) + Define a global variable and its initial value. + +( ) + Defines a default message code for all classes which do not specify + their own code for this message. + + +=== 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. + +* Sound: A sound. + +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 + COLLIDE + COLLIDEBY + CREATE + CREATED + DEPARTED + DESTROY + DESTROYED + END_TURN + FLOATED + HIT + HITBY + INIT + JUMPED + KEY + LASTIMAGE + MOVED + MOVING + PLAYERMOVING + POSTINIT + SUNK + +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 + CLICK + 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 + + +=== 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. + +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. + +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. + +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. + +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. + +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 : int8 + 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. + +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. + +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.) + +Shape : int8 [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. + +Shovable : int8 [c] + Defines what directions the object may be shoved, where bit0 means east, + bit2 means north, bit4 means west, and bit6 means south. + +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. + +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. + +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. + +Some instructions are block instructions; see the next section. + +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. + +. ( 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. + +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. + +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. + +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 combatible 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 ) ( -- number ) + Make a number with only the specified bits set, given numbers 0 to 31. + +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 ) ( message arg1 arg2 -- count ) + An alternative syntax for Broadcast (needed only for compatibility with + EKS Hero Mesh). + +BroadcastEx ( class message arg1 arg2 arg3 -- count ) + As Broadcast 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. + +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. + +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). + +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. + +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 other phases similarly to IgnoreKey if the class is -1. + +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). + +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. + +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. + +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. + +land ( in1 in2 -- out ) + Logical AND. + +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. + +lor ( in1 in2 -- out ) + Logical OR. + +LoseLevel ( -- ) + Ends all execution and results in loss of game. + +lsh ( in shift -- out ) + Left shift. + +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. + +MaxInventory ( number -- ) + Results in an error and loss of game if the number of different + inventory items exceeds the given number, otherwise no effect. + +mod ( in1 in2 -- out ) + Unsigned divide in1 by in2 producing the remainder. + +,mod ( in1 in2 -- out ) + Signed divide in1 by in2 producing the remander. + +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. + +MoveNumber ( -- number ) + The current move number. This is initially zero, and is advanced after + each input phase (before the beginning phase). + +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. + +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. + +NewY ( oldx dir -- newy ) + Advance the number in the direction as though it is a Y coordinate. + +nip ( x y -- y ) + +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.) + +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. + +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 ) ( 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. + +QueueTurn ( key -- ) ** + Queue another turn after this one, using the specified key code, which + must be a number from 0 to 255. The extra turn is not entered into the + replay list and does not increase MoveNumber, but otherwise will act + like any other turn. Popup messages are not removed; they will be + retained, and these extra turns execute the input phase as though there + is no popup quiz. + +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.) + +rot ( x y z -- y z x ) + +-rot ( x y z -- z x y ) + +rsh ( in shift -- out ) + Logical right shift. + +,rsh ( in shift -- out ) + Arithmetic right shift. + +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. + +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. + +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. + +swap ( x y -- y x ) + +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. + +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. + +tuck ( x y -- y x y ) + +VolumeAt ( x y -- volume ) + Finds the greatest volume among objects at the specified location. + +WinLevel ( -- ) + Ends all execution and accepts the input sequence that resulted in the + current game state as a valid solution. + +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. + +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. + + +=== Block instructions === + +These are block flow controls. They include bodies of other instructions. + +begin again ( -- ) + Executes 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 until ( -- ) ( bool -- ) + Executes , and then pops one boolean from the stack; if false, then it + will be repeated, but if true then it stops. + +begin while repeat ( -- ) ( bool -- ) ( -- ) + Executes , and then pops one boolean from the stack; if true, then it + will execute and then repeat; if false then it jumps out of the loop + and does not execute . + +for 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 , 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. + +if [el if ...] [else ] then ( bool -- ) + Takes a boolean value from the stack. If true, then is executed; + otherwise it tries the other parts; "el" means to execute and take + another boolean, and continue; "else" means always do this if none of the + previous parts match. + + +=== Substitution codes === + +%c + Display a single character whose code is the low 8-bits of the value. + +%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. + +%s + Display a string. If the value is not a string, it will display it as + whatever type it is. + +%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. + + +=== 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; they have different purposes.) + +ARRIVED + + +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. + +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. + +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. + +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. + +CREATED + + +DEPARTED + + +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, + or 3 for a conflict with CollisionLayers. The return value is false to + allow it to be destroyed or true to keep the object. + +DESTROYED + + +END_TURN + + +FLOATED + + +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. + +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 + + +MOVED + + +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. + +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 + + + +=== 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. + +bit0 + Do not send the HITBY message to the target object. + +bit1 + Do not destroy either object due to hardness/sharpness. + +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. + +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, nor should any + further objects at the target location be destroyed due to sharpness. + +bit6 + Do not attempt to shove the target object, nor attempt to shove any + other objects at the target location. + +bit7 * + Do not attempt sliding. + +bit8 + Abort after sending the HITBY message. + +bit9 + Abort after hardness/sharpness checking. + +bit10 + Abort after attempting shoving. + +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. + +bit13 * + Abort before actually moving the object and before trying sliding. + +bit14 * + Do not set the Moved flag even if successful. + +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. + +bit22 * + Prevents movement regardless of Height, but may still allow sliding. + +bit23 * + Reserved for future. + +bit24 * + Reserved for future. + +bit25 * + Reserved for future. + +bit26 + Available for your own use; preserved across restarts. + +bit27 + Available for your own use; preserved across restarts. + +bit28 + Available for your own use. + +bit29 + Available for your own use. + +bit30 + Available for your own use. + +bit31 + Available for your own use. + + +=== 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. +