line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Game::Life::Infinite::Board; |
4
|
|
|
|
|
|
|
|
5
|
9
|
|
|
9
|
|
221987
|
use strict; |
|
9
|
|
|
|
|
23
|
|
|
9
|
|
|
|
|
383
|
|
6
|
9
|
|
|
9
|
|
48
|
use warnings; |
|
9
|
|
|
|
|
18
|
|
|
9
|
|
|
|
|
290
|
|
7
|
9
|
|
|
9
|
|
9324
|
use Time::HiRes; |
|
9
|
|
|
|
|
18697
|
|
|
9
|
|
|
|
|
53
|
|
8
|
|
|
|
|
|
|
require 5.10.1; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
BEGIN { |
11
|
9
|
|
|
9
|
|
1289
|
use Exporter (); |
|
9
|
|
|
|
|
21
|
|
|
9
|
|
|
|
|
278
|
|
12
|
9
|
|
|
9
|
|
46
|
use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS); |
|
9
|
|
|
|
|
15
|
|
|
9
|
|
|
|
|
1298
|
|
13
|
9
|
|
|
9
|
|
88
|
$VERSION = sprintf( "%d.%02d", q($Revision: 0.07 $) =~ /\s(\d+)\.(\d+)/ ); |
14
|
9
|
|
|
|
|
125
|
@ISA = qw(Exporter); |
15
|
9
|
|
|
|
|
24
|
@EXPORT_OK = qw(format_is); |
16
|
9
|
|
|
|
|
85410
|
%EXPORT_TAGS = ( ); |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
11
|
|
|
11
|
1
|
716
|
my ( $class, $rulesRef, @args ) = @_; |
21
|
11
|
|
|
|
|
27
|
my $self = {}; |
22
|
11
|
|
|
|
|
52
|
$self->{'maxx'} = $self->{'maxy'} = $self->{'minx'} = $self->{'miny'} = 0; # Board boundaries. |
23
|
11
|
|
|
|
|
39
|
$self->{'gen'} = $self->{'liveCells'} = $self->{'usedCells'} = 0; |
24
|
11
|
|
|
|
|
33
|
$self->{'delta'} = -1; # Number of cells that changed state since previous epoch (newborns+dead). |
25
|
11
|
|
|
|
|
25
|
$self->{'factor2'} = 1; |
26
|
11
|
|
|
|
|
23
|
$self->{'oscilator'} = 0; # If oscilator is detected, contains the period. |
27
|
11
|
|
|
|
|
23
|
$self->{'cells'} = {}; |
28
|
11
|
|
|
|
|
27
|
$self->{'currentFn'} = 'Untitled.cells'; |
29
|
11
|
|
|
|
|
18
|
$self->{'name'} = 'Untitled'; |
30
|
11
|
|
|
|
|
21
|
$self->{'totalTime'} = 0; |
31
|
11
|
|
|
|
|
22
|
$self->{'osccheck'} = 0; |
32
|
11
|
|
|
|
|
32
|
$self->{'color'} = 0; |
33
|
|
|
|
|
|
|
# Check for rules: |
34
|
11
|
|
|
|
|
617
|
&setRules($self, $rulesRef); |
35
|
11
|
|
|
|
|
45
|
&updateCell($self, 0, 0, 0); # Create first cell in 0,0 coordinates. |
36
|
11
|
|
|
|
|
30
|
bless $self, $class; |
37
|
11
|
|
|
|
|
32
|
return $self; |
38
|
|
|
|
|
|
|
}; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub setRules { |
41
|
42
|
|
|
42
|
1
|
60
|
my ( $self, $rulesRef) = @_; |
42
|
42
|
100
|
|
|
|
356
|
my ($breedRef, $liveRef) = (ref($rulesRef) eq "ARRAY") ? ($rulesRef->[0], $rulesRef->[1]) : ([3], [2,3]); |
43
|
42
|
100
|
|
|
|
317
|
if ($self->{'color'} > 0) { |
44
|
|
|
|
|
|
|
# Force standard rules in colourised board. |
45
|
30
|
|
|
|
|
70
|
($breedRef, $liveRef) = ([3], [2,3]); |
46
|
|
|
|
|
|
|
}; |
47
|
42
|
50
|
|
|
|
341
|
$self->{'breedRules'} = (ref($breedRef) eq "ARRAY") ? $breedRef : []; |
48
|
42
|
50
|
|
|
|
110
|
$self->{'liveRules'} = (ref($liveRef) eq "ARRAY") ? $liveRef : []; |
49
|
42
|
|
|
|
|
242
|
return; |
50
|
|
|
|
|
|
|
}; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub setColor { |
53
|
30
|
|
|
30
|
1
|
38
|
my ($self, $color) = @_; |
54
|
30
|
50
|
|
|
|
223
|
$color = (defined $color) ? $color : ''; |
55
|
30
|
50
|
|
|
|
76
|
if ($self->{'gen'} > 0) {return;}; |
|
0
|
|
|
|
|
0
|
|
56
|
30
|
100
|
|
|
|
82
|
if (lc($color) eq 'immigration') { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
57
|
13
|
|
|
|
|
17
|
$self->{'color'} = 1; |
58
|
|
|
|
|
|
|
# Reset rules to standard: |
59
|
13
|
|
|
|
|
28
|
&setRules($self, undef); |
60
|
13
|
|
|
|
|
35
|
return 1; |
61
|
|
|
|
|
|
|
} elsif (lc($color) eq 'quadlife') { |
62
|
17
|
|
|
|
|
24
|
$self->{'color'} = 2; |
63
|
|
|
|
|
|
|
# Reset rules to standard: |
64
|
17
|
|
|
|
|
30
|
&setRules($self, undef); |
65
|
17
|
|
|
|
|
47
|
return 2; |
66
|
|
|
|
|
|
|
} elsif (lc($color) eq 'normal') { |
67
|
0
|
|
|
|
|
0
|
$self->{'color'} = 0; |
68
|
0
|
|
|
|
|
0
|
return 0; |
69
|
|
|
|
|
|
|
} else { |
70
|
0
|
|
|
|
|
0
|
return; |
71
|
|
|
|
|
|
|
}; |
72
|
|
|
|
|
|
|
}; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub getColor { |
75
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
76
|
0
|
|
|
|
|
0
|
return $self->{'color'}; |
77
|
|
|
|
|
|
|
}; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub updateCell { |
80
|
|
|
|
|
|
|
# Update the state of a cell. If non-existing, create it. |
81
|
19509
|
|
|
19509
|
1
|
32737
|
my ( $self, $xpos, $ypos, $state ) = @_; |
82
|
19509
|
100
|
|
|
|
57271
|
defined ($self->{'cells'}->{$xpos, $ypos}) or &createCell($self, $xpos, $ypos); |
83
|
19509
|
100
|
66
|
|
|
79698
|
if (($self->{'cells'}->{$xpos, $ypos}->{'state'}) and (not $state)) { |
84
|
9042
|
|
|
|
|
18665
|
my $oldstate = $self->{'cells'}->{$xpos, $ypos}->{'state'}; |
85
|
9042
|
|
|
|
|
10981
|
--$self->{'liveCells'}; |
86
|
|
|
|
|
|
|
# Update neighbours counts: |
87
|
9042
|
|
|
|
|
18274
|
foreach my $xx ($xpos-1 .. $xpos+1) { |
88
|
27126
|
|
|
|
|
45211
|
foreach my $yy ($ypos-1 .. $ypos+1) { |
89
|
81378
|
100
|
100
|
|
|
212660
|
if (($xx == $xpos) and ($yy == $ypos)) { |
90
|
9042
|
|
|
|
|
11063
|
next; |
91
|
|
|
|
|
|
|
}; |
92
|
72336
|
50
|
|
|
|
192689
|
if (defined ($self->{'cells'}->{$xx, $yy})) { |
93
|
72336
|
|
|
|
|
154895
|
--$self->{'cells'}->{$xx, $yy}->{'neighbours'}->{$oldstate}; |
94
|
72336
|
|
|
|
|
194364
|
--$self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'}; |
95
|
|
|
|
|
|
|
} else { |
96
|
|
|
|
|
|
|
#&createCell($self, $xx, $yy); |
97
|
|
|
|
|
|
|
}; |
98
|
|
|
|
|
|
|
}; |
99
|
|
|
|
|
|
|
}; |
100
|
|
|
|
|
|
|
}; |
101
|
19509
|
100
|
100
|
|
|
88224
|
if ((not $self->{'cells'}->{$xpos, $ypos}->{'state'}) and ($state)) { |
102
|
|
|
|
|
|
|
# Check validity: |
103
|
10456
|
50
|
66
|
|
|
87875
|
if ( |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
104
|
|
|
|
|
|
|
(($state > 1) and ($self->{'color'} < 1)) or |
105
|
|
|
|
|
|
|
(($state > 2) and ($self->{'color'} < 2)) or |
106
|
|
|
|
|
|
|
($state > 4) or |
107
|
|
|
|
|
|
|
($state < 0) |
108
|
|
|
|
|
|
|
) { |
109
|
|
|
|
|
|
|
# Invalid state for current color. |
110
|
0
|
|
|
|
|
0
|
return -1; |
111
|
|
|
|
|
|
|
}; |
112
|
10456
|
|
|
|
|
14514
|
++$self->{'liveCells'}; |
113
|
|
|
|
|
|
|
# Update neighbours counts: |
114
|
10456
|
|
|
|
|
26662
|
foreach my $xx ($xpos-1 .. $xpos+1) { |
115
|
31368
|
|
|
|
|
54615
|
foreach my $yy ($ypos-1 .. $ypos+1) { |
116
|
94104
|
100
|
100
|
|
|
254018
|
if (($xx == $xpos) and ($yy == $ypos)) { |
117
|
10456
|
|
|
|
|
15828
|
next; |
118
|
|
|
|
|
|
|
}; |
119
|
83648
|
100
|
|
|
|
238421
|
if (defined ($self->{'cells'}->{$xx, $yy})) { |
120
|
73211
|
|
|
|
|
166534
|
++$self->{'cells'}->{$xx, $yy}->{'neighbours'}->{$state}; |
121
|
73211
|
|
|
|
|
196885
|
++$self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'}; |
122
|
|
|
|
|
|
|
} else { |
123
|
10437
|
|
|
|
|
19054
|
&createCell($self, $xx, $yy); |
124
|
10437
|
|
|
|
|
23207
|
++$self->{'cells'}->{$xx, $yy}->{'neighbours'}->{$state}; |
125
|
10437
|
|
|
|
|
34189
|
++$self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'}; |
126
|
|
|
|
|
|
|
}; |
127
|
|
|
|
|
|
|
}; |
128
|
|
|
|
|
|
|
}; |
129
|
|
|
|
|
|
|
}; |
130
|
19509
|
|
|
|
|
46496
|
$self->{'cells'}->{$xpos, $ypos}->{'state'} = $state; |
131
|
19509
|
|
|
|
|
42596
|
return; |
132
|
|
|
|
|
|
|
}; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub queryCell { |
135
|
|
|
|
|
|
|
# Return the state of a cell: |
136
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $xpos, $ypos ) = @_; |
137
|
0
|
0
|
|
|
|
0
|
if (defined $self->{'cells'}->{$xpos, $ypos}) { |
138
|
0
|
|
|
|
|
0
|
return $self->{'cells'}->{$xpos, $ypos}->{'state'}; |
139
|
|
|
|
|
|
|
} else { |
140
|
0
|
|
|
|
|
0
|
return; |
141
|
|
|
|
|
|
|
}; |
142
|
|
|
|
|
|
|
}; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub createCell { |
145
|
|
|
|
|
|
|
# Create an empty cell. |
146
|
10693
|
|
|
10693
|
0
|
17676
|
my ($self, $xpos, $ypos, @rest) = @_; |
147
|
10693
|
|
|
|
|
39619
|
$self->{'cells'}->{$xpos, $ypos}->{'state'} = 0; |
148
|
10693
|
|
|
|
|
32848
|
$self->{'cells'}->{$xpos, $ypos}->{'neighbours'}->{1} = 0; |
149
|
10693
|
|
|
|
|
23181
|
$self->{'cells'}->{$xpos, $ypos}->{'neighbours'}->{2} = 0; |
150
|
10693
|
|
|
|
|
22002
|
$self->{'cells'}->{$xpos, $ypos}->{'neighbours'}->{3} = 0; |
151
|
10693
|
|
|
|
|
22069
|
$self->{'cells'}->{$xpos, $ypos}->{'neighbours'}->{4} = 0; |
152
|
10693
|
|
|
|
|
20419
|
$self->{'cells'}->{$xpos, $ypos}->{'neighbours'}->{'total'} = 0; |
153
|
|
|
|
|
|
|
# Update boundaries: |
154
|
10693
|
100
|
|
|
|
25356
|
$self->{'maxx'} < $xpos and $self->{'maxx'} = $xpos; |
155
|
10693
|
100
|
|
|
|
23285
|
$self->{'minx'} > $xpos and $self->{'minx'} = $xpos; |
156
|
10693
|
100
|
|
|
|
21356
|
$self->{'maxy'} < $ypos and $self->{'maxy'} = $ypos; |
157
|
10693
|
100
|
|
|
|
20705
|
$self->{'miny'} > $ypos and $self->{'miny'} = $ypos; |
158
|
10693
|
|
|
|
|
12266
|
++$self->{'usedCells'}; |
159
|
10693
|
|
|
|
|
16019
|
return; |
160
|
|
|
|
|
|
|
}; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub loadInit { |
163
|
|
|
|
|
|
|
# Load an initial grid from a file. |
164
|
11
|
|
|
11
|
1
|
8213
|
my ($self, $fn, @rest) = @_; |
165
|
11
|
|
|
|
|
25
|
my $untitled = 'Untitled.cells'; |
166
|
11
|
50
|
|
|
|
38
|
if (not defined $fn) { return $untitled; }; |
|
0
|
|
|
|
|
0
|
|
167
|
11
|
|
|
|
|
15
|
my @array; |
168
|
11
|
50
|
|
|
|
1839
|
open(my $fh,"<:crlf", $fn) or die "Failed to open $fn: $!"; |
169
|
11
|
|
|
|
|
331
|
while (<$fh>) { push @array, $_; }; |
|
706
|
|
|
|
|
2147
|
|
170
|
11
|
|
|
|
|
184
|
close $fh; |
171
|
11
|
|
|
|
|
53
|
my $ftype = &format_is(\@array); |
172
|
11
|
|
|
|
|
21
|
my $loadok; |
173
|
11
|
50
|
|
|
|
35
|
if (not defined $ftype) { |
174
|
0
|
|
|
|
|
0
|
print "DEBUG: File format could not be detected.\n"; |
175
|
0
|
|
|
|
|
0
|
return $untitled; |
176
|
|
|
|
|
|
|
}; |
177
|
11
|
100
|
66
|
|
|
78
|
if ($ftype->{'format'} eq 'CELLS') { |
|
|
100
|
33
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
178
|
8
|
|
|
|
|
36
|
$loadok = $self->loadCells(\@array); |
179
|
8
|
|
|
|
|
7123
|
print "DEBUG: Loaded CELLS\n"; |
180
|
|
|
|
|
|
|
} elsif ($ftype->{'format'} eq 'RLE') { |
181
|
1
|
|
|
|
|
6
|
$loadok = $self->loadRLE(\@array); |
182
|
1
|
|
|
|
|
380
|
print "DEBUG: Loaded RLE\n"; |
183
|
|
|
|
|
|
|
} elsif (($ftype->{'format'} eq 'Life') and ($ftype->{'version'} eq '1.05')) { |
184
|
1
|
|
|
|
|
8
|
$loadok = $self->loadL105(\@array); |
185
|
1
|
|
|
|
|
364
|
print "DEBUG: Loaded Life 1.05\n"; |
186
|
|
|
|
|
|
|
} elsif (($ftype->{'format'} eq 'Life') and ($ftype->{'version'} eq '1.06')) { |
187
|
1
|
|
|
|
|
5
|
$loadok = $self->loadL106(\@array); |
188
|
1
|
|
|
|
|
301
|
print "DEBUG: Loaded Life 1.06\n"; |
189
|
|
|
|
|
|
|
} else { |
190
|
0
|
|
|
|
|
0
|
print "DEBUG: " . $ftype->{'format'} . " V. " . $ftype->{'version'} . " not supported yet.\n"; |
191
|
0
|
|
|
|
|
0
|
return $untitled; |
192
|
|
|
|
|
|
|
}; |
193
|
11
|
50
|
|
|
|
51
|
if (not $loadok) { |
194
|
0
|
|
|
|
|
0
|
print "DEBUG: Load failed!\n"; |
195
|
0
|
|
|
|
|
0
|
return $untitled; |
196
|
|
|
|
|
|
|
} else { |
197
|
11
|
|
|
|
|
227
|
$self->{'currentFn'} = $fn; |
198
|
11
|
|
|
|
|
259
|
return $fn; |
199
|
|
|
|
|
|
|
}; |
200
|
|
|
|
|
|
|
}; |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub saveGridTxt { |
203
|
|
|
|
|
|
|
# Save a grid to a txt file. |
204
|
0
|
|
|
0
|
1
|
0
|
my ($self, $fn, @rest) = @_; |
205
|
0
|
0
|
|
|
|
0
|
if (not defined $fn) { return; }; |
|
0
|
|
|
|
|
0
|
|
206
|
0
|
|
|
|
|
0
|
my $output; |
207
|
0
|
0
|
|
|
|
0
|
open($output, ">", $fn) or die "cannot open $fn: $!\n"; |
208
|
0
|
|
|
|
|
0
|
for (my $yy = $self->{'miny'}; $yy <= $self->{'maxy'}; $yy++) { |
209
|
0
|
|
|
|
|
0
|
foreach my $xx ($self->{'minx'} .. $self->{'maxx'}) { |
210
|
0
|
0
|
|
|
|
0
|
if (defined ($self->{'cells'}->{$xx, $yy})) { |
211
|
0
|
0
|
|
|
|
0
|
if ($self->{'cells'}->{$xx, $yy}->{'state'} == 1) { |
|
|
0
|
|
|
|
|
|
212
|
0
|
|
|
|
|
0
|
print $output 'O'; |
213
|
|
|
|
|
|
|
} elsif ($self->{'cells'}->{$xx, $yy}->{'state'} > 1) { |
214
|
0
|
|
|
|
|
0
|
print $output $self->{'cells'}->{$xx, $yy}->{'state'}; |
215
|
|
|
|
|
|
|
} else { |
216
|
0
|
|
|
|
|
0
|
print $output '.'; |
217
|
|
|
|
|
|
|
}; |
218
|
|
|
|
|
|
|
} else { |
219
|
0
|
|
|
|
|
0
|
print $output '.'; |
220
|
|
|
|
|
|
|
}; |
221
|
|
|
|
|
|
|
}; |
222
|
0
|
|
|
|
|
0
|
print $output "\n"; |
223
|
|
|
|
|
|
|
}; |
224
|
0
|
|
|
|
|
0
|
close $output; |
225
|
0
|
|
|
|
|
0
|
return $fn; |
226
|
|
|
|
|
|
|
}; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub crudePrintBoard { |
230
|
|
|
|
|
|
|
# Basic board print. |
231
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
232
|
0
|
|
|
|
|
0
|
for (1 .. 80) { |
233
|
0
|
|
|
|
|
0
|
print "-"; |
234
|
|
|
|
|
|
|
}; |
235
|
0
|
|
|
|
|
0
|
print "\n"; |
236
|
0
|
|
|
|
|
0
|
for (my $yy = $self->{'miny'}; $yy <= $self->{'maxy'}; $yy++) { |
237
|
0
|
|
|
|
|
0
|
foreach my $xx ($self->{'minx'} .. $self->{'maxx'}) { |
238
|
0
|
0
|
|
|
|
0
|
if (defined ($self->{'cells'}->{$xx, $yy})) { |
239
|
0
|
0
|
|
|
|
0
|
if ($self->{'cells'}->{$xx, $yy}->{'state'} == 1) { |
|
|
0
|
|
|
|
|
|
240
|
0
|
|
|
|
|
0
|
print 'O'; |
241
|
|
|
|
|
|
|
} elsif ($self->{'cells'}->{$xx, $yy}->{'state'} > 1) { |
242
|
0
|
|
|
|
|
0
|
print $self->{'cells'}->{$xx, $yy}->{'state'}; |
243
|
|
|
|
|
|
|
} else { |
244
|
0
|
|
|
|
|
0
|
print '_'; |
245
|
|
|
|
|
|
|
}; |
246
|
|
|
|
|
|
|
} else { |
247
|
0
|
|
|
|
|
0
|
print '.'; |
248
|
|
|
|
|
|
|
}; |
249
|
|
|
|
|
|
|
}; |
250
|
0
|
|
|
|
|
0
|
print "\n"; |
251
|
|
|
|
|
|
|
}; |
252
|
0
|
|
|
|
|
0
|
my $stats = &statistics($self); |
253
|
0
|
|
|
|
|
0
|
print "---\tGeneration: " . $stats->{'generation'} . " x: " . $stats->{'minx'} . ".." . $stats->{'maxx'} . " y: " . $stats->{'miny'} . ".." . $stats->{'maxy'} . " Size: $stats->{'size'} LiveCells: " . $stats->{'liveCells'} . "\n"; |
254
|
0
|
|
|
|
|
0
|
print "\tDelta: " . $stats->{'delta'} . "\n"; |
255
|
0
|
|
|
|
|
0
|
return; |
256
|
|
|
|
|
|
|
}; |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub tick { |
259
|
|
|
|
|
|
|
# Calculate next epoch. |
260
|
1048
|
|
|
1048
|
1
|
8975
|
my ($self, $oscCheck) = @_; |
261
|
1048
|
|
|
|
|
3372
|
my $t0 = [Time::HiRes::gettimeofday()]; |
262
|
1048
|
|
|
|
|
2498
|
$oscCheck = &setOscCheck($self, $oscCheck); |
263
|
|
|
|
|
|
|
|
264
|
1048
|
|
|
|
|
2118
|
my $resref = &tickMainLoop($self); |
265
|
1048
|
|
|
|
|
1552
|
my @newCells = @{$resref->{'newCells'}}; |
|
1048
|
|
|
|
|
3822
|
|
266
|
1048
|
|
|
|
|
1260
|
my @dieCells = @{$resref->{'dieCells'}}; |
|
1048
|
|
|
|
|
2864
|
|
267
|
1048
|
|
|
|
|
1456
|
my @delCells = @{$resref->{'delCells'}}; |
|
1048
|
|
|
|
|
2677
|
|
268
|
|
|
|
|
|
|
#use Data::Dumper; |
269
|
1048
|
|
|
|
|
2170
|
$self->{'delta'} = scalar(@newCells) + scalar(@dieCells); |
270
|
|
|
|
|
|
|
# Apply changes on board: |
271
|
1048
|
|
|
|
|
1962
|
foreach my $rec (@newCells) { |
272
|
|
|
|
|
|
|
# TODO: Do something in case of error? |
273
|
9040
|
|
|
|
|
22718
|
my $error = &updateCell($self, $rec->[0], $rec->[1], $rec->[2]); |
274
|
9040
|
50
|
|
|
|
19950
|
$error = (defined $error) ? $error : 0; |
275
|
|
|
|
|
|
|
}; |
276
|
1048
|
|
|
|
|
1901
|
foreach my $rec (@dieCells) { |
277
|
9042
|
|
|
|
|
21492
|
my $error = &updateCell($self, $rec->[0], $rec->[1], 0); |
278
|
|
|
|
|
|
|
}; |
279
|
1048
|
|
|
|
|
2099
|
foreach my $rec (@delCells) { |
280
|
|
|
|
|
|
|
# Verify that these cells are still without neighbours: |
281
|
9310
|
100
|
|
|
|
35399
|
if ($self->{'cells'}->{$rec->[0], $rec->[1]}->{'neighbours'}->{'total'} == 0) { |
282
|
5361
|
|
|
|
|
18557
|
delete $self->{'cells'}->{$rec->[0], $rec->[1]}; |
283
|
5361
|
|
|
|
|
8696
|
--$self->{'usedCells'}; |
284
|
|
|
|
|
|
|
}; |
285
|
|
|
|
|
|
|
}; |
286
|
1048
|
|
|
|
|
2026
|
$self->{'gen'} = $self->{'gen'} + 1; |
287
|
1048
|
50
|
33
|
|
|
6017
|
$self->{'factor2'} = ((defined $self->{'usedCells'}) and ($self->{'usedCells'} > 0)) ? $self->{'liveCells'} / $self->{'usedCells'} : 1; |
288
|
1048
|
100
|
|
|
|
2052
|
if ($oscCheck > 1) { &oscCheck($self, $oscCheck); }; |
|
207
|
|
|
|
|
714
|
|
289
|
1048
|
|
|
|
|
4029
|
my $t1 = [Time::HiRes::gettimeofday]; |
290
|
1048
|
|
|
|
|
3845
|
my $t0_t1 = Time::HiRes::tv_interval( $t0, $t1 ); |
291
|
1048
|
|
|
|
|
11087
|
$self->{'lastTI'} = $t0_t1; # Time spend to calculate last epoch. |
292
|
1048
|
|
|
|
|
1513
|
$self->{'totalTime'} += $t0_t1; # Total Time spend calculating this board. |
293
|
1048
|
|
|
|
|
21822
|
return; |
294
|
|
|
|
|
|
|
}; |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
sub tickMainLoop { |
297
|
|
|
|
|
|
|
# TODO: Return new cell's color if board is immigration or quadlife. |
298
|
1048
|
|
|
1048
|
0
|
1198
|
my ($self) = @_; |
299
|
1048
|
|
|
|
|
1055
|
my @newCells; |
300
|
|
|
|
|
|
|
my @dieCells; |
301
|
0
|
|
|
|
|
0
|
my @delCells; |
302
|
1048
|
|
|
|
|
1103
|
foreach my $key (keys %{ $self->{'cells'} }) { |
|
1048
|
|
|
|
|
13812
|
|
303
|
88902
|
|
|
|
|
231207
|
my ($xx, $yy) = split(/$;/, $key, 2); |
304
|
88902
|
|
|
|
|
181850
|
my $rec = [$xx, $yy]; |
305
|
88902
|
100
|
100
|
|
|
1046495
|
if ( |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
306
|
|
|
|
|
|
|
($self->{'cells'}->{$xx, $yy}->{'state'} > 0) and |
307
|
|
|
|
|
|
|
(not $self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'} ~~ $self->{'liveRules'}) |
308
|
|
|
|
|
|
|
) { |
309
|
|
|
|
|
|
|
# Die. |
310
|
9042
|
|
|
|
|
19013
|
push @dieCells, $rec; |
311
|
|
|
|
|
|
|
} elsif ( |
312
|
|
|
|
|
|
|
($self->{'cells'}->{$xx, $yy}->{'state'} == 0) and |
313
|
|
|
|
|
|
|
($self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'} ~~ $self->{'breedRules'}) |
314
|
|
|
|
|
|
|
) { |
315
|
|
|
|
|
|
|
# New. |
316
|
9040
|
100
|
|
|
|
17131
|
if ($self->{'color'} == 0) { |
317
|
|
|
|
|
|
|
# Standard |
318
|
8792
|
|
|
|
|
15206
|
$rec->[2] = 1; |
319
|
8792
|
|
|
|
|
18308
|
push @newCells, $rec; |
320
|
|
|
|
|
|
|
} else { |
321
|
|
|
|
|
|
|
# Colorized |
322
|
|
|
|
|
|
|
#use Data::Dumper; |
323
|
248
|
|
|
|
|
341
|
my @colorcounts = (); |
324
|
248
|
|
|
|
|
302
|
my $ccnt = 0; |
325
|
248
|
|
|
|
|
256
|
foreach my $state (keys %{ $self->{'cells'}->{$xx, $yy}->{'neighbours'} }) { |
|
248
|
|
|
|
|
925
|
|
326
|
1240
|
100
|
|
|
|
2240
|
if ($state ne 'total') { |
327
|
992
|
100
|
|
|
|
2864
|
if ($self->{'cells'}->{$xx, $yy}->{'neighbours'}->{$state} > 0) { |
328
|
309
|
|
|
|
|
807
|
$colorcounts[$state] = $self->{'cells'}->{$xx, $yy}->{'neighbours'}->{$state}; |
329
|
309
|
|
|
|
|
504
|
$ccnt++; |
330
|
|
|
|
|
|
|
}; |
331
|
|
|
|
|
|
|
}; |
332
|
|
|
|
|
|
|
}; |
333
|
248
|
100
|
|
|
|
823
|
if ($ccnt == 2) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# Immigration, or first rule of Quadlife (Identical). |
335
|
|
|
|
|
|
|
# Select maximum. |
336
|
57
|
|
|
|
|
64
|
my $max = -1; |
337
|
57
|
|
|
|
|
79
|
for my $i (1..4) { |
338
|
228
|
100
|
|
|
|
500
|
if (defined $colorcounts[$i]) { |
339
|
114
|
100
|
|
|
|
206
|
if ($colorcounts[$i] > $max) { |
340
|
103
|
|
|
|
|
99
|
$max = $colorcounts[$i]; |
341
|
103
|
|
|
|
|
174
|
$rec->[2] = $i |
342
|
|
|
|
|
|
|
}; |
343
|
|
|
|
|
|
|
}; |
344
|
|
|
|
|
|
|
}; |
345
|
|
|
|
|
|
|
} elsif ($ccnt == 3) { |
346
|
|
|
|
|
|
|
# Second rule of Quadlife |
347
|
2
|
|
|
|
|
5
|
for my $i (1..4) { |
348
|
6
|
100
|
|
|
|
14
|
if (not defined $colorcounts[$i]) { |
349
|
2
|
|
|
|
|
4
|
$rec->[2] = $i; |
350
|
2
|
|
|
|
|
4
|
last; |
351
|
|
|
|
|
|
|
}; |
352
|
|
|
|
|
|
|
}; |
353
|
|
|
|
|
|
|
} elsif ($ccnt == 1) { |
354
|
|
|
|
|
|
|
# Same color as parents: |
355
|
189
|
|
|
|
|
275
|
for my $i (1..4) { |
356
|
471
|
100
|
|
|
|
939
|
if (defined $colorcounts[$i]) { |
357
|
189
|
|
|
|
|
322
|
$rec->[2] = $i; |
358
|
189
|
|
|
|
|
275
|
last; |
359
|
|
|
|
|
|
|
}; |
360
|
|
|
|
|
|
|
}; |
361
|
|
|
|
|
|
|
} else { |
362
|
|
|
|
|
|
|
# Unsupported or standard. Return first color. |
363
|
0
|
|
|
|
|
0
|
$rec->[2] = 1; |
364
|
|
|
|
|
|
|
}; |
365
|
248
|
|
|
|
|
624
|
push @newCells, $rec; |
366
|
|
|
|
|
|
|
}; |
367
|
|
|
|
|
|
|
} elsif ( |
368
|
|
|
|
|
|
|
($self->{'cells'}->{$xx, $yy}->{'state'} == 0) and |
369
|
|
|
|
|
|
|
($self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'} == 0) |
370
|
|
|
|
|
|
|
) { |
371
|
|
|
|
|
|
|
# Isolated empty cell. GC. |
372
|
9310
|
|
|
|
|
18632
|
push @delCells, $rec; |
373
|
|
|
|
|
|
|
}; |
374
|
|
|
|
|
|
|
}; |
375
|
1048
|
|
|
|
|
13496
|
return {'newCells' => \@newCells, 'dieCells' => \@dieCells, 'delCells' => \@delCells}; |
376
|
|
|
|
|
|
|
}; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub setOscCheck { |
379
|
1048
|
|
|
1048
|
0
|
1467
|
my ($self, $oscCheck) = @_; |
380
|
|
|
|
|
|
|
|
381
|
1048
|
50
|
|
|
|
2022
|
$oscCheck = (defined $oscCheck) ? $oscCheck : 0; |
382
|
1048
|
100
|
|
|
|
2541
|
if ($oscCheck != $self->{'osccheck'}) { |
383
|
|
|
|
|
|
|
# Change, delete all previous snapshots: |
384
|
3
|
|
|
|
|
7
|
delete $self->{'snapshots'}; |
385
|
|
|
|
|
|
|
}; |
386
|
1048
|
|
|
|
|
1542
|
$self->{'osccheck'} = $oscCheck; |
387
|
1048
|
|
|
|
|
1722
|
return $oscCheck; |
388
|
|
|
|
|
|
|
}; |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
sub oscCheck { |
391
|
207
|
|
|
207
|
0
|
358
|
my ($self, $oscCheck) = @_; |
392
|
207
|
|
|
|
|
567
|
my $lgen = $self->{'gen'}; |
393
|
207
|
|
|
|
|
1037
|
my $lgenString = sprintf("s%d", $lgen); |
394
|
207
|
|
|
|
|
297
|
my $ogen; |
395
|
|
|
|
|
|
|
my $ogenString; |
396
|
207
|
|
|
|
|
607
|
$self->{'snapshots'}->{$lgenString} = &snapshot($self); # Smile! |
397
|
207
|
|
|
|
|
888
|
for (my $i = 2; $i <= $oscCheck; $i++) { |
398
|
262
|
|
|
|
|
419
|
$ogen = $lgen - $i; |
399
|
262
|
|
|
|
|
962
|
$ogenString = sprintf("s%d", $ogen); |
400
|
262
|
100
|
|
|
|
954
|
if (defined ($self->{'snapshots'}->{$ogenString})) { |
401
|
|
|
|
|
|
|
# Snapshot of grandma! |
402
|
219
|
100
|
66
|
|
|
1734
|
if ( |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
403
|
|
|
|
|
|
|
($self->{'snapshots'}->{$ogenString}->{'snapshot'} eq $self->{'snapshots'}->{$lgenString}->{'snapshot'}) and |
404
|
|
|
|
|
|
|
($self->{'snapshots'}->{$ogenString}->{'minx'} == $self->{'snapshots'}->{$lgenString}->{'minx'}) and |
405
|
|
|
|
|
|
|
($self->{'snapshots'}->{$ogenString}->{'maxx'} == $self->{'snapshots'}->{$lgenString}->{'maxx'}) and |
406
|
|
|
|
|
|
|
($self->{'snapshots'}->{$ogenString}->{'miny'} == $self->{'snapshots'}->{$lgenString}->{'miny'}) and |
407
|
|
|
|
|
|
|
($self->{'snapshots'}->{$ogenString}->{'maxy'} == $self->{'snapshots'}->{$lgenString}->{'maxy'}) |
408
|
|
|
|
|
|
|
) { |
409
|
|
|
|
|
|
|
# Grandma and grandson are identical! |
410
|
10
|
|
|
|
|
21
|
$self->{'oscilator'} = $i; |
411
|
10
|
|
|
|
|
24
|
last; |
412
|
|
|
|
|
|
|
} else { |
413
|
209
|
|
|
|
|
756
|
$self->{'oscilator'} = 0; |
414
|
|
|
|
|
|
|
}; |
415
|
|
|
|
|
|
|
}; |
416
|
|
|
|
|
|
|
}; |
417
|
|
|
|
|
|
|
# Delete oldest snapshot. |
418
|
207
|
|
|
|
|
1103
|
delete $self->{'snapshots'}->{$ogenString}; |
419
|
207
|
|
|
|
|
571
|
return; |
420
|
|
|
|
|
|
|
}; |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub snapshot { |
423
|
|
|
|
|
|
|
# Take a snapshot of the board, in a way that it can be easily stored and compared |
424
|
|
|
|
|
|
|
# to another snapshot. |
425
|
221
|
|
|
221
|
0
|
6775
|
my $self = shift; |
426
|
221
|
|
|
|
|
447
|
my $snapshot = ''; |
427
|
221
|
|
|
|
|
1196
|
for (my $yy = $self->{'miny'}; $yy <= $self->{'maxy'}; $yy++) { |
428
|
6790
|
|
|
|
|
12867
|
foreach my $xx ($self->{'minx'} .. $self->{'maxx'}) { |
429
|
263028
|
100
|
|
|
|
542913
|
if (defined ($self->{'cells'}->{$xx, $yy})) { |
430
|
66796
|
100
|
|
|
|
221512
|
if ($self->{'cells'}->{$xx, $yy}->{'state'} == 1) { |
|
|
100
|
|
|
|
|
|
431
|
17392
|
|
|
|
|
23423
|
$snapshot .= 'O'; |
432
|
|
|
|
|
|
|
} elsif ($self->{'cells'}->{$xx, $yy}->{'state'} > 1) { |
433
|
51
|
|
|
|
|
103
|
$snapshot .= $self->{'cells'}->{$xx, $yy}->{'state'}; |
434
|
|
|
|
|
|
|
} else { |
435
|
49353
|
|
|
|
|
66560
|
$snapshot .= '.'; |
436
|
|
|
|
|
|
|
}; |
437
|
|
|
|
|
|
|
} else { |
438
|
196232
|
|
|
|
|
224162
|
$snapshot .= '.'; |
439
|
|
|
|
|
|
|
}; |
440
|
|
|
|
|
|
|
}; |
441
|
6790
|
|
|
|
|
19578
|
$snapshot .= "\n"; |
442
|
|
|
|
|
|
|
}; |
443
|
|
|
|
|
|
|
return { |
444
|
221
|
|
|
|
|
4592
|
'snapshot' => $snapshot, |
445
|
|
|
|
|
|
|
'minx' => $self->{'minx'}, |
446
|
|
|
|
|
|
|
'maxx' => $self->{'maxx'}, |
447
|
|
|
|
|
|
|
'miny' => $self->{'miny'}, |
448
|
|
|
|
|
|
|
'maxy' => $self->{'maxy'}, |
449
|
|
|
|
|
|
|
}; |
450
|
|
|
|
|
|
|
}; |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
sub shrinkBoard { |
453
|
|
|
|
|
|
|
# Shrink board: Now mostly used to keep boundaries track, for printing and snapshot. |
454
|
7
|
|
|
7
|
1
|
59
|
my $self = shift; |
455
|
7
|
|
|
|
|
34
|
$self->{'minx'} = $self->{'maxx'} = $self->{'miny'} = $self->{'maxy'} = 0; |
456
|
7
|
|
|
|
|
16
|
my $ok = 0; |
457
|
7
|
|
|
|
|
16
|
foreach my $key (keys %{ $self->{'cells'} }) { |
|
7
|
|
|
|
|
84
|
|
458
|
524
|
|
|
|
|
1271
|
my ($xx, $yy) = split(/$;/, $key, 2); |
459
|
524
|
100
|
100
|
|
|
2603
|
if (($self->{'cells'}->{$xx, $yy}->{'state'} == 0) and ($self->{'cells'}->{$xx, $yy}->{'neighbours'}->{'total'} == 0)) { |
460
|
68
|
|
|
|
|
166
|
delete $self->{'cells'}->{$key}; |
461
|
68
|
|
|
|
|
100
|
--$self->{'usedCells'}; |
462
|
|
|
|
|
|
|
} else { |
463
|
456
|
100
|
|
|
|
665
|
if ($ok) { |
464
|
449
|
100
|
|
|
|
875
|
if ($xx > $self->{'maxx'}) { $self->{'maxx'} = $xx; }; |
|
15
|
|
|
|
|
48
|
|
465
|
449
|
100
|
|
|
|
787
|
if ($xx < $self->{'minx'}) { $self->{'minx'} = $xx; }; |
|
14
|
|
|
|
|
27
|
|
466
|
449
|
100
|
|
|
|
822
|
if ($yy > $self->{'maxy'}) { $self->{'maxy'} = $yy; }; |
|
12
|
|
|
|
|
21
|
|
467
|
449
|
100
|
|
|
|
983
|
if ($yy < $self->{'miny'}) { $self->{'miny'} = $yy; }; |
|
14
|
|
|
|
|
27
|
|
468
|
|
|
|
|
|
|
} else { |
469
|
7
|
|
|
|
|
19
|
$self->{'minx'} = $xx; |
470
|
7
|
|
|
|
|
16
|
$self->{'maxx'} = $xx; |
471
|
7
|
|
|
|
|
19
|
$self->{'miny'} = $yy; |
472
|
7
|
|
|
|
|
14
|
$self->{'maxy'} = $yy; |
473
|
7
|
|
|
|
|
22
|
$ok = 1; |
474
|
|
|
|
|
|
|
}; |
475
|
|
|
|
|
|
|
}; |
476
|
|
|
|
|
|
|
}; |
477
|
7
|
|
|
|
|
85
|
return; |
478
|
|
|
|
|
|
|
}; |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
sub statistics { |
481
|
14
|
|
|
14
|
1
|
62
|
my $self = shift; |
482
|
|
|
|
|
|
|
return { |
483
|
14
|
|
|
|
|
274
|
'size' => (($self->{'maxx'} - $self->{'minx'}) * ($self->{'maxy'} - $self->{'miny'})), |
484
|
|
|
|
|
|
|
'generation' => $self->{'gen'}, |
485
|
|
|
|
|
|
|
'minx' => $self->{'minx'}, |
486
|
|
|
|
|
|
|
'maxx' => $self->{'maxx'}, |
487
|
|
|
|
|
|
|
'miny' => $self->{'miny'}, |
488
|
|
|
|
|
|
|
'maxy' => $self->{'maxy'}, |
489
|
|
|
|
|
|
|
'liveCells' => $self->{'liveCells'}, |
490
|
|
|
|
|
|
|
'delta' => $self->{'delta'}, |
491
|
|
|
|
|
|
|
'oscilator' => $self->{'oscilator'}, |
492
|
|
|
|
|
|
|
'totalTime' => $self->{'totalTime'}, |
493
|
|
|
|
|
|
|
'usedCells' => $self->{'usedCells'}, |
494
|
|
|
|
|
|
|
'factor2' => $self->{'factor2'}, |
495
|
|
|
|
|
|
|
'lastTI' => $self->{'lastTI'}, |
496
|
|
|
|
|
|
|
}; |
497
|
|
|
|
|
|
|
}; |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
sub format_is { |
500
|
11
|
|
|
11
|
1
|
24
|
my ($faref) = @_; # Array ref containing file. |
501
|
11
|
|
|
|
|
51
|
my %result = ( |
502
|
|
|
|
|
|
|
format => undef, |
503
|
|
|
|
|
|
|
version => undef |
504
|
|
|
|
|
|
|
); |
505
|
11
|
|
|
|
|
23
|
foreach my $line (@{ $faref }) { |
|
11
|
|
|
|
|
28
|
|
506
|
15
|
|
|
|
|
30
|
chomp($line); |
507
|
15
|
100
|
100
|
|
|
241
|
if (($line =~ /^#Life 1.05/) or ($line =~ /^#Life 1.06/) or ($line =~ /^#MCell/)) { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
508
|
2
|
|
|
|
|
10
|
($result{format}, $result{version}) = split / /, $line, 2; |
509
|
2
|
|
|
|
|
10
|
$result{format} =~ s/#//; |
510
|
2
|
|
|
|
|
7
|
return \%result; |
511
|
|
|
|
|
|
|
} elsif ($line =~ /^(b|o|[[:digit:]])/) { |
512
|
1
|
|
|
|
|
4
|
($result{format}, $result{version}) = ('RLE', 'N/A'); |
513
|
1
|
|
|
|
|
5
|
return \%result; |
514
|
|
|
|
|
|
|
} elsif ($line =~ /^(\.|O|!)/) { |
515
|
8
|
|
|
|
|
32
|
($result{format}, $result{version}) = ('CELLS', 'N/A'); |
516
|
8
|
|
|
|
|
30
|
return \%result; |
517
|
|
|
|
|
|
|
} elsif ($line =~ /^(\.|O|2|3|4|!)/) { |
518
|
0
|
|
|
|
|
0
|
($result{format}, $result{version}) = ('CELLS', 'N/A'); |
519
|
0
|
|
|
|
|
0
|
return \%result; |
520
|
|
|
|
|
|
|
}; |
521
|
|
|
|
|
|
|
}; |
522
|
0
|
|
|
|
|
0
|
return undef; |
523
|
|
|
|
|
|
|
}; |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
sub loadL106 { |
526
|
|
|
|
|
|
|
# Load an initial grid from an array containing |
527
|
|
|
|
|
|
|
# a file in Life 1.06 format. |
528
|
1
|
|
|
1
|
1
|
3
|
my ($self, $array, @rest) = @_; |
529
|
1
|
50
|
|
|
|
3
|
if (not defined $array) { return undef; }; |
|
0
|
|
|
|
|
0
|
|
530
|
1
|
|
|
|
|
9
|
foreach my $input (@{ $array }) { |
|
1
|
|
|
|
|
2
|
|
531
|
325
|
|
|
|
|
339
|
chomp($input); |
532
|
325
|
|
|
|
|
1406
|
$input =~ s/^\s*(.*?)\s*$/$1/; |
533
|
325
|
50
|
|
|
|
579
|
if ($input eq '') { next; }; |
|
0
|
|
|
|
|
0
|
|
534
|
325
|
100
|
|
|
|
496
|
if ($input =~ /^#Life 1.06/) { next; }; |
|
1
|
|
|
|
|
3
|
|
535
|
|
|
|
|
|
|
# Not much checks here. Assume that data are numbers. |
536
|
324
|
|
|
|
|
679
|
my ($xx, $yy) = split / /, $input, 2; |
537
|
324
|
|
|
|
|
394
|
$xx += 0; |
538
|
324
|
|
|
|
|
288
|
$yy += 0; |
539
|
324
|
|
|
|
|
603
|
$self->updateCell($xx, $yy, 1); |
540
|
|
|
|
|
|
|
}; |
541
|
1
|
|
|
|
|
4
|
$self->{'name'} = '#Life 1.06 file'; # :-) |
542
|
1
|
|
|
|
|
10
|
return 1; |
543
|
|
|
|
|
|
|
}; |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
sub loadL105 { |
547
|
|
|
|
|
|
|
# Load an initial grid from an array containing |
548
|
|
|
|
|
|
|
# a file in Life 1.05 format. |
549
|
1
|
|
|
1
|
1
|
3
|
my ($self, $array, @rest) = @_; |
550
|
1
|
50
|
|
|
|
5
|
if (not defined $array) { return undef; }; |
|
0
|
|
|
|
|
0
|
|
551
|
1
|
|
|
|
|
3
|
my $posState = 0; |
552
|
1
|
|
|
|
|
2
|
my $name = 'Untitled'; |
553
|
1
|
|
|
|
|
2
|
my $rules = ''; |
554
|
1
|
|
|
|
|
1
|
my $dataline = ''; |
555
|
1
|
|
|
|
|
2
|
my @descrArr = (); |
556
|
1
|
|
|
|
|
3
|
my $ulcx = my $ulcy = 0; # Upper left corner |
557
|
1
|
|
|
|
|
2
|
my $dlinecnt = 0; |
558
|
1
|
|
|
|
|
1
|
foreach my $input (@{ $array }) { |
|
1
|
|
|
|
|
3
|
|
559
|
203
|
|
|
|
|
257
|
chomp($input); |
560
|
203
|
100
|
|
|
|
331
|
if ($input eq '') { next; }; |
|
1
|
|
|
|
|
4
|
|
561
|
202
|
100
|
33
|
|
|
1781
|
if ($input =~ /^#Life 1.05/) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
562
|
1
|
|
|
|
|
2
|
next; |
563
|
|
|
|
|
|
|
} elsif ($input =~ /^#D Name: /) { |
564
|
|
|
|
|
|
|
# Out of spec, but it seems that it's used: |
565
|
1
|
|
|
|
|
5
|
(undef, undef, $name) = split /(^#D Name: )/, $input, 3; |
566
|
1
|
|
|
|
|
2
|
next; |
567
|
|
|
|
|
|
|
} elsif ($input =~ /^#D /) { |
568
|
2
|
50
|
|
|
|
5
|
if ($dlinecnt >= 22) { return undef }; # Specs. |
|
0
|
|
|
|
|
0
|
|
569
|
2
|
|
|
|
|
8
|
my (undef, undef, $dline) = split /(^#D )/, $input, 3; |
570
|
2
|
|
|
|
|
21
|
$dline =~ s/^\s*(.*?)\s*$/$1/; |
571
|
2
|
50
|
|
|
|
5
|
if (length($dline) > 78) { |
572
|
0
|
|
|
|
|
0
|
print "DEBUG ERROR: D-line too long\n"; |
573
|
0
|
|
|
|
|
0
|
return undef; # Specs. |
574
|
|
|
|
|
|
|
} else { |
575
|
2
|
|
|
|
|
4
|
push @descrArr, $dline; |
576
|
|
|
|
|
|
|
}; |
577
|
2
|
|
|
|
|
4
|
$dlinecnt++; |
578
|
|
|
|
|
|
|
} elsif ($input =~ /^#N/) { |
579
|
1
|
|
|
|
|
2
|
next; |
580
|
|
|
|
|
|
|
} elsif ($input =~ /^#R /) { |
581
|
|
|
|
|
|
|
# Rules. |
582
|
0
|
|
|
|
|
0
|
(undef, undef, $rules) = split /(^#R )/, $input, 3; |
583
|
0
|
|
|
|
|
0
|
my ($sstr, $bstr) = split /\//, $rules, 2; |
584
|
|
|
|
|
|
|
|
585
|
0
|
|
|
|
|
0
|
my $barr = []; |
586
|
0
|
|
|
|
|
0
|
my $sarr = []; |
587
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < length($bstr); $i++) { |
588
|
0
|
0
|
|
|
|
0
|
if (substr($bstr, $i, 1) =~ /[0-8]/) { |
589
|
0
|
|
|
|
|
0
|
push @{ $barr }, substr($bstr, $i, 1); |
|
0
|
|
|
|
|
0
|
|
590
|
|
|
|
|
|
|
} else { |
591
|
|
|
|
|
|
|
# Fail. Specs. |
592
|
0
|
|
|
|
|
0
|
print "DEBUG ERROR: wrong rules\n"; |
593
|
0
|
|
|
|
|
0
|
return undef; |
594
|
|
|
|
|
|
|
}; |
595
|
|
|
|
|
|
|
}; |
596
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < length($sstr); $i++) { |
597
|
0
|
0
|
|
|
|
0
|
if (substr($sstr, $i, 1) =~ /[0-8]/) { |
598
|
0
|
|
|
|
|
0
|
push @{ $sarr }, substr($sstr, $i, 1); |
|
0
|
|
|
|
|
0
|
|
599
|
|
|
|
|
|
|
} else { |
600
|
|
|
|
|
|
|
# Fail. Specs. |
601
|
0
|
|
|
|
|
0
|
print "DEBUG ERROR: wrong rules\n"; |
602
|
0
|
|
|
|
|
0
|
return undef; |
603
|
|
|
|
|
|
|
}; |
604
|
|
|
|
|
|
|
}; |
605
|
0
|
|
|
|
|
0
|
$self->setRules([$barr, $sarr]); |
606
|
|
|
|
|
|
|
} elsif ($input =~ /^#P /) { |
607
|
2
|
|
|
|
|
10
|
(undef, $ulcx, $ulcy) = split / /, $input, 3; |
608
|
2
|
|
|
|
|
4
|
$ulcx += 0; |
609
|
2
|
|
|
|
|
4
|
$ulcy += 0; |
610
|
2
|
|
|
|
|
5
|
$posState = 1; |
611
|
|
|
|
|
|
|
} elsif ( |
612
|
|
|
|
|
|
|
($input =~/^(\.|\*)/) and |
613
|
|
|
|
|
|
|
($posState == 1) |
614
|
|
|
|
|
|
|
) { |
615
|
|
|
|
|
|
|
# Data line: |
616
|
|
|
|
|
|
|
#print "DEBUG: DL: $input\n"; |
617
|
195
|
|
|
|
|
234
|
my $xx = $ulcx; |
618
|
195
|
|
|
|
|
195
|
my $yy = $ulcy; |
619
|
195
|
|
|
|
|
342
|
while (length($input) > 0) { |
620
|
4086
|
|
|
|
|
4889
|
my $char = substr($input, 0, 1); |
621
|
4086
|
|
|
|
|
4876
|
$input = substr($input, 1); |
622
|
4086
|
100
|
|
|
|
7985
|
if ($char eq '*') { |
|
|
50
|
|
|
|
|
|
623
|
|
|
|
|
|
|
#print "\tDEBUG: LIVE ($xx,$yy)\n"; |
624
|
324
|
|
|
|
|
736
|
$self->updateCell($xx, $yy, 1); |
625
|
324
|
|
|
|
|
868
|
$xx++; |
626
|
|
|
|
|
|
|
} elsif ($char eq '.') { |
627
|
3762
|
|
|
|
|
6882
|
$xx++; |
628
|
|
|
|
|
|
|
} else { |
629
|
|
|
|
|
|
|
# Fail. |
630
|
0
|
|
|
|
|
0
|
print "DEBUG ERROR: unknown char\n"; |
631
|
0
|
|
|
|
|
0
|
return undef; |
632
|
|
|
|
|
|
|
}; |
633
|
|
|
|
|
|
|
}; |
634
|
195
|
|
|
|
|
376
|
$ulcy++; |
635
|
|
|
|
|
|
|
} else { |
636
|
|
|
|
|
|
|
# Unrecognized input: |
637
|
0
|
|
|
|
|
0
|
print "DEBUG ERROR: unknown input:\n\t|$input|\n"; |
638
|
0
|
|
|
|
|
0
|
return undef; |
639
|
|
|
|
|
|
|
}; |
640
|
|
|
|
|
|
|
}; |
641
|
1
|
|
|
|
|
4
|
$self->{'description'} = \@descrArr; |
642
|
1
|
|
|
|
|
14
|
$self->{'name'} = $name; |
643
|
1
|
|
|
|
|
5
|
return 1; |
644
|
|
|
|
|
|
|
}; |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
sub loadRLE { |
648
|
|
|
|
|
|
|
# Load an initial grid from an array containing |
649
|
|
|
|
|
|
|
# a file in RLE format. |
650
|
1
|
|
|
1
|
1
|
3
|
my ($self, $array, @rest) = @_; |
651
|
1
|
50
|
|
|
|
4
|
if (not defined $array) { return undef; }; |
|
0
|
|
|
|
|
0
|
|
652
|
1
|
|
|
|
|
3
|
my $posState = 0; |
653
|
1
|
|
|
|
|
4
|
my $name = 'Untitled'; |
654
|
1
|
|
|
|
|
2
|
my $headRules = my $rules = ''; |
655
|
1
|
|
|
|
|
3
|
my $dataline = ''; |
656
|
1
|
|
|
|
|
2
|
my $ulcx = my $ulcy = 0; # Upper left corner |
657
|
1
|
|
|
|
|
2
|
foreach my $input (@{ $array }) { |
|
1
|
|
|
|
|
2
|
|
658
|
20
|
|
|
|
|
25
|
chomp($input); |
659
|
20
|
100
|
33
|
|
|
128
|
if ($input =~ /^#N /) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
660
|
1
|
|
|
|
|
6
|
(undef, undef, $name) = split /(^#N )/, $input, 3; |
661
|
1
|
|
|
|
|
3
|
next; |
662
|
|
|
|
|
|
|
} elsif ($input =~ /^#r /) { |
663
|
|
|
|
|
|
|
# Rules: |
664
|
0
|
|
|
|
|
0
|
(undef, undef, $headRules) = split /(^#r )/, $input, 3; |
665
|
0
|
|
|
|
|
0
|
next; |
666
|
|
|
|
|
|
|
} elsif (($input =~ /^#P /) or ($input =~ /^#R /)) { |
667
|
0
|
|
|
|
|
0
|
(undef, $ulcx, $ulcy) = split / /, $input, 3; |
668
|
0
|
|
|
|
|
0
|
next; |
669
|
|
|
|
|
|
|
} elsif ($input =~ /^#/) { |
670
|
|
|
|
|
|
|
# Ignore all other # lines: |
671
|
2
|
|
|
|
|
6
|
next; |
672
|
|
|
|
|
|
|
} elsif ($input =~ /^x/) { |
673
|
|
|
|
|
|
|
# Header line. |
674
|
1
|
|
|
|
|
6
|
$input =~ s/ //g; |
675
|
1
|
|
|
|
|
2
|
my ($xc, $yc); |
676
|
1
|
|
|
|
|
5
|
($xc, $yc, $rules) = split /,/ , $input; |
677
|
1
|
50
|
33
|
|
|
9
|
if ((not ($xc =~ /x=/)) or (not ($yc =~ /y=/))) { |
678
|
|
|
|
|
|
|
# Fail. |
679
|
0
|
|
|
|
|
0
|
return undef; |
680
|
|
|
|
|
|
|
}; |
681
|
1
|
|
|
|
|
3
|
$posState = 1; |
682
|
1
|
|
|
|
|
2
|
next; |
683
|
|
|
|
|
|
|
} else { |
684
|
|
|
|
|
|
|
# Normal line: |
685
|
16
|
50
|
|
|
|
30
|
if (not $posState) { |
686
|
|
|
|
|
|
|
# No header? |
687
|
0
|
|
|
|
|
0
|
return undef; |
688
|
|
|
|
|
|
|
}; |
689
|
|
|
|
|
|
|
# Join in one big string: |
690
|
16
|
|
|
|
|
20
|
$dataline .= $input; |
691
|
16
|
|
|
|
|
20
|
next; |
692
|
|
|
|
|
|
|
}; |
693
|
|
|
|
|
|
|
}; |
694
|
|
|
|
|
|
|
# Now parse actual data: |
695
|
1
|
|
|
|
|
35
|
my @dataArr = split /\$/, $dataline; |
696
|
1
|
|
|
|
|
5
|
my %extraStates = (); |
697
|
1
|
|
|
|
|
2
|
my $extraStatesCnt = 0; |
698
|
1
|
|
|
|
|
2
|
my $xx = $ulcx; |
699
|
1
|
|
|
|
|
2
|
my $yy = $ulcy; |
700
|
|
|
|
|
|
|
#print "DEBUG: " . scalar(@dataArr) . " lines\n"; |
701
|
1
|
|
|
|
|
2
|
REC: foreach my $rec (@dataArr) { |
702
|
|
|
|
|
|
|
#print "DEBUG: RLE REC: \n\t$rec\n"; |
703
|
|
|
|
|
|
|
#print "\tLINE: $yy\n"; |
704
|
81
|
|
|
|
|
84
|
my $cntstr = '0'; |
705
|
81
|
|
|
|
|
147
|
CHAR: while (length($rec) > 0) { |
706
|
994
|
|
|
|
|
1360
|
my $char = substr($rec, 0, 1); |
707
|
994
|
|
|
|
|
1229
|
$rec = substr($rec, 1); |
708
|
994
|
100
|
|
|
|
2803
|
if ($char =~ /\d/) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
709
|
518
|
|
|
|
|
566
|
$cntstr .= $char; |
710
|
518
|
|
|
|
|
1129
|
next CHAR; |
711
|
|
|
|
|
|
|
} elsif ($char eq 'o') { |
712
|
200
|
100
|
|
|
|
332
|
my $cnt = ($cntstr eq '0') ? 1 : $cntstr + 0; |
713
|
200
|
|
|
|
|
205
|
$cntstr = '0'; # Reset. |
714
|
200
|
|
|
|
|
421
|
for (my $i = 0; $i < $cnt; $i++) { |
715
|
324
|
|
|
|
|
791
|
$self->updateCell($xx++, $yy, 1); |
716
|
|
|
|
|
|
|
}; |
717
|
|
|
|
|
|
|
} elsif ($char eq 'b') { |
718
|
275
|
100
|
|
|
|
580
|
my $cnt = ($cntstr eq '0') ? 1 : $cntstr + 0; |
719
|
275
|
|
|
|
|
323
|
$cntstr = '0'; # Reset. |
720
|
275
|
|
|
|
|
595
|
$xx += $cnt; |
721
|
|
|
|
|
|
|
} elsif ($char eq '!') { |
722
|
|
|
|
|
|
|
# No more! |
723
|
1
|
|
|
|
|
4
|
last REC; |
724
|
|
|
|
|
|
|
} else { |
725
|
|
|
|
|
|
|
# Handle unknown characters as extra states. Good luck with that. |
726
|
|
|
|
|
|
|
# We will handle a max of 3 extra states (Immigration/Quadlife). |
727
|
0
|
0
|
|
|
|
0
|
my $cnt = ($cntstr eq '0') ? 1 : $cntstr + 0; |
728
|
0
|
0
|
|
|
|
0
|
if (defined $extraStates{$char}) { |
729
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < $cnt; $i++) { |
730
|
0
|
|
|
|
|
0
|
$self->updateCell($xx++, $yy, $extraStates{$char}); |
731
|
|
|
|
|
|
|
}; |
732
|
|
|
|
|
|
|
} else { |
733
|
|
|
|
|
|
|
# New state |
734
|
0
|
|
|
|
|
0
|
$extraStatesCnt++; |
735
|
0
|
0
|
|
|
|
0
|
if ($extraStatesCnt > 3) { |
736
|
|
|
|
|
|
|
# Fail. |
737
|
0
|
|
|
|
|
0
|
return undef; |
738
|
|
|
|
|
|
|
} else { |
739
|
0
|
|
|
|
|
0
|
$extraStates{$char} = $extraStatesCnt+1; |
740
|
|
|
|
|
|
|
}; |
741
|
0
|
0
|
|
|
|
0
|
if ($extraStatesCnt == 1) { |
|
|
0
|
|
|
|
|
|
742
|
0
|
0
|
|
|
|
0
|
$self->setColor('immigration') or die "Failed to set color on load!\n"; |
743
|
|
|
|
|
|
|
} elsif ($extraStatesCnt > 1) { |
744
|
0
|
0
|
|
|
|
0
|
$self->setColor('quadlife') or die "Failed to set color on load!\n"; |
745
|
|
|
|
|
|
|
}; |
746
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < $cnt; $i++) { |
747
|
0
|
|
|
|
|
0
|
$self->updateCell($xx++, $yy, $extraStates{$char}); |
748
|
|
|
|
|
|
|
}; |
749
|
|
|
|
|
|
|
}; |
750
|
|
|
|
|
|
|
}; |
751
|
|
|
|
|
|
|
}; |
752
|
|
|
|
|
|
|
# If there are digits left, they are empty lines. |
753
|
80
|
100
|
|
|
|
135
|
my $cnt = ($cntstr eq '0') ? 1 : $cntstr + 0; |
754
|
80
|
|
|
|
|
86
|
$cntstr = '0'; # Reset. |
755
|
80
|
|
|
|
|
88
|
$yy += $cnt; # Next line or skip lines. |
756
|
80
|
|
|
|
|
129
|
$xx = $ulcx; # Reset |
757
|
|
|
|
|
|
|
}; |
758
|
1
|
|
|
|
|
11
|
$self->{'name'} = $name; |
759
|
1
|
50
|
|
|
|
6
|
if ($extraStatesCnt > 1) { |
|
|
50
|
|
|
|
|
|
760
|
0
|
0
|
|
|
|
0
|
$self->setColor('quadlife') or die "Failed to set color on load!\n"; |
761
|
|
|
|
|
|
|
#print "DEBUG: RLE: Quadlife\n"; |
762
|
|
|
|
|
|
|
} elsif ($extraStatesCnt == 1) { |
763
|
0
|
0
|
|
|
|
0
|
$self->setColor('immigration') or die "Failed to set color on load!\n"; |
764
|
|
|
|
|
|
|
#print "DEBUG: RLE: Immigration\n"; |
765
|
|
|
|
|
|
|
}; |
766
|
|
|
|
|
|
|
# Handle rules: |
767
|
1
|
|
|
|
|
3
|
my $bstr = my $sstr = ''; |
768
|
1
|
50
|
|
|
|
3
|
if ($rules ne '') { |
|
|
0
|
|
|
|
|
|
769
|
|
|
|
|
|
|
# Rules in header line have priority over comment line rules: |
770
|
1
|
|
|
|
|
7
|
(undef, $rules) = split /=/, $rules, 2; |
771
|
1
|
|
|
|
|
5
|
($bstr, $sstr) = split /\//, $rules, 2; |
772
|
|
|
|
|
|
|
} elsif ($headRules ne '') { |
773
|
0
|
|
|
|
|
0
|
my ($sstr, $bstr) = split /\//, $headRules, 2; |
774
|
|
|
|
|
|
|
}; |
775
|
1
|
50
|
33
|
|
|
16
|
if (($rules ne '') or ($headRules ne '')) { |
776
|
1
|
|
|
|
|
4
|
my $barr = []; |
777
|
1
|
|
|
|
|
2
|
my $sarr = []; |
778
|
1
|
|
|
|
|
5
|
for (my $i = 0; $i < length($bstr); $i++) { |
779
|
2
|
100
|
|
|
|
16
|
if (substr($bstr, $i, 1) =~ /\d/) { push @{ $barr }, substr($bstr, $i, 1); }; |
|
1
|
|
|
|
|
48
|
|
|
1
|
|
|
|
|
7
|
|
780
|
|
|
|
|
|
|
}; |
781
|
1
|
|
|
|
|
4
|
for (my $i = 0; $i < length($sstr); $i++) { |
782
|
3
|
100
|
|
|
|
14
|
if (substr($sstr, $i, 1) =~ /\d/) { push @{ $sarr }, substr($sstr, $i, 1); }; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
7
|
|
783
|
|
|
|
|
|
|
}; |
784
|
1
|
|
|
|
|
6
|
$self->setRules([$barr, $sarr]); |
785
|
|
|
|
|
|
|
}; |
786
|
1
|
|
|
|
|
13
|
return 1; |
787
|
|
|
|
|
|
|
}; |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
sub loadCells { |
790
|
|
|
|
|
|
|
# Load an initial grid from an array containing |
791
|
|
|
|
|
|
|
# a file in cells (ASCII) format. |
792
|
8
|
|
|
8
|
1
|
19
|
my ($self, $array, @rest) = @_; |
793
|
8
|
50
|
|
|
|
24
|
if (not defined $array) { return undef; }; |
|
0
|
|
|
|
|
0
|
|
794
|
8
|
|
|
|
|
13
|
my $name = 'Untitled'; |
795
|
8
|
|
|
|
|
14
|
my @descrArr = (); |
796
|
8
|
|
|
|
|
17
|
my $xx = my $yy = my $cnt = 0; |
797
|
8
|
|
|
|
|
13
|
my $immigration = my $quadlife = 0; |
798
|
|
|
|
|
|
|
#my $input; |
799
|
|
|
|
|
|
|
#open($input, "<", $fn) or die "cannot open $input: $!\n"; |
800
|
|
|
|
|
|
|
#while (<$input>) { |
801
|
8
|
|
|
|
|
10
|
foreach my $input (@{ $array }) { |
|
8
|
|
|
|
|
20
|
|
802
|
158
|
|
|
|
|
244
|
chomp($input); |
803
|
158
|
100
|
|
|
|
550
|
if ($input =~ /^!Name: /) { |
|
|
100
|
|
|
|
|
|
804
|
1
|
|
|
|
|
33
|
(undef, undef, $name) = split /(^!Name: )/, $input, 3; |
805
|
1
|
|
|
|
|
3
|
next; |
806
|
|
|
|
|
|
|
} elsif ($input =~ /^!/) { |
807
|
2
|
|
|
|
|
3
|
push @descrArr, $input; |
808
|
2
|
|
|
|
|
2
|
next; |
809
|
|
|
|
|
|
|
}; |
810
|
155
|
|
|
|
|
345
|
for ($yy = 0; $yy <= length($input); $yy++) { |
811
|
5835
|
100
|
|
|
|
26455
|
if (substr($input, $yy, 1) eq 'O') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
812
|
417
|
|
|
|
|
1042
|
$self->updateCell($yy, $xx, 1); |
813
|
417
|
|
|
|
|
1022
|
$cnt++; |
814
|
|
|
|
|
|
|
} elsif (substr($input, $yy, 1) eq '2') { |
815
|
12
|
50
|
|
|
|
33
|
$self->setColor('immigration') or die "Failed to set color on load!\n"; |
816
|
12
|
|
|
|
|
29
|
$self->updateCell($yy, $xx, 2); |
817
|
12
|
|
|
|
|
15
|
$immigration = 1; |
818
|
12
|
|
|
|
|
32
|
$cnt++; |
819
|
|
|
|
|
|
|
} elsif (substr($input, $yy, 1) eq '3') { |
820
|
9
|
50
|
|
|
|
21
|
$self->setColor('quadlife') or die "Failed to set color on load!\n"; |
821
|
9
|
|
|
|
|
22
|
$self->updateCell($yy, $xx, 3); |
822
|
9
|
|
|
|
|
12
|
$quadlife = 1; |
823
|
9
|
|
|
|
|
21
|
$cnt++; |
824
|
|
|
|
|
|
|
} elsif (substr($input, $yy, 1) eq '4') { |
825
|
6
|
50
|
|
|
|
25
|
$self->setColor('quadlife') or die "Failed to set color on load!\n"; |
826
|
6
|
|
|
|
|
24
|
$self->updateCell($yy, $xx, 4); |
827
|
6
|
|
|
|
|
7
|
$quadlife = 1; |
828
|
6
|
|
|
|
|
17
|
$cnt++; |
829
|
|
|
|
|
|
|
}; |
830
|
|
|
|
|
|
|
}; |
831
|
155
|
|
|
|
|
207
|
$xx++; |
832
|
|
|
|
|
|
|
}; |
833
|
8
|
|
|
|
|
34
|
$self->{'name'} = $name; |
834
|
8
|
|
|
|
|
39
|
$self->{'description'} = \@descrArr; |
835
|
|
|
|
|
|
|
# Finalize board colour: |
836
|
8
|
100
|
|
|
|
41
|
if ($quadlife) { |
|
|
100
|
|
|
|
|
|
837
|
2
|
50
|
|
|
|
7
|
$self->setColor('quadlife') or die "Failed to set color on load!\n"; |
838
|
|
|
|
|
|
|
} elsif ($immigration) { |
839
|
1
|
50
|
|
|
|
3
|
$self->setColor('immigration') or die "Failed to set color on load!\n"; |
840
|
|
|
|
|
|
|
}; |
841
|
8
|
|
|
|
|
31
|
return 1; |
842
|
|
|
|
|
|
|
}; |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
42; |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
__END__ |