File Coverage

blib/lib/Traveller/Util.pm
Criterion Covered Total %
statement 34 34 100.0
branch 17 18 94.4
condition n/a
subroutine 7 7 100.0
pod 0 5 0.0
total 58 64 90.6


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             # Copyright (C) 2009-2021 Alex Schroeder
3             # Copyright (C) 2020 Christian Carey
4             #
5             # This program is free software: you can redistribute it and/or modify it under
6             # the terms of the GNU General Public License as published by the Free Software
7             # Foundation, either version 3 of the License, or (at your option) any later
8             # version.
9             #
10             # This program is distributed in the hope that it will be useful, but WITHOUT
11             # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12             # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13             #
14             # You should have received a copy of the GNU General Public License along with
15             # this program. If not, see .
16              
17             package Traveller::Util;
18 2     2   72930 use Modern::Perl;
  2         11  
  2         15  
19             require Exporter;
20 2     2   756 use POSIX qw(ceil);
  2         5484  
  2         12  
21             our @ISA = qw(Exporter);
22             our @EXPORT_OK = qw(in distance nearby flush d);
23              
24             # These global functions work on things that have x and y members.
25              
26             sub in {
27 5485     5485 0 7350 my $item = shift;
28 5485         8521 foreach (@_) {
29 92158 100       157941 return $item if $item == $_;
30             }
31             }
32              
33             # Some functions cache their result. You must use the flush function to clear
34             # the cache!
35              
36             my %cache;
37              
38             sub nearby {
39 715     715 0 4962 my ($start, $distance, $candidates) = @_;
40 715 100       3255 return @{$cache{"@_"}} if exists $cache{"@_"};
  102         574  
41 613 50       1591 $distance = 1 unless $distance; # default
42 613         1024 my @result = ();
43 613         1195 foreach my $candidate (@$candidates) {
44 393792 100       677069 next if $candidate == $start;
45 393179 100       556347 if (Traveller::Util::distance($start, $candidate) <= $distance) {
46 4611         10332 push(@result, $candidate);
47             }
48             }
49 613         3396 $cache{"@_"} = \@result;
50 613         4484 return @result;
51             };
52              
53             sub distance {
54 393179     393179 0 548814 my ($from, $to) = @_;
55 393179 100       1122165 return $cache{"@_"} if exists $cache{"@_"};
56 352717         637274 my ($x1, $y1, $x2, $y2) = ($from->x, $from->y, $to->x, $to->y);
57             # transform the Traveller coordinate system into a decent system with one axis
58             # tilted by 60°
59 352717         3079366 $y1 = $y1 - POSIX::ceil($x1/2);
60 352717         555469 $y2 = $y2 - POSIX::ceil($x2/2);
61 352717         532202 my $d = d($x1, $y1, $x2, $y2);
62 352717         1194322 $cache{"@_"} = $d;
63 352717         934708 return $d;
64             };
65              
66             sub d {
67 526466     526466 0 760536 my ($x1, $y1, $x2, $y2) = @_;
68 526466 100       844057 if ($x1 > $x2) {
    100          
69             # only consider moves from left to right and transpose start and
70             # end point to make it so
71 173749         250573 return d($x2, $y2, $x1, $y1);
72             } elsif ($y2>=$y1) {
73             # if it the move has a downwards component add Δx and Δy
74 127942         220908 return $x2-$x1 + $y2-$y1;
75             } else {
76             # else just take the larger of Δx and Δy
77 224775 100       425621 return $x2-$x1 > $y1-$y2 ? $x2-$x1 : $y1-$y2;
78             }
79             }
80              
81             # In order to prevent memory leaks, flush the cache after generating a
82             # sector or subsector.
83             sub flush {
84 1     1 0 81288 %cache = ();
85             }
86              
87             1;