ZeroGrid2D
ZeroGrid2D is a 2D grid-based esoteric programming language developed in March 2026 to explicitly prove Turing-completeness in response to doubts about the computational power of its predecessor, ZeroStack2D. Unlike ZeroStack2D (which uses a 2D code grid but linear stack for data), ZeroGrid2D unifies both code and data into dynamic 2D grids (a "dual 2D grid" design):
- Code grid: The program is a 2D grid of commands traversed by the interpreter;
- Data grid: All memory operations use a 2D grid of "Box" cells (each with 4-directional adjacency), directly mapping to Minsky machine registers and Turing machine tape.
This design eliminates indirect data mapping, making ZeroGrid2D's Turing-completeness transparent and easy to verify—while retaining the core 2D grid paradigm of ZeroStack2D.
Core Concepts
Grid Program
The program is stored as a plain text file, where each line of the file represents a row in a 2D grid of commands. The interpreter starts execution at grid coordinates (x=0, y=0) (the top-left corner of the grid).
Box (Memory Cell)
The language's core memory unit is the "Box", which consists of:
- An integer
datavalue (default: 0) - References to adjacent Boxes (
left/right/up/down), dynamically created when navigation commands are executed
Direction Encoding
The interpreter maintains a movement direction (encoded as an integer) that controls both grid pointer movement and Box navigation:
| Code | Direction | Coordinate Change |
|---|---|---|
| 0 | Right | x += 1 |
| 1 | Up | y -= 1 |
| 2 | Left | x -= 1 |
| 3 | Down | y += 1 |
Instruction Set
All valid commands are single characters; any unrecognized character is treated as a no-op (no operation).
| Command | Behavior |
|---|---|
> |
Set movement direction to Right (0) |
< |
Set movement direction to Left (2) |
^ |
Set movement direction to Up (1) |
v |
Set movement direction to Down (3) |
) |
Navigate to the adjacent Box in the current direction (create a new Box if none exists) |
( |
Navigate to the adjacent Box in the opposite direction (create a new Box if none exists) |
+ |
Increment the current Box's data by 1
|
- |
Decrement the current Box's data by 1
|
? |
Read a single character input; store its ASCII value in the current Box |
~ |
Read an integer input; store it in the current Box |
$ |
Reset the current Box's data to 0
|
. |
Print the current Box's data as an integer (with newline)
|
, |
Print the current Box's data as an ASCII character (no newline)
|
| |
Conditional vertical direction: set to Up (1) if data ≠ 0, else Down (3)
|
_ |
Conditional horizontal direction: set to Right (0) if data ≠ 0, else Left (2)
|
@ |
Terminate the program immediately |
| (other) | No operation; continue moving in the current direction |
Execution Rules
- The interpreter initializes at
(x=0, y=0)with a single Box (data = 0) and direction set to Right (0). - For each execution step:
- Read the command at the current grid coordinates (treat out-of-bounds access as a no-op)
- Execute the command (if valid)
- Move the grid pointer one cell in the current direction
- Execution terminates only when the
@command is encountered.
Implementation
Dependencies
- Python 3.x (no external libraries required)
Usage
To run a ZeroGrid2D program:
python ZeroGrid2D.py [path/to/program.txt]
Reference Implementation
The reference interpreter is written in Python 3 and follows the language specification exactly:
#!/usr/bin/python3
import sys, argparse
# Initialize command-line argument parser to accept the grid program file
arg_parser = argparse.ArgumentParser(description="ZeroGrid2D: 2D Grid Esoteric Language Interpreter")
arg_parser.add_argument("input_file", help="Path to the text file containing the ZeroGrid2D grid program")
# Box class: Represents a data cell in the language's memory model
# Each Box holds an integer value and references to adjacent Boxes (left/right/up/down)
class Box():
def __init__(self, data=0):
# Integer data stored in the Box (default: 0)
self.data = data
# Reference to adjacent Box on the left (initially None)
self.left = None
# Reference to adjacent Box on the right (initially None)
self.right = None
# Reference to adjacent Box above (initially None)
self.up = None
# Reference to adjacent Box below (initially None)
self.down = None
# Load the grid program from the input file
try:
# Parse command-line arguments and get the input file path
args = arg_parser.parse_args()
input_file_path = args.input_file
# Read the program file and convert it into a 2D list (grid)
# Each line becomes a list of characters (one per grid cell)
with open(input_file_path, "r") as f:
program_raw = f.readlines()
program = []
for line in program_raw:
program.append(list(line)) # Convert each line to a char list
except (IndexError, FileNotFoundError):
# Exit silently if file not found or argument error (per original behavior)
sys.exit(0)
# Initialize interpreter state
current_box = Box() # Active Box (data cell) being manipulated
x = 0 # Current horizontal position (column) in the grid (starts at 0)
y = 0 # Current vertical position (row) in the grid (starts at 0)
direction = 0 # Current movement direction (0=right,1=up,2=left,3=down)
# Main interpreter loop (runs until @ command is encountered)
while True:
# Get the current command from the grid; default to space (no-op) if out of bounds
try:
cmd = program[y][x]
except IndexError:
cmd = " " # Treat out-of-bounds as empty command (no operation)
# --------------------------
# Direction control commands
# --------------------------
if cmd == ">":
direction = 0 # Set direction to RIGHT (x increases by 1)
elif cmd == "<":
direction = 2 # Set direction to LEFT (x decreases by 1)
elif cmd == "^":
direction = 1 # Set direction to UP (y decreases by 1)
elif cmd == "v":
direction = 3 # Set direction to DOWN (y increases by 1)
# --------------------------
# Box navigation commands
# --------------------------
# ) : Move to/create adjacent Box in CURRENT direction
elif cmd == ")":
if direction == 0: # Current direction: RIGHT
if not current_box.right:
current_box.right = Box() # Create new Box if none exists
current_box = current_box.right # Switch to the right Box
elif direction == 1: # Current direction: UP
if not current_box.up:
current_box.up = Box()
current_box = current_box.up
elif direction == 2: # Current direction: LEFT
if not current_box.left:
current_box.left = Box()
current_box = current_box.left
elif direction == 3: # Current direction: DOWN
if not current_box.down:
current_box.down = Box()
current_box = current_box.down
# ( : Move to/create adjacent Box in OPPOSITE direction
elif cmd == "(":
if direction == 2: # Opposite of LEFT is RIGHT
if not current_box.right:
current_box.right = Box()
current_box = current_box.right
elif direction == 3: # Opposite of DOWN is UP
if not current_box.up:
current_box.up = Box()
current_box = current_box.up
elif direction == 0: # Opposite of RIGHT is LEFT
if not current_box.left:
current_box.left = Box()
current_box = current_box.left
elif direction == 1: # Opposite of UP is DOWN
if not current_box.down:
current_box.down = Box()
current_box = current_box.down
# --------------------------
# Data manipulation commands
# --------------------------
elif cmd == "+":
current_box.data += 1 # Increment current Box's data by 1
elif cmd == "-":
current_box.data -= 1 # Decrement current Box's data by 1
elif cmd == "?":
# Read a single character input, store its ASCII value in current Box
current_box.data = ord(input())
elif cmd == "~":
# Read an integer input, store it in current Box
current_box.data = int(input())
elif cmd == "$":
current_box.data = 0 # Reset current Box's data to 0
# --------------------------
# Output commands
# --------------------------
elif cmd == ".":
# Print current Box's data as an integer (with newline)
print(current_box.data)
elif cmd == ",":
# Print current Box's data as an ASCII character (no newline)
print(chr(current_box.data), end='')
# --------------------------
# Conditional direction commands
# --------------------------
elif cmd == "|":
# Vertical conditional: UP (1) if data !=0, else DOWN (3)
if current_box.data:
direction = 1
else:
direction = 3
elif cmd == "_":
# Horizontal conditional: RIGHT (0) if data !=0, else LEFT (2)
if current_box.data:
direction = 0
else:
direction = 2
# --------------------------
# Termination command
# --------------------------
elif cmd == "@":
sys.exit(0) # Exit the interpreter immediately
# --------------------------
# Move grid pointer based on current direction
# --------------------------
if direction == 0:
x += 1 # Move right (increase column)
elif direction == 1:
y -= 1 # Move up (decrease row)
elif direction == 2:
x -= 1 # Move left (decrease column)
elif direction == 3:
y += 1 # Move down (increase row)
See Also
- Befunge (2D grid-based esolang)