Cublar is an esoteric programming language inspired by esoteric programming languages Befunge and Piet, and Conway’s Game of Life.
In Cublar, instead of the normal programming concept of execution, we have agents. An agent is executing Cublar code. Agents have several registers:
A accumulator, to store a number
C calling register
D to store the direction of the agent
PX, PY and PZ to store the position of the agent
X, Y and Z to store any position
The registers can store any number, no limit in either size or precision.
However, D is interpreted as follows:
if D is positive, D mod 3 + 1 =
1 = +X
2 = +Y
3 = +Z
if D is negative, abs(D) mod 3 + 1 =
1 = –X
2 = –Y
3 = –Z
A D = 0 value deactivates the agent. If no agent has a value other than 0, the program is finished.
Cublar code is stored in an infinite three-dimensional world addressed by Cartesian x, y, z coordinate triplets. On each coordinate point of the world, there may be a cube and/or an agent. If an agent reaches the same point as a cube, it opens the cube and executes its contents. Then travels on in the direction its register D is sending it to. If an agent is deactivated at a point where there is a cube, it executes the cube exactly once and does nothing until activated again; if this happens, it won’t execute this cube again before starting travelling.
There may be an unlimited number of agents in the world, identified by integer numbers starting at 0. They are acting at the same time: at every given point of time, all active agents take a move in the direction shown by their register D and execute the contents of any cube found at their new position, but this doesn’t mean any change for any other agent. When all agents acted, a snap happens and the world changes for all of them.
Creating and running a Cublar program means arranging the cubes and agents in the world and setting the register D of at least one of them to a nonzero value.
Cubes are grouped into categories. Each category has an own color and covers one or more statements. However, cubes can be also painted to colors, but this won’t alter their contents.
Abbreviations used in the following descriptions:
# | the contents of the cube |
A, C etc. | a register of the agent |
*A, *C etc. | a register of another agent whose ID is in register C |
$ | placeholder for the name of any register |
Black – empty | |
No contents, no execution, agents travel through empty space by one cube per snap. | |
White – data storage | |
LOAD | loads # to A (this type of cube contains a number) |
Red – register manipulation | |
ATOC, ATOX, ATOY, ATOZ | moves the contents of A to another register |
Orange – arithmetics | |
ADD | A=A+C |
SUB | A=A–C |
MUL | A=A*C |
DIV | A=A/C |
POW | A=A↑C |
MOD | A=A MOD C |
ZERO | A=0 |
ONE | A=1 |
Yellow – navigation | |
BOUNCE | D=–D |
RIGHT | D cycles on X, Y, Z, sign doesn’t change |
LEFT | D cycles on Z, Y, X, sign doesn’t change |
Green – communication | |
SEND$ | sends A to the register $ of agent *C (modifying their position registers may be dangerous while they’re active since you can modify only one coordinate at a time!) |
GET$ | reads register $ of agent *C into A |
Cyan – output (statements here have a meaning only if the Cublar world is visualized) | |
PAINT | paints the cube at registers X, Y, Z to color C; this won’t change any statement that may be there |
LOOK | points the camera to this agent, looking towards point X, Y, Z; upwards direction is in D (camera won’t move until another LOOK statement is found, but any changes in the world are shown) |
Blue – program alteration | |
SET | writes a statement at cube X, Y, Z; the code of the command is in C; if it’s a LOAD statement, the value is in A; will change the color of the cube along with the statement |
Purple – file handling | |
WRITE | writes register A to the output file; output format is controlled by C |
READ | reads register A from the input file; input format is controlled by C |
Gray – control structures | |
REMARK | in a single snap, the agent travels in a straight line to the next REMARK cube, skipping anything along the way |
LEFTIF, RIGHTIF | if A!=0 execute a LEFT or RIGHT statement, respectively |