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();
		}
	}
}