Skip to content

Instantly share code, notes, and snippets.

@9point6
Created January 7, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 9point6/500155218210d1aa4607 to your computer and use it in GitHub Desktop.
Save 9point6/500155218210d1aa4607 to your computer and use it in GitHub Desktop.
Basic CoffeeScript Befunge Interpreter
numberize = (fn) -> (a, b) -> fn Number(a), Number(b)
changeDirection = (pos, direction) ->
if direction is '?' then direction = '^v<>'[parseInt Math.random() * 4]
[pos.dx, pos.dy] = {'^': [0,-1], 'v': [0,1], '<': [-1,0], '>': [1,0]}[direction]
pos
operations =
'+': numberize (a, b) -> a + b
'-': numberize (a, b) -> b - a
'*': numberize (a, b) -> a * b
'/': numberize (a, b) -> ~~(a / b)
'%': numberize (a, b) -> ~~(b % a)
'!': (a ) -> Number !a
'`': (a, b) -> Number b > a
'_': (a ) -> if a is 0 then '>' else '<'
'|': (a ) -> if a is 0 then 'v' else '^'
':': (a ) -> [a, a]
'\\':(a, b) -> [a, b]
'$': (a ) -> []
doOp = (stack, ins, pushResult = true) ->
args = []
args.push stack.pop() ? 0 for i in [0...operations[ins].length]
result = operations[ins].apply null, args
if pushResult then stack.concat result else [stack, result]
doMove = (code, pos) ->
pos.x = (pos.x + pos.dx) % code[pos.y].length
pos.y = (pos.y + pos.dy) % code.length
pos
interpret = (code) ->
output = ""
stack = []
code = code.split('\n').map (x) -> x.split ''
pos = x: 0, y: 0, dx: 1, dy: 0
asciiMode = false
while (instruction = code[pos.y][pos.x]) isnt '@'
if instruction is '"' then asciiMode = asciiMode is false
else if asciiMode isnt false then stack.push instruction.charCodeAt 0
else if /[0-9]/.test instruction then stack.push Number instruction
else if /[<>^v\?]/.test instruction then pos = changeDirection pos, instruction
else if /[|_]/.test instruction
[stack, res] = doOp stack, instruction, false
pos = changeDirection pos, res
else if instruction is '.' then output += stack.pop()
else if instruction is ',' then output += String.fromCharCode stack.pop()
else if instruction is '#' then pos = doMove code, pos
else if /[pg]/.test instruction
[y, x] = [stack.pop(), stack.pop()]
if instruction is 'p' then code[y][x] = stack.pop()
else stack.push code[y][x].charCodeAt?(0) ? code[y][x]
else if instruction isnt ' ' then stack = doOp stack, instruction
pos = doMove code, pos
output
@9point6
Copy link
Author

9point6 commented Jan 7, 2015

Missing the commands requiring user input for the time being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment