class Wireworld<Processing::App;def setup;color_mode RGB,1.0
no_stroke;smooth;background 0.45;@cellsize=10;@nx=width/@cellsize
@ny=height/@cellsize;@cells=fresh_cells;@dirty=[]
mark_all_cells_dirty end;def draw
@dirty.each{|item|draw_cell item.first,item.last}
@dirty=[];run_wireworld_rule end;def
mouse_clicked;x=mouse_x/@cellsize;y=mouse_y/@cellsize
if@cells[x][y]==:empty;set x,y,:wire elsif mouse_button==LEFT
set x,y,:empty else set x,y,:electron_head end end;def
draw_cell(x,y)set_color_from@cells[x][y]
rect(x*@cellsize,y*@cellsize,@cellsize-2,@cellsize-2)end;def
set_color_from(state)case state when:empty;fill 0.5,0.5,0.5,1
when:wire;fill 0.75,0.75,0.5,1 when:electron_head;fill 1,1,1,1
when:electron_tail;fill 0.75,0.75,0.75,1 end end;def
run_wireworld_rule;old_cells=@cells;@cells=fresh_cells
each_coord do|x,y|case old_cells[x][y] when:electron_head;set x,y,:electron_tail
when:electron_tail;set x,y,:wire when:empty;when:wire;case
electron_head_count old_cells,x,y when 1,2;set x,y,:electron_head
else@cells[x][y]=:wire end end end end;def
electron_head_count(cells,base_x,base_y)count=0
(base_x-1..base_x+1).each do|x|(base_y-1..base_y+1).each do|y|
if 0<=x and x<@nx and 0<=y and y<@ny and cells[x][y]==:electron_head then
count+=1 end end end;return count end;def each_coord
(0..@nx-1).each do|x|(0..@ny-1).each do|y|yield x,y end end end;def
mark_all_cells_dirty;each_coord do|x,y|@dirty<<[x,y]end end;def
set(x,y,value)@cells[x][y]=value;@dirty<<[x,y]end;def fresh_cells
Array.new(@nx){Array.new(@ny,:empty)}end end
Wireworld.new(:title=>"Wireworld",:width=>1024,:height=>600,:full_screen=>true)

