Triforce
Triforce is a tape based esoteric programming language designed by Anthony Ma in 2013. Triforce is identical to brainfuck while purely using triangles, and with the addition of an operator that resets a memory cell to 0. Triforce files are stored with the extension .▲ The language and name is inspired by the Triforce of the Legend of Zelda series.
Overview
Triforce has a total of 14 operands:
Command | Description |
---|---|
▶
|
Move the pointer to the right |
◀
|
Move the pointer to the left |
▲
|
Increment the memory cell under the pointer |
▼
|
Decrement the memory cell under the pointer |
⧏
|
Output the character signified by the cell at the pointer |
⧐
|
Input a character and store it in the cell at the pointer |
⧎
|
Input and output a character at the same time |
[Space]
|
Reset the memory cell under the pointer to 0 |
◤
|
Jump past the matching ◥ if the cell under the pointer is 0
|
◥
|
Jump back to the matching ◤ if the cell under the pointer is nonzero
|
◢
|
Jump back to the first memory pointer |
◣
|
Jump past to the last memory pointer |
◮
|
Switch to integer mode |
◭
|
Switch to ASCII mode |
Switching to integer will just shift all input and output by 48.
Examples
Hello, World!
Here's the example brainfuck program with the program converted to Triforce:
brainfuck:
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-] <.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.
Triforce:
▶▲▲▲▲▲▲▲▲▲◤◀▲▲▲▲▲▲▲▲▶▼◥◀⧏▶▲▲▲▲▲▲▲◤◀▲▲▲▲▶▼◥◀▲⧏▲▲▲▲▲▲▲⧏⧏▲▲▲⧏▶▶▶▲▲▲▲▲▲▲▲◤◀▲▲▲▲▶▼◥ ◀⧏▶▶▶▲▲▲▲▲▲▲▲▲▲◤◀▲▲▲▲▲▲▲▲▲▶▼◥◀▼▼▼⧏◀◀◀◀⧏▲▲▲⧏▼▼▼▼▼▼⧏▼▼▼▼▼▼▼▼⧏▶▶▲⧏
Implementation
The following is an interpreter of Triforce written in Java with a max pointer register length of 1024. The argument it takes in is the path to the Triforce script. A .jar of the following interpreter is available here.
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; public class Triforce { public static void main(String[] args) { try { parse(readFile(args[0])); } catch (IOException e) { e.printStackTrace(); } } public static void parse(String stuff) { final int toInt = '\u25ee'; final int toAscii = '\u25ed'; final char up = '\u25b2'; final char down = '\u25bc'; final char left = '\u25c0'; final char right = '\u25b6'; final char rightb = '\u25e3'; final char leftb = '\u25e2'; final char rightu = '\u25e5'; final char leftu = '\u25e4'; final char space = ' '; final char nl = '\n'; final char in = '\u29d0'; final char out = '\u29cf'; final char inOut = '\u29ce'; boolean intOut = false; int loopCount = 0; int line = 1; int[] count = new int[1024]; int reg = 0; int nextChar; char[] chars = stuff.toCharArray(); InputStreamReader converter = new InputStreamReader(System.in); BufferedReader input = new BufferedReader(converter); for (nextChar = 0; nextChar < chars.length; nextChar++) { char c = chars[nextChar]; switch (c) { case toInt: intOut = true; break; case toAscii: intOut = false; break; case up: count[reg]++; break; case down: count[reg]--; break; case rightb: reg = 0; break; case leftb: reg = 1023; break; case rightu: if (count[reg] != 0) { for (nextChar = nextChar; nextChar > 0; nextChar--) { if (chars[nextChar] == leftu) { break; } } } else { loopCount--; if (loopCount != 0) { System.out.println("line " + line + ": possible unopened " + leftu); } } break; case leftu: if (count[reg] == 0) { for (nextChar = nextChar; nextChar < chars.length; nextChar++) { if (chars[nextChar] == rightu) { break; } } } else { if (loopCount != 0) { System.out.println("line " + line + ": possible unclosed " + rightu); } loopCount++; } break; case right: if (reg < 1023) reg++; else System.out.println("line " + line + ": max register reached(" + reg + ")"); break; case left: if (reg > 0) reg--; else System.out.println("line " + line + ": min register reached(" + reg + ")"); break; case space: count[reg] = 0; break; case nl: if (loopCount == 0) { line++; } break; case out: if (intOut) System.out.print(count[reg]); else System.out.print((char)count[reg]); break; case in: try { if (intOut) count[reg] = (char)input.read() - 48; else count[reg] = (char)input.read(); } catch (IOException e) { e.printStackTrace(); } break; case inOut: try { if (intOut) count[reg] = (char)input.read() - 48; else count[reg] = (char)input.read(); } catch (IOException e) { e.printStackTrace(); } if (intOut) System.out.print(count[reg]); else System.out.print((char)count[reg]); break; default: System.out.println("line " + line + ": unexpected char '" + c + "'"); break; } } try { converter.close(); input.close(); } catch (IOException e) { e.printStackTrace(); } } private static String readFile(String path) throws IOException { FileInputStream stream = new FileInputStream(new File(path)); try { FileChannel fc = stream.getChannel(); MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); return Charset.defaultCharset().decode(bb).toString(); } finally { stream.close(); } } }