Rules

Introduction

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.

Syntax

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 definitions

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 ith 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
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 px
(get-y p) py
(get-z p) pz
(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 xy ∨ …
(& x y ) xy ∧ …
Relational operators
(= x y) bool any type of x x = y
(!= x y) xy
(< x y) bool int
float
type of x x < y
(<= x y) xy
(> x y) x > y
(>= x y) xy
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 ) xy − …
(* 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) arcsin x
(acos x) arccos x
(angle x) float float arccos x if |x| ≤ √2,
arcsin √(1 − x²) + ½π(1 − (sign x)) otherwise.
More accurate than (acos x) where x ≈ ±1.
For points a and b (representing vectors), the angle between them is (angle (dot (norm a) (norm b))). Ignoring the directions of the vectors, it's (angle (mag (dot (norm a) (norm b)))).
(interpolate x y z) type of x float
point
type of x float x + z(yx)
(smooth-limit x y z) float float float float z − (½(zy))² ÷ (xy) if x ≥ ½(y + z),
y − (½(zy))² ÷ (xz) otherwise.
Like (limit x y z), but with smoothed linear-constant transitions.
(len-sq p) float point |p|² = px² + py² + pz²
(len p) |p| = √(px² + py² + pz²)
(dist-sq p q) float point point |qp|² = (qxpx)² + (qypy)² + (qzpz
(dist p q) |qp| = √((qxpx)² + (qypy)² + (qzpz)²)
(norm p) point point p = p ÷ |p|
(dot p q) float point point pq = pxqx + pyqy + pzqz
(cross p q) point point point p × q = (pyqzpzqy, pzqxpxqz, pxqypyqx)
(project p q) point point point q((pq) ÷ |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 xr.
Loops
(count r v c) int any-range unassigned bool #vr | c
(exists r v c) bool any-range unassigned bool vr | c
(all r v c) vr | c
(all+ r v c d) bool any-range unassigned bool bool (∃vr | c) ∧ (∀vr | cd)
(sum r v c x) type of x any-range unassigned bool int
float
point
x for all vr | c.
(prod r v c x) type of x any-range unassigned bool int
float
x for all vr | c.
(mean r v c x) type of x any-range unassigned bool int
float
point
mean(x) for all vr | c.
(min r v c x) type of x any-range unassigned bool int
float
min(x) for all vr | c. If ¬∃vr | c then the largest representable value.
(max r v c x) max(x) for all vr | c. If ¬∃vr | c then the smallest representable value.
(for r v a) action any-range unassigned action Executes a for all vr.
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
weld-joint
geared-joint
differential-joint
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
weld-joint
geared-joint
differential-joint
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 length motors. Positive for expansion, negative for contraction.
(outer-velocity x) float x's outer casing rotational velocity (rad/s).
(inner-velocity x) float x's inner shaft rotational velocity (rad/s).
(is-axle x) bool ball true if x is an axle ball.
(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 true if x is an angle joint.
(is-hub x) true if x is a hub joint.
(is-fixed x) true if x is a 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).
m1m2 ÷ (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.

Comments

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.

Examples

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