When was this language released?

A Brief History of 2D Programming Languages: 16 (+2) years

v19977/2{@{{4{\_______>/02&&&#????        *    P+++++1P1P-1P+1E     *                         *
\'\02'oo100@n590@n;                       *                         *                         *
>"8991",,,;5-;,@                          *                         *                         *
   *                                      *                         *                         *
  \ *              ++++++++++++++++++++++++  ++++++++++++++++++++++++  ++O--OO++++++++OX*******      *
     *   #2018O@       *                  *      *                  *      *                  *      *
      *                *                  *      *                  *      *                  *      *
       *               *                  *      *                  *      *                  *      *
        *           ****    ****          *   ****    ****          *   ****    ****          *   ****    *****
         *         *   *   *    *         *  *   *   *    *         *  *   *   *    *         *  *   *   *
          *        *   *  *      *        *  *   *  *      *        *  *   *  *      *        *  *   *  *
           *      *    * ****     *       * *    * ****     *       * *    * ****     *       * *    * ****
            *     *    *     *            * *    *     *            * *    *     *            * *    *     *
R"2014";     *****      *******       ******      *******       ******      *******       ******      *******

 x
x%"2010"x
 x

$'main'        \/\/\/\
 \-[2005]o-#   \++++++\
               /++++++/
               \++++++\
               /++++++/
               \/\/\/\++.--..+++.#

S1^2^2^6^8MAOUOAOOF

      /K:0:1:@

  >      "7102"4&o@

|        }+++++[>++++++++++<-]>.--..++++++.@

Did I mention that I like 2D programming languages?

1993: Befunge

The language that (allegedly, see the last section) started it all. In Befunge, you can redirect the control flow with <v>^, but the now ubiquitous mirrors \ and / weren't a thing yet. The Befunge interpreter used on Anarchy Golf ignores unknown commands. We can use this to distinguish the Befunge family from the ><> family. Hence, the code executed by Befunge is this:

v
\
>"8991",,,;5-;,@

The "8991" pushes the individual characters onto the stack. ,,, prints the first three of them. Then ; is unknown (which we'll use to distinguish it from Befunge 98), 5- turns the 8 into a 3 and , prints that as well before @ terminates the program.

1997: Wierd

Writing this part of the solution took me probably as long as writing all the others and fitting them together...

Wierd only knows two symbols: space, and everything else. The instruction pointer tries to follow the path formed by the non-space characters, starting diagonally from the top left corner and always trying to go as straight as possible. The bends in the path form the actual instructions (with the degrees of the turn determining which instruction to execute). So the code seen by Wierd is this:

v1997                                     *                         *                         *
 '                                        *                         *                         *
  8                                       *                         *                         *
   *                                      *                         *                         *
    *              ++++++++++++++++++++++++  ++++++++++++++++++++++++  ++O--OO++++++++OX*******      *
     *                 *                  *      *                  *      *                  *      *
      *                *                  *      *                  *      *                  *      *
       *               *                  *      *                  *      *                  *      *
        *           ****    ****          *   ****    ****          *   ****    ****          *   ****    *****
         *         *   *   *    *         *  *   *   *    *         *  *   *   *    *         *  *   *   *
          *        *   *  *      *        *  *   *  *      *        *  *   *  *      *        *  *   *  *
           *      *    * ****     *       * *    * ****     *       * *    * ****     *       * *    * ****
            *     *    *     *            * *    *     *            * *    *     *            * *    *     *
             *****      *******       ******      *******       ******      *******       ******      *******

The 1997 at the top isn't actually executed, but Wierd lets us read it from the source code, which is a lot shorter than trying to construct the character codes for the four digits itself (even if it doesn't look like it...). I don't feel like breaking this entire thing down, but you can clearly see the four repeated sections. What this does is that we first store 1 on the stack and then each of those four sections increments this 1, and then branches. The bottom branch pushes another 1, retrieves the source character at these coordinates and prints it, whereas the top branch is redirected to the next section. You might wonder why the ends of the paths are so unnecessarily long, but that's because when Wierd hits the end of a path it tries to jump to a nearby path before deciding that it should terminate the current branch. To avoid this, we need to move these ends sufficiently far away from any other code.

1998: Befunge 98

Befunge got a fairly well-known update in 1998 with a very rigorous spec that can be generalised to arbitrary dimensions (and I think also arbitrary topologies). It's largely backwards-compatible with Befunge though, which makes it fairly easy to polyglot the two. This Befunge still didn't have any mirrors, so the executed path is the same as for Befunge 93:

v
\
>"8991",,,;5-;,@

The difference is that Befunge 98 doesn't ignore the ;. Instead it acts a bit like a comment in that all commands until the next ; are ignored. This way, we don't decrement that 8 to 3 and print the 1998 as is.

2001: A Space Od... PingPong

2001 is the year of Piet, but I really didn't feel like polyglotting an image file with all the other programs, so here is a lesser known 2D language. It seems to have quite a lot of features (which we're not going to use). Thanks to Sp3000 for finding the original interpreter (which is the only dead link on the archived version of the official website).

PingPong is somewhat unusual in that it has only mirrors and no <v>^ redirectors. So this moves through the v19977 at the start and then hits the mirror which wraps it to the bottom. The relevant code is then:

v19977/

...

      /K:0:1:@

...

The actual code is quite simple: K pushes 20, the digits push themselves, : prints an integer and @ terminates the program.

2003: SNUSP

This is first language where things get a bit easier, because SNUSP supports an explicit entry point. That entry point is marked by $. Judging from some articles on esolangs, this language has inspired several others, but unfortunately, at the end of the day it's just a Brainfuck derivative. That said, I think the way this sets the current cell to 48 is quite neat (and was stolen from the esolangs article). Here is the relevant part of the code:

$'main'        \/\/\/\
               \++++++\
               /++++++/
               \++++++\
               /++++++/
               \/\/\/\++.--..+++.#

Those are 24 +s and the mirrors send the IP through each one exactly twice.

2004: Axo

For whatever reason, this language does have the <^> redirectors but instead of the usual v it uses %. Hence this just moves across the first line. The relevant code is:

v19977/2{@{{4{\

We push a few digits to begin with, perform a division. Then 2{ prints the 2, @ clears the stack. {{ prints two (implicit) 0s. 4{ prints the 4 and \ terminates the program.

2005: Rail

2005 was a difficult choice. For no other year did I find as many 2D languages, and there is ADJUST and Archway, both of which start in the lower left corner (which would have made them easy additions). I like Rail though and since it has an explicit entry point is wasn't hard to add either. Rail looks for a line start with $'main' and starts moving south-east from the $. That means the relevant code is:

$'main'
 \-[2005]o-#

The \ and - are just tracks (no-ops). The [2005] is a string literal which o prints before # terminates the program.

2006: BestFriends.js

A two-dimensional Brainfuck. There is another interesting language for this year called Black, which starts at coordinate (3,3) (1-based) which would have made using this in a polyglot interesting, too. I couldn't find an interpreter though. So we'll have to work with another BF-derivative instead...

The interesting thing about this one is that it doesn't format the grid into lines with linefeeds like most other 2D languages. Instead | is used as the line separator. Since I didn't use | for any other languages, I could simply put a | on the last line which makes the entire rest of the program a single line as far as BF.js is concerned. The relevant code is then this (turning the | into an actual linefeed):

v19977/2{...
        }+++++[>++++++++++<-]>.--..++++++.@

BF.js uses neither <v>^ nor mirrors. The only ways to redirect control flow is with {} which turn the IP direction by 90°. So those braces move the IP to the second line. The remainder is a plain Brainfuck solution (not particularly well golfed) that sets a cell to 50 (code point of 2) and then prints 2006 by shifting the value around a bit. @ terminates the program.

2008: BrainSpace 1.0

For this year I really wanted to use DOBELA which uses multiple entry points and looks like the lovechild of Fission and Ziim. Unfortunately, I haven't been able to get the interpreter to work. So here is another BF derivative (the last one, I promise).

As opposed to the last one, this one knows both <v>^ and mirrors, so the relevant code is:

v
\'\
  8

  \ *              ++++++++++++++++++++++++  ++++++++++++++++++++++++  ++O--OO++++++++OX

This one doesn't have the usual BF-style [] loop (instead you'd need to form an actual 2D loop), so I just decided to hardcode the 50 since I had a ton of characters in a row from Wierd anyway. Note that the ' and 8 are ignored, the * is a conditional trampoline which we can ignore and the O is Brainfuck's .. The X terminates the program.

2009: ><>

Probably the most popular Fungeoid (other than Befunge itself) at least around these parts. ><> has both <v>^ and mirrors but also string literals, so the executed code is this:

v
\'\02'oo100@n590@n;

The string literal mostly serves to skip the \ we used for BrainSpace 1.0 but while we're at it we might as well push the first two characters. oo prints them. Then 100 pushes three digits, @ shoves the top one to the bottom and n prints the 0 underneath. We do the same thing again with 590 which prints the 9. If you're wondering why I'm not just printing 2009 as is, wait for 2015. ; terminates the program.

2010: Cardinal

This one was simple, because it has an explicit entry point at %. However, this one creates 4 IPs in all directions (hence the language name, I suppose), and we need to get rid of 3 of them. Here is the relevant code:

 x
x%"2010"x
 x

Well, yeah. (In Cardinal, string mode prints directly instead of pushing the characters onto a stack.)

2011: RunR

Another language with an explicit entry point (by David Catt who has created a few other very nice esolangs), this time at S. This makes the relevant code this part:

S1^2^2^6^8MAOUOAOOF

RunR is a bit interesting because most operations work with a sort of register and values need to be moved to the stack explicitly for binary operations. The digits set the register values to themselves and ^ pushes the current register to the stack. Then M is multiplication (register times value popped from stack), U is subtraction, A is addition, O is output. F terminates the program.

2012: Ropy

Like Wierd, Ropy tries to follow sections of non-space characters, but here the bends don't determine the commands. In fact, it turns out that Ropy is more similar to my own Labyrinth in that the chosen direction depends on the top of the stack. However, we don't really need to worry about that here, because Ropy just moves along the first line:

v19977/2{@{{4{\_______>/02&&&#????

There's a lot of stuff we can ignore up to the >. All we need to know is that the top of the stack will at that point be a 4 and there'll be 2 below.

> duplicates the 4, / is division turning it into a 1. Then we push 02. &&& joins the top four numbers of the stack in reverse order, giving 2012. # outputs it. ???? just clears the stack because otherwise the top of the stack is output as well.

One point of interest is that the second 7 in 19977 was added because of Ropy. The / division in Ropy does top / second (opposite of the usual order in many stack-based languages), where 7 / 9 would give 0. If we had a zero on top of the stack, Ropy would do some wild stuff with its direction of movement, so we need to push the other 7 to ensure that the top of the stack remains positive and Ropy keeps moving east.

2014: Fission

With its explicit entry points, this one is easy. RDLU create atoms (instruction pointers) in the corresponding direction, so the relevant bit is just this:

R"2014";

Note that there's a U in the source code as well, but that atom eventually hits one of the * from Wierd, which terminates the program (and this atom takes a lot longer than the R needs to print 2014).

2015: Gol><>

Sp3000's more powerful ><> derivative. It's largely backwards compatible with ><> so the executed code is still:

v
\'\02'oo100@n590@n;

However, the rotation direction of @ was changed, which is the standard trick to distinguish ><> and Gol><> in polyglots, so this one prints 15 instead of 09. Hence the weirdness in the second half of the program.

2016: CSL

CSL is quite interesting in that commands aren't executed immediately. Instead, each command is pushed onto a command-stack and e and E can be used to execute commands from it. The relevant code becomes:

v19977/2{@{{4{\_______>/02&&&#????        *    P+++++1P1P-1P+1E

So the E executes the entire command stack, which means that the stuff in front of it is executed in reverse. We only need to look up to the *:

1+P1-P1P1+++++P*

The 1s push themselves onto the data stack. + and - are decrement/increment. P prints the top of the stack. Then * tries to multiply the top two values of the stack. However, the stack is empty, so this terminates the program.


At this point we get to languages which were released after this challenge was posted, so I'm not really counting them for the score, especially since I created these myself (not with this challenge in mind though). However, they do have some novel IP movement semantics, which made it easy to fit them into the polyglot while also adding something interesting to this showcase of 2D languages.

2017: Alice

Alice was designed to be a feature-rich Fungeoid. One interesting difference to the majority of (but not all) other 2D languages is that the IP can move either orthogonally, or diagonally. Switching between these also changes the semantics of almost all commands in the language. Furthermore, Alice supports both the traditional <^>v direction setters and \/ mirrors, but mirrors have very unique behaviour in Alice (which makes it easy to lead the Alice IP to a so far unused portion of the code).

While most languages treat \ and / as if they were mirrors at a 45° angle, and the IP as a light ray bouncing off of it, Alice treats them as having a 67.5° angle (which is closer to the angle of the actual slash glyphs), and the IP also moves through the mirror (hence the language's name). Due to this angle, mirrors switch between movement along orthogonal or diagonal directions. Furthermore, while in Ordinal mode (i.e. while the IP moves along diagonals), the grid doesn't wrap around and instead the IP bounces off the edges (whereas in Cardinal mode it does wrap around).

All in all, the code executed by Alice is the following:

v19
\ \

...

  >      "7102"4&o@

...

The IP starts in the top left corner as usual, v sends it south. Now the \ reflects the IP to move northwest, where it immediately bounces off the left edge of the grid (and moves northeast instead). 1 can be ignored, the IP bounces off the top edge to move southeast next. We hit another \ which reflects the IP north. 9 can also be ignored and then the IP wraps to the bottom of the grid. After a couple of lines we redirect it east with > for convenience. Then "7102" pushes the code points of the 2017, 4&o prints those four characters and @ terminates the program.

2018: Wumpus

Wumpus is the first 2D language on a triangular grid, which makes movement through the code quite different (and again lets us reach an unused part of the code easily). So instead of thinking of each character in the grid as a little square, you should think of them as alternating upward and downward triangles. The top left corner is always an upward triangle.

Wumpus doesn't have direction setters like <^>v, but it does have mirrors \/. However, due to the triangular grid, these work differently from most other languages. The IP bounces off them like a light ray (as usual) but you should think of them as having an angle of 60° degrees. So an IP moving east will end up moving along the northwest axis of the grid.

As another difference to most other languages, the edges of the grid don't wrap, but the IP bounces off the edges instead (as if those edge cells contained the appropriate mirrors). Another fun little detail is that diagonals through the triangular grid actually look like staircases in the source code.

With that in mind, the code executed by Wumpus is the following (where I've replaced spaces with . for clarity:

v19977/
   02
  89
 ..
..
.....*...#2018O@

The v19977 are just junk that we can ignore. / sends the IP northwest, where it moves through the 977 (from the right) again while bouncing off the top edge. Then the IP moves southwest through the 2089 and a bunch of spaces, before it hits the left edge to be reflected east again. * is also junk. Then finally #2018 pushes 2018, O prints it and @ terminates the program.


Missing years

Finally, some notes about years I haven't covered.

While researching 2D languages to find suitable ones across the years which could be used in a polyglot, I found out that contrary to popular belief, Befunge was not the first 2D language. That title seems to be held by Biota which was already created in 1991. Unfortunately, the language doesn't have any output, so I wasn't able to use it for this challenge.

As far as I can tell no 2D languages were created in 1992 and 1995. That leaves a few years I haven't covered:

  • 1994: Orthagonal was created, independently of Befunge. The languages are semantically quite similar actually, but Orthagonal doesn't actually lay out the source code in 2D. Instead each line is an (x, y, instruction) tuple. I even obtained the language spec and original interpreter from the creator Jeff Epler, but in the end, the fact that the syntax isn't 2D made the language unsuitable for this polyglot.
  • 1996: Orthogonal, a successor to Orthagonal (created by someone else) was created, but for the purposes of this polyglot suffers the same problems as Orthagonal.
  • 1999: The only language I could find was Chris Pressey's cellular automaton REDGREEN. Unfortunately, as opposed to its predecessor RUBE, it doesn't seem to have any I/O semantics.
  • 2000: There's another cellular automaton of Chris Pressey's called noit o' mnain worb but it also doesn't have any I/O. There's also Numberix which I haven't tried to get running and I'm not sure whether it would ignore non-hex characters in the source code.
  • 2002: There's Clunk with no I/O and ZT whose language specification terrifies me.
  • 2007: I found three languages here. Zetaplex is image based (so nope) and RubE On Conveyor Belts seems to require a header with a rather strict format which would have messed with the first line of the program. There's also Cellbrain by Quintopia, but it also seems to require a specific header.
  • 2013: Again, I found three languages. Fishing might be possible with a good amount of restructuring but it would require the program to begin with a valid dock. Quipu, from memory, is way too strict about its syntax to allow much polyglotting. And Swordfish is another member of the ><> family, but unfortunately I haven't been able to find an interpreter. Otherwise, this one would probably be fairly easy to add.

If anyone is interested, here is the complete list of implemented 2D languages sorted by years as far as I could find them (at the time this answer was posted). If any are missing from this list, please let me know in chat as I'd be really interested in a complete list.


15 years, Python

Versions: 0.9.1, 2.0.0, 2.2.0, 2.2.2, 2.5.0, 2.5.1, 3.0.0, 3.1.0, 3.1.3, 3.2.1, 3.3.0, 3.3.3, 3.4.0, 3.5.0 and 3.6.0a4. Versions not linked can be found on the downloads page.

The release date of 0.9.1 can be found here. Unfortunately I had to skip a large bunch of years due to missing old versions and compilation problems on my computer. The represented years are 1991, 2000-2002 and 2006-2016.

Tested on Arch Linux, using the gzipped versions.

# Note: This file needs a trailing newline due to 0.9.1

# 0.9.1: No bitwise operators
# This one errors out by division by zero.
try:
    eval('1&2')
except:
    print(1991)
    1/0

import sys

# 2.0.0: repr('\n') gives "'\012'" instead of "'\n'"
# == doesn't exist until Python 0.9.3 and <> doesn't exist in Python 3, hence we
# use <. Also, 0.9.1 doesn't have double quoted strings.
if repr('\n') < '\'\\n\'':
    print(2000)
    sys.exit()

# 2.2.0: email module still has a _Parser class - module revamped in 2.2.2
# I would use whether or not True exists as a name here, but weirdly "True"
# worked in 2.2.2 even though the docs say it was introduced in 2.3...
try:
    import email
    email._Parser
    print(2001)
    sys.exit()
except AttributeError:
    pass

# 2.2.2: a in b only works for strings a of length 1.
try:
    eval('"art" in "Martin"')
except TypeError:
    print(2002)
    sys.exit()

# 2.5.0: int() allows null bytes in integer to convert when given an explicit
# base.
try:
    print(int('2006\x00Hello, World!', 10))
    exit()
except ValueError:
    pass

# 2.5.1: pow overflows
# Note that we can't use ** here since that doesn't exist in 0.9.1.
if pow(2, 100) < 1:
    print(2007)
    exit()

# 3.0.0: round returns a float rather than an int.
if str(round(1, 0)) > '1':
    print(2008)
    exit()

# 3.1.0: bug caused complex formatting to sometimes drop the real part.
if format(complex(-0.0, 2.0), '-') < '(-':
    print(2009)
    exit()

# 3.1.3: str of a float is shorter than the repr of the same float.
if str(1.0/7) < repr(1.0/7):
    print(2010)
    exit()

# 3.2.1: For some weird reason, u'...' Unicode strings were disabled then
# re-enabled later.
try:
    eval('u"abc"')
except:
    print(2011)
    exit()

# 3.3.0: int still works without a first argument.
try:
    int(base=10)
    print(2012)
    exit()
except TypeError:
    pass

# 3.3.3: no enum module :(
try:
    import enum
except ImportError:
    print(2013)
    exit()

# 3.4.0: PEP 448 (additional unpacking generalisations) not implemented yet
try:
    eval('[*[1], *[2], *[3]]')
except SyntaxError:
    print(2014)
    exit()

# 3.5.0: No f-strings
try:
    eval('f"abc"')
except SyntaxError:
    print(2015)
    exit()

print(2016)

Short and sweet; the three APLs (K, J201, Dyalog 7.1) in 8 bytes

1993+1^2

1993 plus...

K: the first 1 integer {0} except {2}, i.e. {0}; 1993 – Try it online!

J: 12 = 1; 1994 – Try it online!

APL: LCM(1,2) = 2; 1995 – Try it online!