+ my $allroutes= $routes{$oceanname};
+
+ my @propqueue= ();
+
+ sub distance_set_propagate ($$$$) {
+ my ($lev, $start, $upto, $start2upto) = @_;
+ $allroutes->{$start}{$upto}= $start2upto;
+ push @propqueue, [ $lev, $start, $upto ];
+ }
+
+ sub distance_propagate_now {
+ my ($lev, $start, $upto) = @_;
+ my $startref= $allroutes->{$start};
+ my $start2upto= $startref->{$upto};
+ my $uptoref= $allroutes->{$upto};
+
+ for my $next (keys %$uptoref) {
+ next if $next eq $upto;
+ my $unext= $uptoref->{$next};
+ next unless defined $unext;
+ distance_update("${lev}p", $start, $next, $start2upto + $unext);
+ }
+ }
+
+ sub distance_update ($$$$) {
+ my ($lev, $x, $y, $newdist) = @_;
+ distance_update_one("${lev}x",$x,$y,$newdist);
+ distance_update_one("${lev}y",$y,$x,$newdist);
+ }
+
+ sub distance_update_one ($$$$) {
+ my ($lev, $x, $y, $newdist) = @_;
+ my $xref= $allroutes->{$x};
+ my $currently= $xref->{$y};
+ return if defined($currently) and $currently <= $newdist;
+ distance_set_propagate("${lev}o",$x,$y,$newdist);
+ }
+
+ foreach my $xn (keys %$allroutes) {
+ my $routes= $allroutes->{$xn};
+ distance_set_propagate('0', $xn, $xn, 0);
+ foreach my $yn (keys %$routes) {
+ distance_set_propagate('0', $yn, $yn, 0);
+ distance_set_propagate('X', $xn, $yn, $routes->{$yn});
+ distance_set_propagate('Y', $yn, $xn, $routes->{$yn});
+ }
+ }
+ my $ref;
+ while ($ref= shift @propqueue) {
+ distance_propagate_now(@$ref);
+ }
+