Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Created June 30, 2017 20:37
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 JoshCheek/c047eba4e4db5cd9db5c39e92febf789 to your computer and use it in GitHub Desktop.
Save JoshCheek/c047eba4e4db5cd9db5c39e92febf789 to your computer and use it in GitHub Desktop.
Rule 30... and friends (use arrow keys)
require 'graphics'
require 'set'
class RuleN < Graphics::Simulation
def initialize(pixel_size, w, h)
self.pixel_size = pixel_size
self.rule_index = 30
self.needs_draw = true
self.cursor_pixel_offset = 0
self.initial_pixel_offsets = Set[0]
super w, h, 24
end
def draw(n)
return sleep 0.01 unless needs_draw
self.needs_draw = false
clear :white
pixels_wide = w/pixel_size
mid_pixel = pixels_wide/2
initial_pixels = initial_pixel_offsets.reduce({}) { |pixels, offset|
pixels[(offset+mid_pixel)%pixels_wide] = true
pixels
}
initial_row = InitialRowOff.new rule_index, initial_pixels
rows = [initial_row]
pixels_high.times { rows << rows.last.succ }
rows.each_with_index do |row, y|
0.upto pixels_wide do |x|
draw_pixel x, y, :black if row[x]
end
end
label = rows[0].n.to_s
margin = 5
rect 20-margin, h-40-margin, 20*label.size+2*margin, 20+2*margin, :white, :fill
text label, 20, h-50, :red
draw_pixel (cursor_pixel_offset+mid_pixel)%pixels_wide, 0, :red
end
def handle_event(event, n)
case event
when SDL::Event::Quit
exit
when SDL::Event::Keydown
case event.sym
when SDL::Key::Q
self.done = true
when SDL::Key::UP
self.rule_index = (rule_index-1) % 256
self.needs_draw = true
when SDL::Key::DOWN
self.rule_index = (rule_index+1) % 256
self.needs_draw = true
when SDL::Key::EQUALS
self.pixel_size = pixel_size + 1
self.needs_draw = true
when SDL::Key::MINUS
self.pixel_size = pixel_size - 1
self.pixel_size = 1 if pixel_size < 1
self.needs_draw = true
when SDL::Key::LEFT
self.cursor_pixel_offset = cursor_pixel_offset - 1
self.needs_draw = true
when SDL::Key::RIGHT
self.cursor_pixel_offset = cursor_pixel_offset + 1
self.needs_draw = true
when SDL::Key::SPACE
if initial_pixel_offsets.include? cursor_pixel_offset
initial_pixel_offsets.delete cursor_pixel_offset
else
initial_pixel_offsets << cursor_pixel_offset
end
self.needs_draw = true
end
end
end
private
attr_accessor :pixel_size, :needs_draw, :rule_index, :cursor_pixel_offset, :initial_pixel_offsets
def pixels_wide
w/pixel_size
end
def pixels_high
h/pixel_size
end
def draw_pixel(x, y, color)
if pixel_size == 1
point(x*pixel_size, h-y*pixel_size, color)
else
rect(x*pixel_size, h-y.succ*pixel_size, pixel_size, pixel_size, color, :fill)
end
end
end
class SuccessiveRow
def initialize(n, predecessor)
self.n = n
self.pred = predecessor
self.cache = {}
end
def succ
SuccessiveRow.new(n, self)
end
def [](x)
cache.fetch x do
cache[x] = on? pred[x-1], pred[x], pred[x+1]
end
end
attr_reader :n
private
attr_writer :n
attr_accessor :pred, :cache
def on?(a, b, c)
nc = (c ? 1 : 0) << 0
nb = (b ? 1 : 0) << 1
na = (a ? 1 : 0) << 2
1 == n[nc + nb + na]
end
end
class InitialRowOff
def initialize(n, ons)
self.n = n
self.ons = ons
end
def succ
SuccessiveRow.new n, self
end
def [](n)
ons[n]
end
attr_reader :n
private
attr_writer :n, :ons
attr_reader :ons
end
w = 1400
h = 900
s = 10
RuleN.new(s, w, h).run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment