(svn r18366) -Codechange: move the OPF ship pathfinder 'magic' that was in ship_cmd.cpp to the pathfinder code itself
This commit is contained in:
106
src/ship_cmd.cpp
106
src/ship_cmd.cpp
@@ -368,92 +368,6 @@ static void ShipArrivesAt(const Vehicle *v, Station *st)
|
||||
}
|
||||
}
|
||||
|
||||
struct PathFindShip {
|
||||
TileIndex skiptile;
|
||||
TileIndex dest_coords;
|
||||
uint best_bird_dist;
|
||||
uint best_length;
|
||||
};
|
||||
|
||||
static bool ShipTrackFollower(TileIndex tile, PathFindShip *pfs, int track, uint length)
|
||||
{
|
||||
/* Found dest? */
|
||||
if (tile == pfs->dest_coords) {
|
||||
pfs->best_bird_dist = 0;
|
||||
|
||||
pfs->best_length = minu(pfs->best_length, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Skip this tile in the calculation */
|
||||
if (tile != pfs->skiptile) {
|
||||
pfs->best_bird_dist = minu(pfs->best_bird_dist, DistanceMaxPlusManhattan(pfs->dest_coords, tile));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const byte _ship_search_directions[6][4] = {
|
||||
{ 0, 9, 2, 9 },
|
||||
{ 9, 1, 9, 3 },
|
||||
{ 9, 0, 3, 9 },
|
||||
{ 1, 9, 9, 2 },
|
||||
{ 3, 2, 9, 9 },
|
||||
{ 9, 9, 1, 0 },
|
||||
};
|
||||
|
||||
static const byte _pick_shiptrack_table[6] = {1, 3, 2, 2, 0, 0};
|
||||
|
||||
static uint FindShipTrack(Vehicle *v, TileIndex tile, DiagDirection dir, TrackBits bits, TileIndex skiptile, Track *track)
|
||||
{
|
||||
PathFindShip pfs;
|
||||
Track i, best_track;
|
||||
uint best_bird_dist = 0;
|
||||
uint best_length = 0;
|
||||
uint r;
|
||||
byte ship_dir = v->direction & 3;
|
||||
|
||||
pfs.dest_coords = v->dest_tile;
|
||||
pfs.skiptile = skiptile;
|
||||
|
||||
best_track = INVALID_TRACK;
|
||||
|
||||
do {
|
||||
i = RemoveFirstTrack(&bits);
|
||||
|
||||
pfs.best_bird_dist = UINT_MAX;
|
||||
pfs.best_length = UINT_MAX;
|
||||
|
||||
OPFShipFollowTrack(tile, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, &pfs);
|
||||
|
||||
if (best_track != INVALID_TRACK) {
|
||||
if (pfs.best_bird_dist != 0) {
|
||||
/* neither reached the destination, pick the one with the smallest bird dist */
|
||||
if (pfs.best_bird_dist > best_bird_dist) goto bad;
|
||||
if (pfs.best_bird_dist < best_bird_dist) goto good;
|
||||
} else {
|
||||
if (pfs.best_length > best_length) goto bad;
|
||||
if (pfs.best_length < best_length) goto good;
|
||||
}
|
||||
|
||||
/* if we reach this position, there's two paths of equal value so far.
|
||||
* pick one randomly. */
|
||||
r = GB(Random(), 0, 8);
|
||||
if (_pick_shiptrack_table[i] == ship_dir) r += 80;
|
||||
if (_pick_shiptrack_table[best_track] == ship_dir) r -= 80;
|
||||
if (r <= 127) goto bad;
|
||||
}
|
||||
good:;
|
||||
best_track = i;
|
||||
best_bird_dist = pfs.best_bird_dist;
|
||||
best_length = pfs.best_length;
|
||||
bad:;
|
||||
|
||||
} while (bits != 0);
|
||||
|
||||
*track = best_track;
|
||||
return best_bird_dist;
|
||||
}
|
||||
|
||||
static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, NPFFindStationOrTileData *target, TransportType type, Owner owner, RailTypes railtypes)
|
||||
{
|
||||
@@ -494,25 +408,9 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, Tr
|
||||
if (ftd.best_trackdir != 0xff) return TrackdirToTrack(ftd.best_trackdir); // TODO: Wrapper function?
|
||||
} break;
|
||||
|
||||
default:
|
||||
case VPF_OPF: { // OPF
|
||||
TileIndex tile2 = TILE_ADD(tile, -TileOffsByDiagDir(enterdir));
|
||||
Track track;
|
||||
default: NOT_REACHED();
|
||||
|
||||
/* Let's find out how far it would be if we would reverse first */
|
||||
TrackBits b = GetTileShipTrackStatus(tile2) & DiagdirReachesTracks(ReverseDiagDir(enterdir)) & v->state;
|
||||
|
||||
uint distr = UINT_MAX; // distance if we reversed
|
||||
if (b != 0) {
|
||||
distr = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track);
|
||||
if (distr != UINT_MAX) distr++; // penalty for reversing
|
||||
}
|
||||
|
||||
/* And if we would not reverse? */
|
||||
uint dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track);
|
||||
|
||||
if (dist <= distr) return track;
|
||||
} break;
|
||||
case VPF_OPF: return OPFShipChooseTrack(v, tile, enterdir, tracks);
|
||||
}
|
||||
|
||||
return INVALID_TRACK; // We could better reverse
|
||||
|
Reference in New Issue
Block a user