```# http://davidtran.doublegifts.com/blog/?p=10

class SimFrost

STATUS = [:VACUUM, :VAPOR, :ICE]

def initialize(width, height, vapor_chance=0.5)
raise "width must be even and >= 2" unless (width % 2 == 0) && (width >= 2)
raise "height must be even and >= 2" unless (height % 2 == 0) &&
(height >= 2)
@width = width
@height = height
@grid = Array.new(@height) do
Array.new(@width) { rand < vapor_chance ? :VAPOR : :VACUUM }
end
@grid[@height / 2][@width / 2] = :ICE
@ticks = 0
end

def tick
shift unless (@ticks % 2 == 0)
(0...@height).step(2) do |r|
(0...@width).step(2) do |c|
cells = [[r,c], [r,c+1], [r+1,c], [r+1,c+1]]
if cells.any? { |y, x| @grid[y][x] == :ICE }
cells.each { |y, x| @grid[y][x] = :ICE if @grid[y][x] == :VAPOR }
else
cells_rotate = rand(2).zero? \
? [cells[2], cells[0], cells[3], cells[1]] \
: [cells[1], cells[3], cells[0], cells[2]]
rotate_values = cells_rotate.map { |y,x| @grid[y][x] }
cells.each_with_index { |(y,x), i| @grid[y][x] = rotate_values[i] }
end
end
end
unshift unless (@ticks % 2 == 0)
@ticks = @ticks + 1
@grid
end

def done?
not @grid.flatten.include?(:VAPOR)
end

private

def shift
@grid << @grid.shift
@grid.each { |row| row << row.shift }
end

def unshift
@grid.unshift(@grid.pop)
@grid.each { |row| row.unshift(row.pop) }
end
end

if __FILE__ == \$0
if ARGV.size < 3
puts "Usage: #\$0 gif_file_name width height [vapor_chance]"
exit
end

file_name = ARGV[0]
width = ARGV[1].to_i
height = ARGV[2].to_i
vapor_chance = ARGV[3] ? ARGV[3].to_f : 0.5

require 'RMagick'
ICE_COLOR = 'blue'
imageList = Magick::ImageList.new
simFrost = SimFrost.new(width, height, vapor_chance)
while (not simFrost.done?) do
image = Magick::Image.new(width, height)
grid = simFrost.tick
(0...height).each do |y|
(0...width).each do |x|
image.pixel_color(x, y, ICE_COLOR) if grid[y][x] == :ICE
end
end
imageList << image
end
imageList.write(file_name)
end

```