Loading

Paste #pfvcyec2z

  1. /** Directions to search towards given track bits and the ship's enter direction. */
  2. static const DiagDirection _ship_search_directions[6][4] = {
  3.     { DIAGDIR_NE,      INVALID_DIAGDIR, DIAGDIR_SW,      INVALID_DIAGDIR },
  4.     { INVALID_DIAGDIR, DIAGDIR_SE,      INVALID_DIAGDIR, DIAGDIR_NW      },
  5.     { INVALID_DIAGDIR, DIAGDIR_NE,      DIAGDIR_NW,      INVALID_DIAGDIR },
  6.     { DIAGDIR_SE,      INVALID_DIAGDIR, INVALID_DIAGDIR, DIAGDIR_SW      },
  7.     { DIAGDIR_NW,      DIAGDIR_SW,      INVALID_DIAGDIR, INVALID_DIAGDIR },
  8.     { INVALID_DIAGDIR, INVALID_DIAGDIR, DIAGDIR_SE,      DIAGDIR_NE      },
  9. };
  10.  
  11. /** Track to "direction (& 3)" mapping. */
  12. static const byte _pick_shiptrack_table[6] = {DIR_NE, DIR_SE, DIR_E, DIR_E, DIR_N, DIR_N};
  13.  
  14. static uint FindShipTrack(const Ship *v, TileIndex tile, DiagDirection dir, TrackBits bits, TileIndex skiptile, Track *track)
  15. {
  16.     TrackPathFinder pfs;
  17.     uint best_bird_dist = 0;
  18.     uint best_length    = 0;
  19.     byte ship_dir = v->direction & 3;
  20.  
  21.     pfs.dest_coords = v->dest_tile;
  22.     pfs.skiptile = skiptile;
  23.  
  24.     Track best_track = INVALID_TRACK;
  25.  
  26.     assert(bits != TRACK_BIT_NONE);
  27.     do {
  28.         Track i = RemoveFirstTrack(&bits);
  29.  
  30.         pfs.best_bird_dist = UINT_MAX;
  31.         pfs.best_length = UINT_MAX;
  32.  
  33.         OPFShipFollowTrack(tile, _ship_search_directions[i][dir], &pfs);
  34.  
  35.         if (best_track != INVALID_TRACK) {
  36.             if (pfs.best_bird_dist != 0) {
  37.                 /* neither reached the destination, pick the one with the smallest bird dist */
  38.                 if (pfs.best_bird_dist > best_bird_dist) goto bad;
  39.                 if (pfs.best_bird_dist < best_bird_dist) goto good;
  40.             } else {
  41.                 if (pfs.best_length > best_length) goto bad;
  42.                 if (pfs.best_length < best_length) goto good;
  43.             }
  44.  
  45.             TileIndex tile_i = TileAddByDiagDir(tile, TrackdirToExitdir(TrackEnterdirToTrackdir(i, dir)));
  46.             TileIndex tile_best_track = TileAddByDiagDir(tile, TrackdirToExitdir(TrackEnterdirToTrackdir(best_track, dir)));
  47.             if (IsValidTile(tile_i) && IsValidTile(tile_best_track)) {
  48.  
  49.                 uint distancempm_i = DistanceMaxPlusManhattan(pfs.dest_coords, tile_i);
  50.                 uint distancempm_best_track = DistanceMaxPlusManhattan(pfs.dest_coords, tile_best_track);
  51.                 uint distancem_i = DistanceManhattan(pfs.dest_coords, tile_i);
  52.                 uint distancem_best_track = DistanceManhattan(pfs.dest_coords, tile_best_track);
  53.                 uint distances_i = DistanceSquare(pfs.dest_coords, tile_i);
  54.                 uint distances_best_track = DistanceSquare(pfs.dest_coords, tile_best_track);
  55.  
  56.                 assert((distancempm_i < distancempm_best_track) == (distances_i < distances_best_track));
  57.                 assert((distancempm_i == distancempm_best_track) == (distances_i == distances_best_track));
  58.                 assert((distancempm_i > distancempm_best_track) == (distances_i > distances_best_track));
  59.  
  60.                 if (distancempm_i > distancempm_best_track) goto bad;
  61.                 if (distancempm_i < distancempm_best_track) goto good;
  62.  
  63.                 if (distances_i > distances_best_track) goto bad;
  64.                 if (distances_i < distances_best_track) goto good;
  65.  
  66.                 if (distancem_i > distancem_best_track) goto bad;
  67.                 if (distancem_i < distancem_best_track) goto good;
  68.             }
  69.             /* if we reach this position, there's two paths of equal value so far.
  70.              * pick one randomly. */
  71.             uint r = GB(Random(), 0, 8);
  72.             if (_pick_shiptrack_table[i] == ship_dir) r += 80;
  73.             if (_pick_shiptrack_table[best_track] == ship_dir) r -= 80;
  74.             if (r <= 127) goto bad;
  75.         }
  76. good:;
  77.         best_track = i;
  78.         best_bird_dist = pfs.best_bird_dist;
  79.         best_length = pfs.best_length;
  80. bad:;
  81.  
  82.     } while (bits != TRACK_BIT_NONE);
  83.  
  84.     *track = best_track;
  85.     return best_bird_dist;
  86. }

Comments