Adding odd numbered Wolfram 1D rules to Golly
Posted: January 19th, 2011, 5:56 am
All done with a pair of Perl scripts. The first creates rule tree files for W1 through W255 (odd only):Yeah I know I could have just zipped up the rule tree files but it might be good if more people found out how easy they can be to make, the way I did in a last minute rush before a recent conference presentation. You need to run that first script and move/copy the files it generates to your Rules folder. The second needs to go in the Golly/Scripts/Perl folder:This script expects you to have a one cell high seed pattern with at least some state 1 or state 2 cells and converts any state 2 to state 1 in case you had populated them with Edit>Random Fill. It then adds a line of state 2 cells beneath your seed to indicate where the Wnnn.tree rule needs to apply the Wnnn rule. The length of that line is based on the width of your seed unless you have a bounded grid. Once you have done that you just start generation as you would for the built in even Wnnn rules.
Code: Select all
#!/usr/bin/perl
# Create Wn.trees for odd numbered Wolfram 1D Rules 1-255
# by Tony Smith, Meme Media, Melbourne, Australia, January 2011
# extends Golly/Rules/TreeGenerators/RuleTreeGen.pl
# using Mark Jeronimus's approach of a next line of state 2 cells
use strict;
my ( @bits, %world, $nodeseq, @r, @params );
my $numStates = 3 ;
my $numNeighbors = 8 ;
my $numParams = $numNeighbors + 1 ;
for ( my $odd = 1; $odd < 256; $odd += 2 ) {
my $rule = $odd;
foreach my $bit ( 0 .. 7 ) { $bits[$bit] = $rule & 1; $rule = $rule >> 1 }
%world = ();
$nodeseq = 0;
@r = ();
@params = (0) x $numParams;
recur($numParams);
open ( NEW, '>', "W$odd.tree" ) || die "Cannot open file for output!";
print NEW "num_states=$numStates\n";
print NEW "num_neighbors=$numNeighbors\n";
print NEW "num_nodes=", scalar @r, "\n";
print NEW "$_\n" for @r ;
close NEW;
}
sub f {
my ($nw, $ne, $sw, $se, $n, $w, $e, $s, $c) = @_ ;
if ( $nw == 2 or $n == 2 or $ne == 2 ) { return 2 } # allow widening patterns
elsif ( $c != 2 ) { return $c } # past rows
else { return $bits[ 4 * $nw + 2 * $n + $ne ] } # next row
}
sub recur {
my $at = shift;
return f(@params) if $at == 0;
my $n = $at;
for (my $i=0; $i<$numStates; $i++) {
$params[$numParams-$at] = $i;
$n .= " " . recur($at-1);
}
return $world{$n} if defined($world{$n});
$world{$n} = $nodeseq;
push @r, $n;
return $nodeseq++;
}
Code: Select all
# Validates 1D rule/seed combination and adds next line indicator cells.
# Author: Tony Smith (ts@meme.com.au), January 2010.
use strict;
g_exit( 'There is no pattern.' ) if g_empty();
my $rulestring = g_getrule();
my ( $rule, $bounds ) = split( ':', $rulestring );
g_exit( 'Only for odd W rules.' ) unless $rule =~ s/W// and $rule > 0 and $rule < 256 and $rule % 2 == 1;
my @seedrect = g_getrect();
g_exit( 'Seed pattern must be only one cell high.' ) unless $seedrect[3] == 1;
my $cells = g_getcells( @seedrect );
if ( scalar @$cells % 2 ) { # may contain some state 2 cells
my @replace;
while ( scalar @$cells ) {
my @cell = splice( @$cells, 0, 3 );
$cell[2] = 1 if $cell[2] == 2; # convert any state 2 to state 1 in case seeded by randfill
push( @replace, @cell );
}
g_putcells( \@replace );
}
my $width = g_getwidth();
my ( $left, $right );
if ( $width ) { # bounded
$left = - int ( $width / 2 );
$right = $width + $left;
}
else { # unbounded
$left = $seedrect[0] - 1;
$right = $seedrect[0] + $seedrect[2];
}
for ( my $x = $left; $x < $right; $x ++ ) { g_setcell( $x, $seedrect[1] + 1, 2 ) }