Skip to content

Instantly share code, notes, and snippets.

@BenGoldberg1
Created July 24, 2016 03:32
Show Gist options
  • Save BenGoldberg1/cba85868130b9d887beb672286e14259 to your computer and use it in GitHub Desktop.
Save BenGoldberg1/cba85868130b9d887beb672286e14259 to your computer and use it in GitHub Desktop.
forest fire simulation for rosettacode
#!perl
# forest fire simulation for rosettacode
use strict;
use warnings;
use autodie;
use 5.010;
use Imager;
use constant height => 150;
use constant width => 150;
use constant frames => 250;
use constant populate => 0.5;
use constant p => 0.03;
use constant f => p / 1000;
use constant +{
Empty => Imager::Color->new( 0, 0, 0 ),
Tree => Imager::Color->new( 0, 0, 255 ),
Heating => Imager::Color->new( 255, 255, 0 ),
Burning => Imager::Color->new( 255, 0, 0 ),
};
my %state;
my %neighbors;
for my $delta_x (-1 .. 1) {
for my $delta_y (-1 .. 1) {
next unless $delta_x || $delta_y;
for my $x ( 0 .. width - 1 ) {
my $neighbor_x = $x + $delta_x;
next if $neighbor_x < 0 or $neighbor_x >= width;
for my $y ( 0 .. height - 1 ) {
my $neighbor_y = $y + $delta_y;
next if $neighbor_y < 0 or $neighbor_y >= height;
my $n = "$neighbor_x,$neighbor_y";
$state{ $n } = (rand() < populate) ? Tree : Empty;
push @{$neighbors{"$x,$y"}}, \$state{$n};
}
}
}
}
my @images;
my @heat;
my %transition = (
Empty, sub { rand() < p ? Tree : Empty },
Tree, sub { rand() < f ? Heating : Tree },
Heating, sub { push @heat, shift; Burning },
Burning, sub { Empty },
);
for ( 1..frames ) {
my $frame = Imager->new( xsize => width, ysize => height, type => 'paletted' );
my @colors = (Empty, Tree, Heating, Burning);
my $index = $frame->addcolors(colors => \@colors);
my %packed = map {; $colors[$_] => pack 'C', ($_+$index) } 0 .. $#colors;
for my $y ( 0 .. height - 1 ) {
my $pixels = '';
for my $x ( 0 .. width - 1 ) {
for ( $state{"$x,$y"} ) {
$pixels .= $packed{$_};
$_ = $transition{$_}->("$x,$y");
}
}
$frame->setscanline( y => $y, pixels => $pixels, type => 'index');
}
for my $hot (splice @heat) {
for my $maybe_tree (@{$neighbors{$hot}}) {
$$maybe_tree = Heating if $$maybe_tree == Tree;
}
}
push @images, $frame;
}
Imager->write_multi( {file => 'ff.gif', gif_loop => 0}, @images);
exit 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment