File Coverage

blib/lib/Games/RolePlay/MapGen/Generator/Perfect.pm
Criterion Covered Total %
statement 68 70 97.1
branch 12 14 85.7
condition 18 18 100.0
subroutine 7 8 87.5
pod 0 3 0.0
total 105 113 92.9


line stmt bran cond sub pod time code
1             # vi:tw=0 syntax=perl:
2              
3             package Games::RolePlay::MapGen::Generator::Perfect;
4              
5 8     8   5535 use common::sense;
  8         17  
  8         69  
6 8     8   387 use Carp;
  8         16  
  8         574  
7 8     8   1557 use parent q(Games::RolePlay::MapGen::Generator);
  8         347  
  8         57  
8 8     8   6728 use Games::RolePlay::MapGen::Tools qw( _group _tile choice roll );
  8         28  
  8         9906  
9              
10             1;
11              
12             # create_tiles {{{
13             sub create_tiles {
14 8     8 0 17 my $this = shift;
15 8         16 my $opts = shift;
16 8         24 my @map = ();
17              
18 8         49 for my $i (0 .. $opts->{y_size}-1) {
19 170         263 my $a = [];
20              
21 170         469 for my $j (0 .. $opts->{x_size}-1) {
22 3800 50       8519 $opts->{t_cb}->() if exists $opts->{t_cb};
23              
24 3800         10015 push @$a, &_tile(x=>$j, y=>$i);
25             }
26              
27 170         429 push @map, $a;
28             }
29              
30 8         104 return @map;
31             }
32             # }}}
33             # generate_perfect_maze {{{
34             sub generate_perfect_maze {
35 8     8 0 22 my $this = shift;
36 8         22 my $opts = shift;
37 8         91 my $map = new Games::RolePlay::MapGen::_interconnected_map(shift);
38             # This object interconnects the map; but, also ensures that the self-refs are broken when it goes out of scope!
39              
40 8         55 my @dirs = (qw(n s e w));
41 8         60 my $cur = &choice(map(@$_, @$map));
42 8         339 my @togo = @dirs;
43 8         50 my $dir = &choice(@togo);
44 8         62 my @visited = ( $cur );
45              
46 8         43 $cur->{type} = "corridor";
47              
48             # open DEBUG, ">debug.log" or die $!;
49              
50 8         21 for(;;) {
51 15203         61433 my $nex = $cur->{nb}{$dir};
52              
53 15203     0   50673 my $show = sub { my $n = shift; sprintf '(%2d, %2d)', $n->{x}, $n->{y} };
  0         0  
  0         0  
54              
55 15203 50       49995 $opts->{t_cb}->() if exists $opts->{t_cb};
56              
57             # printf DEBUG '@visited=%3d; $cur=%s; $nex=%s;%s', int @visited, $show->($cur), $show->($nex);
58              
59 15203 100 100     106454 if( $nex and not $nex->{visited} ) {
    100          
60             # print DEBUG " NEXT";
61              
62 3800         14968 $cur->{od}{$dir} = 1;
63              
64 3800         5050 $cur = $nex;
65 3800         6844 $cur->{visited} = 1;
66 3800         6364 push @visited, $cur;
67              
68 3800         11063 $cur->{od}{$Games::RolePlay::MapGen::opp{$dir}} = 1;
69 3800         17079 $cur->{type} = 'corridor';
70              
71 3800   100     5680 @togo = grep { !$cur->{od}{$_} and !$cur->{_pud}{$_} } @dirs;
  15200         80940  
72 3800 100       12675 $dir = &choice(@togo) if &roll(1, 100) > $opts->{same_way_percent};
73             # $opts->{same_way_percent} of the time, we won't change the direction
74              
75             } elsif( @togo ) {
76             # print DEBUG " TOGO";
77              
78 7602         22761 $cur->{_pud}{$dir} = 1; # perfect's used dir
79              
80             # $opts->{same_node_percent} of the time, we try to use the same node
81 7602 100 100     32660 if( @visited>1 and (&roll(1, 100) > $opts->{same_node_percent}) ) {
82             # print DEBUG " SAME";
83             # Pick a new node with a random direction that makes sense.
84 5239         39456 $cur = &choice(@visited);
85 5239   100     10493 @togo = grep { !$cur->{od}{$_} and !$cur->{_pud}{$_} } @dirs;
  20956         128177  
86 5239         15274 $dir = &choice(@togo); # whenever we switch nodes, we pick a random direction though
87              
88             } else {
89             # print DEBUG " DIFF";
90             # Try a different direction at this same node.
91 2363   100     5677 @togo = grep { !$cur->{od}{$_} and !$cur->{_pud}{$_} } @dirs;
  9452         48216  
92 2363         11870 $dir = &choice(@togo);
93             }
94              
95             } else {
96             # print DEBUG " DULL";
97             # This node is so boring, we don't want to accidentally try it again
98 3801         32421 @visited = grep {$_ != $cur} @visited;
  1005456         2628639  
99              
100 3801 100       50031 last unless @visited;
101              
102             # Pick a new node with a random direction that makes sense.
103 3793         27135 $cur = &choice(@visited);
104 3793   100     22196 @togo = grep { !$cur->{od}{$_} and !$cur->{_pud}{$_} } @dirs;
  15172         81063  
105 3793         24809 $dir = &choice(@togo);
106             }
107              
108             # print DEBUG "\n";
109             }
110              
111 8         96 delete $_->{_pud} for (map(@$_, @$map))
112              
113             }
114             # }}}
115              
116             # genmap {{{
117             sub genmap {
118 8     8 0 31 my $this = shift;
119 8         17 my $opts = shift;
120 8         75 my @map = $this->create_tiles( $opts );
121 8         38 my @groups = ();
122              
123 8         169 $this->generate_perfect_maze($opts, \@map);
124              
125 8         5299 return (\@map, \@groups);
126             }
127             # }}}
128              
129             __END__