Design a turing-complete marble run with ascii/unicode art
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
marbles
samples
.gitignore
LICENSE.md
README.md
asciify.py
demo.gif
interpret.py
prettify.py
toggler.gif
transformations.txt

README.md

MarbleComplete

Build and simulate your own turing-complete marble runs with ascii/unicode art

I have always had a love for mechanical computers. After reading a wonderful post on turing-complete marble runs, I decided that I wanted to design a turing-complete marble tower. From this desire was born MarbleComplete, the 2d esolang for designing (turing-complete) marble runs using AsciiDots syntax.

Join the chat at https://gitter.im/marble-complete/Lobby

Fun demo looks cool

Unlike it's parent AsciiDots, the only logical operator in MarbleComplete is a toggler:

Turing Tumble Bit Piece

The Turing Tumble kickstarter has a gif of the real life equivalent.

Running the Interpreter

Run python3 interpret.py --help to read about available flags.

For the demo gif, I ran the interpreter in auto-stepped debug mode with a delay of 0.25 seconds. The code was prettified, too.

python3 interpret.py test.marbles -a 0.25 -d -p

Documentation

Starting & Ending

A starting marble is represented with a lowercase o (o).
Program execution ends when a marble rolls over an ampersand (&).

Comments

Everything on a line after a pound symbol (#) is considered a comment and is ignored by the interpreter.

& # This text is a comment.

Paths

Marbles travel down paths (| or -):

o # This is where the program starts
| # The marble travels downwards
| # Keep on going!
& # The program ends

Think as these two paths as mirrors:
/
\

You can use them to make a path turn:

/-&         # This is where the program ends!
|
\-\ /-\
  | | |
/-/ | \-\
\---/   |
        |
        \-o # Here's where the program starts

Special Paths

+ is the crossing of paths (they do not interact)

> acts like a regular, 2-way, horizontal, path, except marbles can be inserted into the path from the bottom or the top. Those marbles will go to the right
< does likewise except new marbles go to the left
^ (caret) does this but upwards
v (the lowercase letter 'v') does likewise but downwards

Here's a way to "bounce" a marble backwards along its original path using these symbols:

/->-- # Input/output comes through here
| |
\-/

But there's an easier way to do that:

( reflects a marble backwards along its original path. It accepts marble coming from the left, and lets them pass through to the right
) does likewise but for the opposite direction

* duplicates a marble and distributes copies including the original marble to all attached paths except the origin of marble

Here's a fun example of using these special paths. Don't worry—we'll soon be able to do more than just start then end a program.

  /-\ /-& # End
  | | |
  \-+-v
    | | /-\
(-<-/ | | |
  |   \-<-/
  \-\
    |
    o    # Start

Togglers

If you want to create a toggler that starts learning left (like \), use a lowercase t (t -> ).
If you want to create a toggler that starts learning right (like /), use an uppercase T (T -> ).

Here's a visualization of what a toggler does:

Toggler

Wires

In order to make togglers move in unison (thereby allowing turing-completeness), connect them with wires.

In ascii, wires are represented via periods (.). These can be automatically prettified into unicode lines (e.g. ).

Gates

Marbles can also be controlled via gates.
An open gate is represented by a colon (:) and a closed gate is represented by an exclamation mark (!).

A gate can be opened/closed via a pulse from a toggler down a connected wire.

Gates are useful when you want to control the order in which marbles move.

IO

Getting input from stdin is very simple. Whenever a marble rolls onto a question mark (?), it reads one character from stdin. If that character is a 0, the marble moves to the left, and if the character is a 1, the marble moves to the right. If the character read from std in is neither a 0 nor a 1, an exception is thrown.

Example:

  o
  |
/-?-\
|   |
|   \-- # the input was `1`
|
\------ # the input was `0`

If a wire activates a 1, a 1 is printed to stdout. If a wire activates a 0, a 0 is printed to stdout.
0's and 1's are conductive, meaning that can act like wires.

Ascii vs Unicode source

Programs are typically written with AsciiDots' ascii path rules:

 /---
 |
 |
/t\
|.+..
\v/ .
/t\ .
|.+./
| |
| *---
| |
| |
| |

... And then translated into Unicode box drawings via prettify.py:

 ╔═══
 ║    
 ║    
╔↘╗   
║╰+┄╮
╚⇓╝ ┆
╔↘╗ ┆
║╰+┄╯
║ ║   
║ *══
║ ║   
║ ║   
║ ║

Prettified code can always be re-asciified via asciify.py.

Sample Programs

Memory Cell:

 o
 |
 v----------------- # query
 |
 |     /----------- # set to 0
 |     |   /------- # set to 1
 |     |   |
 |     |   |    /-- # toggle
 |     v\ /v    |
/t\   /t/ \t\  /t\
|.+.. |.   .|  |.|
\v/ ..+.....+..+.|
/t\ . |     |  | |
|.+.. |     |  | \-- # now 1
| |   |     |  \---- # now 0
0 1

Memory tape:

           /v----o
 o     o   \T
 |    \v\-\ .
 |     !+.+.*
/t\    || | .
|.+.. /T+-* .
\v/ ..+.| | .
 |  . | | | .
/+\ . *-+-v .
||t.. | | | .
\+----+-+-/ .
 |    \v\-\ .
 |     !+.+.*
/t\    || | .
|.+.. /T+-* .
\v/ ..+.| | .
 |  . | | | .
/+\ . *-+-v .
||t.. | | | .
\+----+-+-/ .
 |    \v\-\ .

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.