1
0
Fork 0

(svn r4919) - Backport from trunk (r4812, r4008, r4110):

NTP properly checks for railtypes on non-plain-rail-tiles
release/0.4
Darkvater 2006-05-20 15:54:46 +00:00
parent 0f012198c4
commit f6e8773297
6 changed files with 57 additions and 31 deletions

24
npf.c
View File

@ -576,7 +576,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
/* check correct rail type (mono, maglev, etc) */
if (type == TRANSPORT_RAIL) {
RailType dst_type = GetTileRailType(dst_tile, src_trackdir);
if (!IsCompatibleRail(aystar->user_data[NPF_RAILTYPE], dst_type))
if (!HASBIT(aystar->user_data[NPF_RAILTYPES], dst_type))
return;
}
@ -649,7 +649,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
* multiple targets that are spread around, we should perform a breadth first
* search by specifiying CalcZero as our heuristic.
*/
static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailType railtype, uint reverse_penalty)
static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, byte railtypes, uint reverse_penalty)
{
int r;
NPFFoundTargetData result;
@ -691,7 +691,7 @@ static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start
/* Initialize user_data */
_npf_aystar.user_data[NPF_TYPE] = type;
_npf_aystar.user_data[NPF_OWNER] = owner;
_npf_aystar.user_data[NPF_RAILTYPE] = railtype;
_npf_aystar.user_data[NPF_RAILTYPES] = railtypes;
/* GO! */
r = AyStarMain_Main(&_npf_aystar);
@ -709,7 +709,7 @@ static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start
return result;
}
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype)
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes)
{
AyStarNode start1;
AyStarNode start2;
@ -723,15 +723,15 @@ NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir track
start2.direction = trackdir2;
start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtype, 0);
return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtypes, 0);
}
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype)
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes)
{
return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtype);
return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtypes);
}
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty)
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, byte railtypes, uint reverse_penalty)
{
AyStarNode start1;
AyStarNode start2;
@ -747,15 +747,15 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir t
/* perform a breadth first search. Target is NULL,
* since we are just looking for any depot...*/
return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtype, reverse_penalty);
return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtypes, reverse_penalty);
}
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype)
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes)
{
return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtype, 0);
return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtypes, 0);
}
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype)
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes)
{
/* Okay, what we're gonna do. First, we look at all depots, calculate
* the manhatten distance to get to each depot. We then sort them by

12
npf.h
View File

@ -37,7 +37,7 @@ typedef struct NPFFindStationOrTileData { /* Meant to be stored in AyStar.target
enum { /* Indices into AyStar.userdata[] */
NPF_TYPE = 0, /* Contains a TransportTypes value */
NPF_OWNER, /* Contains an Owner value */
NPF_RAILTYPE, /* Contains the RailType value of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise. */
NPF_RAILTYPES, /* Contains a bitmask the compatible RailTypes of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise. */
};
enum { /* Indices into AyStarNode.userdata[] */
@ -63,27 +63,27 @@ typedef struct NPFFoundTargetData { /* Meant to be stored in AyStar.userpath */
/* Will search from the given tile and direction, for a route to the given
* station for the given transport type. See the declaration of
* NPFFoundTargetData above for the meaning of the result. */
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype);
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes);
/* Will search as above, but with two start nodes, the second being the
* reverse. Look at the NPF_FLAG_REVERSE flag in the result node to see which
* direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype);
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes);
/* Will search a route to the closest depot. */
/* Search using breadth first. Good for little track choice and inaccurate
* heuristic, such as railway/road.*/
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype);
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes);
/* Same as above but with two start nodes, the second being the reverse. Call
* NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
* orginated. All pathfs from the second node will have the given
* reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
* tile).
*/
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty);
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, byte railtypes, uint reverse_penalty);
/* Search by trying each depot in order of Manhattan Distance. Good for lots
* of choices and accurate heuristics, such as water. */
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype);
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes);
void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);

View File

@ -5,8 +5,8 @@
#include "functions.h"
#include "map.h"
#include "tile.h"
#include "pathfind.h"
#include "rail.h"
#include "pathfind.h"
#include "debug.h"
#include "variables.h"
#include "depot.h"
@ -442,7 +442,8 @@ typedef struct {
void *userdata;
TileIndex dest;
byte tracktype;
TransportType tracktype;
byte railtypes;
uint maxlength;
HashLink *new_link;
@ -728,6 +729,11 @@ start_at:
/* We are not driving into the tunnel, or it
* is an invalid tunnel */
continue;
if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
bits = 0;
break;
}
flotr = FindLengthOfTunnel(tile, direction);
si.cur_length += flotr.length * DIAG_FACTOR;
tile = flotr.tile;
@ -760,6 +766,12 @@ start_at:
// Check that the tile contains exactly one track
if (bits == 0 || KILL_FIRST_BIT(bits) != 0) break;
if ((IsTileType(tile, MP_STREET) && !HASBIT(tpf->railtypes, GB(_m[tile].m4, 0, 4))) ||
!HASBIT(tpf->railtypes, GetRailType(tile))) {
bits = 0;
break;
}
///////////////////
// If we reach here, the tile has exactly one track.
// tile - index to a tile that is not rail tile, but still straight (with optional signals)
@ -781,6 +793,11 @@ start_at:
* bits, not just reachable ones, to prevent infinite loops. */
if (bits == 0 || TracksOverlap(allbits)) break;
if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
bits = 0;
break;
}
/* If we reach here, the tile has exactly one track, and this
track is reachable => Rail segment continues */
@ -916,14 +933,15 @@ start_at:
// new pathfinder for trains. better and faster.
void NewTrainPathfind(TileIndex tile, TileIndex dest, byte direction, NTPEnumProc *enum_proc, void *data)
void NewTrainPathfind(TileIndex tile, TileIndex dest, byte railtypes, byte direction, NTPEnumProc *enum_proc, void *data)
{
NewTrackPathFinder tpf;
tpf.dest = dest;
tpf.userdata = data;
tpf.enum_proc = enum_proc;
tpf.tracktype = 0;
tpf.tracktype = TRANSPORT_RAIL;
tpf.railtypes = railtypes;
tpf.maxlength = min(_patches.pf_maxlength * 3, 10000);
tpf.nstack = 0;
tpf.new_link = tpf.links;

View File

@ -66,6 +66,6 @@ typedef struct {
} FindLengthOfTunnelResult;
FindLengthOfTunnelResult FindLengthOfTunnel(TileIndex tile, uint direction);
void NewTrainPathfind(TileIndex tile, TileIndex dest, byte direction, NTPEnumProc *enum_proc, void *data);
void NewTrainPathfind(TileIndex tile, TileIndex dest, byte railtypes, byte direction, NTPEnumProc *enum_proc, void *data);
#endif /* PATHFIND_H */

View File

@ -88,6 +88,7 @@ void TrainConsistChanged(Vehicle* v)
rvi_v = RailVehInfo(v->engine_type);
first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_VEHICLE;
v->u.rail.cached_total_length = 0;
v->u.rail.compatible_railtypes = 0;
for (u = v; u != NULL; u = u->next) {
const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
@ -98,6 +99,7 @@ void TrainConsistChanged(Vehicle* v)
// update the 'first engine'
u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine;
u->u.rail.railtype = GetEngine(u->engine_type)->railtype;
if (rvi_u->visual_effect != 0) {
u->u.rail.cached_vis_effect = rvi_u->visual_effect;
@ -135,6 +137,11 @@ void TrainConsistChanged(Vehicle* v)
}
}
/* Do not count powered wagons for the compatible railtypes, as
* wagons always have railtype normal */
if (rvi_u->power > 0)
v->u.rail.compatible_railtypes |= GetRailTypeInfo(u->u.rail.railtype)->compatible_railtypes;
// max speed is the minimum of the speed limits of all vehicles in the consist
if (!(rvi_u->flags & RVI_WAGON) || _patches.wagon_speed_limits)
if (rvi_u->max_speed != 0 && !UsesWagonOverride(u))
@ -1793,7 +1800,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
assert (trackdir != INVALID_TRACKDIR);
ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, NPF_INFINITE_PENALTY);
ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
if (ftd.best_bird_dist == 0) {
/* Found target */
tfdd.tile = ftd.node.tile;
@ -1809,13 +1816,13 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
// search in the forward direction first.
i = v->direction >> 1;
if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) i = (i - 1) & 3;
NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
if (tfdd.best_length == (uint)-1){
tfdd.reverse = true;
// search in backwards direction
i = (v->direction^4) >> 1;
if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) i = (i - 1) & 3;
NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
}
}
@ -2137,7 +2144,7 @@ static byte ChooseTrainTrack(Vehicle *v, TileIndex tile, int enterdir, TrackdirB
trackdir = GetVehicleTrackdir(v);
assert(trackdir != 0xff);
ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype);
ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
if (ftd.best_trackdir == 0xff) {
/* We are already at our target. Just do something */
@ -2161,7 +2168,7 @@ static byte ChooseTrainTrack(Vehicle *v, TileIndex tile, int enterdir, TrackdirB
fd.best_track = 0xFF;
NewTrainPathfind(tile - TileOffsByDir(enterdir), v->dest_tile,
enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
if (fd.best_track == 0xff) {
// blaha
@ -2217,7 +2224,7 @@ static bool CheckReverseTrain(Vehicle *v)
assert(trackdir != 0xff);
assert(trackdir_rev != 0xff);
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype);
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
if (ftd.best_bird_dist != 0) {
/* We didn't find anything, just keep on going straight ahead */
reverse_best = false;
@ -2232,7 +2239,7 @@ static bool CheckReverseTrain(Vehicle *v)
fd.best_bird_dist = (uint)-1;
fd.best_track_dist = (uint)-1;
NewTrainPathfind(v->tile, v->dest_tile, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd);
NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd);
if (best_track != -1) {
if (best_bird_dist != 0) {
@ -2601,7 +2608,7 @@ static bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
return
IsTileOwner(tile, v->owner) && (
!IsFrontEngine(v) ||
IsCompatibleRail(v->u.rail.railtype, GetRailType(tile))
HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile))
);
}

View File

@ -71,6 +71,7 @@ typedef struct VehicleRail {
byte track;
byte force_proceed;
byte railtype;
byte compatible_railtypes;
byte flags;