function DisplayPort( WhichPort : Portindex ) : string;
begin
  if WhichPort = 0 then
    DisplayPort := ' Port data not found!'
  else
    with space.ports.data[ WhichPort ] do
      DisplayPort :=  ' F:' + str(amts[fuel], 5) + ' ' + str(usage[fuel],3) +
                      '% O:' + str( amts[ organics], 5) + ' ' + str(usage[organics],3) +
                      '% E:' + str( amts[ equipment ], 5 )+ ' ' + str(usage[equipment],3) + '%';
end; {DisplayPort}

function DisplayNote( s : sector ) : string;
{ print the note associated with sector s }
var
  n : 0..MaxNote;
begin
  n := NoteNumber( s );
  if n = 0 then
    Displaynote := ' Missing note! '
  else
    Displaynote := ' ' + space.notes.data[n].info;
end; {write note}

procedure DisplaySector( s : sector; whatIs : string; dist : integer;  
                         ToFile : boolean; var TheFile : text);
var
  line : string;
begin
  with space.sectors[s] do
    begin
      line := 'Sctr:' + str( s, 3);
      if dist <> Error then
        line := line + WhatIs + str( dist, 2 );
      if number = UnExplored then
        if verbose then
          line := line + ' Unexplored sector'
        else
          line := line + ' UEX';
      if portType <> NotAPort then
        begin
          line := line + ' port ' + status( portType );
          if portType <> Class0 then
            line := line + DisplayPort( portnumber( s ) );
        end; {if port}
      if (etc and SpaceLane) <> Nothing then
        if verbose then
          line := line + ' space lane'
        else
          line := line + ' SL';
      if (etc and StarDock) <> Nothing then
        if verbose then
          line := line + ' Star Dock'
        else
          line := line + ' SD';
      if (etc and Avoid) <> Nothing then
        if verbose then
          line := line + ' avoid'
        else
          line := line + ' AV';
      if (etc and HasFighters) <> Nothing then
        if verbose then
          line := line + ' has fighters'
        else
          line := line + ' F';
      if (etc and NoteExists) <> Nothing then
        line := line + DisplayNote( s );
      if number = 1 then
        if AppearanceCount(s) = 1 then
          if verbose then
            line := line + ' dead end (' + str(HowFar( s ),1) + ')'
          else
            line := line + ' DE(' + str(HowFar(s),1) + ')';
      if (etc and Busted ) <> Nothing then
        if verbose then
          line := line + ' busted'
        else
          line := line + ' X';
      writeln( line);
      if ToFile then
        writeln( TheFile, line );
    end; {with}
end; {DisplaySector}

function HasGoods( sales : PortSales ) : boolean;
{ return true if there are 365 equipment or 660 organics available for
  robbing.  Basically, set return value to true and exit if it really is,
  otherwise return false. }
begin
  HasGoods := true;
  if sales.amts[ equipment ] > 365 then
    exit
  else if (sales.usage[ equipment ] > 0)  {blocked: guess no}
       and (sales.amts[ equipment ] * (100 - sales.usage[ equipment ])
           / sales.usage[ equipment ] >= 365) then
    exit
  else if sales.amts[ organics ] >= 660 then
    exit
  else if (sales.usage[ organics ] > 0) {blocked: best no}
       and (sales.amts[ organics ] * (100 - sales.usage[ organics ])
           / sales.usage[ organics ] >= 365) then
    exit;
  HasGoods := false;
end; {hasGoods}

type
  WhichStuff = (any, PortOnly, NoteOnly, UnExpOnly, FighterOnly, SpecPort,
                RobHolds, BuyEquipSellOrganic, BuyOrganicSellEquip );

procedure EliminateUnwanted( var distances   : distanceArray;
                                 keepMe      : WhichStuff;
                             var HowManyLeft : sectorIndex;
                                 PortClass   : stuff );
{ Remove the sectors you don't want in the list by pushing them to the back}
var
  pindex : portIndex;
  whichSector : sector;
  keep : boolean;
begin
  HowManyLeft := 0;
  for whichSector := 1 to MaxSector do
    begin
      case keepMe of
        any : keep := distances[ whichSector ].d <> maxint;
        PortOnly : keep := space.sectors[whichSector].porttype <> NotAPort;
        NoteOnly : keep := space.sectors[whichSector].etc and NoteExists
                           <> Nothing;
        UnExpOnly: keep := (space.sectors[whichSector].number = UnExplored)
                           and (distances[ whichSector ].d <> maxint);
        FighterOnly : keep := (space.sectors[whichSector].etc and HasFighters)
                           <> Nothing;
        SpecPort : keep := space.sectors[whichSector].porttype = PortClass;
        RobHolds : begin
                     pindex := PortNumber( whichsector );
                     if pindex = 0 then
                       keep := false
                     else
                       keep :=  (space.ports.data[pindex].bustdate = 0)
                            and HasGoods( space.ports.data[pindex] );
                   end; {Robbing}
        BuyEquipSellOrganic,
        BuyOrganicSellEquip : begin
                                pindex := PortNumber( whichsector );
                                if pindex = 0 then
                                  keep := false
                                else
                                  if keepme = BuyOrganicSellEquip then
                                    keep := space.sectors[WhichSector].porttype in [2, 3]
                                  else
                                    keep := space.sectors[WhichSector].porttype in [4, 5];
                              end; {BE & SO or BO & SE}
      end; {case}
      if keep then
        begin
          HowManyLeft := HowManyLeft + 1;
          distances[ howManyLeft ] := distances[ whichSector ];
        end; {if}
    end; {for}
  write('Total of ', HowManyLeft );
  case keepMe of
    any      : writeln(' sectors from base sector');
    PortOnly : writeln(' known ports');
    NoteOnly : writeln(' sectors with notes');
    UnExpOnly: writeln(' unexplored sectors with known position');
    FighterOnly : writeln(' fighter clouds');
    SpecPort : writeln(' ports of type ', status( PortClass ) );
    RobHolds : writeln(' ports that can be robbed for holds');
    BuyEquipSellOrganic : writeln(' ports buying equipment and selling organics.');
    BuyOrganicSellEquip : writeln(' ports buying organic and selling equipment.');
  end; {case}
end; {EliminateUnwanted}

procedure FindSmallest( var distances : DistanceArray;
                        lowest, highest : sector );
{ Examine the distance array from lowest to highest, and move the
sector at smallest distance into the "lowest" slot. }
var
  temp     : dist;
  s,
  smallest : sector;
begin
  Smallest := lowest;
  for s := lowest to highest do
    if distances[ s ].d < distances[ smallest ].d then
      smallest := s;
  temp := distances[ smallest ];
  distances[ smallest ] := distances[ lowest ];
  distances[ lowest ] := temp;
end; {FindSmallest}

procedure nearestStuff( Filter : WhichStuff; StuffType : stuff );
var
  Number : sectorIndex;
  s, n : integer;
  log  : boolean;
  f    : text;
begin
  write('Stuff Nearby ');
  if SetUpDistances then
    begin
      EliminateUnwanted( distances, filter, Number, StuffType );
      log := prompt( 'Log to disk? ');
      if log then
        begin
          assign( f, GetNewFileName('File name for report?  ', 'report.txt') );
          rewrite( f );
        end;
      if Number <> 0 then
        begin
          for n := 1 to Number do
            begin
              FindSmallest( distances, n, Number );
              DisplaySector( distances[ n ].s, ' Dist:', distances[n].d, log, f );
              if n mod 20 = 0 then
                if not prompt( 'more? ') then
                  begin
                    if log then
                      close( f );
                      exit;
                  end;
            end; {for}
        end; {if}
      if log then
        close( f );
    end; {if}
end; {nearport}

procedure SortPorts( var NumPorts : sectorindex );
var
  s, n : integer;
begin
  NumPorts := 0;
  if SetUpDistances then
    begin
      EliminateUnwanted( distances, PortOnly, NumPorts, 0 );
      writeln('Sorting...');
      SortDistances( distances, NumPorts )
    end; {if}
end; {SortPorts}