Created
June 30, 2017 20:37
-
-
Save JoshCheek/c047eba4e4db5cd9db5c39e92febf789 to your computer and use it in GitHub Desktop.
Rule 30... and friends (use arrow keys)
This file contains 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
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