| 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 |  | 86124 | use Modern::Perl; | 
|  | 2 |  |  |  |  | 15 |  | 
|  | 2 |  |  |  |  | 16 |  | 
| 19 |  |  |  |  |  |  | require Exporter; | 
| 20 | 2 |  |  | 2 |  | 897 | use POSIX qw(ceil); | 
|  | 2 |  |  |  |  | 6715 |  | 
|  | 2 |  |  |  |  | 13 |  | 
| 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 | 4961 |  |  | 4961 | 0 | 7150 | my $item = shift; | 
| 28 | 4961 |  |  |  |  | 7942 | foreach (@_) { | 
| 29 | 79902 | 100 |  |  |  | 143120 | 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 | 684 |  |  | 684 | 0 | 4550 | my ($start, $distance, $candidates) = @_; | 
| 40 | 684 | 100 |  |  |  | 2979 | return @{$cache{"@_"}} if exists $cache{"@_"}; | 
|  | 56 |  |  |  |  | 360 |  | 
| 41 | 628 | 50 |  |  |  | 1458 | $distance = 1 unless $distance; # default | 
| 42 | 628 |  |  |  |  | 1095 | my @result = (); | 
| 43 | 628 |  |  |  |  | 1115 | foreach my $candidate (@$candidates) { | 
| 44 | 415414 | 100 |  |  |  | 731619 | next if $candidate == $start; | 
| 45 | 414786 | 100 |  |  |  | 636019 | if (Traveller::Util::distance($start, $candidate) <= $distance) { | 
| 46 | 4508 |  |  |  |  | 10898 | push(@result, $candidate); | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  | } | 
| 49 | 628 |  |  |  |  | 3338 | $cache{"@_"} = \@result; | 
| 50 | 628 |  |  |  |  | 4306 | return @result; | 
| 51 |  |  |  |  |  |  | }; | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | sub distance { | 
| 54 | 414786 |  |  | 414786 | 0 | 599596 | my ($from, $to) = @_; | 
| 55 | 414786 | 100 |  |  |  | 1263233 | return $cache{"@_"} if exists $cache{"@_"}; | 
| 56 | 397150 |  |  |  |  | 737370 | 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 | 397150 |  |  |  |  | 3551129 | $y1 = $y1 - POSIX::ceil($x1/2); | 
| 60 | 397150 |  |  |  |  | 669432 | $y2 = $y2 - POSIX::ceil($x2/2); | 
| 61 | 397150 |  |  |  |  | 636487 | my $d = d($x1, $y1, $x2, $y2); | 
| 62 | 397150 |  |  |  |  | 1399349 | $cache{"@_"} = $d; | 
| 63 | 397150 |  |  |  |  | 1098312 | return $d; | 
| 64 |  |  |  |  |  |  | }; | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | sub d { | 
| 67 | 592195 |  |  | 592195 | 0 | 920205 | my ($x1, $y1, $x2, $y2) = @_; | 
| 68 | 592195 | 100 |  |  |  | 1035850 | if ($x1 > $x2) { | 
|  |  | 100 |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | # only consider moves from left to right and transpose start and | 
| 70 |  |  |  |  |  |  | # end point to make it so | 
| 71 | 195045 |  |  |  |  | 304673 | return d($x2, $y2, $x1, $y1); | 
| 72 |  |  |  |  |  |  | } elsif ($y2>=$y1) { | 
| 73 |  |  |  |  |  |  | # if it the move has a downwards component add Δx and Δy | 
| 74 | 152254 |  |  |  |  | 270887 | return $x2-$x1 + $y2-$y1; | 
| 75 |  |  |  |  |  |  | } else { | 
| 76 |  |  |  |  |  |  | # else just take the larger of Δx and Δy | 
| 77 | 244896 | 100 |  |  |  | 488696 | 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 | 75604 | %cache = (); | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | 1; |