To define the purpose of a level, you need to create rules for it. Rules describe what's allowed to be built in a level, what it takes to win, and can also be used to control objects within the game world.
Rules are formed from expressions, which can be either atomic or compound. Expressions are separated by white space (spaces, tabs, and new lines) and brackets. Atomic expressions are a single word. Compound expressions have one or more expressions as parameters in the form:
(function parameter1 parameter2 parameter3
… parameterN)
Parameters of compound expressions can themselves be compound expressions.
Units are kilograms, metres, and seconds (except time
, which is given in
milliseconds). Angles are measured in radians. The co-ordinate system is right-handed, with the y
axis pointing up. The rules are invoked every simulation step, 500 times a second.
Expression | Type | Types of parameters | Notes | ||||
---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | Extra | |||
Types | |||||||
bool-type |
bool-type | Boolean value (true/false) | |||||
int-type |
int-type | Integer | |||||
float-type |
float-type | Real number | |||||
point-type |
point-type | 3D point | |||||
node-type |
node-type | ||||||
link-type |
link-type | ||||||
ball-type |
ball-type | ||||||
sheet-type |
sheet-type | ||||||
object-type |
object-type | link/ball/sheet | |||||
weld-joint-type |
weld-joint-type | ||||||
geared-joint-type |
geared-joint-type | ||||||
differential-joint-type |
differential-joint-type | ||||||
curve-type |
curve-type | ||||||
target-type |
target-type | ||||||
motor-type |
motor-type | ||||||
material-type |
material-type | ||||||
contact-type |
contact-type | A pair of items. | |||||
Variable declarations | |||||||
(const t v x) |
none | type | unassigned | t |
Declares v as a constant variable of type t , with value
x . Constant variables are initialised once and then always hold the same value. |
||
(static t v x) |
Declares v as a static variable of type t , initialised to
x . Static variables are initialised once and then maintain their previous value each
time the rules are invoked. |
||||||
(dynamic t v x) |
Declares v as a dynamic variable of type t , initialised to
x . Dynamic variables are initialised to the value of x each time the
rules are invoked. |
||||||
(const t (v n) x …) |
none | type | unassigned | t |
t |
Declares v as an array variable of type t with
n elements. x and any subsequent parameters are used to initialise the
elements – there must be either 1 or n initialisation parameters. If there is 1
then all elements are initialised to x . If there are n then each element
is initialised to the corresponding parameter. Arrays are indexed from 0, so the first element is
(v 0) and the last element is (v (- n 1)) . |
|
(static t (v n) x …) |
|||||||
(dynamic t (v n) x …) |
|||||||
(const-loop-init t (v n) i x) |
none | type | unassigned | unassigned | t |
Declares v as an array variable of type t with
n elements. The elements are initialised to x for i ∈
[0, n ). So (static-loop-init int-type (a 4) i i) would initialise the
array a to (0, 1, 2, 3). |
|
(static-loop-init t (v n) i x) |
|||||||
(dynamic-loop-init t (v n) i x) |
|||||||
Variables | |||||||
v |
type of v |
The current value of the variable v . |
|||||
(v i) |
type of v |
int | The current value of the i th element of the array variable v . Can be
used in place of a non-array variable in the following expression definitions. |
||||
Constants | |||||||
false |
bool | ||||||
true |
|||||||
0 , 1 , -29 etc. |
int | ||||||
0.0 , 1.2 , -29.384 etc. |
float | ||||||
pi |
float | π | |||||
2pi |
2π | ||||||
max-num-players |
int | The (maximum) number of players. Player indexes start from 0, forming the range [0,
num-players ) – including 0 but not num-players . |
|||||
num-players |
|||||||
num-nodes |
int | The number of items. | |||||
num-links |
|||||||
num-balls |
|||||||
num-sheets |
|||||||
num-objects |
|||||||
num-weld-joints |
|||||||
num-geared-joints |
|||||||
num-differential-joints |
|||||||
num-curves |
|||||||
num-targets |
|||||||
num-motors |
|||||||
num-materials |
|||||||
(num-player-nodes p) |
int | int | The number of items for player p . p = −1 refers to
the level items – the things created as part of the level. |
||||
(num-player-links p) |
|||||||
(num-player-balls p) |
|||||||
(num-player-sheets p) |
|||||||
(num-player-objects p) |
|||||||
(num-player-weld-joints p) |
|||||||
(num-player-geared-joints p) |
|||||||
(num-player-differential-joints p) |
|||||||
(num-player-motors p) |
|||||||
metal |
material | ||||||
wood |
|||||||
rubber |
|||||||
super |
|||||||
ice |
|||||||
plastic |
|||||||
damp |
|||||||
rocket |
|||||||
helium |
|||||||
Ranges | |||||||
(interval x y) |
int-range | int | int | The range [x , y ) – including x but not
y . |
|||
nodes |
node-range | The range of the items. | |||||
links |
link-range | ||||||
balls |
ball-range | ||||||
sheets |
sheet-range | ||||||
objects |
object-range | ||||||
weld-joints |
weld-joint-range | ||||||
geared-joints |
geared-joint-range | ||||||
differential-joints |
differential-joint-range | ||||||
curves |
curve-range | ||||||
targets |
target-range | ||||||
motors |
motor-range | ||||||
materials |
material-range | ||||||
(player-nodes p) |
node-range | int | The range of items for player p . p = −1 refers to
the level items – the things created as part of the level. |
||||
(player-links p) |
link-range | ||||||
(player-balls p) |
ball-range | ||||||
(player-sheets p) |
sheet-range | ||||||
(player-objects p) |
object-range | ||||||
(player-weld-joints p) |
weld-joint-range | ||||||
(player-geared-joints p) |
geared-joint-range | ||||||
(player-differential-joints p) |
differential-joint-range | ||||||
(player-motors p) |
motor-range | ||||||
(group x y …) |
(type of x )-range |
any | type of x |
type of x |
The range containing x , y , … |
||
(object-group x y …) |
object-range | link ball sheet object |
link ball sheet object |
link ball sheet object |
|||
contacts |
contact-range | The range containing all the pairs of items currently in contact. | |||||
Conversions | |||||||
(float x) |
float | int | |||||
(int x) |
int | float | Rounds towards zero, losing the fractional part. | ||||
(int-round x) |
Rounds to the nearest integer. | ||||||
(point x y z) |
point | float | float | float | (x , y , z ) |
||
(get-x p) |
float | point | p x |
||||
(get-y p) |
p y |
||||||
(get-z p) |
p z |
||||||
(object x) |
object | link ball sheet |
|||||
(contact x y) |
contact | int link ball sheet object curve |
int link ball sheet object curve |
The pair of items. int parameters specify world boundaries, which have the range
[0, 5], corresponding to the left/right/bottom/top/back/front of the world space. |
|||
Boolean operators | |||||||
(! x) |
bool | bool | ¬x |
||||
(| x y …) |
bool | bool | bool | bool | x ∨ y ∨ … |
||
(& x y …) |
x ∧ y ∧ … |
||||||
Relational operators | |||||||
(= x y) |
bool | any | type of x |
x = y |
|||
(!= x y) |
x ≠ y |
||||||
(< x y) |
bool | int float |
type of x |
x < y |
|||
(<= x y) |
x ≤ y |
||||||
(> x y) |
x > y |
||||||
(>= x y) |
x ≥ y |
||||||
Arithmetic operators | |||||||
(- x) |
type of x |
int float point |
−x |
||||
(+ x y …) |
type of x |
int float point |
type of x |
type of x |
x + y + … |
||
(- x y …) |
x − y − … |
||||||
(* x y …) |
type of x |
int float |
type of x |
type of x |
x × y × … |
||
(/ x y …) |
x ÷ y ÷ … |
||||||
(* x y …) |
point | point | float | float | x × y × … |
||
(/ x y …) |
x ÷ y ÷ … |
||||||
(% x y) |
int | int | int | x mod y |
|||
(~ x y …) |
type of x |
int float point |
type of x |
type of x |
mean(x , y , …) |
||
(<< x y …) |
type of x |
int float |
type of x |
type of x |
min(x , y , …) |
||
(>> x y …) |
max(x , y , …) |
||||||
(limit-min x y) |
type of x |
int float |
type of x |
max(x , y ) |
|||
(limit-max x y) |
min(x , y ) |
||||||
(limit x y z) |
type of x |
int float |
type of x |
type of x |
min(max(x , y ), z ) |
||
(mag x) |
type of x |
int float |
|x | |
||||
(sign x) |
1 if x is positive,−1 otherwise. |
||||||
(sq x) |
type of x |
int float |
x ² |
||||
(sqrt x) |
float | float | √x |
||||
(sin x) |
float | float | sin x |
||||
(cos x) |
cos x |
||||||
(asin x) |
sin−1 x , in the range [−½π, ½π]. |
||||||
(acos x) |
cos−1 x , in the range [0, π]. |
||||||
(atan x y) |
float | float | float | tan−1 (y ÷ x ), in the range [−π,
π].Has no discontinuities if √( x ² + y ²) >
0. |
|||
(interpolate x y z) |
type of x |
float point |
type of x |
float | x + z (y − x ) |
||
(smooth-limit x y z) |
float | float | float | float | z − (½(z − y ))² ÷
(x − y ) if x ≥ ½(y +
z ),y − (½(z − y ))²
÷ (x − z ) otherwise.Like (limit x y z) , but
with smoothed linear-constant transitions. |
||
(len-sq p) |
float | point | |p |² = p x² + p y² +
p z² |
||||
(len p) |
|p | = √(p x² + p y²
+ p z²) |
||||||
(dist-sq p q) |
float | point | point | |q − p |² =
(q x − p x)² +
(q y − p y)² +
(q z − p z)² |
|||
(dist p q) |
|q − p | =
√((q x − p x)² +
(q y − p y)² +
(q z − p z)²) |
||||||
(norm p) |
point | point | p = p ÷ |p | |
||||
(dot p q) |
float | point | point | p ⋅ q = p xq x +
p yq y +
p zq z |
|||
(cross p q) |
point | point | point | p × q = (p yq z
− p zq y,
p zq x −
p xq z,
p xq y −
p yq x) |
|||
(project p q) |
point | point | point | q ((p ⋅ q ) ÷ |q |²)p projected on to q . |
|||
Conditionals | |||||||
(? c x y) |
type of x |
bool | any | type of x |
x if c ,y otherwise. |
||
(if c a) |
action | bool | action | Executes a if c . |
|||
(if-else c a b) |
action | bool | action | action | Executes a if c ,executes b otherwise. |
||
Range tests | |||||||
(in x r) |
bool | any | (type of x )-range |
true if x ∈ r . |
|||
Loops | |||||||
(count r v c) |
int | any-range | unassigned | bool | #v ∈ r | c |
||
(exists r v c) |
bool | any-range | unassigned | bool | ∃v ∈ r | c |
||
(all r v c) |
∀v ∈ r | c |
||||||
(all+ r v c d) |
bool | any-range | unassigned | bool | bool | (∃v ∈ r | c ) ∧ (∀v
∈ r | c ⇒ d ) |
|
(sum r v c x) |
type of x |
any-range | unassigned | bool | int float point |
∑ x for all v ∈ r | c . |
|
(prod r v c x) |
type of x |
any-range | unassigned | bool | int float |
∏ x for all v ∈ r | c . |
|
(mean r v c x) |
type of x |
any-range | unassigned | bool | int float point |
mean(x ) for all v ∈ r | c . |
|
(min r v c x) |
type of x |
any-range | unassigned | bool | int float |
min(x ) for all v ∈ r | c . If
¬∃v ∈ r | c then the largest representable
value. |
|
(max r v c x) |
max(x ) for all v ∈ r | c . If
¬∃v ∈ r | c then the smallest representable
value. |
||||||
(for r v a) |
action | any-range | unassigned | action | Executes a for all v ∈ r . |
||
Assignments | |||||||
(++ v) |
action | int-variable float-variable |
Increments the value of the variable v . |
||||
(-- v) |
Decrements the value of the variable v . |
||||||
(set v x) |
action | any-variable | type of v |
Sets the value of the variable v to x . |
|||
(set-won p x) |
action | int | int | Sets player p won, with a score of x . x has the range
[−1, 1000]. x = −1 indicates that the level is not scored. |
|||
(set-lost p) |
action | int | Sets player p lost. |
||||
(set-auto x y) |
action | int | float | Sets the value of the automated input x to y . x has the
range [1, 16] and y has the range [−1, 1]. |
|||
(set-broken x) |
action | link ball sheet object |
Sets x broken. |
||||
(set-position x y) |
action | target | point | Sets x 's position to y (m). |
|||
(set-radius x y) |
action | target | float | Sets x 's radius to y (m). |
|||
(set-gravity x) |
action | float | Sets the gravity to x × normal gravity. |
||||
(set-air-density x) |
action | float | Sets the air density to x × normal air density. |
||||
Action combinations | |||||||
(do a b …) |
action | action | action | action | Executes a , then b , then … |
||
Simulation properties | |||||||
time |
int | The current simulation time, in milliseconds. | |||||
(won p) |
bool | int | true if player p has won. |
||||
(lost p) |
true if player p has lost. |
||||||
(auto x) |
float | int | The current value of the automated input x , in the range [−1, 1].
x has the range [1, 16]. |
||||
(axis x) |
float | int | The current value of the input axis x , in the range [−1, 1]. x
has the range [1, 6]. |
||||
(button x) |
bool | int | The current value of the input button x . x has the range [1,
16]. |
||||
Item IDs | |||||||
(node x) |
node | int | The item with ID x . Item IDs are only distinct within that item type,
so two items of different types can have the same ID (e.g. (link 0) and (ball
0) ). |
||||
(link x) |
link | ||||||
(ball x) |
ball | ||||||
(sheet x) |
sheet | ||||||
(weld-joint x) |
weld-joint | ||||||
(geared-joint x) |
geared-joint | ||||||
(differential-joint x) |
differential-joint | ||||||
(curve x) |
curve | ||||||
(target x) |
target | ||||||
(motor x) |
motor | ||||||
(material x) |
material | ||||||
(id x) |
int | node link ball sheet weld-joint geared-joint differential-joint curve target motor material |
x 's ID. |
||||
Item properties | |||||||
(player x) |
int | node link ball sheet object weld-joint geared-joint differential-joint motor |
x 's player. |
||||
(material x) |
material | link ball sheet object curve |
x 's material. |
||||
(radius x) |
float | link ball sheet object curve target |
x 's radius (m). |
||||
(mass x) |
float | node link ball sheet object |
x 's mass (kg). |
||||
(anchored x) |
bool | node link ball sheet object |
true if x is anchored. |
||||
(broken x) |
bool | link ball sheet object |
true if x is broken. |
||||
(position x) |
point | node link ball sheet object target |
x 's position (m). |
||||
(velocity x) |
point | node link ball sheet object |
x 's velocity (m/s). |
||||
(moi-d x) |
float | link | x 's moment of inertia around its direction axis (kg·m²). |
||||
(moi-p x) |
float | x 's moment of inertia around an axis perpendicular to its direction
(kg·m²). |
|||||
(length x) |
float | x 's length (m). |
|||||
(direction x) |
point | x 's direction (unit-length). |
|||||
(expansion x) |
float | x 's expansion (controlled by its length motors), in the range [−1, 1].
Positive for expansion, negative for contraction. |
|||||
(rotation-velocity x) |
float | x 's rotation velocity (rad/s). |
|||||
(rotation-reaction-velocity x) |
float | x 's rotation reaction velocity (rad/s). |
|||||
(is-axle x) |
bool | ball | true if x has an axle joint. |
||||
(is-axle-hub x) |
bool | true if x has an axle hub joint. |
|||||
(is-axle-fixed x) |
bool | true if x has an axle fixed joint. |
|||||
(moi x) |
float | x 's moment of inertia (kg·m²). |
|||||
(normal x) |
point | sheet | x 's normal (unit-length). |
||||
(is-angle x) |
bool | weld-joint geared-joint differential-joint |
true if x is an angle joint. |
||||
(is-hub x) |
bool | weld-joint | true if x is a hub joint. |
||||
(is-fixed x) |
true if x is a fixed joint. |
||||||
(is-rotation-motor-reaction-hub x) |
true if x is a rotation motor reaction hub joint. |
||||||
(is-rotation-motor-reaction-fixed x) |
true if x is a rotation motor reaction fixed joint. |
||||||
(is-cylinder x) |
bool | curve | true if x is a cylinder curve. |
||||
(is-torus x) |
true if x is a torus curve. |
||||||
(is-flat x) |
true if x is a flat curve. |
||||||
(start-position x) |
point | target | x 's start position (m). |
||||
(start-radius x) |
float | x 's start radius (m). |
|||||
(is-length x) |
bool | motor | true if x is a length motor. |
||||
(is-rotation x) |
true if x is a rotation motor. |
||||||
(is-thrust x) |
true if x is a thrust motor. |
||||||
Item accessors | |||||||
(connected-ball x) |
ball | node | x 's connected ball. |
||||
(node-1 x) |
node | link sheet |
x 's first node. |
||||
(node-2 x) |
x 's second node. |
||||||
(node-3 x) |
node | sheet | x 's third node. |
||||
(centre-node x) |
node | ball | x 's centre node. |
||||
(axle-link x) |
link | ball | x 's axle link. |
||||
(link-1 x) |
link | sheet weld-joint geared-joint differential-joint |
x 's first link. |
||||
(link-2 x) |
x 's second link. |
||||||
(link-3 x) |
link | sheet differential-joint |
x 's third link. |
||||
Item tests | |||||||
(inside x y) |
bool | link ball sheet object |
target | true if x is completely inside y . |
|||
(partly-inside x y) |
true if x is partly inside y . |
||||||
Contacts | |||||||
(1-player x) |
int | contact | x 's first/second item's player. |
||||
(2-player x) |
|||||||
(1-anchored x) |
bool | contact | true if x 's first/second item is anchored. |
||||
(2-anchored x) |
|||||||
(1-is-link x) |
bool | contact | true if x 's first/second item is a link. |
||||
(2-is-link x) |
|||||||
(1-is-ball x) |
bool | contact | true if x 's first/second item is a ball. |
||||
(2-is-ball x) |
|||||||
(1-is-sheet x) |
bool | contact | true if x 's first/second item is a sheet. |
||||
(2-is-sheet x) |
|||||||
(1-is-object x) |
bool | contact | true if x 's first/second item is an object. |
||||
(2-is-object x) |
|||||||
(1-is-curve x) |
bool | contact | true if x 's first/second item is a curve. |
||||
(2-is-curve x) |
|||||||
(1-is-world x) |
bool | contact | true if x 's first/second item is a world boundary. |
||||
(2-is-world x) |
|||||||
(1-link x) |
link | contact | x 's first/second item. |
||||
(2-link x) |
|||||||
(1-ball x) |
ball | contact | |||||
(2-ball x) |
|||||||
(1-sheet x) |
sheet | contact | |||||
(2-sheet x) |
|||||||
(1-object x) |
object | contact | |||||
(2-object x) |
|||||||
(1-curve x) |
curve | contact | |||||
(2-curve x) |
|||||||
(1-world x) |
int | contact | x 's first/second item. World boundaries have the range [0, 5],
corresponding to the left/right/bottom/top/back/front of the world space. |
||||
(2-world x) |
|||||||
(overlap x) |
float | contact | The overlap between x 's items (m). |
||||
(velocity-n x) |
float | contact | The velocity between x 's items along the contact normal direction (m/s). Positive
if the items are moving towards each other, negative if they are moving away from each other. |
||||
(velocity-p x) |
float | contact | The velocity between x 's items along the contact perpendicular direction (m/s).
Always positive. |
||||
(effective-mass x) |
float | contact | The effective mass between x 's items (kg).m1 m2 ÷ (m1 +
m2 ) |
||||
Build requirement definitions | |||||||
(require v x) |
none | unassigned | bool | Defines the build requirement that x must evaluate to true for
v ∈ [0, num-players ). |
|||
Display definitions | |||||||
(display v) |
none | bool-variable int-variable float-variable point-variable |
Displays the variable v on the play screen. |
||||
(player-display v) |
Displays the variable v on the play screen for each player. If v is
an array variable then the index is offset by the player index. So (player-display (v
0)) would use (v 0) for the first player, (v 1) for the second
player, (v 2) for the third player, and so on. |
||||||
(edit-display v) |
Displays the variable v on the edit screen. |
||||||
(display v x) |
none | float-variable point-variable |
int | As above, but with v displayed to x decimal places. |
|||
(player-display v x) |
|||||||
(edit-display v x) |
|||||||
(display-time v) |
none | int-variable | As above, but with v interpreted as a time in milliseconds and
displayed as [hh:]mm:ss.sss . |
||||
(player-display-time v) |
|||||||
(edit-display-time v) |
|||||||
(display-bar v) |
none | float-variable | As above, but with v displayed as a bar. Bars can display values of
v in the range [0, 1]. |
||||
(player-display-bar v) |
|||||||
(edit-display-bar v) |
|||||||
silent-won |
none | Supresses the win notification. Used to make "tea break" bonus levels that are won by just watching. |
Top-level expressions must be either a varible declaration, an action, a build requirement definition, or a display definition.
The input rules are not allowed to use the set-won
, set-lost
,
set-broken
, set-position
, set-radius
,
set-gravity
, set-air-density
, require
,
player-display
, player-display-time
, player-display-bar
, or
silent-won
expressions.
Single-line comments start with a #
or @
character and continue to the
end of the line. Multi-line comments are enclosed between {}
characters, and can be
nested. The @
comments are used as a description of the following rule – shown
in the level preview and in place of the rule code when a build requirement has not been met.
These rules define something like a sumo competition, where players start off inside a target and try to push each other out. The last player remaining inside wins.
@Your creation mass must be under 100 kilograms.
(require
p
(<=
(sum
(player-objects p)
o
true
(mass o)
)
100.0
))
@You lose if any part of your creation goes outside the target, or it gets completely broken.
(for
(interval 0 num-players)
p
(if
(!
(all+
(player-objects p)
o
(! (broken o))
(inside o (target 0))
))
(set-lost p)
))
@The last player remaining wins.
(for
(interval 0 num-players)
p
(if
(&
(! (lost p))
(all
(interval 0 num-players)
p2
(|
(= p2 p)
(lost p2)
)))
(set-won p -1)
))