| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Games::Worms::Board; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | # A (base) class encapsulating a worm universe. | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 3 |  |  | 3 |  | 17 | use strict; | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 129 |  | 
| 6 | 3 |  |  | 3 |  | 16 | use vars qw($Debug $VERSION %Default $Use_Error %Boards); | 
|  | 3 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 3250 |  | 
| 7 |  |  |  |  |  |  | $VERSION = "0.60"; | 
| 8 |  |  |  |  |  |  | $Debug = 0; | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | $Use_Error = ''; | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | %Boards = (); | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | # | 
| 17 |  |  |  |  |  |  | # We need methods Seg and Node that report the names of | 
| 18 |  |  |  |  |  |  | # the classes our segments and nodes should belong to. | 
| 19 |  |  |  |  |  |  | # | 
| 20 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 21 |  |  |  |  |  |  | # Constants for this universe | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | my $D60 = 3.14159 / 6;  # sixty degrees | 
| 24 |  |  |  |  |  |  | my $SIN60 = sin($D60);  # the sin of 60 degrees, tweaked | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 27 |  |  |  |  |  |  | %Default = ( | 
| 28 |  |  |  |  |  |  | 'cells_wide' => 50, | 
| 29 |  |  |  |  |  |  | 'cells_high' => 50, | 
| 30 |  |  |  |  |  |  | 'tri_base' => 10, | 
| 31 |  |  |  |  |  |  | 'aspect' => 1.3, | 
| 32 |  |  |  |  |  |  | 'bg_color' => "#000000", | 
| 33 |  |  |  |  |  |  | 'line_color' => "#202020", | 
| 34 |  |  |  |  |  |  | ); | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | # return a hash of the defaults in this class | 
| 37 | 0 |  |  | 0 | 0 |  | sub Default { return %Default } | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | sub new { | 
| 42 | 0 |  |  | 0 | 0 |  | my $c = shift; | 
| 43 | 0 |  | 0 |  |  |  | $c = ref($c) || $c; | 
| 44 | 0 |  |  |  |  |  | my $it = bless { $c->Default, @_ }, $c; | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | # deriveds | 
| 47 | 0 | 0 |  |  |  |  | unless(defined $it->{'inner_border'}) { | 
| 48 | 0 |  |  |  |  |  | $it->{'inner_border'} = int($it->{'tri_base'} / 10); | 
| 49 | 0 | 0 |  |  |  |  | $it->{'inner_border'} = 3 if $it->{'inner_border'} < 3; | 
| 50 |  |  |  |  |  |  | } | 
| 51 | 0 |  | 0 |  |  |  | $it->{'worms'} ||= []; | 
| 52 |  |  |  |  |  |  |  | 
| 53 | 0 |  |  |  |  |  | $it->{'tri_height'} = | 
| 54 |  |  |  |  |  |  | int($it->{'tri_base'} * $SIN60 * $it->{'aspect'} + .5); | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 0 |  |  |  |  |  | $it->{'canvas_width'} = 2 * $it->{'inner_border'} + | 
| 57 |  |  |  |  |  |  | ($it->{'cells_wide'} + .5) * $it->{'tri_base'}; | 
| 58 | 0 |  |  |  |  |  | $it->{'canvas_height'} = 2 * $it->{'inner_border'} + | 
| 59 |  |  |  |  |  |  | $it->{'cells_high'} * $it->{'tri_height'}; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 0 |  |  |  |  |  | $it->init; | 
| 62 | 0 |  |  |  |  |  | return $it; | 
| 63 |  |  |  |  |  |  | } | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 0 |  |  | 0 | 0 |  | sub init { return; } | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | #sub worms { # return worms on this board (whether live or dead) | 
| 70 |  |  |  |  |  |  | #  my $board = $_[0]; | 
| 71 |  |  |  |  |  |  | #  return @{$board->{'worms'}}; | 
| 72 |  |  |  |  |  |  | #} | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | sub tick { # do system update tasks -- override in derived classes | 
| 77 | 0 |  |  | 0 | 0 |  | return; | 
| 78 |  |  |  |  |  |  | } | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | sub run { | 
| 83 | 0 |  |  | 0 | 0 |  | my($board, @Worm_names) = @_; | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 0 |  |  |  |  |  | $Games::Worms::Color_counter = 0; | 
| 86 | 0 |  |  |  |  |  | $board->{'generations'} = 0; | 
| 87 | 0 | 0 |  |  |  |  | @Worm_names = ('Games::Worms::Random2', 'Games::Worms::Random2', | 
| 88 |  |  |  |  |  |  | 'Games::Worms::Beeler', 'Games::Worms::Beeler', | 
| 89 |  |  |  |  |  |  | ) unless @Worm_names; | 
| 90 |  |  |  |  |  |  |  | 
| 91 | 0 |  |  |  |  |  | my $n = 0; | 
| 92 | 0 |  |  |  |  |  | foreach my $w (@Worm_names) { | 
| 93 | 0 |  |  |  |  |  | my $rules = ''; | 
| 94 | 0 | 0 |  |  |  |  | if($w =~ s(.*)><>) { | 
| 95 | 0 |  |  |  |  |  | $rules = $1; | 
| 96 | 0 | 0 |  |  |  |  | $w = 'Games::Worms::Beeler' unless length $w; | 
| 97 |  |  |  |  |  |  | } | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 0 | 0 |  |  |  |  | unless(&_try_use($w)) { | 
| 100 | 0 |  |  |  |  |  | die "Can't use $w : $Use_Error\n"; | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  | $w->new( | 
| 103 | 0 |  |  |  |  |  | 'current_node' => | 
| 104 | 0 |  |  |  |  |  | $board->{'nodes'}[ rand(scalar( @{$board->{'nodes'}} )) ], | 
| 105 |  |  |  |  |  |  | 'board' => $board, | 
| 106 |  |  |  |  |  |  | 'rules' => $rules, | 
| 107 |  |  |  |  |  |  | 'name' => $w . '(' . $n++ . ')', | 
| 108 |  |  |  |  |  |  | ); | 
| 109 |  |  |  |  |  |  | } | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 0 |  |  |  |  |  | $board->worm_status_setup; | 
| 112 |  |  |  |  |  |  |  | 
| 113 | 0 |  |  |  |  |  | while(1) { | 
| 114 | 0 |  |  |  |  |  | my @worms = grep {$_->is_alive} @{$board->{'worms'}}; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 115 | 0 | 0 |  |  |  |  | unless(@worms) { | 
| 116 | 0 | 0 |  |  |  |  | print "All dead.\n" if $Debug; | 
| 117 | 0 |  |  |  |  |  | last; | 
| 118 |  |  |  |  |  |  | } | 
| 119 | 0 |  |  |  |  |  | foreach my $worm (@worms) { $worm->try_move } | 
|  | 0 |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | } continue { | 
| 122 | 0 |  |  |  |  |  | $board->{'generations'}++; | 
| 123 | 0 |  |  |  |  |  | $board->tick; | 
| 124 |  |  |  |  |  |  | } | 
| 125 |  |  |  |  |  |  |  | 
| 126 | 0 |  |  |  |  |  | $board->end_game; | 
| 127 | 0 |  |  |  |  |  | return; | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 131 |  |  |  |  |  |  | # Something to do once everything's died -- override in derived class | 
| 132 | 0 |  |  | 0 | 0 |  | sub end_game { return; } | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 135 |  |  |  |  |  |  | # Whatever needs to be done to set up the status for the newly created | 
| 136 |  |  |  |  |  |  | #  worms -- override in derived class | 
| 137 | 0 |  |  | 0 | 0 |  | sub worm_status_setup { return; } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 140 |  |  |  |  |  |  | # Basically a wrapper around "use Modulename" | 
| 141 |  |  |  |  |  |  | my %tried = (); | 
| 142 |  |  |  |  |  |  | sub _try_use { | 
| 143 |  |  |  |  |  |  | # "Many men have tried..."  "They tried and failed?"  "They tried and died." | 
| 144 | 0 |  |  | 0 |  |  | my $module = $_[0];   # ASSUME sane module name! | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 0 | 0 |  |  |  |  | return $tried{$module} if exists $tried{$module};  # memoization | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 3 |  |  | 3 |  | 21 | { no strict; | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 18925 |  | 
|  | 0 |  |  |  |  |  |  | 
| 149 | 0 |  |  |  |  |  | return($tried{$module} = 1) | 
| 150 | 0 | 0 | 0 |  |  |  | if defined(%{$class . "::VERSION"}) || defined(@{$class . "::ISA"}); | 
|  | 0 |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | # we never use'd it, but there it is! | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  |  | 
| 154 | 0 | 0 |  |  |  |  | die "illegal module name \"$module\"\n" | 
| 155 |  |  |  |  |  |  | unless $module =~ m/^[-a-zA-Z0-9_:']+$/s; | 
| 156 | 0 | 0 |  |  |  |  | print " About to use $module ...\n" if $Debug; | 
| 157 |  |  |  |  |  |  | { | 
| 158 | 0 |  |  |  |  |  | local $SIG{'__DIE__'} = undef; | 
|  | 0 |  |  |  |  |  |  | 
| 159 | 0 |  |  |  |  |  | eval "package Nullius; use $module"; | 
| 160 |  |  |  |  |  |  | } | 
| 161 | 0 | 0 |  |  |  |  | if($@) { | 
| 162 | 0 | 0 |  |  |  |  | print "Error using $module \: $@\n" if $Debug > 1; | 
| 163 | 0 |  |  |  |  |  | $Use_Error = $@; | 
| 164 | 0 |  |  |  |  |  | return($tried{$module} = 0); | 
| 165 |  |  |  |  |  |  | } else { | 
| 166 | 0 | 0 |  |  |  |  | print " OK, $module is used\n" if $Debug; | 
| 167 | 0 |  |  |  |  |  | $Use_Error = ''; | 
| 168 | 0 |  |  |  |  |  | return($tried{$module} = 1); | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  | } | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 173 |  |  |  |  |  |  | # Initialize space -- link up nodes and segments | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | sub init_grid { | 
| 176 | 0 |  |  | 0 | 0 |  | my $it = shift; | 
| 177 |  |  |  |  |  |  |  | 
| 178 | 0 |  |  |  |  |  | my $Seg = $it->Seg; # class name we want to make segments in | 
| 179 | 0 |  |  |  |  |  | my $Node = $it->Node; # class name we want to make nodes in | 
| 180 |  |  |  |  |  |  | # die "No canvas?" unless $it->{'canvas'}; | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 0 |  |  |  |  |  | my $cell = 0; | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | # We use these two lists for comprehensive destruction. | 
| 185 | 0 |  |  |  |  |  | $it->{'nodes'} = []; | 
| 186 | 0 |  |  |  |  |  | $it->{'segments'} = []; | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | # Set up the grid now. -- fill a space with rows of nodes. | 
| 189 |  |  |  |  |  |  |  | 
| 190 | 0 |  |  |  |  |  | $it->{'node_space'} = [];  # this is a List of Lists. | 
| 191 |  |  |  |  |  |  | # usage: $node = $it->{'node_space'}[rownum][colnum] | 
| 192 | 0 |  |  |  |  |  | for(my $row = 0; $row < $it->{'cells_high'}; ++$row) { | 
| 193 | 0 |  |  |  |  |  | my $row_r = []; | 
| 194 | 0 |  |  |  |  |  | push @{$it->{'node_space'}}, $row_r; | 
|  | 0 |  |  |  |  |  |  | 
| 195 | 0 |  |  |  |  |  | for(my $col = 0; $col < $it->{'cells_wide'}; ++$col) { | 
| 196 | 0 |  |  |  |  |  | my $node = $Node->new; | 
| 197 | 0 |  |  |  |  |  | push @$row_r, $node; | 
| 198 | 0 |  |  |  |  |  | push @{$it->{'nodes'}}, $node; | 
|  | 0 |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  | # Now link up each node in this row to its next, and back | 
| 201 | 0 |  |  |  |  |  | for(my $col = 0; $col < $it->{'cells_wide'}; ++$col) { | 
| 202 | 0 |  |  |  |  |  | my $here = $row_r->[$col]; | 
| 203 | 0 |  |  |  |  |  | my $next = $row_r->[ ($col + 1) % scalar(@$row_r) ]; # % for wraparound | 
| 204 | 0 |  |  |  |  |  | $here->{'nodes_toward'}[3] = $next; | 
| 205 | 0 |  |  |  |  |  | $next->{'nodes_toward'}[0] = $here; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | # now link each node to its southern neighbor, and back | 
| 210 | 0 |  |  |  |  |  | for(my $row = 0; $row < $it->{'cells_high'}; ++$row) { | 
| 211 | 0 |  |  |  |  |  | my $here_row_r = $it->{'node_space'}[$row]; | 
| 212 | 0 |  |  |  |  |  | my $next_row_r = $it->{'node_space'}[ ($row + 1) % scalar(@{$it->{'node_space'}})]; | 
|  | 0 |  |  |  |  |  |  | 
| 213 | 0 |  |  |  |  |  | for(my $col = 0; $col < $it->{'cells_wide'}; ++$col) { | 
| 214 | 0 |  |  |  |  |  | my $here = $here_row_r->[$col]; | 
| 215 | 0 |  |  |  |  |  | my $south = $next_row_r->[$col]; | 
| 216 | 0 |  |  |  |  |  | my $row_type_top = ((1 + $row) % 2);  # 1, 0, 1, 0, 1, 0, ... | 
| 217 | 0 | 0 |  |  |  |  | if($row_type_top) {  # Rows 0, 2, 4... | 
| 218 | 0 |  |  |  |  |  | $here->{'nodes_toward'}[4] = $south; | 
| 219 | 0 |  |  |  |  |  | $south->{'nodes_toward'}[1] = $here; | 
| 220 |  |  |  |  |  |  | } else {  # Rows 1, 3, 5... | 
| 221 | 0 |  |  |  |  |  | $here->{'nodes_toward'}[5] = $south; | 
| 222 | 0 |  |  |  |  |  | $south->{'nodes_toward'}[2] = $here; | 
| 223 |  |  |  |  |  |  | } | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | # now link each node to its remaining neighbors | 
| 228 | 0 |  |  |  |  |  | for(my $row = 0; $row < $it->{'cells_high'}; ++$row) { | 
| 229 | 0 |  |  |  |  |  | my $here_row_r = $it->{'node_space'}[$row]; | 
| 230 | 0 |  |  |  |  |  | my $next_row_r = $it->{'node_space'}[ ($row + 1) % scalar(@{$it->{'node_space'}})]; | 
|  | 0 |  |  |  |  |  |  | 
| 231 | 0 |  |  |  |  |  | for(my $col = 0; $col < $it->{'cells_wide'}; ++$col) { | 
| 232 | 0 |  |  |  |  |  | my $here = $here_row_r->[$col]; | 
| 233 | 0 |  |  |  |  |  | my $row_type_top = ((1 + $row) % 2);  # 1, 0, 1, 0, 1, 0, ... | 
| 234 | 0 | 0 |  |  |  |  | if($row_type_top) {  # Rows 0, 2, 4... | 
| 235 | 0 |  |  |  |  |  | my $sw = $here->{'nodes_toward'}[4]{'nodes_toward'}[0]; | 
| 236 | 0 |  |  |  |  |  | $here->{'nodes_toward'}[5] = $sw; | 
| 237 | 0 |  |  |  |  |  | $sw->{'nodes_toward'}[2] = $here; | 
| 238 |  |  |  |  |  |  | } else {  # Rows 1, 3, 5... | 
| 239 | 0 |  |  |  |  |  | my $se = $here->{'nodes_toward'}[5]{'nodes_toward'}[3]; | 
| 240 | 0 |  |  |  |  |  | $here->{'nodes_toward'}[4] = $se; | 
| 241 | 0 |  |  |  |  |  | $se->{'nodes_toward'}[1] = $here; | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  | } | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 | 0 |  |  |  |  |  | my $Tri_height = $it->{'tri_height'}; | 
| 247 | 0 |  |  |  |  |  | my $Tri_base = $it->{'tri_base'}; | 
| 248 | 0 |  |  |  |  |  | my $Inner_Border = $it->{'inner_border'}; | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | # Create segments now, drawing them, and linking them to nodes. | 
| 251 |  |  |  |  |  |  |  | 
| 252 | 0 |  |  |  |  |  | for(my $row = 0; $row < $it->{'cells_high'}; ++$row) { | 
| 253 | 0 |  |  |  |  |  | my $row_type_top = ((1 + $row) % 2);  # 1, 0, 1, 0, 1, 0, ... | 
| 254 |  |  |  |  |  |  | # There are two types of rows: top-type, and not. | 
| 255 |  |  |  |  |  |  | # | 
| 256 | 0 | 0 |  |  |  |  | print "Row $row; Row type top: $row_type_top\n" if $Debug > 2; | 
| 257 | 0 |  |  |  |  |  | for(my $col = 0; $col < $it->{'cells_wide'}; ++$col) { | 
| 258 | 0 |  |  |  |  |  | my $x_base = $Inner_Border + $col * $Tri_base; | 
| 259 | 0 |  |  |  |  |  | my $y_base = $Inner_Border + $row * $Tri_height; | 
| 260 | 0 | 0 |  |  |  |  | print " Row $row (t$row_type_top) Col $col | xb $x_base | yb $y_base\n" | 
| 261 |  |  |  |  |  |  | if $Debug > 2; | 
| 262 | 0 |  |  |  |  |  | my($s1, $s2, $s3); | 
| 263 | 0 |  |  |  |  |  | my $n = $it->{'node_space'}[$row][$col]; | 
| 264 | 0 | 0 |  |  |  |  | if($row_type_top) { # rows 0,2,4,... | 
| 265 |  |  |  |  |  |  | #(top-type) | 
| 266 |  |  |  |  |  |  | # 1 means draw this:          i.e., one item is: | 
| 267 |  |  |  |  |  |  | #           --- --- ---           N---n_d3   s1 | 
| 268 |  |  |  |  |  |  | #           \ / \ / \ /            \ /      s2 s3 | 
| 269 |  |  |  |  |  |  | #                                  n_d4 | 
| 270 | 0 |  |  |  |  |  | my $n_d3 = $n->{'nodes_toward'}[3]; | 
| 271 | 0 |  |  |  |  |  | my $n_d4 = $n->{'nodes_toward'}[4]; | 
| 272 |  |  |  |  |  |  |  | 
| 273 | 0 |  |  |  |  |  | $s1 = $Seg->new('coords' => | 
| 274 |  |  |  |  |  |  | [ $x_base, $y_base, $x_base + $Tri_base, $y_base ], | 
| 275 |  |  |  |  |  |  | 'board' => $it); | 
| 276 |  |  |  |  |  |  | # @{$s1->{'nodes'}} = ($n, $n_d3); | 
| 277 | 0 |  |  |  |  |  | $n->{'segments_toward'}[3] = $n_d3->{'segments_toward'}[0] = $s1; | 
| 278 |  |  |  |  |  |  |  | 
| 279 | 0 |  |  |  |  |  | $s2 = $Seg->new('coords' => | 
| 280 |  |  |  |  |  |  | [ $x_base, $y_base, | 
| 281 |  |  |  |  |  |  | $x_base + $Tri_base / 2, $y_base + $Tri_height ], | 
| 282 |  |  |  |  |  |  | 'board' => $it); | 
| 283 |  |  |  |  |  |  | # @{$s2->{'nodes'}} = ($n, $n_d4); | 
| 284 | 0 |  |  |  |  |  | $n->{'segments_toward'}[4] = $n_d4->{'segments_toward'}[1] = $s2; | 
| 285 |  |  |  |  |  |  |  | 
| 286 | 0 |  |  |  |  |  | $s3 = $Seg->new( 'coords' => | 
| 287 |  |  |  |  |  |  | [ $x_base + $Tri_base / 2, $y_base + $Tri_height, | 
| 288 |  |  |  |  |  |  | $x_base + $Tri_base, $y_base ], | 
| 289 |  |  |  |  |  |  | 'board' =>  $it); | 
| 290 |  |  |  |  |  |  | # @{$s3->{'nodes'}} = ($n_d3, $n_d4); | 
| 291 | 0 |  |  |  |  |  | $n_d3->{'segments_toward'}[5] = $n_d4->{'segments_toward'}[2] = $s3; | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | } else { # rows 1,3,5,.. | 
| 294 |  |  |  |  |  |  | #(top-type) | 
| 295 |  |  |  |  |  |  | # 0 means draw this:          i.e., one item is: | 
| 296 |  |  |  |  |  |  | #             --- --- ---           N---nd_3     s1 | 
| 297 |  |  |  |  |  |  | #           / \ / \ / \            / \        s2 s3 | 
| 298 |  |  |  |  |  |  | #                                n_d5 n_d4 | 
| 299 | 0 |  |  |  |  |  | my $n_d3 = $n->{'nodes_toward'}[3]; | 
| 300 | 0 |  |  |  |  |  | my $n_d4 = $n->{'nodes_toward'}[4]; | 
| 301 | 0 |  |  |  |  |  | my $n_d5 = $n->{'nodes_toward'}[5]; | 
| 302 |  |  |  |  |  |  |  | 
| 303 | 0 |  |  |  |  |  | $s1 = $Seg->new( 'coords' => | 
| 304 |  |  |  |  |  |  | [ $x_base + $Tri_base / 2, $y_base, | 
| 305 |  |  |  |  |  |  | $x_base + $Tri_base * 1.5, $y_base ], | 
| 306 |  |  |  |  |  |  | 'board' => $it); | 
| 307 |  |  |  |  |  |  | # @{$s1->{'nodes'}} = ($n, $n_d3); | 
| 308 | 0 |  |  |  |  |  | $n->{'segments_toward'}[3] = $n_d3->{'segments_toward'}[0] = $s1; | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 0 |  |  |  |  |  | $s2 = $Seg->new('coords' => | 
| 311 |  |  |  |  |  |  | [ $x_base + $Tri_base / 2, $y_base, | 
| 312 |  |  |  |  |  |  | $x_base, $y_base + $Tri_height ], | 
| 313 |  |  |  |  |  |  | 'board' => $it); | 
| 314 |  |  |  |  |  |  | # @{$s2->{'nodes'}} = ($n, $n_d5); | 
| 315 | 0 |  |  |  |  |  | $n->{'segments_toward'}[5] = $n_d5->{'segments_toward'}[2] = $s2; | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 0 |  |  |  |  |  | $s3 = $Seg->new('coords' => | 
| 318 |  |  |  |  |  |  | [ $x_base + $Tri_base, $y_base + $Tri_height, | 
| 319 |  |  |  |  |  |  | $x_base + $Tri_base / 2, $y_base ], | 
| 320 |  |  |  |  |  |  | 'board' => $it); | 
| 321 |  |  |  |  |  |  | # @{$s3->{'nodes'}} = ($n, $n_d4); | 
| 322 | 0 |  |  |  |  |  | $n->{'segments_toward'}[4] = $n_d4->{'segments_toward'}[1] = $s3; | 
| 323 |  |  |  |  |  |  |  | 
| 324 |  |  |  |  |  |  | } | 
| 325 | 0 |  |  |  |  |  | push @{$it->{'segments'}}, $s1, $s2, $s3; | 
|  | 0 |  |  |  |  |  |  | 
| 326 |  |  |  |  |  |  | } | 
| 327 |  |  |  |  |  |  | } | 
| 328 | 0 |  |  |  |  |  | return; | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 332 |  |  |  |  |  |  | # Reset the grid, then draw | 
| 333 |  |  |  |  |  |  | sub refresh_and_draw_grid { | 
| 334 | 0 |  |  | 0 | 0 |  | my $board = $_[0]; | 
| 335 | 0 | 0 |  |  |  |  | if($board->{'segments'}) { | 
| 336 | 0 |  |  |  |  |  | foreach my $seg ( @{$board->{'segments'}} ) { | 
|  | 0 |  |  |  |  |  |  | 
| 337 | 0 |  |  |  |  |  | $seg->refresh; | 
| 338 | 0 |  |  |  |  |  | $seg->draw; | 
| 339 |  |  |  |  |  |  | } | 
| 340 |  |  |  |  |  |  | } else { | 
| 341 | 0 |  |  |  |  |  | $board->init_grid; | 
| 342 | 0 |  |  |  |  |  | foreach my $seg ( @{$board->{'segments'}} ) { | 
|  | 0 |  |  |  |  |  |  | 
| 343 | 0 |  |  |  |  |  | $seg->draw; | 
| 344 |  |  |  |  |  |  | } | 
| 345 |  |  |  |  |  |  | } | 
| 346 | 0 |  |  |  |  |  | return; | 
| 347 |  |  |  |  |  |  | } | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 350 |  |  |  |  |  |  | # Null out contents of all segments, nodes, and worms | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | sub destroy { | 
| 353 | 0 |  |  | 0 | 0 |  | my $it = shift; | 
| 354 | 0 | 0 |  |  |  |  | print "Destroy called on $it\n" if $Debug;; | 
| 355 | 0 | 0 |  |  |  |  | if(ref($it->{'segments'})) { | 
| 356 | 0 | 0 |  |  |  |  | print "Destroying ", scalar(@{$it->{'segments'}}) ," segments...\n" if $Debug; | 
|  | 0 |  |  |  |  |  |  | 
| 357 | 0 |  |  |  |  |  | foreach my $s (@{$it->{'segments'}}) { %$s = (); bless $s, 'DEAD'; } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | } | 
| 359 | 0 | 0 |  |  |  |  | if(ref($it->{'nodes'})) { | 
| 360 | 0 | 0 |  |  |  |  | print "Destroying ", scalar(@{$it->{'nodes'}}) ," nodes...\n" if $Debug; | 
|  | 0 |  |  |  |  |  |  | 
| 361 | 0 |  |  |  |  |  | foreach my $s (@{$it->{'nodes'}}) { %$s = (); bless $s, 'DEAD'; } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | } | 
| 363 | 0 | 0 |  |  |  |  | if(ref($it->{'worms'})) { | 
| 364 | 0 | 0 |  |  |  |  | print "Destroying ", scalar(@{$it->{'worms'}}) ," worms...\n" if $Debug; | 
|  | 0 |  |  |  |  |  |  | 
| 365 | 0 |  |  |  |  |  | foreach my $s (@{$it->{'worms'}}) { %$s = (); bless $s, 'DEAD'; } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | } | 
| 367 | 0 |  |  |  |  |  | %$it = (); | 
| 368 | 0 |  |  |  |  |  | bless $it, 'DEAD'; | 
| 369 | 0 | 0 |  |  |  |  | print "Done destroying $it\n" if $Debug; | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 0 |  |  |  |  |  | return; | 
| 372 |  |  |  |  |  |  | } | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | # *DESTROY = \&destroy; | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | #-------------------------------------------------------------------------- | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | 1; | 
| 379 |  |  |  |  |  |  |  | 
| 380 |  |  |  |  |  |  | __END__ |