1
0
Fork 0

(svn r12132) -Cleanup: convert pathfinder selection from if/else to switch/case at many places

release/0.6
smatz 2008-02-13 17:54:11 +00:00
parent 480036254b
commit fd51465c8b
3 changed files with 330 additions and 309 deletions

View File

@ -414,38 +414,36 @@ static bool EnumRoadSignalFindDepot(TileIndex tile, void* data, Trackdir trackdi
static const Depot* FindClosestRoadDepot(const Vehicle* v) static const Depot* FindClosestRoadDepot(const Vehicle* v)
{ {
TileIndex tile = v->tile; switch (_patches.pathfinder_for_roadvehs) {
case VPF_YAPF: /* YAPF */
return YapfFindNearestRoadDepot(v);
if (_patches.pathfinder_for_roadvehs == VPF_YAPF) { /* YAPF is being used */ case VPF_NPF: { /* NPF */
Depot* ret = YapfFindNearestRoadDepot(v); /* See where we are now */
return ret; Trackdir trackdir = GetVehicleTrackdir(v);
} else if (_patches.pathfinder_for_roadvehs == VPF_NPF) { /* NPF is being used */
NPFFoundTargetData ftd;
/* See where we are now */
Trackdir trackdir = GetVehicleTrackdir(v);
ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, ReverseTrackdir(trackdir), false, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0); NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, ReverseTrackdir(trackdir), false, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0);
if (ftd.best_bird_dist == 0) {
return GetDepotByTile(ftd.node.tile); /* Target found */
} else {
return NULL; /* Target not found */
}
/* We do not search in two directions here, why should we? We can't reverse right now can we? */
} else { /* OPF is being used */
RoadFindDepotData rfdd;
rfdd.owner = v->owner; if (ftd.best_bird_dist == 0) return GetDepotByTile(ftd.node.tile); /* Target found */
rfdd.best_length = (uint)-1; } break;
/* search in all directions */ default:
for (DiagDirection i = DIAGDIR_BEGIN; i != DIAGDIR_END; i++) { case VPF_OPF: { /* OPF */
FollowTrack(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, i, EnumRoadSignalFindDepot, NULL, &rfdd); RoadFindDepotData rfdd;
}
if (rfdd.best_length == (uint)-1) return NULL; rfdd.owner = v->owner;
rfdd.best_length = UINT_MAX;
return GetDepotByTile(rfdd.tile); /* search in all directions */
for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
FollowTrack(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, d, EnumRoadSignalFindDepot, NULL, &rfdd);
}
if (rfdd.best_length != UINT_MAX) return GetDepotByTile(rfdd.tile);
} break;
} }
return NULL; /* Target not found */
} }
/** Send a road vehicle to the depot. /** Send a road vehicle to the depot.
@ -1217,77 +1215,82 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
return_track(FindFirstBit2x64(trackdirs)); return_track(FindFirstBit2x64(trackdirs));
} }
if (_patches.pathfinder_for_roadvehs == VPF_YAPF) { /* YAPF */ switch (_patches.pathfinder_for_roadvehs) {
Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir); case VPF_YAPF: { /* YAPF */
if (trackdir != INVALID_TRACKDIR) return_track(trackdir); Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir);
return_track(PickRandomBit(trackdirs)); if (trackdir != INVALID_TRACKDIR) return_track(trackdir);
} else if (_patches.pathfinder_for_roadvehs == VPF_NPF) { /* NPF */ return_track(PickRandomBit(trackdirs));
NPFFindStationOrTileData fstd; } break;
NPFFoundTargetData ftd;
Trackdir trackdir;
NPFFillWithOrderData(&fstd, v); case VPF_NPF: { /* NPF */
trackdir = DiagdirToDiagTrackdir(enterdir); NPFFindStationOrTileData fstd;
//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES); NPFFillWithOrderData(&fstd, v);
if (ftd.best_trackdir == INVALID_TRACKDIR) { Trackdir trackdir = DiagdirToDiagTrackdir(enterdir);
/* We are already at our target. Just do something //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
* @todo: maybe display error?
* @todo: go straight ahead if possible? */
return_track(FindFirstBit2x64(trackdirs));
} else {
/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
the direction we need to take to get there, if ftd.best_bird_dist is not 0,
we did not find our target, but ftd.best_trackdir contains the direction leading
to the tile closest to our target. */
return_track(ftd.best_trackdir);
}
} else { /* OPF */
DiagDirection dir;
if (IsTileType(desttile, MP_ROAD)) { NPFFoundTargetData ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES);
if (GetRoadTileType(desttile) == ROAD_TILE_DEPOT) { if (ftd.best_trackdir == INVALID_TRACKDIR) {
dir = GetRoadDepotDirection(desttile); /* We are already at our target. Just do something
goto do_it; * @todo: maybe display error?
* @todo: go straight ahead if possible? */
return_track(FindFirstBit2x64(trackdirs));
} else {
/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
* the direction we need to take to get there, if ftd.best_bird_dist is not 0,
* we did not find our target, but ftd.best_trackdir contains the direction leading
* to the tile closest to our target. */
return_track(ftd.best_trackdir);
} }
} else if (IsTileType(desttile, MP_STATION)) { } break;
/* For drive-through stops we can head for the actual station tile */
if (IsStandardRoadStopTile(desttile)) { default:
dir = GetRoadStopDir(desttile); case VPF_OPF: { /* OPF */
DiagDirection dir;
if (IsTileType(desttile, MP_ROAD)) {
if (GetRoadTileType(desttile) == ROAD_TILE_DEPOT) {
dir = GetRoadDepotDirection(desttile);
goto do_it;
}
} else if (IsTileType(desttile, MP_STATION)) {
/* For drive-through stops we can head for the actual station tile */
if (IsStandardRoadStopTile(desttile)) {
dir = GetRoadStopDir(desttile);
do_it:; do_it:;
/* When we are heading for a depot or station, we just /* When we are heading for a depot or station, we just
* pretend we are heading for the tile in front, we'll * pretend we are heading for the tile in front, we'll
* see from there */ * see from there */
desttile += TileOffsByDiagDir(dir); desttile += TileOffsByDiagDir(dir);
if (desttile == tile && trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]) { if (desttile == tile && trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]) {
/* If we are already in front of the /* If we are already in front of the
* station/depot and we can get in from here, * station/depot and we can get in from here,
* we enter */ * we enter */
return_track(FindFirstBit2x64(trackdirs & _road_exit_dir_to_incoming_trackdirs[dir])); return_track(FindFirstBit2x64(trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]));
}
} }
} }
} /* Do some pathfinding */
/* Do some pathfinding */ frd.dest = desttile;
frd.dest = desttile;
best_track = INVALID_TRACKDIR; best_track = INVALID_TRACKDIR;
uint best_dist = (uint)-1; uint best_dist = UINT_MAX;
uint best_maxlen = (uint)-1; uint best_maxlen = UINT_MAX;
uint bitmask = (uint)trackdirs; uint bitmask = (uint)trackdirs;
uint i; uint i;
FOR_EACH_SET_BIT(i, bitmask) { FOR_EACH_SET_BIT(i, bitmask) {
if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track
frd.maxtracklen = (uint)-1; frd.maxtracklen = UINT_MAX;
frd.mindist = (uint)-1; frd.mindist = UINT_MAX;
FollowTrack(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); FollowTrack(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) { if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) {
best_dist = frd.mindist; best_dist = frd.mindist;
best_maxlen = frd.maxtracklen; best_maxlen = frd.maxtracklen;
best_track = (Trackdir)i; best_track = (Trackdir)i;
}
} }
} } break;
} }
found_best_track:; found_best_track:;
@ -1299,24 +1302,23 @@ found_best_track:;
static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile) static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
{ {
uint dist;
if (_patches.pathfinder_for_roadvehs == VPF_YAPF) { if (_patches.pathfinder_for_roadvehs == VPF_YAPF) {
/* use YAPF */ /* use YAPF */
dist = YapfRoadVehDistanceToTile(v, tile); return YapfRoadVehDistanceToTile(v, tile);
} else {
/* use NPF */
NPFFindStationOrTileData fstd;
Trackdir trackdir = GetVehicleTrackdir(v);
assert(trackdir != INVALID_TRACKDIR);
fstd.dest_coords = tile;
fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
dist = NPFRouteToStationOrTile(v->tile, trackdir, false, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES).best_path_dist;
/* change units from NPF_TILE_LENGTH to # of tiles */
if (dist != UINT_MAX)
dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
} }
/* use NPF */
Trackdir trackdir = GetVehicleTrackdir(v);
assert(trackdir != INVALID_TRACKDIR);
NPFFindStationOrTileData fstd;
fstd.dest_coords = tile;
fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
uint dist = NPFRouteToStationOrTile(v->tile, trackdir, false, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES).best_path_dist;
/* change units from NPF_TILE_LENGTH to # of tiles */
if (dist != UINT_MAX) dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
return dist; return dist;
} }

View File

@ -113,34 +113,32 @@ int Ship::GetImage(Direction direction) const
static const Depot* FindClosestShipDepot(const Vehicle* v) static const Depot* FindClosestShipDepot(const Vehicle* v)
{ {
if (_patches.pathfinder_for_ships == VPF_NPF) { /* NPF is used */
Trackdir trackdir = GetVehicleTrackdir(v);
NPFFoundTargetData ftd = NPFRouteToDepotTrialError(v->tile, trackdir, false, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES);
if (ftd.best_bird_dist == 0) return GetDepotByTile(ftd.node.tile); /* Found target */
return NULL; /* Did not find target */
}
/* OPF or YAPF - find the closest depot */
const Depot* depot; const Depot* depot;
const Depot* best_depot = NULL; const Depot* best_depot = NULL;
uint dist; uint best_dist = UINT_MAX;
uint best_dist = (uint)-1;
TileIndex tile;
TileIndex tile2 = v->tile;
if (_patches.pathfinder_for_ships == VPF_NPF) { /* NPF is used */ FOR_ALL_DEPOTS(depot) {
NPFFoundTargetData ftd; TileIndex tile = depot->xy;
Trackdir trackdir = GetVehicleTrackdir(v); if (IsTileDepotType(tile, TRANSPORT_WATER) && IsTileOwner(tile, v->owner)) {
ftd = NPFRouteToDepotTrialError(v->tile, trackdir, false, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES); uint dist = DistanceManhattan(tile, v->tile);
if (ftd.best_bird_dist == 0) { if (dist < best_dist) {
best_depot = GetDepotByTile(ftd.node.tile); /* Found target */ best_dist = dist;
} else { best_depot = depot;
best_depot = NULL; /* Did not find target */
}
} else { /* OPF or YAPF */
FOR_ALL_DEPOTS(depot) {
tile = depot->xy;
if (IsTileDepotType(tile, TRANSPORT_WATER) && IsTileOwner(tile, v->owner)) {
dist = DistanceManhattan(tile, tile2);
if (dist < best_dist) {
best_dist = dist;
best_depot = depot;
}
} }
} }
} }
return best_depot; return best_depot;
} }
@ -525,52 +523,52 @@ static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Tra
* direction in which we are entering the tile */ * direction in which we are entering the tile */
static Track ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) static Track ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
{ {
assert(enterdir >= 0 && enterdir <= 3); assert(IsValidDiagDirection(enterdir));
if (_patches.pathfinder_for_ships == VPF_YAPF) { /* YAPF */ switch (_patches.pathfinder_for_ships) {
Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks); case VPF_YAPF: { /* YAPF */
return (trackdir != INVALID_TRACKDIR) ? TrackdirToTrack(trackdir) : INVALID_TRACK; Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks);
} else if (_patches.pathfinder_for_ships == VPF_NPF) { /* NPF */ if (trackdir != INVALID_TRACKDIR) return TrackdirToTrack(trackdir);
NPFFindStationOrTileData fstd; } break;
NPFFoundTargetData ftd;
Trackdir trackdir = GetVehicleTrackdir(v);
assert(trackdir != INVALID_TRACKDIR); // Check that we are not in a depot
NPFFillWithOrderData(&fstd, v); case VPF_NPF: { /* NPF */
NPFFindStationOrTileData fstd;
Trackdir trackdir = GetVehicleTrackdir(v);
assert(trackdir != INVALID_TRACKDIR); // Check that we are not in a depot
ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPES); NPFFillWithOrderData(&fstd, v);
NPFFoundTargetData ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPES);
if (ftd.best_trackdir != 0xff) {
/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
the direction we need to take to get there, if ftd.best_bird_dist is not 0, * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
we did not find our target, but ftd.best_trackdir contains the direction leading * we did not find our target, but ftd.best_trackdir contains the direction leading
to the tile closest to our target. */ * to the tile closest to our target. */
return TrackdirToTrack(ftd.best_trackdir); /* TODO: Wrapper function? */ if (ftd.best_trackdir != 0xff) return TrackdirToTrack(ftd.best_trackdir); /* TODO: Wrapper function? */
} else { } break;
return INVALID_TRACK; /* Already at target, reverse? */
}
} else { /* OPF */
uint tot_dist, dist;
Track track;
TileIndex tile2;
tile2 = TILE_ADD(tile, -TileOffsByDiagDir(enterdir)); default:
tot_dist = (uint)-1; case VPF_OPF: { /* OPF */
TileIndex tile2 = TILE_ADD(tile, -TileOffsByDiagDir(enterdir));
Track track;
/* Let's find out how far it would be if we would reverse first */ /* Let's find out how far it would be if we would reverse first */
TrackBits b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagDir(enterdir)] & v->u.ship.state; TrackBits b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagDir(enterdir)] & v->u.ship.state;
if (b != 0) {
dist = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track); uint distr = UINT_MAX; // distance if we reversed
if (dist != (uint)-1) if (b != 0) {
tot_dist = dist + 1; distr = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track);
} if (distr != UINT_MAX) distr++; // penalty for reversing
/* And if we would not reverse? */ }
dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track);
if (dist > tot_dist) /* And if we would not reverse? */
/* We could better reverse */ uint dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track);
return INVALID_TRACK;
return track; if (dist <= distr) return track;
} break;
} }
return INVALID_TRACK; /* We could better reverse */
} }
static const Direction _new_vehicle_direction_table[] = { static const Direction _new_vehicle_direction_table[] = {

View File

@ -2000,7 +2000,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
TrainFindDepotData tfdd; TrainFindDepotData tfdd;
tfdd.owner = v->owner; tfdd.owner = v->owner;
tfdd.best_length = (uint)-1; tfdd.best_length = UINT_MAX;
tfdd.reverse = false; tfdd.reverse = false;
TileIndex tile = v->tile; TileIndex tile = v->tile;
@ -2010,36 +2010,43 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
return tfdd; return tfdd;
} }
if (_patches.pathfinder_for_trains == VPF_YAPF) { /* YAPF is selected */ switch (_patches.pathfinder_for_trains) {
bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse); case VPF_YAPF: { /* YAPF */
tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
} else if (_patches.pathfinder_for_trains == VPF_NPF) { /* NPF is selected */ tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
Vehicle* last = GetLastVehicleInChain(v); } break;
Trackdir trackdir = GetVehicleTrackdir(v);
Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
assert(trackdir != INVALID_TRACKDIR); case VPF_NPF: { /* NPF */
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY); Vehicle* last = GetLastVehicleInChain(v);
if (ftd.best_bird_dist == 0) { Trackdir trackdir = GetVehicleTrackdir(v);
/* Found target */ Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
tfdd.tile = ftd.node.tile;
/* Our caller expects a number of tiles, so we just approximate that assert(trackdir != INVALID_TRACKDIR);
* number by this. It might not be completely what we want, but it will NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
* work for now :-) We can possibly change this when the old pathfinder if (ftd.best_bird_dist == 0) {
* is removed. */ /* Found target */
tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH; tfdd.tile = ftd.node.tile;
if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true; /* Our caller expects a number of tiles, so we just approximate that
} * number by this. It might not be completely what we want, but it will
} else { /* NTP */ * work for now :-) We can possibly change this when the old pathfinder
/* search in the forward direction first. */ * is removed. */
DiagDirection i = TrainExitDir(v->direction, v->u.rail.track); tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
if (tfdd.best_length == (uint)-1){ }
tfdd.reverse = true; } break;
/* search in backwards direction */
i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track); default:
case VPF_NTP: { /* NTP */
/* search in the forward direction first. */
DiagDirection i = TrainExitDir(v->direction, v->u.rail.track);
NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
} if (tfdd.best_length == UINT_MAX){
tfdd.reverse = true;
/* search in backwards direction */
i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track);
NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
}
} break;
} }
return tfdd; return tfdd;
@ -2358,68 +2365,76 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir
/* quick return in case only one possible track is available */ /* quick return in case only one possible track is available */
if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks); if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks);
if (_patches.pathfinder_for_trains == VPF_YAPF) { /* YAPF is selected */ switch (_patches.pathfinder_for_trains) {
Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found); case VPF_YAPF: { /* YAPF */
if (trackdir != INVALID_TRACKDIR) { Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
best_track = TrackdirToTrack(trackdir); if (trackdir != INVALID_TRACKDIR) {
} else { best_track = TrackdirToTrack(trackdir);
best_track = FindFirstTrack(tracks); } else {
} best_track = FindFirstTrack(tracks);
} else if (_patches.pathfinder_for_trains == VPF_NPF) { /* NPF is selected */ }
void* perf = NpfBeginInterval(); } break;
NPFFindStationOrTileData fstd; case VPF_NPF: { /* NPF */
NPFFillWithOrderData(&fstd, v); void *perf = NpfBeginInterval();
/* The enterdir for the new tile, is the exitdir for the old tile */
Trackdir trackdir = GetVehicleTrackdir(v);
assert(trackdir != 0xff);
NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes); NPFFindStationOrTileData fstd;
NPFFillWithOrderData(&fstd, v);
/* The enterdir for the new tile, is the exitdir for the old tile */
Trackdir trackdir = GetVehicleTrackdir(v);
assert(trackdir != INVALID_TRACKDIR);
if (ftd.best_trackdir == 0xff) { NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
/* We are already at our target. Just do something
* @todo maybe display error?
* @todo: go straight ahead if possible? */
best_track = FindFirstTrack(tracks);
} else {
/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
the direction we need to take to get there, if ftd.best_bird_dist is not 0,
we did not find our target, but ftd.best_trackdir contains the direction leading
to the tile closest to our target. */
if (ftd.best_bird_dist != 0) path_not_found = true;
/* Discard enterdir information, making it a normal track */
best_track = TrackdirToTrack(ftd.best_trackdir);
}
int time = NpfEndInterval(perf); if (ftd.best_trackdir == INVALID_TRACKDIR) {
DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size); /* We are already at our target. Just do something
} else { /* NTP is selected */ * @todo maybe display error?
void* perf = NpfBeginInterval(); * @todo: go straight ahead if possible? */
best_track = FindFirstTrack(tracks);
} else {
/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
* the direction we need to take to get there, if ftd.best_bird_dist is not 0,
* we did not find our target, but ftd.best_trackdir contains the direction leading
* to the tile closest to our target. */
if (ftd.best_bird_dist != 0) path_not_found = true;
/* Discard enterdir information, making it a normal track */
best_track = TrackdirToTrack(ftd.best_trackdir);
}
TrainTrackFollowerData fd; int time = NpfEndInterval(perf);
FillWithStationData(&fd, v); DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
} break;
/* New train pathfinding */ default:
fd.best_bird_dist = (uint)-1; case VPF_NTP: { /* NTP */
fd.best_track_dist = (uint)-1; void *perf = NpfBeginInterval();
fd.best_track = INVALID_TRACKDIR;
NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile, TrainTrackFollowerData fd;
v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd); FillWithStationData(&fd, v);
/* check whether the path was found or only 'guessed' */ /* New train pathfinding */
if (fd.best_bird_dist != 0) path_not_found = true; fd.best_bird_dist = UINT_MAX;
fd.best_track_dist = UINT_MAX;
fd.best_track = INVALID_TRACKDIR;
if (fd.best_track == 0xff) { NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
/* blaha */ v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
best_track = FindFirstTrack(tracks);
} else {
best_track = TrackdirToTrack(fd.best_track);
}
int time = NpfEndInterval(perf); /* check whether the path was found or only 'guessed' */
DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0); if (fd.best_bird_dist != 0) path_not_found = true;
if (fd.best_track == INVALID_TRACKDIR) {
/* blaha */
best_track = FindFirstTrack(tracks);
} else {
best_track = TrackdirToTrack(fd.best_track);
}
int time = NpfEndInterval(perf);
DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
} break;
} }
/* handle "path not found" state */ /* handle "path not found" state */
if (path_not_found) { if (path_not_found) {
/* PF didn't find the route */ /* PF didn't find the route */
@ -2469,81 +2484,87 @@ static bool CheckReverseTrain(Vehicle *v)
int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)]; int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)];
if (_patches.pathfinder_for_trains == VPF_YAPF) { /* YAPF is selected */ switch (_patches.pathfinder_for_trains) {
reverse_best = YapfCheckReverseTrain(v); case VPF_YAPF: { /* YAPF */
} else if (_patches.pathfinder_for_trains == VPF_NPF) { /* NPF if selected for trains */ reverse_best = YapfCheckReverseTrain(v);
NPFFindStationOrTileData fstd; } break;
NPFFoundTargetData ftd;
Trackdir trackdir, trackdir_rev;
Vehicle* last = GetLastVehicleInChain(v);
NPFFillWithOrderData(&fstd, v); case VPF_NPF: { /* NPF */
NPFFindStationOrTileData fstd;
NPFFoundTargetData ftd;
Vehicle* last = GetLastVehicleInChain(v);
trackdir = GetVehicleTrackdir(v); NPFFillWithOrderData(&fstd, v);
trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
assert(trackdir != 0xff);
assert(trackdir_rev != 0xff);
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes); Trackdir trackdir = GetVehicleTrackdir(v);
if (ftd.best_bird_dist != 0) { Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
/* We didn't find anything, just keep on going straight ahead */ assert(trackdir != INVALID_TRACKDIR);
reverse_best = false; assert(trackdir_rev != INVALID_TRACKDIR);
} else {
if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) { ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
reverse_best = true; if (ftd.best_bird_dist != 0) {
} else { /* We didn't find anything, just keep on going straight ahead */
reverse_best = false; reverse_best = false;
} } else {
} if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) {
} else { /* NTP is selected */ reverse_best = true;
int best_track = -1;
uint reverse = 0;
uint best_bird_dist = 0;
uint best_track_dist = 0;
for (;;) {
fd.best_bird_dist = (uint)-1;
fd.best_track_dist = (uint)-1;
NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
if (best_track != -1) {
if (best_bird_dist != 0) {
if (fd.best_bird_dist != 0) {
/* neither reached the destination, pick the one with the smallest bird dist */
if (fd.best_bird_dist > best_bird_dist) goto bad;
if (fd.best_bird_dist < best_bird_dist) goto good;
} else {
/* we found the destination for the first time */
goto good;
}
} else { } else {
if (fd.best_bird_dist != 0) { reverse_best = false;
/* didn't find destination, but we've found the destination previously */
goto bad;
} else {
/* both old & new reached the destination, compare track length */
if (fd.best_track_dist > best_track_dist) goto bad;
if (fd.best_track_dist < best_track_dist) goto good;
}
} }
/* if we reach this position, there's two paths of equal value so far.
* pick one randomly. */
int r = GB(Random(), 0, 8);
if (_pick_track_table[i] == (v->direction & 3)) r += 80;
if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
if (r <= 127) goto bad;
} }
} break;
default:
case VPF_NTP: { /* NTP */
int best_track = -1;
uint reverse = 0;
uint best_bird_dist = 0;
uint best_track_dist = 0;
for (;;) {
fd.best_bird_dist = UINT_MAX;
fd.best_track_dist = UINT_MAX;
NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
if (best_track != -1) {
if (best_bird_dist != 0) {
if (fd.best_bird_dist != 0) {
/* neither reached the destination, pick the one with the smallest bird dist */
if (fd.best_bird_dist > best_bird_dist) goto bad;
if (fd.best_bird_dist < best_bird_dist) goto good;
} else {
/* we found the destination for the first time */
goto good;
}
} else {
if (fd.best_bird_dist != 0) {
/* didn't find destination, but we've found the destination previously */
goto bad;
} else {
/* both old & new reached the destination, compare track length */
if (fd.best_track_dist > best_track_dist) goto bad;
if (fd.best_track_dist < best_track_dist) goto good;
}
}
/* if we reach this position, there's two paths of equal value so far.
* pick one randomly. */
int r = GB(Random(), 0, 8);
if (_pick_track_table[i] == (v->direction & 3)) r += 80;
if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
if (r <= 127) goto bad;
}
good:; good:;
best_track = i; best_track = i;
best_bird_dist = fd.best_bird_dist; best_bird_dist = fd.best_bird_dist;
best_track_dist = fd.best_track_dist; best_track_dist = fd.best_track_dist;
reverse_best = reverse; reverse_best = reverse;
bad:; bad:;
if (reverse != 0) break; if (reverse != 0) break;
reverse = 2; reverse = 2;
} }
} break;
} }
return reverse_best != 0; return reverse_best != 0;
@ -3025,7 +3046,7 @@ static void TrainController(Vehicle *v, bool update_image)
* the signal status. */ * the signal status. */
uint32 tracks = ts | (ts >> 8); uint32 tracks = ts | (ts >> 8);
TrackBits bits = (TrackBits)(tracks & TRACK_BIT_MASK); TrackBits bits = (TrackBits)(tracks & TRACK_BIT_MASK);
if ((_patches.pathfinder_for_trains != VPF_NTP) && _patches.forbid_90_deg && prev == NULL) { if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) {
/* We allow wagons to make 90 deg turns, because forbid_90_deg /* We allow wagons to make 90 deg turns, because forbid_90_deg
* can be switched on halfway a turn */ * can be switched on halfway a turn */
bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
@ -3459,7 +3480,7 @@ static bool TrainCheckIfLineEnds(Vehicle *v)
/* mask unreachable track bits if we are forbidden to do 90deg turns */ /* mask unreachable track bits if we are forbidden to do 90deg turns */
TrackBits bits = (TrackBits)((ts | (ts >> 8)) & TRACK_BIT_MASK); TrackBits bits = (TrackBits)((ts | (ts >> 8)) & TRACK_BIT_MASK);
if ((_patches.pathfinder_for_trains != VPF_NTP) && _patches.forbid_90_deg) { if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) {
bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
} }