Hi monks!

I came to program this as I was reading Stephen Wolfram's A New Kind Of Science, and I wanted to experiment this automaton stuff too.
My first version displayed the automaton in the shell with sharps and spaces and one had to set the rules by editing the source.
So I used GD to display an image (it pipes it to the display prgram, but one can write it in a file), and GTK (for the first time) so that rules are set up easily.
Though one still has to edit the file to change the resolution and size of the picture, it's pretty usable, as long as you understand what the rules mean:
001->1 means "if the pixel above left, the pixel above are 0 and the pixel above right is 1, then current pixel is 1". I higly suggest you buy that book if you want to know more about automatons...

This principal reason I put this here, is Spleenwort Fern Fractal viewer in Tk as it drew a Sierpinsky triangle, which can be obtained with rules "100" and "001" together (or eventually with adding "010").

I do hope you enjoy and that it is a right place to put this.

Pied.

#!/usr/bin/perl #Simple 2D 2Colors automaton. # # Use the TRUE and FALSE constants exported by the Glib module. use Glib qw/TRUE FALSE/; use Gtk2 '-init'; use strict; use GD; my %laws= ( "0,0,0" => 0, "0,0,0" => 0, "0,0,1" => 0, "0,1,0" => 0, "0 +,1,1" => 0, "1,0,0" => 0, "1,0,1" => 0, "1,1,0" => 0, "1,1,1" => 0); sub OnToggled{ my ($arg,$arg2)=@_; if ($arg->get_active){ print "activating $arg2!\n"; $laws{"0,0,0"}=1 if ($arg2=="000"); $laws{"0,0,1"}=1 if ($arg2=="001"); $laws{"0,1,0"}=1 if ($arg2=="010"); $laws{"0,1,1"}=1 if ($arg2=="011"); $laws{"1,0,0"}=1 if ($arg2=="100"); $laws{"1,0,1"}=1 if ($arg2=="101"); $laws{"1,1,0"}=1 if ($arg2=="110"); $laws{"1,1,1"}=1 if ($arg2=="111"); } else{ print "deactivating $arg2!\n"; $laws{"0,0,0"}=0 if ($arg2=="000"); $laws{"0,0,1"}=0 if ($arg2=="001"); $laws{"0,1,0"}=0 if ($arg2=="010"); $laws{"0,1,1"}=0 if ($arg2=="011"); $laws{"1,0,0"}=0 if ($arg2=="100"); $laws{"1,0,1"}=0 if ($arg2=="101"); $laws{"1,1,0"}=0 if ($arg2=="110"); $laws{"1,1,1"}=0 if ($arg2=="111"); } print "$laws{'0,0,0'} $laws{'0,0,1'} $laws{'0,1,0'} $laws{'0,1,1'} $ +laws{'1,0,0'} $laws{'1,0,1'} $laws{'1,1,0'} $laws{'1,1,1'}\n"; }; sub hello { my ($widget, $window) = @_; my @screen; my $height=200; my $width= 2 *$height ; my $size=2; my $min_x=$height-10; my $max_x=$height+10 ; @screen=&init ($width,$height,@screen); @screen=&docalcul (\%laws,\$min_x,\$max_x,$width,$height,@screen); &display ($size,\$min_x,\$max_x,$width,$height,@screen); } sub init { my ($width,$height,@screen)=@_; $width+=1; $height+=1; foreach my $y (0..$height){ foreach my $x (0..$width){ $screen[$x][$y]=0; } } my $mid =$width / 2; $screen[$mid][0]=1; return @screen; }; sub display { my ($size,$rminx1,$rminx2,$width,$height,@screen)=@_; # create a new image print "bornes: $$rminx1 .. $$rminx2\n"; my $im = new GD::Image(($$rminx2-$$rminx1)*$size,$height*$size); # allocate some colors my $white = $im->colorAllocate(255,255,255); my $black = $im->colorAllocate(0,0,0); foreach my $y (0..$height){ foreach my $x ($$rminx1 .. $$rminx2){ if ($screen[$x][$y]==0){ $im->filledRectangle(($$rminx1-$x)*$size,$y*$size,(1+($$rminx1 +-$x))*$size,(1+$y)*$size,$white); } else { $im->filledRectangle($x*$size,$y*$size,(1+$x)*$size,(1+$y)*$si +ze,$black); } } #print "\n"; } open DISPLAY, "| display 2>/dev/null" or die "can't fork: $!"; local $SIG{PIPE} = sub { die "display pipe broke" }; binmode DISPLAY; print DISPLAY $im->png; close DISPLAY or die "bad spool: $! $?"; }; sub docalcul { my ($rlaws,$rminx,$rmaxx,$width,$height,@screen)=@_; foreach my $y (0..$height){ foreach my $x (0..$width-2){ #we don't want to overflow. my $value="$screen[$x-1][$y],$screen[$x+0][$y],$screen[$x+1][$y] +"; $screen[$x+0][$y+1]=$$rlaws{$value}; $$rminx=$x if ($$rlaws{$value}==1 && $x<$$rminx); $$rmaxx=$x if ($$rlaws{$value}==1 && $x>$$rmaxx); } } return @screen; }; sub delete_event { Gtk2->main_quit; return FALSE; } sub make_box { my ($img,$window,$homogenous, $spacing, $expand, $fill, $padding) = +@_; # Create a new hbox with the appropriate homogeneous and spacing set +tings my $box = Gtk2::HBox->new($homogenous, $spacing); my $toggle = Gtk2::CheckButton->new; #my $toggle_image = Gtk2::Image::new_from_file( "foo", "${img}.jpg" +) ; my $toggle_image = Gtk2::Label->new( "$img") ; my $label = Gtk2::Label->new("->"); $box->pack_start( $toggle_image, TRUE, TRUE, 0 ) ; $box->pack_start( $label, TRUE, TRUE, 0 ) ; $box->pack_start( $toggle, TRUE, TRUE, 0 ) ; $toggle->signal_connect( "toggled",\&OnToggled,"$img") ; $toggle_image->show() ; $label->show(); $toggle->show() ; return $box; } # Create our window my $window = Gtk2::Window->new('toplevel'); # connect the delete_event signal to the main window. $window->signal_connect(delete_event => \&delete_event); $window->set_border_width(10); # We create a vertical box (vbox) to pack the horizontal boxes into. my $box1 = Gtk2::VBox->new(FALSE, 0); my $which = $ARGV[0]; # create a new label. my $label = Gtk2::Label->new("Select Rules!"); $label->set_alignment(0.0, 0.0); $box1->pack_start($label, FALSE, FALSE, 0); $label->show; # Call our make box function - homogeneous = FALSE, spacing = 0, # expand = FALSE, fill = FALSE, padding = 0 foreach ( qw / 000 001 010 011 100 101 110 111 / ){ my $box2 = make_box("$_",$window,TRUE, 0, TRUE, TRUE, 0); $box1->pack_start($box2, TRUE, TRUE, 0); $box2->show; } my $separator = Gtk2::HSeparator->new; $box1->pack_start($separator, FALSE, TRUE, 5); $separator->show; $label = Gtk2::Label->new("Action!"); $label->set_alignment(0.0, 0.0); $box1->pack_start($label, FALSE, FALSE, 0); $label->show; my $quitbox = Gtk2::HBox->new(FALSE, 0); $separator = Gtk2::HSeparator->new; my $button = Gtk2::Button->new("Quit"); my $run = Gtk2::Button->new("Run"); $button->signal_connect(clicked => sub { Gtk2->main_quit; }); $run->signal_connect(clicked => \&hello, $window); $quitbox->pack_start($run, FALSE, TRUE, 0); $quitbox->pack_start($separator, FALSE, TRUE, 5); $quitbox->pack_start($button, TRUE, FALSE, 0); $separator->show; $box1->pack_start($quitbox, FALSE, FALSE, 0); $window->add($box1); # And show everything left $button->show; $run->show; $quitbox->show; $box1->show; $window->show; Gtk2->main; 0;

If you have anything more perlish or any comment to do with the code, I'd be glad to hear it.

janitored by ybiC: Balanced <readmore> tags around long-ish codeblock, as per Monastery convention