Last active
December 16, 2015 08:08
-
-
Save fowlmouth/5403274 to your computer and use it in GitHub Desktop.
SNUSP Needed a stACK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
esolangs.org /==.==<==\ | |
/wiki/SNUSP | | | |
/+++++++++++==&\==>===?!/==<<==# | |
\+++++++++++\ | | |
$==>==+++++++++++/ \==>==,==# |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/ 'B' @=@@=@@++++# | |
// / 'u' @@@@@=@+++++# | |
// // / 'z' @=@@@@+@++++# | |
// // // / 'i' @@@@@@=+++++# | |
// // // // / 'F' @@@=@@+++++# | |
// // // // // / NL ++++++++++# | |
// // // // // // / 100 @@@=@@@=++++# | |
$@/>@/>@/>@/>@/>@/>@/\ 0 | |
/ / http://rosettacode.org/wiki/FizzBuzz | |
! /======= Fizz <<<.<.<..>>># | |
/ | \ | |
\?!#->+ @\.>?!#->+ @\.>?!#->+@/.>\ | | |
/ ! ! ! / | | |
\?!#->+ @\.>?!#->+@\ .>?!#->+@/.>\ | | |
/ ! \!===\! ! / | | |
\?!#->+ @\.>?!#->+ @\.>?!#->+@/.>\ | | |
/ ! ! | ! / | | |
\?!#->+@\ .>?!#->+ @\.>?!#->+@/.>\ | | |
/ \!==========!===\! ! / | | |
\?!#->+ @\.>?!#->+ @\.>?!#->+@/>>@\.>/ | |
! | | | | |
/==========/ \========!\=== Buzz <<<<<<<.>.>..>>># | |
| | |
\!/=dup==?\>>@\<!/back?\<<<# | |
\<<+>+>-/ | \>+<- / | |
| | |
/======================/ | |
| | |
| /recurse\ #/?\ zero | |
\print=!\@\>?!\@/<@\.!\-/ | |
| \=/ \=itoa=@@@+@+++++# | |
! /+ !/+ !/+ !/+ \ mod10 | |
/<+> -\!?-\!?-\!?-\!?-\! | |
\?!\-?!\-?!\-?!\-?!\-?/\ div10 | |
# +/! +/! +/! +/! +/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class GosuInput | |
def initialize | |
@t = Gosu::TextInput.new | |
@i = 0 | |
end | |
def open?() $window.text_input == @t end | |
def open | |
$window.text_input = @t | |
end | |
def hasInput? | |
@i < @t.text.size | |
end | |
def text; @t.text end | |
def readChar | |
r = text[@i] | |
@i += 1 | |
r | |
end | |
def writeChar c; nil; end | |
end | |
class OutputHandler | |
attr_accessor :file | |
def initialize file | |
@file = file | |
end | |
def open?; !file.closed? end | |
def open; file.open unless open? end | |
def writeChar c; file.write c end | |
end | |
class GosuOutput | |
attr_reader :font, :text,:pos | |
def initialize font, text='' | |
@font=font | |
@pos = Vec.new(10,10) | |
@text = text | |
end | |
def pos=(p) @pos = Vec.new(p.x,p.y) end | |
def draw | |
h = font.height | |
text.split(?\n).each_with_index do |line, i| | |
font.draw line, pos.x, pos.y + i * h, 0 | |
end | |
end | |
def writeChar c; text << c; end | |
def open()end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%w/gosu ostruct optparse/.each &method(:require) | |
include Gosu | |
file = nil | |
playfieldSize = nil | |
mode = :SNACK | |
ipf = 1 | |
font = './LiberationMono-Regular.ttf' | |
autostart = false | |
opars = OptionParser.new do|o| | |
o.on '-f', '--file FILE', 'File to load' do|f| | |
unless File.exists? f | |
raise "File does not exist: #{f}" | |
else | |
file = f | |
end | |
end | |
o.on '--autostart', 'hmm' do | |
autostart = true | |
end | |
o.on '--font F', "specify a MONOSPACE font. (default: #{font})" do|f| | |
font = f | |
end | |
o.on '--ipf NUM', "specify the instructions per frame. (default: #{ipf})" do |i| | |
ipf = i.to_i | |
end | |
o.on '-s', '--size X,Y', 'Size of the field' do|s| | |
playfieldSize = Vec.new(*s.scan(/(\d+),(\d+)/).flatten.map(&:to_i)) | |
end | |
o.on '--screen SIZEX,SIZEY', 'Size of the screen' do|s| | |
ScreenW, ScreenH = *s.scan(/(\d+),(\d+)/).flatten.map(&:to_i) | |
end | |
o.on '--fullscreen', 'Run fullscreen' do | |
FullScreen = true | |
end | |
o.on '-m', '--mode MODE', 'Set the operating mode (SNUSP or SNACK)' do|m| | |
case m | |
when /snusp/i | |
mode = :SNUSP | |
when /snack/i | |
mode = :SNACK | |
else | |
puts "Invalid mode `#{m}`" | |
end | |
end | |
o.on '-h', '--help' do | |
puts o | |
puts <<-eof | |
Use the mouse! | |
There are buttons. | |
Mouse over a cell and | |
right click to shift through the operations | |
type a character to set the cell | |
eof | |
exit | |
end | |
end | |
ScreenW = 640 | |
ScreenH = 480 | |
FullScreen = false | |
PlayfieldFontHeight = 16 | |
PlayfieldFontWidth = 8 | |
OPS = [ | |
?$, ?\\, ?/, ?!, ??, ?#, ?@, ?&, | |
?a,?s,?m,?d,?e, | |
?0,?1,?2,?3,?4,?5,?6,?7,?8,?9, | |
?:,?;,?~,?`,?,, | |
' ' | |
] | |
KeyboardToOp = { #US-QWERTY biased, sorry world | |
true => { #shifting | |
KbSemicolon => ?:, KbBacktick => ?~, | |
Kb1 => ?!, Kb2 => ?@, Kb3 => ?#, Kb4 => ?$, | |
Kb7 => ?&, Kb8 => ?*, | |
KbEqual => ?a,KbComma => ?<,KbPeriod => ?., | |
KbSlash => ??, | |
}, false => { | |
KbSlash => ?/, KbBackslash => ?\\, | |
KbBacktick=>?`, | |
Kb0 => ?0,Kb1 => ?1,Kb2 => ?2,Kb3 => ?3,Kb4 => ?4, | |
Kb5 => ?5,Kb6 => ?6,Kb7 => ?7,Kb8 => ?8,Kb9 => ?9, | |
KbMinus=> ?s, | |
KbEqual => ?=, | |
KbComma => ?,, | |
KbSemicolon => ?;, | |
KbSpace => ' ', } | |
} | |
KeyboardToOp.each_value.each_with_object({ | |
KbNumpad0 => ?0,KbNumpad1 => ?1,KbNumpad2 => ?2,KbNumpad3 => ?3, | |
KbNumpad4 => ?4,KbNumpad5 => ?5,KbNumpad6 => ?6,KbNumpad7 => ?7, | |
KbNumpad8 => ?8,KbNumpad9 => ?9, | |
KbNumpadAdd => ?a,KbA => ?a, | |
KbNumpadSubtract=> ?s,KbS => ?s, | |
KbNumpadDivide=>?d,KbD => ?d, | |
KbNumpadMultiply=>?m,KbM=>?m, | |
KbZ => ?$, | |
KbC => ' ' | |
}, &:merge!) | |
class Space | |
attr_accessor :w,:h,:lines,:entrypoints | |
def initialize opts = {} | |
if opts[:str] | |
self.lines = opts[:str] | |
self.w = lines[0].size | |
self.h = lines.size | |
elsif opts[:w] and opts[:h] | |
self.w = opts[:w] | |
self.h = opts[:h] | |
@lines = Array.new(h) do ' '*w end | |
scan | |
else | |
raise "What do?" | |
end | |
end | |
def lines= v | |
v = v.split(?\n) if v.is_a? String | |
#dont #kill the empty lines | |
#v = v.map{|_| _.chomp!; _.size == 0 ? nil : _} | |
# .compact | |
#make the fat lines feel less disgusting | |
max = v.max_by(&:size).size | |
@lines = v.map{ |_| _ << (' ' * (max - _.size)) } | |
scan | |
end | |
def scan | |
#scan for entrypoints | |
self.entrypoints = [] | |
lines.each_with_index do |str, y| | |
x = -1 | |
loop do | |
x = str.index(?$, x+1) | |
break unless x | |
entrypoints << [x, y] | |
end | |
end | |
end | |
def [] x, y | |
lines[y][x] | |
end | |
def []= x, y, v | |
lines[y][x] = v | |
end | |
end | |
class Vec | |
attr_accessor :x,:y | |
def initialize x,y | |
@x,@y = x,y | |
end | |
def to_a; [x,y] end | |
def [] i; to_a[i] end | |
end | |
class Frame < Struct.new(:ip, :dir) | |
def initialize ip,dir=:right | |
self.ip = ip | |
self.dir = dir | |
end | |
def dup() Frame.new(ip, dir) end | |
def ip=(v) super(Vec.new(*v)) end | |
end | |
Direction2Velocity = { | |
up: [0, -1], down: [0, 1], | |
left:[-1, 0], right:[1, 0], | |
nw: [-1,-1], ne: [1,-1], | |
sw: [-1, 1], se: [1, 1]} | |
Deflection = { | |
'/' => { up: :right, left: :down, down: :left, right: :up, | |
nw: :se, se: :nw, | |
ne: :ne, sw: :sw }, | |
?\\ => { up: :left, left: :up, down: :right, right: :down, | |
nw: :nw, se: :se, | |
ne: :sw, sw: :ne } } | |
class Actor < Struct.new(:frame, :callstack, :stack) | |
def initialize at | |
self.frame = at.is_a?(Actor) ? | |
at.frame.dup : | |
Frame.new(at, :right) | |
self.stack = [] | |
self.callstack = [] | |
end | |
def pushframe | |
callstack << frame.dup | |
end | |
def popframe ## returns true if out of callframes | |
r = callstack.size > 0 ? | |
(self.frame = callstack.pop; false) : | |
true | |
advance! | |
r | |
end | |
def push v; stack << v end | |
def pop; stack.pop || 0 end | |
def peek; stack.last end | |
def spawn() self.class.new(self) end | |
def deflect! op | |
frame.dir = Deflection[op][frame.dir] | |
end | |
def advance! | |
d2v = Direction2Velocity[frame.dir] | |
frame.ip.x += d2v[0] | |
frame.ip.y += d2v[1] | |
end | |
def x() frame.ip.x end | |
def y() frame.ip.y end | |
def x=(v) frame.ip.x = v end | |
def y=(v) frame.ip.y = v end | |
def dir() frame.dir end | |
def dir=(v) frame.dir = v end | |
end | |
class Game < Struct.new(:space, :bounded_mode, :actors, :state, :last_exit) | |
attr_reader :bounds,:inputHandler,:outputHandler | |
def initialize space, bounded_mode = :toroidal | |
self.space = space | |
self.bounded_mode = bounded_mode | |
refresh_actors | |
self.last_exit = 0 | |
@inputHandler = GosuInput.new | |
@outputHandler = GosuOutput.new($window.pf) | |
post_init | |
end | |
def post_init() end | |
def refresh_actors | |
space.scan | |
self.actors = space.entrypoints.map{ |(x, y)| | |
Actor.new [x,y] | |
} | |
end | |
def remove_actor a | |
self.last_exit = a.pop | |
actors.delete a | |
end | |
def space= v | |
super v | |
update_bounds | |
end | |
def update_bounds | |
@bounds = Rect.new(0,0,space.w-1,space.h-1) | |
end | |
def self.load str, bounds = :toroidal | |
new Space.new(str: str), bounds | |
end | |
def tick | |
i = 0 | |
new_actors = nil | |
while i < actors.size | |
act = actors[i] | |
op = space[act.x, act.y] | |
died = false | |
case op | |
when ?/, ?\\ | |
act.deflect! op | |
when ?! | |
act.advance! | |
when ?? | |
act.advance! if act.pop != 0 | |
when ?# | |
died = act.popframe | |
when ?@ | |
act.pushframe | |
when ?a | |
act.push act.pop+act.pop | |
when ?s # 1 2 - #=> 1 - 2 | |
b = act.pop | |
act.push act.pop - b | |
when ?m | |
act.push act.pop * act.pop | |
when ?d # 1 2 / #=> | |
b = act.pop | |
act.push act.pop / b | |
when ?& | |
act.advance! | |
(new_actors ||= []) << act.spawn | |
when ?: | |
act.push act.peek | |
when ?; | |
act.push act.stack[-1 - act.pop] | |
when ?~ | |
a = act.pop | |
b = act.pop | |
act.push b, a | |
when ?` | |
n = act.pop | |
a = act.pop | |
act.push act.stack[-n] | |
act.stack[-1 - n] = a | |
when ?, | |
n = act.pop | |
act.stack[- n] = act.pop | |
when ?< | |
b = act.pop | |
act.push(act.pop < b ? 1 : 0 ) | |
when ?> | |
b = act.pop | |
act.push(act.pop > b ? 1 : 0 ) | |
when ?= | |
act.push(act.pop == act.pop ? 1 : 0) | |
when ?0..?9 | |
act.push op.to_i | |
end | |
act.advance! | |
if died or !still_alive(act) | |
remove_actor act | |
else | |
i += 1 | |
end | |
end | |
new_actors && (self.actors += new_actors) | |
end | |
def still_alive actor | |
case bounded_mode | |
when :toroidal | |
if actor.x > space.w-1 | |
actor.x = 0 | |
elsif actor.x < 0 | |
actor.x = space.w - 1 | |
end | |
if actor.y > space.h - 1 | |
actor.y = 0 | |
elsif actor.y < 0 | |
actor.y = space.h - 1 | |
end | |
true | |
when :deadly | |
@bounds.include?(actor.x,actor.y) | |
end | |
end | |
def info | |
actors.size == 0 ? | |
last_exit.to_s : | |
[actors.first.stack.to_s, actors.first.callstack.to_s] | |
end | |
def w() space.w end | |
def h() space.h end | |
def incr_w | |
space.w += 1 | |
space.lines.each {|_|_<<' '} | |
update_bounds | |
end | |
def incr_h | |
space.h += 1 | |
space.lines << ' '*space.w | |
update_bounds | |
end | |
def decr_w | |
space.w -= 1 | |
space.lines.map! {|_| _[0, space.w]} | |
update_bounds | |
end | |
def decr_h | |
space.h -= 1 | |
space.lines.pop | |
update_bounds | |
end | |
end | |
Rect = Struct.new(:x,:y,:w,:h) do | |
def includes? x,y | |
x >= self.x and | |
x <= self.x+w and | |
y >= self.y and | |
y <= self.y+h | |
end | |
alias include? includes? | |
end | |
def button(font, text, x,y, &blck) | |
b = OpenStruct.new({ | |
font: font, text: text, | |
pos: Vec.new(x,y), onclick: blck, | |
bounds: nil, | |
fX: 1, fY: 1 }) | |
def b.draw(z) | |
font.draw text, *pos, z | |
end | |
def b.clicked?(x,y) | |
bounds.includes?(x,y) ? | |
(onclick.call rescue nil; true) : | |
false | |
end | |
def b.update_pos x,y | |
pos.x += x | |
pos.y += y | |
update_bounds | |
end | |
def b.set_pos x,y | |
pos.x = x | |
pos.y = y | |
update_bounds | |
end | |
def b.update_bounds | |
self.bounds = Rect.new(*pos, font.text_width(text, fX), PlayfieldFontHeight) | |
end | |
b.update_bounds | |
b | |
end | |
class GameWindow < Gosu::Window | |
attr_reader :game,:pf | |
def initialize(file, playfieldSize, game_mode, font, ipf, autostart) | |
super ScreenW, ScreenH, FullScreen | |
$window = self | |
@ipf = ipf | |
@pf = Gosu::Font.new self, font, | |
PlayfieldFontHeight | |
cls = game_mode == :SNUSP ? SNUSP : Game | |
@game = \ | |
if file | |
cls.load(File.read(file)) | |
elsif playfieldSize | |
cls.new(Space.new(w: playfieldSize[0], h: playfieldSize[1])) | |
else | |
cls.load ' | |
$\\ | |
0 | |
1 | |
@ | |
\\ # | |
# ' | |
end | |
@state = autostart ? :run : :pause | |
@buttons = [] | |
x, y = ScreenW - 100, 10 | |
add_button @pf, "Step", x, y, &method(:single_step) | |
y += PlayfieldFontHeight | |
add_button @pf, "Refresh actors", x, y do | |
game.refresh_actors | |
end | |
y += PlayfieldFontHeight | |
b = add_button @pf, "#{other_state}", x, y do | |
toggle_state | |
b.text = "#{other_state}" | |
end | |
if file | |
y += PlayfieldFontHeight | |
add_button @pf, "Save file #{file}", x, y do | |
File.open(file, "w+") do |f| | |
game.space.lines.each do |_| | |
f.puts _ | |
end | |
end | |
end | |
y += PlayfieldFontHeight | |
add_button @pf, "Load file #{file}", x, y do | |
game.space = Space.new str: File.read(file) | |
set_buttons | |
end | |
end | |
@width_buttons = [ | |
add_button(@pf, "", 0,0), | |
add_button(@pf, "inc", 0,0){ game.incr_w; set_buttons }, | |
add_button(@pf, "dec", 0,0){ game.decr_w; set_buttons } | |
] | |
@height_buttons = [ | |
add_button(@pf, "", 0,0), | |
add_button(@pf, "inc", 0,0){ game.incr_h; set_buttons }, | |
add_button(@pf, "dec", 0,0){ game.decr_h; set_buttons } | |
] | |
set_buttons | |
def @buttons.draw(z = 0) | |
each_with_index do|b, i| b.draw z+i end | |
end | |
def @buttons.click(mx,my) | |
each do |b| break if b.clicked?(mx, my) end | |
end | |
end | |
def other_state() @state == :pause ? :run : :pause end | |
def toggle_state() @state = other_state end | |
def set_buttons | |
x, y = PlayfieldFontWidth*(1+ game.w), 0 | |
@width_buttons[0].text = "#{game.w} wide" | |
@width_buttons.each do |b| | |
b.set_pos x, y | |
x += b.bounds.w + 5 | |
end | |
x, y = 0, PlayfieldFontHeight*(1+ game.h) | |
@height_buttons[0].text = "#{game.h} high" | |
@height_buttons.each do |b| | |
b.set_pos x, y | |
x += b.bounds.w + 5 | |
end | |
end | |
def add_button *args,&b | |
@buttons << button(*args,&b) | |
@buttons.last | |
end | |
def single_step; @ipf.times do game.tick end end | |
def button_down id | |
mx, my = mouse_x, mouse_y | |
active_tile = [(mx / PlayfieldFontWidth).to_i, (my / PlayfieldFontHeight).to_i] | |
game.bounds.include?(*active_tile) || active_tile = nil | |
case id | |
when MsLeft | |
@buttons.click mx,my | |
when KbSpace | |
single_step | |
when MsRight | |
if active_tile | |
op = game.space[*active_tile] | |
op = OPS[ ((OPS.index(op) || -1) + 1) % OPS.size] | |
game.space[*active_tile] = op | |
end | |
when KbP | |
require'pry' | |
binding.pry | |
when KbR | |
game.refresh_actors | |
when KbEscape | |
close | |
else | |
if active_tile | |
op = KeyboardToOp[button_down?(KbLeftShift)][id] | |
game.space[*active_tile] = op if op && OPS.include?(op) | |
end | |
end | |
end | |
def update | |
single_step if @state == :run | |
end | |
def needs_cursor?() true end | |
def draw | |
game.space.lines.each_with_index do |line, y| | |
@pf.draw line, 0, y*PlayfieldFontHeight, 0 | |
end | |
game.actors.each do |a| | |
@pf.draw \ | |
'O', | |
a.x * PlayfieldFontWidth, | |
a.y * PlayfieldFontHeight, | |
0 | |
end | |
info = Vec.new(0, ScreenH - PlayfieldFontHeight) | |
[*game.info].reverse.each do |i| | |
@pf.draw i, *info, 0 | |
info.y -= PlayfieldFontHeight | |
end | |
@buttons.draw | |
#draw_grid | |
end | |
GridColor = Gosu::Color::GRAY | |
def draw_grid | |
(0 .. ScreenW-1).step(PlayfieldFontWidth).each do |x| | |
draw_line x, 0, GridColor, x, ScreenH, GridColor | |
end | |
(0 .. ScreenH-1).step(PlayfieldFontHeight).each do |y| | |
draw_line 0, y, GridColor, ScreenW, y, GridColor | |
end | |
end | |
end | |
require_relative 'SNUSP' | |
require_relative 'input_handler' | |
if __FILE__==$0 | |
ov, $VERBOSE = $VERBOSE, nil | |
opars.parse! | |
$VERBOSE = ov | |
GameWindow.new(file, playfieldSize, mode, font, ipf, autostart).show | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SNUSP_Actor < Actor | |
attr_accessor :ptr | |
def initialize at | |
super | |
@ptr = at.is_a?(SNUSP_Actor) ? | |
at.ptr.dup : | |
Vec.new(0,0) | |
end | |
end | |
class Mem | |
def initialize w=1, h=1 | |
@mem = Array.new(h) do | |
[0] * w end | |
end | |
def [](x, y) @mem[y][x] end | |
def []=(x, y, v) @mem[y][x] = v end | |
def validate x,y | |
#stretches the membranes to fit your configuration, | |
#returns a better pointer | |
r = Vec.new(x,y) | |
if y >= @mem.size | |
(@mem.size - x).times do @mem << [0] end | |
elsif y < 0 | |
r.y = 0 | |
end | |
if x >= @mem[y].size | |
@mem[y] += [0]*(x - @mem[y].size + 1) | |
elsif x < 0 | |
r.x = 0 | |
end | |
r | |
end | |
end | |
class SNUSP < Game | |
attr_reader :mem | |
def post_init | |
self.bounded_mode = :deadly | |
inputHandler.open | |
outputHandler.open | |
@mem = Mem.new | |
end | |
def refresh_actors() | |
#only the first $ foun | |
super | |
self.actors = [actors.empty? ? | |
SNUSP_Actor.new([0,0]) : | |
SNUSP_Actor.new(actors.first) ] | |
puts actors.inspect | |
end | |
def tick | |
i = 0 | |
new_actors = nil | |
while i < actors.size | |
act = actors[i] | |
op = space[act.x, act.y] | |
died,blocked = false,false | |
case op | |
when ?, # READ | |
blocked = !inputHandler.hasInput? | |
mem[*act.ptr] = inputHandler.readChar.ord \ | |
unless blocked | |
when ?. # WRITE | |
outputHandler.writeChar mem[*act.ptr].chr | |
when ?% # RAND | |
mem[*act.ptr] = (rand * (mem[*act.ptr]+1)).to_i | |
when ?< # LEFT | |
movePtrX act, -1 | |
when ?> # RIGHT | |
movePtrX act, 1 | |
when ?: # up | |
movePtrY act, -1 | |
when ?; # down | |
movePtrY act, 1 | |
when ?+ # INCR | |
mem[*act.ptr] += 1 | |
when ?- # DECR | |
mem[*act.ptr] -= 1 | |
when ?@ # ENTER | |
act.pushframe | |
when ?# # LEAVE | |
died = act.popframe | |
when ?& # SPAWN | |
act.advance! | |
(new_actors ||= []) << act.spawn | |
when ?/, ?\\ # LURD,RULD | |
act.deflect! op | |
when ?! # SKIP | |
act.advance! | |
when ?? # SKIPZ | |
act.advance! if mem[*act.ptr] == 0 | |
end | |
act.advance! unless blocked | |
if died or !still_alive(act) | |
remove_actor act | |
else | |
i += 1 | |
end | |
end | |
self.actors += new_actors if new_actors | |
end | |
def info | |
"Output: #{outputHandler.text}".split(?\n) + | |
"Input: #{inputHandler.text}".split(?\n) | |
end | |
def movePtrX act, by | |
# act.ptr.x += by | |
# mem.validate *act.ptr | |
act.ptr = mem.validate act.ptr.x+by, act.ptr.y | |
end | |
def movePtrY act, by | |
# act.ptr.y += by | |
# mem.validate *act.ptr | |
act.ptr = mem.validate act.ptr.x, act.ptr.y+by | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SNUSP-inspired | |
$ actor start point | |
/ deflection | |
\ deflection | |
! move forward | |
? move forward if POP != 0 | |
# pop frame (leave function), kills the actor if the callstack is empty | |
@ move forward and push frame (enter function) | |
& move forward and spawn a new actor | |
stack ops: | |
a - add | |
s - sub | |
m - mul | |
d - div | |
= - == | |
< - less than | |
> - less than | |
0-9 - push a number | |
: - dup | |
; - dup the Nth stack item | |
~ - swap the top two stack items | |
` - swap the Nth stack item | |
, - n = POP; stack[n] = POP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment