yes
yes = true
Source: enu/types
yes = true
Source: enu/types
no = false
Source: enu/types
Magic speed value. speed = ASAP makes a build draw everything at once instead of block by block.
ASAP = 0.0
Source: enu/types
UP = (0.0, 1.0, 0.0)
Source: enu/vectors
DOWN = (0.0, -1.0, 0.0)
Source: enu/vectors
BACK = (0.0, 0.0, 1.0)
Source: enu/vectors
FORWARD = (0.0, 0.0, -1.0)
Source: enu/vectors
RIGHT = (1.0, 0.0, 0.0)
Source: enu/vectors
LEFT = (-1.0, 0.0, 0.0)
Source: enu/vectors
UNSET_POSITION = (inf, inf, inf)
Source: enu/vectors
The 6 directions a unit can move, turn or lean. Each one has a single-letter shorthand, so turn r means turn right.
Directions = enum
up, u, down, d, left, l, right, r, forward, f, back, b
Source: enu/types
The colors blocks come in. eraser isn't really a color — it removes blocks instead of drawing them.
Colors = enum
eraser, blue, red, green, black, white, brown
Source: enu/types
Everything that can go in a player's toolbar: the code editor, one tool for each block color, and the bot placer.
Tools = enum
CodeMode, BlueBlock, RedBlock, GreenBlock, BlackBlock, WhiteBlock, BrownBlock,
PlaceBot, None
Source: enu/types
BoxPivot = enum
corner, centre, bottom_centre
Source: enu/builds
A robot character. Bots can walk, run, play animations, and be programmed to do whatever you like.
Bot = ref object of Unit
Source: enu/types
Every unit of a kind in the world: Bot.all, Build.all, Player.all, Sign.all or Unit.all. Loop over them with for bot in Bot.all:.
proc all(_: type Bot): Query[seq[Bot]]
Head back to the start position by turning around and walking there. Also resets scale, glow, and hides any open sign.
proc go_home(self: Bot)
Play an animation by name, like play "wave". Play "" to stop.
proc play(self: Bot; animation_name: string)
Running speed. The same as speed = 5.
proc run(self: Bot)
Walking speed. The same as speed = 1.
proc walk(self: Bot)
Something made of blocks. Builds have a drawing turtle that commands like forward and turn steer around.
Build = ref object of Unit
Source: enu/types
proc all(T: type Build): Query[seq[Build]]
Translate the turtle by steps along its current forward direction without going through begin_move. No drawing, no animation, no speed/ASAP interaction. Used by wall / floor to leave the turtle at the far end of the shape.
proc advance(self: Build; steps: float)
proc begin_asap(self: Build)
The box this build would take up at a different position, rotation or scale. Check before you leap.
proc bounds_at(self: Build; position: Vector3; rotation: float = 0.0;
scale: float = 0.0): WorldBox
Draw a box. box 5, 3, 8 makes one 5 wide, 3 tall and 8 deep, starting where the turtle is and facing the way it faces. Or draw it somewhere else with at = vec3(...), or between two corners with box corner1, corner2. fill = false makes it hollow, like a room.
proc box(self: Build; width, height, depth: int; color = self.color;
fill = true; pivot: BoxPivot = corner)
proc box(self: Build; width, height, depth: int; at: Vector3;
color = self.color; rotation = 0.0; fill = true;
pivot: BoxPivot = corner)
proc box(self: Build; at, to: Vector3; color = self.color; fill = true)
Draw a cylinder, size blocks across and height blocks tall, standing on the turtle's spot. Draw it somewhere else with at = vec3(...). can means the same thing.
proc cylinder(self: Build; size: float; height: int; color = self.color;
fill = true)
proc cylinder(self: Build; size: float; height: int; at: Vector3;
color = self.color; fill = true)
proc cylinder(self: Build; size: int; height: int; color = self.color;
fill = true)
proc cylinder(self: Build; size: int; height: int; at: Vector3;
color = self.color; fill = true)
Where the turtle is. Assign a position (or a unit) to teleport the turtle there and keep drawing.
proc draw_position(self: Build): Vector3
proc draw_position=(self: Build; value: Vector3)
proc draw_position=(self: Build; unit: Unit)
Paints a COMPUTED block at the given position. Re-runs of the script regenerate it, so it isn't persisted to the save file. Used by place (the box/sphere/cylinder primitives draw host-side). For persistent placement (eg. user edits via eval, holes for windows) use place_block from builds_private, which marks the voxel MANUAL.
proc draw_voxel(self: Build; position: Vector3; color: Colors)
Whether the turtle draws blocks as it moves. drawing = false lets you sneak the turtle somewhere without leaving a trail.
proc drawing(self: Build): bool
proc drawing=(self: Build; drawing: bool)
proc end_asap(self: Build)
Draw a filled square, length blocks on a side.
proc fill_square(self: Build; length = 1)
Head back to the start position by going forward, left, and down the right amounts. Also resets rotation, scale and glow.
proc go_home(self: Build)
Put a single block at exact coordinates, without moving the turtle. place 3, 0, 5, red.
proc place(self: Build; x, y, z: int; color = self.color)
Reloads the Build's voxel data from disk without stopping the script.
proc reload_unit(self: Build)
proc rendered_voxel_count_get(self: Build): int
Jump the turtle back to a spot remembered with save.
proc restore(self: Build; name = "default")
Remember the turtle's position, direction, color and drawing state, so restore can jump back later. Give it a name to keep more than one: save "doorway".
proc save(self: Build; name = "default")
Draw a sphere, size blocks across, centred on the turtle. Draw it somewhere else with at = vec3(...). ball means the same thing and is more fun to say.
proc sphere(self: Build; size: float; color = self.color; fill = true)
proc sphere(self: Build; size: float; at: Vector3; color = self.color;
fill = true)
proc sphere(self: Build; size: int; color = self.color; fill = true)
proc sphere(self: Build; size: int; at: Vector3; color = self.color; fill = true)
Context = ref object
stack*: seq[Frame]
Source: enu/types
advance state machine. Returns true if statemachine is still running. It's ok to run this from within the statemachine, but Halt exceptions must be allowed to propagate.
proc advance(ctx: Context; frame: Frame = nil): bool
Tip the unit (or the drawing turtle) forward, back, left or right. Like turn, but instead of spinning like a top, you tilt — which lets the turtle draw up and down walls or loop-the-loops.
template lean(direction: Directions; degrees = 90.0)
Shorthand for turn.
template t(direction: Directions; degrees = 90.0)
Turn the unit (or the drawing turtle). You can turn:
t is the short version.
template turn(direction: Directions; degrees = 90.0)
An amount of time. Subtracting two timestamps gives you one.
Duration = object
Source: enu/types
proc init(_: type Duration; seconds: float): Duration
proc `$`(d: Duration): string
proc `>=`(a, b: Duration): bool
proc `>`(a, b: Duration): bool
proc `<=`(a, b: Duration): bool
proc `<`(a, b: Duration): bool
proc `+`(a, b: Duration): Duration
proc `-`(a, b: Duration): Duration
proc `==`(a, b: Duration): bool
The duration as a number of milliseconds.
proc milliseconds(d: Duration): float
The duration as a number of seconds.
proc seconds(d: Duration): float
Frame = ref object
manager*: proc (active: bool): bool
action*: proc ()
Source: enu/types
Halt = object of CatchableError
Source: enu/types
Loop = ref object
states*: Table[string, NimNode]
from_states*: seq[(string, NimNode)]
Source: enu/types
A person playing the game. The one at this computer is named player.
Player = ref object of Unit
Source: enu/types
Players who joined since the last time you asked. Useful in a loop to greet newcomers.
proc added(_: type Player): Query[seq[Player]]
proc all(_: type Player): Query[seq[Player]]
The players currently touching this unit, if any. if Player.hit as toucher: grabs one to work with.
proc hit(_: type Player): Query[seq[Player]]
Launch the player into the air. More power, more air.
proc bounce(me: Player; power = 1.0)
The unit whose code the player has open, or nil if the editor is closed. Assign a unit to open its code for them.
proc coding(self: Player): Unit
proc coding=(self: Player; value: Unit)
Whether the player is flying. player.flying = true — no double-jump needed.
proc flying(self: Player): bool
proc flying=(self: Player; value: bool)
God mode: hidden things show up, and locked things can be edited. With great power, etc.
proc god(self: Player): bool
proc god=(self: Player; value: bool)
Which player this is: player 1, player 2, and so on.
proc number(self: Player): int
The sign the player is reading, or nil if none. Assign a sign to shove it in front of them.
proc open_sign(self: Player): Sign
proc open_sign=(self: Player; value: Sign)
true in play mode, false in edit mode. Assign to switch.
proc playing(self: Player): bool
proc playing=(self: Player; value: bool)
Whether the player is running.
proc running(self: Player): bool
proc running=(self: Player; value: bool)
The tool the player is holding right now, like CodeMode or BlueBlock. Assign to switch tools for them.
proc tool(self: Player): Tools
proc tool=(self: Player; value: Tools)
The tools in the player's toolbar. Check with in, add with incl, remove with excl, or assign a whole set: player.tools = {CodeMode, BlueBlock}.
proc tools(self: Player): ToolSet
Replace the whole toolbar at once: player.tools = {CodeMode, BlueBlock, PlaceBot}.
proc tools=(self: Player; value: set[Tools])
proc tools_clear(self: Player)
proc tools_excl(self: Player; tool: Tools)
proc tools_has(self: Player; tool: Tools): bool
proc tools_incl(self: Player; tool: Tools)
A position plus a distance, like home + 5. Move commands accept these as targets.
PositionOffset = object
position*: Vector3
offset*: float
direction*: Vector3
Source: enu/types
Add or subtract extra distance from a spot like home. forward home + 2 stops 2 blocks past home.
proc `+`(self: PositionOffset; offset: float): PositionOffset
proc `-`(self: PositionOffset; offset: float): PositionOffset
template back(offset: PositionOffset)
template down(offset: PositionOffset)
template forward(offset: PositionOffset)
template left(offset: PositionOffset)
template right(offset: PositionOffset)
template up(offset: PositionOffset)
The answer to a question like Bot.all or ?player. Acts like true or false in an if, and may carry results you can loop over.
Query[T] = object of RootObj
result*: T
truthy*: bool
Source: enu/types
proc init[T](_: type Query; results: openArray[T]): Query[seq[T]]
proc `[]`[T: Unit](self: Query[seq[T]]; index: int): T
Grab a result from a query and give it a name, right inside an if: if Player.hit as toucher: toucher.bounce. Only works inside a command loop.
template `as`[T](q: Query[seq[T]]; name: untyped): bool
iterator items[T](self: Query[seq[T]]): T
proc len[T: Unit](self: Query[seq[T]]): int
A sign or message floating in the world.
Sign = ref object of Unit
Source: enu/types
proc all(_: type Sign): Query[seq[Sign]]
Whether the sign spins to always face the player, like it's watching you. (Politely.)
proc billboard(self: Sign): bool
proc billboard=(self: Sign; value: bool)
How tall the sign is, in blocks.
proc height(self: Sign): float
proc height=(self: Sign; value: float)
The text on the sign. It's markdown, so **bold**, lists and headings all work.
proc message(self: Sign): string
proc message=(self: Sign; value: string)
Extra text shown when the player opens the sign — good for the long version of the story.
proc more(self: Sign): string
proc more=(self: Sign; value: string)
Whether the sign is open full-screen for reading. Set it to pop the sign open (or slam it shut).
proc open(self: Sign): bool
proc open=(self: Sign; value: bool)
The text size. Bigger numbers, bigger letters.
proc size(self: Sign): int
proc size=(self: Sign; value: int)
How wide the sign is, in blocks.
proc width(self: Sign): float
proc width=(self: Sign; value: float)
A point in time, measured in seconds since Enu started. Get one with now().
Timestamp = object
Source: enu/types
proc init(_: type Timestamp; seconds: float): Timestamp
proc `$`(t: Timestamp): string
proc `>`(a, b: Timestamp): bool
proc `<`(a, b: Timestamp): bool
proc `+`(a: Timestamp; b: Duration): Timestamp
Subtract timestamps to find out how much time passed between them.
proc `-`(a, b: Timestamp): Duration
proc `-`(a: Timestamp; b: Duration): Timestamp
Set-like view over a player's available tools. Operations forward to the host one tool at a time, so no real set crosses the bridge.
ToolSet = distinct Player
Source: enu/players
proc `$`(tools: ToolSet): string
Empty the toolbar completely.
proc clear(tools: ToolSet)
true if the tool is in the toolbar: if PlaceBot in player.tools:.
proc contains(tools: ToolSet; tool: Tools): bool
Take a tool out of the toolbar.
proc excl(tools: ToolSet; tool: Tools)
Add a tool to the toolbar.
proc incl(tools: ToolSet; tool: Tools)
iterator items(tools: ToolSet): Tools
proc len(tools: ToolSet): int
Anything that exists in the world — a build, a bot, a sign, or the player. Most commands work on any unit.
Unit = ref object of RootObj
name*: string
advance_state_machine*: proc (): bool
sign*: Sign
query_results*: Table[string, seq[Unit]]
Source: enu/types
proc all(_: type Unit): Query[seq[Unit]]
A minus sign in front of a unit means "away from it". turn -player turns your back on the player. Rude, but allowed.
proc `-`(node: Unit): NegativeNode
proc `in`(unit: Unit): bool
Make another unit this unit's child, so it moves when this one moves.
proc adopt(self: Unit; unit: Unit)
Re-anchor an existing instance. Visibly moves/reorients the instance because it's already rendered; the unit's position and rotation stay constant from the user's perspective.
template anchor(target: Unit; body: untyped)
How many degrees this unit would have to turn to face a position (or another unit).
proc angle_to(self: Unit; position: Vector3): float
proc angle_to(self: Unit; enu_target: Unit): float
Teleport the unit, unless the position is unset. Used by Enu internally.
proc apply_position(self: Unit; position: Vector3)
Shorthand for back.
template b(self: Unit; steps = 1.0)
Like forward, but backward.
proc back(self: Unit; steps: float; move_mode: int)
template back(self: Unit; steps = 1.0)
proc back(self: Unit; value: PositionOffset; move_mode: int)
template back(self: Unit; value: PositionOffset)
proc block_log(self: Unit): string
The invisible box around the unit and everything it's made of.
proc bounds(self: Unit): WorldBox
Switch to build mode: commands like forward and turn steer the drawing turtle, leaving a trail of blocks. This is the normal mode for a Build, so you mostly need it to switch back after move, or to aim commands at a different unit: build enemy.
template build(new_enu_target: Unit)
proc capture_start_transform(self: Unit)
proc clear_block_log(self: Unit)
The unit's color. For a Build this is the drawing color — blocks you draw after changing it use the new color.
proc color(self: Unit): Colors
proc color=(self: Unit; color: Colors)
proc create_new(self: Unit)
proc current_colliders(self: Unit; name: string): seq[Unit]
Shorthand for down.
template d(self: Unit; steps = 1.0)
Remove the unit from the level, along with its script and saved data. There's no undo, so be really sure.
proc delete(self: Unit)
proc distance(node: Unit): float
Go down this many blocks (1 if you don't say).
proc down(self: Unit; steps: float; move_mode: int)
template down(self: Unit; steps = 1.0)
proc down(self: Unit; value: PositionOffset; move_mode: int)
template down(self: Unit; value: PositionOffset)
proc exec_instance(self: Unit)
Shorthand for forward.
template f(self: Unit; steps = 1.0)
Go forward this many blocks (1 if you don't say). In build mode the turtle draws blocks as it goes; in move mode the whole unit moves. You can also pass a spot like home: forward home goes forward until you're even with it, and forward home + 2 goes 2 blocks past.
proc forward(self: Unit; steps: float; move_mode: int)
template forward(self: Unit; steps = 1.0)
proc forward(self: Unit; value: PositionOffset; move_mode: int)
template forward(self: Unit; value: PositionOffset)
The frame number when the unit was created.
proc frame_created(self: Unit): int
Whether the unit lives in world space (true) or moves around with its parent (false).
proc global(self: Unit): bool
proc global=(self: Unit; global: bool)
How much the unit glows. 0 is no glow; crank it up to make something impossible to miss.
proc glow(self: Unit): float
proc glow=(self: Unit; energy: float)
Teleport the unit to a position, or to another unit. The same as setting position=.
proc go(self: Unit; position: Unit | Vector3)
Travel to another unit: turn to face it, head forward until you arrive, then drop down to its height.
proc go(unit: Unit)
proc height(self: Unit): float
proc hit(self: Unit; node: Unit): bool
true if this unit is touching another unit. if player.hit:.
proc hit(unit: Unit): bool
The unit's name, like "bot_1729". Every unit has a different one.
proc id(self: Unit): string
Shorthand for left.
template l(self: Unit; steps = 1.0)
Tip the unit (or the drawing turtle) forward, back, left or right. Like turn, but instead of spinning like a top, you tilt — which lets the turtle draw up and down walls or loop-the-loops.
proc lean(self: Unit; direction: Directions; degrees = 90.0; move_mode: int)
proc lean(self: Unit; degrees: float; move_mode: int)
template lean(self: Unit; direction: Directions; degrees = 90.0)
template lean(self: Unit; degrees: float)
Go left this many blocks (1 if you don't say). Slides sideways — no turning.
proc left(self: Unit; steps: float; move_mode: int)
template left(self: Unit; steps = 1.0)
proc left(self: Unit; value: PositionOffset; move_mode: int)
template left(self: Unit; value: PositionOffset)
Where the unit is compared to its parent, instead of the world.
proc local_position(self: Unit): Vector3
Locked units can't be edited in the world with the mouse. Good for finished builds you don't want to nudge by accident.
proc lock(self: Unit): bool
proc lock=(self: Unit; value: bool)
proc new_instance(src, dest: Unit)
proc over(node: Unit): bool
true if two units' boxes overlap.
proc overlaps(a: Unit; b: Unit): bool
How many block changes are still being worked on. 0 means everything you've drawn is actually on screen.
proc pending_block_updates(self: Unit): int
Unfinished voxel pipeline work (queued, in-flight, or awaiting apply) for the unit and its descendants. 0 = every submitted edit is meshed and visible.
proc pending_block_updates_get(self: Unit): int
Where the unit is. Assign to it to teleport: position = player.position (zap!).
proc position(self: Unit): Vector3
Teleport the unit. No walking, no animation — it's just there now. You can also assign another unit to teleport to wherever it is: me.position = player.position, or just me.position = player.
proc position=(self: Unit; position: Vector3)
proc position=(self: Unit; unit: Unit)
Shorthand for right.
template r(self: Unit; steps = 1.0)
proc register_active(self: Unit)
proc register_template_node(self: Unit; name: string)
Let a child unit go free. The opposite of adopt.
proc release(self: Unit)
Send the unit back to its start position, rotation and scale. With clear = true, a Build also forgets its drawn blocks.
proc reset(self: Unit; clear = false)
Go right this many blocks (1 if you don't say). Slides sideways — no turning.
proc right(self: Unit; steps: float; move_mode: int)
template right(self: Unit; steps = 1.0)
proc right(self: Unit; value: PositionOffset; move_mode: int)
template right(self: Unit; value: PositionOffset)
Which way the unit is facing, in degrees. Assign to spin it around: rotation = 180 does an about-face.
proc rotation(self: Unit): float
proc rotation=(self: Unit; degrees: float)
Show a message on a sign above the unit: say "Hello!". Call it again to change the message, or say "" to put the sign away. Markdown works, more adds extra text for when the sign is opened, and width/height/size control the shape if you're picky.
proc say(self: Unit; message: string; more = ""; width = float.high;
height = float.high; size = int.high; billboard = none(bool)): Sign
How big the unit is. 1 is normal size, 2 is double, 0.5 is half. Careful going tiny — it's easy to lose things.
proc scale(self: Unit): float
proc scale=(self: Unit; scale: float)
true if this unit can see the target: nothing solid in the way, and it's closer than less_than (100 blocks unless you say otherwise). sees works too, so if me.sees player: reads nicely.
template see(target: Unit; less_than = 100.0): bool
proc see(self: Unit; target: Unit; less_than = 100.0): bool
The unit's random seed. See seed=.
proc seed(self: Unit): int
Random numbers in Enu follow a secret recipe called a seed. Give two units the same seed and they'll roll the same "random" numbers in the same order. By default every unit gets a different seed.
proc seed=(self: Unit; seed: int)
Alias of see.
template sees(target: Unit; less_than = 100.0): bool
proc sees(self: Unit; target: Unit; less_than = 100.0): bool
Whether the unit is visible. show = false makes it vanish. It's still there. It's just being sneaky.
proc show(self: Unit): bool
proc show=(self: Unit; value: bool)
How fast the unit moves or builds. 1 is normal, bigger is faster, and 0 means "all at once" for building.
proc speed(self: Unit): float
proc speed=(self: Unit; speed: float)
Where the unit starts when the level loads. Assigning moves the start point, and that sticks around after a reload.
proc start_position(self: Unit): Vector3
Change where the unit starts. Unlike position=, this is remembered when the level reloads.
proc start_position=(self: Unit; position: Vector3)
template t(self: Unit; degrees: float)
template t(enu_target: Unit)
Turn the unit (or the drawing turtle). You can turn:
t is the short version.
proc turn(self: Unit; direction: Directions; degrees = 90.0; move_mode: int)
proc turn(self: Unit; degrees: float; move_mode: int)
template turn(self: Unit; direction: Directions; degrees = 90.0)
template turn(self: Unit; degrees: float)
proc turn(self: Unit; position: Vector3; move_mode: int)
template turn(self: Unit; position: Vector3)
proc turn(self: Unit; enu_target: Unit; move_mode: int)
template turn(self: Unit; enu_target: Unit)
template turn(enu_target: Unit)
template turn(self: Unit; enu_target: NegativeNode)
Shorthand for up.
template u(self: Unit; steps = 1.0)
proc under(node: Unit): bool
Go up this many blocks (1 if you don't say).
proc up(self: Unit; steps: float; move_mode: int)
template up(self: Unit; steps = 1.0)
proc up(self: Unit; value: PositionOffset; move_mode: int)
template up(self: Unit; value: PositionOffset)
How fast (and which way) the unit is moving right now.
proc velocity(self: Unit): Vector3
proc velocity=(self: Unit; velocity: Vector3)
proc wake(self: Unit)
A spot (or a direction) in the world. x is left/right, y is up/down, and z is forward/back.
Vector3 = tuple[x, y, z: float]
Source: enu/types
proc `<`(a, b: Vector3): bool
proc `*=`(a: var Vector3; b: Vector3)
proc `*=`(a: var Vector3; b: float32)
proc `*`(a, b: Vector3): Vector3
proc `*`(a: Vector3; b: float32): Vector3
proc `+=`(a: var Vector3; b: Vector3)
proc `+`(a, b: Vector3): Vector3
proc `-=`(a: var Vector3; b: Vector3)
proc `-`(a, b: Vector3): Vector3
proc `-`(self: Vector3): Vector3
proc `/=`(a: var Vector3; b: Vector3)
proc `/=`(a: var Vector3; b: float32)
proc `/`(a, b: Vector3): Vector3
proc `/`(a: Vector3; b: float32): Vector3
proc `==`(a, b: Vector3): bool
proc abs(self: Vector3): Vector3
proc angleTo(self, other: Vector3): float32
The color of the block at that spot.
proc block_color_at(position: Vector3): Colors
proc bounce(self, n: Vector3): Vector3
template box(at, to: Vector3; color = active_unit().color; fill = true)
proc ceil(self: Vector3): Vector3
proc cross(self, other: Vector3): Vector3
proc cubicInterpolate(self, b, preA, postB: Vector3; t: float32): Vector3
How far away something is from this unit, in blocks. player.distance or distance vec3(10, 0, 10).
proc distance(position: Vector3): float
proc distanceSquaredTo(self, other: Vector3): float32
How far apart two positions are.
proc distanceTo(self, other: Vector3): float32
proc dot(self, other: Vector3): float32
proc floor(self: Vector3): Vector3
proc fuzzed(self, range: Vector3): Vector3
proc fuzzed(self: Vector3; range: float): Vector3
proc fuzzed(self: Vector3; x, y, z: float): Vector3
true if this build has a block at that spot.
proc has_block_at(position: Vector3): bool
How high up something is. The same as position.y.
proc height(self: Vector3): float
proc inverse(self: Vector3): Vector3
proc isNormalized(self: Vector3): bool
How long the vector is. If it's the difference between two positions, this is the distance between them.
proc length(self: Vector3): float32
proc lengthSquared(self: Vector3): float32
Blend between two vectors. t is how far to go: 0.0 gives you the first vector, 1.0 gives you the second, 0.5 is halfway.
proc lerp(self: Vector3; other: Vector3; t: float32): Vector3
proc maxAxis(self: Vector3): int
proc minAxis(self: Vector3): int
Take one step of size delta from one position toward another, without overshooting.
proc moveToward(vFrom, to: Vector3; delta: float32): Vector3
Shrink or stretch the vector so its length is exactly 1, keeping its direction. A vector like this is handy for pointing at things.
proc normalize(self: var Vector3)
Like normalize, but returns a new vector instead of changing this one.
proc normalized(self: Vector3): Vector3
proc reflect(self, n: Vector3): Vector3
proc sign(self: Vector3): Vector3
proc slide(self, n: Vector3): Vector3
proc snap(self: var Vector3; other: Vector3)
proc snapped(self: Vector3; other: Vector3): Vector3
template t(position: Vector3)
template turn(position: Vector3)
proc zero(self: var Vector3)
The world itself. There's exactly one, named world. Change its settings to change the scenery.
World = ref object of RootObj
Source: enu/types
The world's scenery and lighting, like "default" or "space". world.environment = "space" — instant outer space.
proc environment(self: World): string
proc environment=(self: World; value: string)
How sharp the screen looks. Lower numbers are blurrier but faster — try turning this down if things get choppy.
proc megapixels(self: World): float
proc megapixels=(self: World; value: float)
An invisible box around a unit, described by its lowest corner and its highest corner. Used to check what fits where.
WorldBox = tuple[min, max: Vector3]
Source: enu/types
true if nothing is in the box — handy for checking a spot before building there.
proc box_is_free(box: WorldBox): bool
The point in the middle of the box.
proc centre(b: WorldBox): Vector3
true if the point is inside the box.
proc contains(b: WorldBox; p: Vector3): bool
A copy of the box, grown by margin in every direction.
proc expanded(b: WorldBox; margin: float): WorldBox
true if two boxes overlap.
proc intersects(a, b: WorldBox): bool
Width, height and depth of the box, as a Vector3.
proc size(b: WorldBox): Vector3
Every unit whose box overlaps this one.
proc units_overlapping(box: WorldBox): seq[Unit]
base_bridgeProperties and queries that every unit has, like position, speed, color and scale. These commands cross over into the Enu engine itself.
Source: enu/base_bridge
proc active_unit(): Unit
proc added_units(): seq[Unit]
Every bot in the world. Bot.all is the fancier way.
proc all_bots(): seq[Bot]
Every build in the world. Build.all is the fancier way.
proc all_builds(): seq[Build]
Everyone playing right now.
proc all_players(): seq[Player]
Every sign in the world.
proc all_signs(): seq[Sign]
Every unit in the world — builds, bots, signs and players.
proc all_units(): seq[Unit]
Erase every block inside the box between two corners.
proc clear_box(x1: float; y1: float; z1: float; x2: float; y2: float; z2: float): bool
proc echo_console(msg: string)
proc exit(exit_code = 0; msg = "")
proc find_voxel_overlaps(limit: int = 50): string
The height of the ground at a spot — the y of the highest solid block, plus 1.
proc floor_at(x: float; z: float): int
proc frame_count(): int
The name of the current level.
proc level_name(): string
Switch to a different level.
proc load_level(level: string; world = "")
Seconds since Enu started. now() is usually nicer.
proc now_seconds(): float
Pretend a button was pressed, like "jump". release_action lets it go. Yes, this means you can prank the player.
proc press_action(name: string)
proc release_action(name: string)
Restart the current level from scratch.
proc reset_level()
proc signal_test_complete(exit_code: int)
Every unit inside the box between two corners.
proc units_in_box(x1: float; y1: float; z1: float; x2: float; y2: float;
z2: float): seq[Unit]
The name of the current world.
proc world_name(): string
proc write_stack_trace()
buildsCommands for building with blocks: shapes like box, ball, wall and floor, plus turtle controls like drawing and save/restore.
Source: enu/builds
Draw everything inside the block instantly, instead of block by block. Like speed = ASAP, but it puts the speed back afterward.
template asap(body: untyped)
A sphere, but friendlier. Same as sphere.
template ball(size: int | float; color = active_unit().color; fill = true)
template ball(size: int | float; at: Vector3; color = active_unit().color;
fill = true)
template box(width, height, depth: int; color = active_unit().color;
fill = true; pivot: BoxPivot = corner)
template box(width, height, depth: int; at: Vector3;
color = active_unit().color; rotation = 0.0; fill = true;
pivot: BoxPivot = corner)
A cylinder, but friendlier. Same as cylinder.
template can(size: int | float; height: int; color = active_unit().color;
fill = true)
template can(size: int | float; height: int; at: Vector3;
color = active_unit().color; fill = true)
template cylinder(size: int | float; height: int; color = active_unit().color;
fill = true)
template cylinder(size: int | float; height: int; at: Vector3;
color = active_unit().color; fill = true)
Draw a flat slab, length deep and width wide (square unless you say). Like wall, the turtle ends up at the far edge, ready for whatever you're building next.
template floor(length: int; width: int = length;
color: Colors = active_unit().color)
template place(x, y, z: int; color = active_unit().color)
Triggers an immediate level save. Used for testing persistence.
proc save_level_now()
template sphere(size: int | float; color = active_unit().color; fill = true)
template sphere(size: int | float; at: Vector3; color = active_unit().color;
fill = true)
Draw a wall, length blocks long and height tall (4 unless you say), heading the way the turtle faces. The turtle ends up at the far end, so wall 10; turn right; wall 10 makes a perfect corner. Four of those and you've got yourself a fort.
template wall(length: int; height: int = 4; color: Colors = active_unit().color)
coreThe heart of the Enu API: moving, turning, building, random numbers, timers, and the other everyday commands that every script can use.
Source: enu/core
"Is this something?" ?player.open_sign is true if the player has a sign open, false if there's nothing there. Works on most things: empty text, empty lists and zero all count as "nothing".
template `?`[T: ref](self: T): Query[T]
template `?`[T: object](self: T): Query[T]
template `?`[T](option: Option[T]): Query[T]
template `?`[T: SomeNumber](self: SomeNumber): Query[T]
template `?`(self: string): Query[string]
template `?`[T: openArray](self: T): Query[T]
template `?`[T: Table](self: T): Query[T]
template `?`[T: set](self: T): Query[T]
template `?`[T: HashSet](self: T): Query[T]
Put values inside text: \"score: {score}" becomes "score: 10". Anything in curly braces gets filled in.
template `\`(s: string): string
Pick the first value that's "something". name or "mystery guest" gives you name, unless it's empty.
proc `or`[T: not bool](a, b: T): T
Declare the unit's pivot. Inside the block, turtle commands (forward, right, up, turn, lean, …) accumulate into the unit's anchor pose instead of drawing voxels or moving the unit. The turtle starts at the proto's local (0, 0, 0) facing -Z.
After the block, position places the anchor pivot at the given world coord, rotation pivots around it, and move me; forward moves along the anchor's intrinsic forward.
template anchor(body: untyped)
Shorthand for back.
template b(steps = 1.0)
Like forward, but backward. b for short.
template back(steps = 1.0)
Roll the dice: 1 in 10 is true 1 time out of 10. Use it for things that should only happen sometimes: if 1 in 100: echo "jackpot!".
proc contains(max, chance: int): bool
Each time it's called, hand back the next value in the list, looping around forever: red, green, blue, red, green, blue... color = cycle(red, green, blue).
template cycle[T](args: varargs[T]): T
Shorthand for down.
template d(steps = 1.0)
Go down this many blocks (1 if you don't say). d for short.
template down(steps = 1.0)
Print an expression and its value. dump score prints score = 10. Saves you typing the name twice while debugging.
macro dump(x: typed): untyped
Print something to the console. The best way to spy on what your script is up to: echo "score is ", score.
proc echo(args: varargs[string, `$`])
true for even numbers. if frame.even: does something every other time.
proc even(self: int): bool
Shorthand for forward.
template f(steps = 1.0)
true if something is farther than greater_than blocks (100 unless you say otherwise).
proc far(node: Unit | Vector3; greater_than = 100.0): bool
Search every unit in the world for the one with this id. Returns nil if there's no such unit.
proc find_by_id(id: string): Unit
The first unit of a kind: Player.first is the first player, Bot.first the first bot. nil if there aren't any.
proc first[T: Unit](_: type T): T
proc first_key[K, V](self: Table[K, V]): K
Do something forever. The same as while true, but friendlier. o is the short version (it looks like a loop, see?).
template forever(body)
Go forward this many blocks (1 if you don't say). In build mode the turtle draws blocks as it goes; in move mode the whole unit moves. f is the short version.
template forward(steps = 1.0)
A copy of a number or position, nudged by a random amount up to range. position.fuzzed(0.5) is great for jitters, shivers and nervous-looking bots.
proc fuzzed(self, range: float): float
Head back to the start position by going forward, left, and down the right amounts. Something solid can block the trip, so if it really matters, compare position to start_position afterward to check you made it.
template go_home()
Make an error you can raise. For example, raise ValueError.init("that's not going to work").
proc init[T: Exception](kind: type[T]; message: string;
parent: ref Exception = nil): ref Exception
Used by Enu while a level loads. You won't need this in a script.
proc initialize_state()
Enu stops scripts that grind away for ~2 seconds without pausing, in case they're stuck. If your loop really does need that long, call this now and then to say "not stuck, just busy!"
proc keep_alive()
Shorthand for left.
template l(steps = 1.0)
template lean(degrees: float)
Go left this many blocks (1 if you don't say). Slides sideways — no turning. l for short.
template left(steps = 1.0)
Called by Enu at the end of each trip through a command loop. You won't need this in a script.
proc loop_finished()
Switch to move mode: commands like forward and turn now move the unit around instead of drawing blocks. move me moves this unit; move enemy steers a different one. (If the speed was 0, it's bumped to 1 so you can actually see something happen.)
template move[T: Unit](new_enu_target: T)
true if something is closer than less_than blocks (5 unless you say otherwise). if player.near: or if player.near(20):.
proc near(node: Unit | Vector3; less_than = 5.0): bool
The time right now. Subtract two of these to see how much time passed: let start = now() # ... do something slow ... echo "Took ", now() - start
proc now(): Timestamp
Shorthand for forever.
template o(body)
true for odd numbers.
proc odd(self: int): bool
Stop the script.
proc quit(code = 0; msg = "")
Shorthand for right.
template r(steps = 1.0)
A random number from a range: rand(1..6) rolls a die. Mostly you don't even need to call this — passing a range where a number goes does it automatically, like forward 2..10.
proc rand[T: int | float](range: Slice[T]): T
Pick one of the choices at random. color = random(red, green, blue).
proc random[T](args: varargs[T]): T
Used by Enu while a level loads. You won't need this in a script.
proc register_state_init(callback: proc ())
Send the unit back to its start position, rotation and scale. With clear = true, a Build also forgets its drawn blocks.
template reset(clear = false)
Go right this many blocks (1 if you don't say). Slides sideways — no turning. r for short.
template right(steps = 1.0)
Do nothing for this many seconds. With no argument (or 0), naps for up to half a second, but wakes up early if something bumps into the unit — perfect for a loop that mostly waits around.
proc sleep(seconds = 0.0)
template t(degrees: float)
template t(enu_target: NegativeNode)
Do something over and over. 4.times: forward 5; turn right draws a square. Inside the block, first and last tell you if this is the first or last time through. Want a counter? Ask for one: 8.times(side): counts side up from 0 to 7.
template times(count: int; body: untyped): untyped
template times(count: int; name: untyped; body: untyped): untyped
template turn(degrees: float)
template turn(enu_target: NegativeNode)
Shorthand for up.
template u(steps = 1.0)
Lists every Unit in the world whose xz-distance to (x, y, z) is <= radius, sorted nearest-first. One line per unit, formatted as: d=DD.D unit_id (X, Y, Z) Useful when chasing overlap reports / "# CLAUDE: ..." marker blocks from MCP: pass the marker's position and skim the candidates.
proc units_near(x, y, z: float; radius = 30.0): string
Go up this many blocks (1 if you don't say). u for short.
template up(steps = 1.0)
Shorthand for times. 5.x: forward 2.
template x(count: int; body: untyped): untyped
playersCommands for the people playing: their tools, whether they're flying or playing, and what they have open.
Source: enu/players
The player who ran this script. runner is the friendly name.
proc executing_player(): Player
The player who ran this script — useful in multiplayer, where player is just the first one.
template runner(): Player
signsSigns and speech: say something, and control how the sign looks.
Source: enu/signs
template say(message: string; more = ""; width = float.high;
height = float.high; size = int.high; billboard = none(bool)): Sign
state_machineCommand loops and states: loop, and the -> and ==> rules that switch between behaviors.
Source: enu/state_machine
A state change rule for loop. wander -> hide means "if we're wandering, start hiding". nil is the state you begin in, any matches every state, others matches every state except the one you're switching to, and (a, b) -> c matches either. Add a do: block to run something once at the moment of the switch.
macro `->`(from_state: untyped; to_state: untyped; body: untyped = nil)
Like ->, but impatient: switches states right away instead of waiting for the current state to finish what it's doing.
macro `==>`(from_state: untyped; to_state: untyped; body: untyped = nil)
A command loop — the heart of a unit's behavior. The body runs over and over (about twice a second), switching between states with -> rules:
loop: nil -> wander if player.near: wander -> hide
macro loop(body: untyped)
macro loop(sig: untyped; body: untyped): untyped
macro smart_call(call: untyped)
testingA little testing framework, for checking that your creations do what you think they do: suite, test and check.
Source: enu/testing
Check that something is true. If it isn't, the test fails and tells you what went wrong.
template check(cond: untyped)
The same as check.
template require(cond: untyped)
A group of related tests: suite "gravity": ....
template suite(name: string; body: untyped)
One test with a name. Put checks inside.
template test(name: string; body: untyped)
Print how many tests passed and failed. Call it at the end.
proc test_summary()
true if any test has failed so far.
proc tests_failed(): bool
vectorsMath for positions and directions: Vector3 arithmetic, distances, and the WorldBox helpers.
Source: enu/vectors
proc `*`(b: float32; a: Vector3): Vector3
true if two numbers are so close that the difference doesn't matter.
proc isEqualApprox(a, b: float32): bool
proc isEqualApprox(a, b: float64): bool
-1.0 for negative numbers, 1.0 for everything else.
proc sign(a: float32): float32
proc sign(a: float64): float64
Snap value to the nearest multiple of step. stepify(7.3, 5.0) is 5.0. stepify(8.0, 5.0) is 10.0.
proc stepify(value, step: float64): float64
proc stepify(value, step: float32): float32
Make a Vector3 — a spot (or a direction) in the world. x is left/right, y is up/down, and z is forward/back.
proc vec3(x, y, z: float): Vector3