File Coverage

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   104349 use Modern::Perl;
  2         4  
  2         13  
19             require Exporter;
20 2     2   934 use POSIX qw(ceil);
  2         6537  
  2         14  
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 3077     3077 0 4605 my $item = shift;
28 3077         5298 foreach (@_) {
29 59441 100       122824 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 413     413 0 4048 my ($start, $distance, $candidates) = @_;
40 413 100       2613 return @{$cache{"@_"}} if exists $cache{"@_"};
  20         159  
41 393 50       1293 $distance = 1 unless $distance; # default
42 393         936 my @result = ();
43 393         880 foreach my $candidate (@$candidates) {
44 239250 100       499541 next if $candidate == $start;
45 238857 100       394381 if (Traveller::Util::distance($start, $candidate) <= $distance) {
46 2881         7556 push(@result, $candidate);
47             }
48             }
49 393         2905 $cache{"@_"} = \@result;
50 393         3525 return @result;
51             };
52              
53             sub distance {
54 238857     238857 0 381321 my ($from, $to) = @_;
55 238857 100       774207 return $cache{"@_"} if exists $cache{"@_"};
56 216457         459019 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 216457         2235394 $y1 = $y1 - POSIX::ceil($x1/2);
60 216457         399809 $y2 = $y2 - POSIX::ceil($x2/2);
61 216457         391343 my $d = d($x1, $y1, $x2, $y2);
62 216457         961459 $cache{"@_"} = $d;
63 216457         610720 return $d;
64             };
65              
66             sub d {
67 320779     320779 0 563470 my ($x1, $y1, $x2, $y2) = @_;
68 320779 100       608306 if ($x1 > $x2) {
    100          
69             # only consider moves from left to right and transpose start and
70             # end point to make it so
71 104322         180674 return d($x2, $y2, $x1, $y1);
72             } elsif ($y2>=$y1) {
73             # if it the move has a downwards component add Δx and Δy
74 80959         161794 return $x2-$x1 + $y2-$y1;
75             } else {
76             # else just take the larger of Δx and Δy
77 135498 100       297138 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 273 %cache = ();
85             }
86              
87             1;