I have this (Mongoose?) Traveller Subsector Mapper. I started thinking that maybe I should start looking at automatically drawing communications and trade routes. I started writing some code that calculates the distance between two hexes. And I started wasting hours. Whoa, big time code failure on my part!
There was something about |Δx| div 2 + |Δy| and all that stuff, but there was always some case in which it wouldn’t work. I googled many times, but finally I found what I needed to know in a rec.games.design archive.
And it works!
I guess I’ll look at communications routes next week-end. 
use POSIX;
sub d {
my ($x1, $y1, $x2, $y2) = @_;
if ($x1 > $x2) {
return d($x2, $y2, $x1, $y1);
} elsif ($y2>=$y1) {
return $x2-$x1 + $y2-$y1;
} else {
return $x2-$x1 > $y1-$y2 ? $x2-$x1 : $y1-$y2;
}
}
sub pt {
my ($x1, $y1, $x2, $y2) = @_;
my $s = sprintf("%02d%02d:", $x2, $y2);
# shift coordinate system
my $y1 = $y1 - POSIX::ceil($x1/2);
my $y2 = $y2 - POSIX::ceil($x2/2);
$s .= sprintf("%.1f ", d($x1, $y1, $x2, $y2));
return $s;
}
my ($x1, $y1) = (4,5);
foreach my $y (1..10) {
print join(" ", map { pt($x1, $y1, $_, $y) } (1, 3, 5, 7)), "\n";
print join(" ", "", map { pt($x1, $y1, $_, $y) } (2, 4, 6, 8)), "\n";
}Result:
0101:6.0 0301:5.0 0501:5.0 0701:6.0
0201:5.0 0401:4.0 0601:5.0 0801:6.0
0102:5.0 0302:4.0 0502:4.0 0702:5.0
0202:4.0 0402:3.0 0602:4.0 0802:5.0
0103:4.0 0303:3.0 0503:3.0 0703:4.0
0203:3.0 0403:2.0 0603:3.0 0803:4.0
0104:3.0 0304:2.0 0504:2.0 0704:3.0
0204:2.0 0404:1.0 0604:2.0 0804:4.0
0105:3.0 0305:1.0 0505:1.0 0705:3.0
0205:2.0 0405:0.0 0605:2.0 0805:4.0
0106:3.0 0306:1.0 0506:1.0 0706:3.0
0206:2.0 0406:1.0 0606:2.0 0806:4.0
0107:3.0 0307:2.0 0507:2.0 0707:3.0
0207:3.0 0407:2.0 0607:3.0 0807:4.0
0108:4.0 0308:3.0 0508:3.0 0708:4.0
0208:4.0 0408:3.0 0608:4.0 0808:5.0
0109:5.0 0309:4.0 0509:4.0 0709:5.0
0209:5.0 0409:4.0 0609:5.0 0809:6.0
0110:6.0 0310:5.0 0510:5.0 0710:6.0
0210:6.0 0410:5.0 0610:6.0 0810:7.0