mirror of https://github.com/OpenTTD/OpenTTD
(svn r4919) - Backport from trunk (r4812, r4008, r4110):
NTP properly checks for railtypes on non-plain-rail-tilesrelease/0.4
parent
0f012198c4
commit
f6e8773297
24
npf.c
24
npf.c
|
@ -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
12
npf.h
|
@ -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);
|
||||
|
||||
|
|
26
pathfind.c
26
pathfind.c
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
23
train_cmd.c
23
train_cmd.c
|
@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue