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   91757 use Modern::Perl;
  2         15  
  2         18  
19             require Exporter;
20 2     2   934 use POSIX qw(ceil);
  2         7446  
  2         16  
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 2100     2100 0 2983 my $item = shift;
28 2100         3366 foreach (@_) {
29 31706 100       57428 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 293     293 0 2361 my ($start, $distance, $candidates) = @_;
40 293 100       1527 return @{$cache{"@_"}} if exists $cache{"@_"};
  40         218  
41 253 50       712 $distance = 1 unless $distance; # default
42 253         546 my @result = ();
43 253         550 foreach my $candidate (@$candidates) {
44 155664 100       269500 next if $candidate == $start;
45 155411 100       232724 if (Traveller::Util::distance($start, $candidate) <= $distance) {
46 1773         4472 push(@result, $candidate);
47             }
48             }
49 253         1468 $cache{"@_"} = \@result;
50 253         1994 return @result;
51             };
52              
53             sub distance {
54 155411     155411 0 223171 my ($from, $to) = @_;
55 155411 100       482815 return $cache{"@_"} if exists $cache{"@_"};
56 141635         259200 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 141635         1303483 $y1 = $y1 - POSIX::ceil($x1/2);
60 141635         240901 $y2 = $y2 - POSIX::ceil($x2/2);
61 141635         226216 my $d = d($x1, $y1, $x2, $y2);
62 141635         524363 $cache{"@_"} = $d;
63 141635         399795 return $d;
64             };
65              
66             sub d {
67 204576     204576 0 311955 my ($x1, $y1, $x2, $y2) = @_;
68 204576 100       350463 if ($x1 > $x2) {
    100          
69             # only consider moves from left to right and transpose start and
70             # end point to make it so
71 62941         98055 return d($x2, $y2, $x1, $y1);
72             } elsif ($y2>=$y1) {
73             # if it the move has a downwards component add Δx and Δy
74 60032         105685 return $x2-$x1 + $y2-$y1;
75             } else {
76             # else just take the larger of Δx and Δy
77 81603 100       167545 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 290 %cache = ();
85             }
86              
87             1;