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__ |