Skip to content

Instantly share code, notes, and snippets.

@gberger
Last active August 29, 2015 13:56
Show Gist options
  • Save gberger/9258741 to your computer and use it in GitHub Desktop.
Save gberger/9258741 to your computer and use it in GitHub Desktop.
Befunge interpreter in CoffeeScript
interpret = (code) ->
commands =
'+' : =>
@stack.push(@stack.pop() + @stack.pop())
'-' : =>
@stack.push(-@stack.pop() + @stack.pop())
'*' : =>
@stack.push(@stack.pop() * @stack.pop())
'/' : =>
a = @stack.pop()
b = @stack.pop()
if a == 0
@stack.push(0)
else
@stack.push(Math.floor(b/a))
'%' : =>
a = @stack.pop()
b = @stack.pop()
if a == 0
@stack.push(a)
else
@stack.push(b%a)
'!' : =>
@stack.push(if @stack.pop() == 0 then 1 else 0)
'`' : =>
@stack.push(if @stack.pop() < @stack.pop() then 1 else 0)
'>' : => @direction = '>'
'<' : => @direction = '<'
'^' : => @direction = '^'
'v' : => @direction = 'v'
'?' : => @direction = '><^v'[Math.floor(Math.random()*4)]
'_' : =>
@direction = (if @stack.pop() == 0 then '>' else '<')
'|' : =>
@direction = (if @stack.pop() == 0 then 'v' else '^')
'"' : =>
@strMode = !@strMode
':' : =>
a = @stack.pop()
if a is undefined
@stack.push(0)
else
@stack.push(a)
@stack.push(a)
'\\' : =>
a = @stack.pop()
b = @stack.pop() or 0
@stack.push(b)
@stack.push(a)
'$' : =>
@stack.pop()
'.' : =>
@output += @stack.pop().toString()
',' : =>
@output += String.fromCharCode(@stack.pop())
'p' : =>
y = @stack.pop()
x = @stack.pop()
v = @stack.pop()
@codeMap[y][x] = String.fromCharCode(v)
'g' : =>
y = @stack.pop()
x = @stack.pop()
@stack.push(@codeMap[y][x].charCodeAt(0))
for i in [0..9]
commands[i] = do (i) => => @stack.push(i)
mright = =>
@x += 1
if @x >= @width
@x = 0
mleft = =>
@x -= 1
if @x < 0
@x = @width - 1
mup = =>
@y -= 1
if @y < 0
@y = @height - 1
mdown = =>
@y += 1
if @y >= @height
@y = 0
move = =>
{
'>' : mright
'<' : mleft
'^' : mup
'v' : mdown
}[@direction]()
@direction = '>'
@codeMap = code.split('\n').map (c) -> c.split('')
@width = 80
@height = 25
@stack = []
@output = ''
@x = 0
@y = 0
@strMode = false
while true
cmd = @codeMap[@y][@x]
if @strMode and cmd isnt '"'
@stack.push(cmd.charCodeAt(0))
move()
else
switch cmd
when '@'
return @output
when ' '
move()
when '#'
move()
move()
else
commands[cmd]()
move()
2>:3g" "-!v\ g30 <
|!`"O":+1_:.:03p>03g+:"O"`|
@ ^ p3\" ":<
2 234567890123456789012345678901234567890123456789012345678901234567890123456789
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment