Language version 1.5, revision 2012.0826.
©1997-2012 Chris Pressey, Cat's Eye Technologies. All rights reserved. Distributed under a BSD-style license; see the file LICENSE.
What is RUBE?
RUBE is a twisted programming language in tribute to Rube Goldberg, creator of all those unique cartoon contrivances, who showed the world that anything can be done in a more complicated fashion than necessary. The RUBE programming language has some similarities to said contrivances.
Anyone who's played The Incredible Machine (and to some extent, Donkey Kong) will understand RUBE almost immediately. "Instructions" in the program interact to execute the algorithm required. I made the choice to use a "warehouse" paradigm for these interacting instructions (because this is what happens to your brain when you work at a lumberyard. Which, I submit, is far better than what happens to your brain when you go to grad school.)
The RUBE language can be described as a two-dimensional "bully automaton": like a cellular automaton, but certain state transitions force other, non-adjacent cells to assume certain states. Although this may sound like an interesting notion, the number of interactions climbs quickly as more objects do things, and things get much messier than they do in a regular ol' cellular automaton like John Conway's Game of Life. Also unlike a regular cellular automaton, RUBE supports rudimentary input and output functionality.
Because implementing an algorithm in RUBE is a clumsy job of co-ordinating concurrently operating sections of the playfield, few non-trivial RUBE programs exist. In particular, it has never to the author's knowledge been shown that RUBE is Turing-complete. On the other hand, it has never been shown that it's not.
Sadly, the ubiquitous "Hello, world!" in RUBE is a very unfriendly
4666622767662 85ccfc07f2c41 OOOOOOOOOOOOO ccccccccccccc =============
Or an equally ugly
(21646c726f77202c6f6c6c6548 =========================== O F c =
A RUBE program is a two-dimensional grid of ASCII characters, or at least represented by characters drawn from the ASCII set.
Integral are the crates,
f. These represent data. They also
represent movable boxes which are subject to gravity, being pushed
around, and conveyor belts, among other things.
= are stationary parts of the program on which crates can
be piled. When there's no girder directly below a crate, that crate
) push crates around. Dozers are subject to gravity,
and must travel on girders. Dozers turn around when there is a
front and above them. As an interesting side effect they also
replicate themselves at
\\ are used for dozers to move from girder to girder.
< carry crates along with no help needed from
dozers. Note that conveyor belots do not affect dozer motion.
W and down
M move crates from girder to girder.
"Swinches" move crates up
V or down
A and then switch states.
K compare crates to a reference crate and move the crate
depending on if it's less than, or more than/equal to the
t | t = target crate l = lesser crates K | r = reference crate g = greater than or equal to lrg |
+ and Unpackers
- perform 4-bit arithmetic on crates:
+ + - - 12 -> 3 ef -> 1 === === === ===
F destroy everything one space left, right, below, and
: make a copy below them of whatever is above them,
usually a crate or a dozer. Special replicators
; only make
copies of crates. Upside-down special replicators
. work like
but make a copy above them of what's below them.
Dozers turn around when they hit certain instructions.
* disappear after being hit horizontally by a dozer.
Program output provides a print mechanism. If there is a
O, the value specified by the two crates above the
(if they exist) is output as an ASCII character. If there is a
crate below the
O, they are output as the decimal representation,
in ASCII, of the byte (numerical) value of the crates.
The following outputs a space:
2 0 O c =
Table of Instructions
Symbol Name Bump R Bump L Surface Gravity Implemented: space pass pass no no 0..f crate move r move l yes yes ( dozer right move r move l yes yes ) dozer left move r move l yes yes = girder rev rev yes no F furnace die die die no \ ramp +1 elev +1 elev yes no / ramp +1 elev +1 elev yes no > conveyor belt right rev rev yes no < conveyor belt left rev rev yes no : replicator rev rev yes no ; special replicator rev rev yes no . upside down replicator rev rev yes no , turn signal no no * crumble-wall break break yes no O output rev rev yes no b byte<-crate crate c char<-crate crate K gate rev rev yes no W winch up rev rev yes no M winch down rev rev yes no V swinch up rev rev yes no A swinch down rev rev yes no + packer rev rev yes no - unpacker rev rev yes no C crate killer die cr die cr die cr no D dozer killer die doz die doz die doz no Planned: I input input input yes no b byte->crate crate c char->crate crate T scale rev rev yes no | door rev rev yes no Kinda Silly (extraneous to real programming): km monkey rev rev yes yes wl weasel rev rev yes yes H mulberry bush rev rev yes yes Q supergoo rev rev yes kinda ~ water wet wet wet kinda u pontoon rev rev yes yes (floats) sz electric eel die die die yes
rube.c is the reference implementation of the RUBE programming language.
In fact, it is far more "reference" than I care for -- if, in this
implementation, a dozer (say) falls on another dozer while it is turning
around and pushing a crate, and that combination results in only one dozer
remaining there (or perhaps creates a new dozer out of nowhere for a total
of three dozers), well, hey, that's what the language defines for that
The reference implementation loads the grid of instructions from an ASCII text file. Coincidentally (because I ripped off the Befunge-93 routines to write it) it's currently restricted to an 80x25 source file. However, that should not be taken as an defining limitation; the language itself imposes no bounds on the size of a RUBE playfield.