home *** CD-ROM | disk | FTP | other *** search
/ Game Killer / Game_Killer.bin / 094.TOUR.INC < prev    next >
Text File  |  1992-07-16  |  13KB  |  456 lines

  1. const
  2.   MaxRoute = 1500;
  3. type
  4.   SectorVisitStatus = (unreachable, visited, scanned, open);
  5.   ScannerMap = array [1..MaxSector] of SectorVisitStatus;
  6.   route = record
  7.             length : sectorIndex;               { actual trip length   }
  8.             more   : integer;                   { how many more to hit }
  9.             path   : array [ 1..MaxRoute ] of sector;
  10.           end;
  11.  
  12.   nodeptr = ^node;
  13.   node    = record next : nodeptr; s : sector; end;
  14.   squeue  = record front, rear : nodeptr; end;
  15.  
  16. procedure ensqueue( e : sector; var q : squeue );
  17. var
  18.   NewGuy : nodeptr;
  19. begin
  20.   New( NewGuy );
  21.   if NewGuy = nil then
  22.     begin
  23.       writeln('error: out of memory during ensqueue');
  24.       readln;
  25.       halt;
  26.     end;
  27.   with NewGuy^ do
  28.     begin
  29.       s := e;
  30.       next := nil;
  31.     end; {with}
  32.   if q.rear = nil then
  33.     q.front := newguy
  34.   else
  35.     q.rear^.next := newguy;
  36.   q.rear := newguy;
  37. end;
  38.  
  39. procedure sserve( var e : sector; var q : squeue );
  40. var
  41.   killer : nodeptr;
  42. begin
  43.   if q.front = nil then
  44.     begin
  45.       writeln('error: serve from empty squeue');
  46.       readln;
  47.       halt;
  48.     end;
  49.   killer := q.front;
  50.   with killer^ do
  51.     begin
  52.       e := s;
  53.       q.front := next;
  54.     end; {with}
  55.   if q.front = nil then
  56.     q.rear := nil;
  57.   dispose( killer );
  58. end;
  59.  
  60. procedure screate( var q : squeue );
  61. begin
  62.   q.front := nil;
  63.   q.rear := nil;
  64. end;
  65.  
  66. procedure Scan( s : sector; var m : scannerMap; var LeftOpen : integer );
  67. { visit s; mark every sector adjacent to s as examined. }
  68. var
  69.   j : warpindex;
  70. begin
  71.   m[s] := visited;
  72.   with space.sectors[s] do
  73.     for j := 1 to number do
  74.       if m[ data[j] ] = open then
  75.         begin
  76.           m[ data[j] ] := scanned;
  77.           LeftOpen := LeftOpen - 1;
  78.           write('.');
  79.         end;
  80. end; {scan}
  81.  
  82. procedure InitToOpen( var s : ScannerMap );
  83. { initialize all known or adjacent to known sectors to "open", rest to
  84. unreachable.  Warn if there are reachable unexplored sectors. }
  85. var
  86.   i : sector;
  87.   q : squeue;
  88.   j : warpindex;
  89. begin
  90.   for i := 1 to MaxSector do
  91.     s[i] := unreachable;
  92.   screate( q );
  93.   ensqueue( 1, q );
  94.   while q.front <> nil do
  95.     begin
  96.       sserve( i, q );
  97.       s[i] := open;
  98.       with space.sectors[i] do
  99.         for j := 1 to number do
  100.           if s[ data[j] ] = unreachable then
  101.             ensqueue( data[ j ], q );
  102.     end; {while}
  103.   for i := 1 to MaxSector do
  104.     if s[i] = unreachable then
  105.       writeln('Sector ', i, ' unreachable.');
  106. end; {Initialize to all open}
  107.  
  108. procedure SaveMapToDisk( var s : scannermap );
  109. var
  110.   f : text;
  111.   i : sector;
  112. begin
  113.   assign( f, GetNewFileName('File to store sector map? ',BBSName+'.map'));
  114.   rewrite( f );
  115.   for i := 1 to MaxSector do
  116.     case s[i] of
  117.       unreachable : writeln( f, i:4, ' unreachable');
  118.       visited     : writeln( f, i:4, ' visited');
  119.       scanned     : writeln( f, i:4, ' scanned');
  120.       open        : ;
  121.     end; {for case}
  122.   close( f );
  123. end;
  124.  
  125. procedure EditMap( var s : scannermap );
  126. var
  127.   dummy : integer;
  128.   i  : SectorIndex;
  129. begin
  130.   writeln('First, enter those sectors you know about (i.e. from Etherprobes)');
  131.   writeln('but where the adjacent sectors were not scanned.');
  132.   writeln;
  133.   writeln('Enter 0 to finish.');
  134.   i := readNumberFromTerminal;
  135.   while i <> 0 do
  136.     begin
  137.       s[i] := scanned;
  138.       i := readNumberFromTerminal;
  139.     end; {while}
  140.   writeln('Now enter those sectors that you have performed scans in.  0 to finish.');
  141.   i := readNumberFromTerminal;
  142.   while i <> 0 do
  143.     begin
  144.       Scan( i, s, dummy );
  145.       i := readNumberFromTerminal;
  146.     end; {while}
  147.   readln;
  148. end;
  149.  
  150. procedure InitMapFromDisk( var s : scannermap );
  151. var
  152.   f : text;
  153.   i : integer;
  154.   SVStatus : string;
  155. begin
  156.   for i := 1 to MaxSector do
  157.     s[i] := open;
  158.   assign( f, GetOldFileName( 'Name map is saved under? ', BBSName+'.map' ));
  159.   reset( f );
  160.   while not eof( f ) do
  161.     begin
  162.       i := ReadNumber( f );
  163.       readln( f, SVstatus );
  164.       if i <> 0 then
  165.         case SVStatus[1] of
  166.           'u' : s[i] := unreachable;
  167.           's' : s[i] := scanned;
  168.           'v' : s[i] := visited;
  169.         else
  170.           writeln('Line "', i, ' ', SVstatus, '" not understood.');
  171.         end; {if case}
  172.     end; {while}
  173. end;
  174.  
  175. procedure SetUpToVisit( var s : scannermap );
  176. var
  177.   i : sector;
  178.   ch: char;
  179. begin
  180.   write('Start with <F>resh map, or <R>ead in map from disk?  ');
  181.   readln( ch );
  182.   if upcase( ch ) = 'R' then
  183.     InitMapFromDisk( s )
  184.   else
  185.     InitToOpen( s );
  186.   repeat
  187.     write('<E>dit map, <S>ave map, or <C>ontinue?  ');
  188.     readln( ch );
  189.     if upcase( ch ) = 'E' then
  190.       EditMap( s )
  191.     else if upcase( ch ) = 'S' then
  192.       SaveMapToDisk( s );
  193.   until not (ch in ['e','E','s','S']);
  194. end;
  195.  
  196. function PathToThing( start : sector;
  197.                   var map : scannermap;
  198.                       which : integer ) : sectorindex;
  199. { Adjusts Distances from start up to point where "which" criteria is found;
  200.   returns sector or 0 if no appropriate sector found. }
  201. var
  202.   s : sector;
  203.   breadth : queue;
  204.   daddy, sonny : sector;
  205.   i : warpindex;
  206.   done : boolean;
  207. begin
  208.   for s := 1 to maxSector do
  209.     Distances[s].d := -1;
  210.   breadth.front := 0;
  211.   enqueue( breadth, start, start );
  212.   repeat
  213.       serve( breadth, daddy, sonny );
  214.       if Distances[ sonny ].d = -1 then {haven't hit him before:}
  215.         begin
  216.           distances[ sonny ].d := distances[ daddy ].d + 1;
  217.           distances[ sonny ].s := daddy;
  218.           with space.sectors[ sonny ] do if number > 0 then
  219.             if (space.sectors[sonny].etc and avoid) = Nothing then
  220.               for i := 1 to number do
  221.                 enqueue( breadth, sonny, data[ i ] );
  222.           case which of
  223.           1 : done := map[ sonny ] = open;
  224.           2 : done := (space.sectors[ sonny ].number = 1) and (map[sonny]=open);
  225.           end; {case}
  226.         end; {if}
  227.   until done or (breadth.front = 0);
  228.   if done then
  229.     PathToThing := sonny
  230.   else
  231.     PathToThing := 0;
  232. end; {Path to Open}
  233.  
  234.  
  235.  
  236. function NumberOpen( var m : ScannerMap ) : integer;
  237. { return the number of open sectors in array }
  238. var
  239.   count : integer;
  240.   i     : sector;
  241. begin
  242.   count := 0;
  243.   for i := 1 to MaxSector do
  244.     if m[i] = open then
  245.       count := count + 1;
  246.   NumberOpen := count;
  247. end;
  248.  
  249. procedure AddToRoute( target : sector;
  250.                   var Travels : route;
  251.                   var map : scannermap );
  252. { assumes Distances has already been properly set up.  We travel from
  253.   current position to target. If target is adjacent to the current location,
  254.   great, extend path; otherwise we have to recursively move one step
  255.   closer, and add that. }
  256. begin
  257.   if not IsWarp( travels.path[ travels.length ], target ) then
  258.     AddToRoute( distances[ target ].s, travels, map );
  259.   if travels.length < maxroute then
  260.     travels.length := travels.length + 1
  261.   else
  262.     writeln('error -- map exceeds maximum of ', maxroute, ' turns!');
  263.   travels.path[ travels.length ] := target;
  264.   scan( target, map, travels.more );
  265. end;
  266.  
  267. procedure DoSomethingRandom(var visit : route;       { travels so far      }
  268.                             var map   : scannerMap); { map visited sectors }
  269. { Go adjacent to a random open sector }
  270. var
  271.   target : sectorindex;
  272.   skip : sectorindex;
  273. begin
  274.   skip := random( visit.more ) + 1;
  275.   target := 0;
  276.   repeat
  277.     target := target + 1;
  278.     while map[ target ] <> open do
  279.       target := target + 1;
  280.     skip := skip - 1;
  281.   until skip = 0;
  282.   writeln('random jog to ', target, ' of length ',
  283.     FixPath( visit.path[ visit.length ], target, maxint - 1 ) );
  284.   AddToRoute( distances[ target ].s, visit, map );
  285. end; {DoSomethingRandom}
  286.  
  287. procedure VisitNearestOpen(var visit : route;       { travels so far      }
  288.                            var map   : scannerMap); { map visited sectors }
  289. begin
  290.   AddToRoute( distances[ pathToThing( visit.path[visit.length], map, 1 ) ].s,
  291.               visit, map );
  292. end; {VisitNearestOpen}
  293.  
  294. procedure VisitNearestDeadEnd( var visit : route;
  295.                                var map   : scannerMap );
  296. var
  297.   s : sectorIndex;
  298. begin
  299.   s := PathToThing( visit.path[ visit.length ], map, 2);
  300.   if s = 0 then
  301.     begin
  302.       writeln('Out of dead ends');
  303.       VisitNearestOpen( visit, map );
  304.     end
  305.   else
  306.     AddToRoute( distances[s].s, visit, map );
  307. end;
  308.  
  309. procedure FindRandomRoute( var Travels : route; map : ScannerMap );
  310. { Find a route through the galaxy that visits or scans every sector in the
  311. map that isn't marked unreachable. }
  312. var
  313.   roll  : integer;
  314.   greed : integer;      { percentage of  doing something random }
  315.   ToGo  : integer;      { how many open sectors remain          }
  316. begin
  317.   write('Starting sector? ');
  318.   readln( travels.path[1] );
  319.   travels.length := 1;
  320.   Scan( travels.path[1], map, travels.more );
  321.   travels.more := NumberOpen( map );
  322.   write('Random percentage?  (0=greedy algorithm, 100=random path) ');
  323.   greed := readNumberFromTerminal;
  324.   while travels.more > 0 do
  325.     begin
  326.       roll := random( 100 );
  327.       if roll < greed then
  328.         DoSomethingRandom( travels, map )
  329.       else if roll < greed * 10 then
  330.         VisitNearestDeadEnd( travels, map )
  331.       else
  332.         VisitNearestOpen( travels, map );
  333.     end; {while}
  334. end; {FindRandomRoute}
  335.  
  336. procedure PrintTour( var t : route );
  337. {print tour to screen, and optionally to disk }
  338. var
  339.   f : text;
  340.   i : sectorindex;
  341.   filename : string;
  342. begin
  343.   writeln('path is of length ', t.length );
  344.   write('Name of file?  Hit return to display to screen: ');
  345.   readln( filename );
  346.   assign( f, filename );
  347.   rewrite( f );
  348.   for i := 1 to t.length do
  349.     begin
  350.       write( f, t.path[i] : 8 );
  351.       if i mod 8 = 0 then
  352.         writeln(f);
  353.     end; {for}
  354.   writeln( f );
  355.   if filename <> '' then
  356.     close( f );
  357. end; {PrintTour}
  358.  
  359.  
  360. procedure VisitEverySector;
  361. { Passed "SPACE" by side effect.  Goal is to find a (short) path that will be
  362. adjacent to every observed sector in the galaxy. }
  363. var
  364.   KnownGalaxy : scannerMap;
  365.   GalacticTour: route;
  366. begin
  367.   SetUpToVisit( KnownGalaxy );
  368.   FindRandomRoute( GalacticTour, KnownGalaxy );
  369.   PrintTour( GalacticTour );
  370. end; {VisitEverySector}
  371.  
  372. procedure IncPath( var home : sectorindex; sec : sector;
  373.                    var count : integer;
  374.                    var map   : ScannerMap );
  375. { add one for each open sector encountered }
  376. begin
  377.   if home <> sec then
  378.     IncPath( home, distances[ sec ].s, count, map );
  379.   if map[sec] = open then
  380.     Inc( count );
  381. end;
  382.  
  383.  
  384. procedure FindScanResults( var BaseSector     : sectorIndex;
  385.                            var EtherProbeInfo : distanceArray;
  386.                            var map            : scannermap );
  387. { Load EtherProbeInfo with EtherProbeInfo.d = # open sectors on path from
  388. base point to EtherProbeInfo.s }
  389. var
  390.   i          : sector;
  391. begin
  392.   TwoWayDistances( BaseSector, distances, false, true );
  393.   for i := 1 to MaxSector do
  394.     begin
  395.       EtherProbeInfo[i].d := 0;
  396.       if distances[i].d <> maxint then
  397.         IncPath( BaseSector, i, EtherProbeInfo[i].d, map );
  398.       EtherProbeInfo[i].s := i;
  399.     end; {for}
  400. end;
  401.  
  402. procedure MarkPath( var home : sectorindex; sec : sector;
  403.                    var map   : ScannerMap );
  404. { subtract one for each open sector encountered }
  405. begin
  406.   if home <> sec then
  407.     MarkPath( home, distances[ sec ].s, map );
  408.   if map[ sec ] = open then
  409.     write( sec : 5 );
  410.   map[sec] := visited;
  411. end;
  412.  
  413. function Largest( var ER : distanceArray ) : sectorIndex;
  414. var
  415.   i : sectorIndex;
  416.   best : sectorIndex;
  417. begin
  418.   best := 1;
  419.   for i := 2 to MaxSector do
  420.     if ER[i].d > ER[Best].d then
  421.       best := i;
  422.   largest := best;
  423. end;
  424.  
  425. procedure SuggestEtherProbes;
  426. {Also passed "space" by side effect.  Will suggest a list of etherprobe
  427. targets that should be fired in sequence to cover as much as possible.}
  428. var
  429.   KnownGalaxy : scannerMap;
  430.   Target,
  431.   BaseSector  : sectorindex;
  432.   NewScanned  : distancearray;
  433.   i, HowMany  : integer;
  434. begin
  435.   write('How many ether probes do you want to fire? ');
  436.   howmany := readNumberFromTerminal;
  437.   if HowMany = 0 then exit;
  438.   SetUpToVisit( KnownGalaxy );
  439.   write('Base Etherprobe ');
  440.   BaseSector := GetSector;
  441.   if BaseSector = 0 then exit;
  442.   if NewScanned[1].d <> -maxint then  {abort at previous step?}
  443.     for i := 1 to HowMany do
  444.       begin
  445.         FindScanResults( BaseSector, NewScanned, KnownGalaxy );
  446.         Target := Largest( NewScanned );
  447.         writeln('Target: ', target : 4, '   New sectors : ',
  448.                  NewScanned[target].d: 4);
  449.         write('Picked up: ');
  450.         MarkPath( basesector, target, KnownGalaxy );
  451.         if i mod 5 = 0 then
  452.           readln;
  453.         writeln;
  454.       end; {if}
  455. end; {SuggestEtherProbes}
  456.