App-GUI-GoLP
view release on metacpan or search on metacpan
return load_RLE_file($filename);
}
warn("Unknown file type: '$filename'");
return undef;
}
sub load_RLE_file {
my ($filename) = @_;
my $fh;
unless ( defined open($fh, "<", $filename) ) {
warn("Could not open file '$filename': $!");
return undef;
}
my ($birth, $survival) = ( [3], [2,3] );
my ($width, $height) = (0, 0);
my $rle_data = "";
READ_RLE_FILE: while (my $line = <$fh>) {
chomp($line);
if ( $line =~ /\A \s* \#/imsx ) { # skip comments
next READ_RLE_FILE;
}
if ($line =~ /\A x \s* = \s* (\d+), \s* y \s* = \s* (\d+)/imsx) { # parse header
($width, $height) = ($1, $2);
# check for rule
if ( $line =~ m|rule \s* = \s* B \s* (\d+) \s* / \s* S \s* (\d+)|imsx ) {
($birth, $survival) = map { [split //] } ($1, $2);
}
elsif ( $line =~ m|rule \s* = \s* (\d+) \s* / \s* (\d+)|imsx ) {
($birth, $survival) = map { [split //] } ($2, $1);
}
next READ_RLE_FILE;
}
$rle_data .= $line;
}
close $fh;
if ( ($width <= 0) || ($height <= 0) ) {
warn("File '$filename' seems to be missing header, cannot load.");
return undef;
}
# process RLE data
$rle_data =~ s/!//g;
my @rows;
my $x = 0;
my $y = 0;
my $count = "";
foreach my $char (split //, $rle_data) {
if ($char =~ /\d/) {
$count .= $char; # Accumulate digit characters
} elsif ($char eq 'b' || $char eq 'o') {
$count = $count eq "" ? 1 : $count; # Default count is 1
my $state = ($char eq 'o') ? 1 : 0; # 'o' is live (1), 'b' is dead (0)
# Fill the grid with the decoded run
for (1 .. $count) {
$rows[$y][$x++] = $state;
}
$count = ""; # Reset count
} elsif ($char eq '$') {
$count = $count eq "" ? 1 : $count;
for (1 .. $count) {
$y++;
$x = 0; # Move to the next row
}
$count = "";
}
}
# Ensure all rows have the same width
for my $row (@rows) {
push @{$row}, (0) x ($width - scalar @{$row});
}
return { rows => $height, cols => $width, data => \@rows, birth => $birth, survival => $survival };
}
sub load_cells_file {
my ($filename) = @_;
my $fh;
unless ( defined open($fh, "<", $filename) ) {
warn("Could not open file '$filename': $!");
return undef;
}
my $max_row_len = 0;
my %cell_state_map = ( '.' => 0, 'o' => 1, 'O' => 1, 'x' => 1, 'X' => 1, );
my @file_grid;
READ_CELLS_FILE: while ( my $line = <$fh> ) {
chomp($line);
next READ_CELLS_FILE if $line =~ /!/; # skip comments
# sometimes in .cells files the trailing dead cells in a row are omitted
my $row_len = length($line);
if ( $row_len > $max_row_len ) {
$max_row_len = $row_len;
}
my @row_cells = map { $cell_state_map{$_} } split(//, $line);
push @file_grid, \@row_cells;
}
close($fh);
my @grid;
# we can't guarantee that the grid read from the file has uniform length rows.
foreach my $row (@file_grid) {
my @file_row = @{$row};
my $trailing = $max_row_len - scalar(@file_row);
if ( $trailing < 0 ) {
warn("Somehow calculating the row length went wrong");
return undef;
( run in 2.085 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )