File Coverage

blib/lib/Language/Homespring.pm
Criterion Covered Total %
statement 136 144 94.4
branch 36 46 78.2
condition 11 21 52.3
subroutine 17 18 94.4
pod 4 4 100.0
total 204 233 87.5


line stmt bran cond sub pod time code
1             package Language::Homespring;
2              
3             $VERSION = 0.04;
4              
5 4     4   77219 use strict;
  4         9  
  4         152  
6 4     4   22 use warnings;
  4         7  
  4         121  
7              
8 4     4   8735 use Language::Homespring::Node;
  4         10  
  4         113  
9 4     4   2562 use Language::Homespring::Salmon;
  4         10  
  4         120  
10 4     4   3116 use Language::Homespring::Snowmelt;
  4         21  
  4         109  
11 4     4   2246 use Language::Homespring::River;
  4         9  
  4         6605  
12              
13             sub new {
14 26     26 1 16607 my $class = shift;
15 26         80 my $self = bless {}, $class;
16              
17 26         43 my $options = shift;
18 26         84 $self->{root_node} = undef;
19 26         109 $self->{salmon} = [];
20 26         52 $self->{snowmelt} = [];
21 26         57 $self->{new_salmon} = [];
22 26         52 $self->{dead_salmon} = [];
23 26         58 $self->{output} = '';
24 26         48 $self->{universe_ok} = 1;
25              
26 26         67 return $self;
27             }
28              
29             sub parse {
30 26     26 1 104 my ($self, $source) = @_;
31              
32 151         381 my @tokens =
33 151         276 map{s/(\.$)|(^\.)/\n/g; $_}
  151         183  
34 151         275 map{s/\. / /g; $_}
  151         174  
35 26         365 map{s/ \././g; $_}
  151         239  
36             split /(?:(?
37              
38             #print((join '|', @tokens)."\n\n");
39              
40 26         287 $self->{root_node} = new Language::Homespring::Node({
41             'interp' => $self,
42             'node_name' => shift @tokens,
43             });
44 26         71 my $parent = $self->{root_node};
45              
46 26         40 for my $token(@tokens){
47 125 100       225 if ($token){
48 95         469 my $new_node = new Language::Homespring::Node({
49             'interp' => $self,
50             'node_name' => $token,
51             'parent_node' => $parent,
52             });
53 95         414 $parent->add_child($new_node);
54              
55 95         583 my $new_river = new Language::Homespring::River({
56             'interp' => $self,
57             'up_node' => $new_node,
58             'down_node' => $parent,
59             });
60 95         436 $parent->add_river_up($new_river);
61 95         233 $new_node->add_river_down($new_river);
62              
63 95         226 $parent = $new_node;
64             }else{
65 30 50       77 if (defined $parent->{parent_node}){
66 30         53 $parent = $parent->{parent_node};
67             }
68             }
69             }
70             }
71              
72             sub tick {
73 155     155 1 819 my ($self) = @_;
74 155         176 my @nodes;
75              
76 155         223 $self->{output} = '';
77              
78             # has our universe been smashed?
79 155 100       366 return if !$self->{universe_ok};
80              
81             # process snowmelts
82 151         274 @nodes = $self->_get_nodes('snowmelt');
83 151         240 for (@nodes){
84             #spawn a new snowmelt
85 31         167 my $snowmelt = new Language::Homespring::Snowmelt({'interp' => $self, 'location' => $_});
86 31         67 push @{$self->{snowmelt}}, $snowmelt;
  31         95  
87             }
88 151         170 $_->move() for (@{$self->{snowmelt}});
  151         352  
89              
90             # has our universe been smashed?
91 151 100       337 return if !$self->{universe_ok};
92            
93              
94             # process water
95              
96             # turn everything off
97 149         314 $self->_set_all('water', 0);
98              
99             # water from springs
100 149         322 @nodes = $self->_get_all_nodes();
101 149         263 for (@nodes){
102 700 100       1767 $self->_water_downwards($_) if $_->{spring};
103             }
104              
105             # process electricity
106              
107             # turn everything off
108 149         411 $self->_set_recurse($self->{root_node}, 'power', 0);
109              
110             # process "powers"
111 149         367 @nodes = $self->_get_nodes('powers');
112 149         247 for(@nodes){
113 116 100       290 if (!$_->{destroyed}){
114 110         206 $self->_power_downwards($_);
115             }
116             }
117              
118             # process "hydro power"
119 149         332 @nodes = $self->_get_nodes('hydro power');
120 149         225 for (@nodes){
121 19 100 100     126 $self->_power_downwards($_) if $_->{water} && !$_->{destroyed};
122             }
123              
124             # process "power invert"
125 149         5313 @nodes = $self->_get_nodes('power invert');
126 149         223 for (@nodes){
127 18 100 66     100 $self->_power_downwards($_) if !$_->{power} && !$_->{destroyed};
128             }
129              
130             # process salmon
131              
132 149         159 $_->move() for (@{$self->{salmon}});
  149         510  
133              
134             # sort out dead salmon
135 149         323 @{$self->{salmon}} = grep{
  338         356  
136 149         281 my $ok = 1;
137 338         321 for my $dead(@{$self->{dead_salmon}}){
  338         650  
138 781 100       1835 $ok = 0 if $_ == $dead;
139             }
140 338         592 $ok;
141 149         210 }@{$self->{salmon}};
142              
143             # sort out new salmon
144 149         178 push @{$self->{salmon}}, @{$self->{new_salmon}};
  149         200  
  149         232  
145 149         295 $self->{new_salmon} = [];
146              
147             # process others
148              
149 149         408 @nodes = $self->_get_nodes('hatchery');
150 149         267 for (@nodes){
151 149 100       392 if ($_->{power}){
152 103         104 my $location = @{$_->{rivers_up}}[0];
  103         176  
153 103         580 my $salmon = new Language::Homespring::Salmon({'interp' => $self,'mature' => 1, 'upstream' => 1, 'location' => $location});
154 103         209 push @{$self->{salmon}}, $salmon;
  103         314  
155             }
156             }
157              
158             # @nodes = $self->_get_nodes('bear');
159             # for (@nodes){
160             # for my $salmon($_->get_salmon()){
161             # $salmon->kill() if $salmon->{mature};
162             # }
163             # }
164              
165 149         476 return $self->{output};
166             }
167              
168             sub run{
169 0     0 1 0 my ($self, $max_ticks, $delimit) = @_;
170 0         0 my $tick = 0;
171 0         0 while(1){
172 0         0 print $self->tick();
173 0 0       0 print $delimit if defined($delimit);
174 0         0 $tick++;
175 0 0 0     0 return if (defined($max_ticks) && ($tick >= $max_ticks));
176 0 0       0 return if !$self->{universe_ok};
177             }
178             }
179              
180             sub _set_all {
181 149     149   226 my ($self, $prop, $value) = @_;
182 149         348 $self->_set_recurse($self->{root_node}, $prop, $value);
183             }
184              
185             sub _set_recurse {
186 1400     1400   1903 my ($self, $node, $prop, $value) = @_;
187 1400         1901 $node->{$prop} = $value;
188 1400         1387 $self->_set_recurse($_, $prop, $value) for @{$node->{child_nodes}};
  1400         5317  
189             }
190              
191             sub _get_nodes {
192 747     747   959 my ($self, $name) = @_;
193 747         1684 return $self->_get_nodes_i($self->{root_node}, $name);
194             }
195              
196             sub _get_nodes_i {
197 3512     3512   4352 my ($self, $node, $name) = @_;
198 3512         4197 my @out = ();
199 3512 100       7593 push @out, $node if ($node->{node_name} eq $name);
200 3512         4546 push @out, $self->_get_nodes_i($_, $name) for @{$node->{child_nodes}};
  3512         9712  
201 3512         9043 return @out;
202             }
203              
204             sub _get_all_nodes {
205 149     149   196 my ($self) = @_;
206 149         560 return $self->_get_all_nodes_i($self->{root_node});
207             }
208              
209             sub _get_all_nodes_i {
210 700     700   1097 my ($self, $node) = @_;
211 700         917 my @out = ();
212 700         787 push @out, $node;
213 700         1096 push @out, $self->_get_all_nodes_i($_) for @{$node->{child_nodes}};
  700         1674  
214 700         2463 return @out;
215             }
216              
217             sub _power_downwards {
218 337     337   383 my ($self, $node) = @_;
219              
220 337 100       819 return if (!$node->{parent_node});
221              
222 234         301 $node->{parent_node}->{power} = 1;
223              
224 234 100       494 return if ($node->{parent_node}->{node_name} eq 'power invert');
225 229 100       436 return if ($node->{parent_node}->{node_name} eq 'insulated');
226 224 100       435 return if ($node->{parent_node}->{node_name} eq 'force field');
227 211 50 33     533 return if (($node->{parent_node}->{node_name} eq 'bridge') && ($node->{parent_node}->{destroyed}));
228              
229             # TODO: "sense" and "switch"
230              
231 211         425 $self->_power_downwards($node->{parent_node});
232             }
233              
234             sub _water_downwards {
235 506     506   649 my ($self, $node) = @_;
236              
237 506 100       1326 return if (!$node->{parent_node});
238              
239 340         525 $node->{parent_node}->{water} = 1;
240              
241 340 100 100     1098 return if (($node->{parent_node}->{node_name} eq 'force field') && ($node->{parent_node}->{power}));
242 334 50 33     822 return if (($node->{parent_node}->{node_name} eq 'bridge') && ($node->{parent_node}->{destroyed}));
243 334 50 33     858 return if (($node->{parent_node}->{node_name} eq 'evaporates') && ($node->{parent_node}->{power}));
244              
245 334         670 $self->_water_downwards($node->{parent_node});
246             }
247              
248             __END__