File Coverage

blib/lib/Games/Lineofsight.pm
Criterion Covered Total %
statement 12 54 22.2
branch 0 10 0.0
condition 0 9 0.0
subroutine 4 8 50.0
pod 0 4 0.0
total 16 85 18.8


line stmt bran cond sub pod time code
1             package Games::Lineofsight;
2              
3 1     1   30284 use 5.008;
  1         4  
  1         46  
4 1     1   6 use strict;
  1         1  
  1         32  
5 1     1   6 use warnings;
  1         6  
  1         142  
6             require Exporter;
7              
8             our @ISA = qw(Exporter);
9             our %EXPORT_TAGS = ( 'all' => [ qw(get_barriers analyze_map lineofsight) ] );
10             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
11             our @EXPORT = qw( );
12             our $VERSION = '1.0';
13              
14 1     1   9725 use Math::Complex;
  1         36898  
  1         957  
15              
16             # returns map where the non-visible squares are replaced with $hidden_str
17             # $map == reference to $map[$width][$height]
18             # $man_x,$man_y == location of the viewer
19             # $barrier_str == the square in the map that identifies the barrier; for example "X"
20             # $hidden_str == string that replaces non-visible squares
21             sub lineofsight{
22 0     0 0   my($map,$man_x,$man_y,$barrier_str,$hidden_str)=@_;
23 0           my($width)=scalar(@{@$map[0]});
  0            
24 0           my($height)=scalar(@$map);
25              
26             # read the barriers
27 0           my %barrier=get_barriers($width,$height,\@$map,$barrier_str);
28              
29             # recreate the map and replace the squares behind the barriers with $hidden_str
30 0           my @map2=analyze_map($width,$height,\@$map,\%barrier,$man_x,$man_y,$hidden_str);
31              
32 0           return(@map2);
33             }
34              
35             # returns barrier coordinates in a hash needed for analyze_map() -subroutine
36             # $width == width of the map
37             # $height == height of the map
38             # $map == reference to $map[$width][$height]
39             # $barrier_str == the square in the map that identifies the barrier; for example "X"
40             sub get_barriers{
41 0     0 0   my($width,$height,$map,$barrier_str)=@_;
42 0           my($i,$j)=undef;
43 0           my %barrier=();
44 0           for($i=0;$i < $height;$i++){
45 0           for($j=0;$j < $width;$j++){
46 0 0         $barrier{"$i,$j"}=1 if($$map[$i][$j] =~ /$barrier_str/);
47             }
48             }
49 0           return %barrier;
50             }
51              
52             # returns map where the non-visible squares are replaced with $hidden_str
53             # $width == width of the map
54             # $height == height of the map
55             # $map == reference to $map[$width][$height]
56             # $barrier == reference to barrier hash. Hash can be generated using the get_barriers() -subroutine.
57             # $man_x,$man_y == location of the viewer
58             # $hidden_str == string that replaces non-visible squares
59             sub analyze_map{
60 0     0 0   my($width,$height,$map,$barrier,$man_x,$man_y,$hidden_str)=@_;
61 0           my($e,$i,$j,$hidden,$xx,$yy)=undef;
62 0           my @map2=();
63 0           for($i=0;$i < $height;$i++){
64 0           for($j=0;$j < $width;$j++){
65              
66             # set the square visible
67 0           $hidden=0;
68              
69             # browse all barriers
70 0           foreach $e(keys %$barrier){
71              
72             # get the barrier x- and y- coordinate
73 0           ($yy,$xx)=split ",",$e;
74              
75             # declare the location as hidden if it's behind this barrier
76 0 0 0       if(($xx != $j || $yy != $i) && los($man_x,$man_y,$xx,$yy,$j,$i) < .5){
      0        
77 0           $hidden=1;
78 0           last;
79             }
80             }
81              
82             # set the location as hidden or normal to the output-map
83 0 0         $map2[$i][$j]=($hidden ? $hidden_str : $$map[$i][$j]);
84              
85             }
86             }
87 0           return(@map2);
88             }
89              
90             # checks if the viewer sees the chosen location because of a barrier
91             # returns <.5 if the viewer don't see the chosen location because of a barrier
92             # x1,y1 == location of the viewer
93             # x2,y2 == location of the barrier
94             # x3,y3 == location of the chosen position
95             sub los{
96 0     0 0   my($x1,$y1,$x2,$y2,$x3,$y3)=@_;
97              
98             # line from the man to the barrier
99 0           my $dx1=$x2-$x1;
100 0           my $dy1=$y2-$y1;
101 0           my $length1=sqrt($dx1*$dx1+$dy1*$dy1);
102 0 0         return 10 unless($length1); # return if barrier and man overlap
103              
104             # line from the man to the chosen position
105 0           my $dx2=$x3-$x1;
106 0           my $dy2=$y3-$y1;
107 0           my $length2=sqrt($dx2*$dx2+$dy2*$dy2);
108              
109             # return if the man and the chosen position overlap or
110             # if the chosen position is nearer the man than the barrier
111 0 0 0       return 10 if($length2 <= $length1 || !$length2);
112              
113             # cut the line to the barrier to the same length than the line to the
114             # chosen position
115 0           my $lengthdivisor=$length2/$length1;
116 0           $dx2/=$lengthdivisor;
117 0           $dy2/=$lengthdivisor;
118              
119             # return the distance of the lines's heads
120 0           my $ddx=$dx1-$dx2;
121 0           my $ddy=$dy1-$dy2;
122 0           return sqrt($ddx*$ddx+$ddy*$ddy);
123             }
124              
125             1;
126              
127             __END__