BooleanFunge/Interpreter

From Esolang
Jump to navigation Jump to search

BooleanFunge interpreter in Python, without input:

from random import randint
import os.path
import sys

# GLOBAL VARIABLES
grid = []
x = 0 # X COORDINATE OF POINTER
y = 0 # Y COORDINATE OF POINTER
direction = "right" # CURRENT DIRECTION OF MOTION
stack = [] # LIFO NUMBER STORAGE
directions = ["left", "up", "right", "down"] # ALL POSSIBLE DIRECTIONS

def main():
    """Read file and repeatedly traverse grid"""
    grid = readFile()
    while grid[y][x] != "@" or True in grid:
        step()

def readFile():
    """Read the file at the first commandline argument and griddify it"""
    # CONFIRM A FILENAME WAS GIVEN
    if len(sys.argv) < 2:
        print "ERROR: No input file specified!"
        sys.exit()
    filename = sys.argv[1]

    # CONFIRM VALID FILENAME
    if not os.path.isfile(filename):
        print "ERROR: Specified input file does not exist!"
        sys.exit()

    # GET GRID DIMENSIONS
    numLines = 0
    lineLength = 0
    with open(filename) as f:
        for line in f:
            numLines += 1
            lineLength = max(lineLength, len(line.rstrip('\n')))

    # GENERATE THE GRID
    for row in range(numLines):
        grid.append([])
        for col in range(lineLength):
            grid[row].append(" ")

    # POPULATE THE GRID
    with open(filename) as f:
        row = 0
        for line in f:
            col = 0
            for char in line:
                if char != "\n":
                    grid[row][col] = char
                col += 1
            row += 1

    return grid

def printGrid(grid):
    """
    Print the contents of a given grid into the terminal
        Useful for debugging

    Keyword arguments:
    grid -- the grid to print out
    """
    for row in grid:
        for col in row:
            print col,
        print

def step():
    """Advance the Befunge grid one step"""
    processInstruction(grid[y][x],x,y)
    move()

def processInstruction(instruction,x,y):
    """
    Process the instruction that's currently being pointed to

    Keyword arguments:
    instruction -- string representation of the current instruction
    """

    global direction

    if instruction == " ":
        pass
    elif instruction == ">":
        direction = "right"
        stack.append(1)
    elif instruction == "<":
        direction = "left"
        stack.append(0)
    elif instruction == "^":
        if len(stack) == 0:
            instruction = '<'
            direction = "left"
            stack.append(0)
        elif len(stack) == 1:
            instruction = '>'
            direction = "right"
            stack.append(1)
        else:
            stack.pop(2)
            direction = "up"
        grid[y][x] = instruction
    elif instruction == "v":
        direction = "down"
        stack.pop(randint(0,1))
    elif instruction == "#":
        value = stack.pop()
        if value == 0:
            direction = (directions.index(directions)+1)%4
        else:
            direction = (directions.index(directions)-1)%4
    elif instruction == "&":
        if len(stack) < 8:
            grid[y][x] = "$"
        else:
            print(stack.pop())

def move():
    """Move the pointer in the current direction"""
    global x
    global y
    if direction == "right":
        x += 1
    elif direction == "left":
        x -= 1
    elif direction == "up":
        y -= 1
    elif direction == "down":
        y += 1

    if x < 0:
        x += len(grid[0])
    elif x == len(grid[0]):
        x = 0
    if y < 0:
        y += len(grid)
    elif y == len(grid):
        y = 0

main()