summaryrefslogtreecommitdiff
path: root/src/pathfinder
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2019-04-06 07:46:15 +0100
committerMichael Lutz <michi@icosahedron.de>2019-05-01 21:36:27 +0200
commitc02ef3e4564b7b54d49f0827d2d7625cbc38f335 (patch)
tree1c0ee62b6ce55124b247daaafa42300bfaa932e7 /src/pathfinder
parent21edf67f89c60351d5a0d84625455aa296b6b950 (diff)
downloadopenttd-c02ef3e4564b7b54d49f0827d2d7625cbc38f335.tar.xz
Feature: Add NotRoadTypes (NRT)
Diffstat (limited to 'src/pathfinder')
-rw-r--r--src/pathfinder/follow_track.hpp26
-rw-r--r--src/pathfinder/npf/npf.cpp50
-rw-r--r--src/pathfinder/yapf/yapf_costrail.hpp2
-rw-r--r--src/pathfinder/yapf/yapf_road.cpp8
4 files changed, 55 insertions, 31 deletions
diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp
index 999f7f94d..31a781650 100644
--- a/src/pathfinder/follow_track.hpp
+++ b/src/pathfinder/follow_track.hpp
@@ -32,7 +32,7 @@ struct CFollowTrackT
enum ErrorCode {
EC_NONE,
EC_OWNER,
- EC_RAIL_TYPE,
+ EC_RAIL_ROAD_TYPE,
EC_90DEG,
EC_NO_WAY,
EC_RESERVED,
@@ -60,6 +60,7 @@ struct CFollowTrackT
inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES, CPerformanceTimer *pPerf = nullptr)
{
+ assert(IsRailTT());
m_veh = nullptr;
Init(o, railtype_override, pPerf);
}
@@ -92,7 +93,7 @@ struct CFollowTrackT
inline static TransportType TT() { return Ttr_type_; }
inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
- inline bool IsTram() { return IsRoadTT() && HasBit(RoadVehicle::From(m_veh)->compatible_roadtypes, ROADTYPE_TRAM); }
+ inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(m_veh)->roadtype); }
inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
inline static bool Allow90degTurns() { return T90deg_turns_allowed_; }
inline static bool DoTrackMasking() { return Tmask_reserved_tracks; }
@@ -103,7 +104,7 @@ struct CFollowTrackT
assert(IsTram()); // this function shouldn't be called in other cases
if (IsNormalRoadTile(tile)) {
- RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
+ RoadBits rb = GetRoadBits(tile, RTT_TRAM);
switch (rb) {
case ROAD_NW: return DIAGDIR_NW;
case ROAD_SW: return DIAGDIR_SW;
@@ -126,7 +127,7 @@ struct CFollowTrackT
m_err = EC_NONE;
assert(
((TrackStatusToTrackdirBits(
- GetTileTrackStatus(m_old_tile, TT(), (IsRoadTT() && m_veh != nullptr) ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0)
+ GetTileTrackStatus(m_old_tile, TT(), (IsRoadTT() && m_veh != nullptr) ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0)
) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
(IsTram() && GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR) // Disable the assertion for single tram bits
);
@@ -151,7 +152,7 @@ struct CFollowTrackT
if (IsRoadTT() && !IsTram() && TryReverse()) return true;
/* CanEnterNewTile already set a reason.
- * Do NOT overwrite it (important for example for EC_RAIL_TYPE).
+ * Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
* Only set a reason if CanEnterNewTile was not called */
if (m_new_td_bits == TRACKDIR_BIT_NONE) m_err = EC_NO_WAY;
@@ -241,7 +242,7 @@ protected:
if (IsRailTT() && IsPlainRailTile(m_new_tile)) {
m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101);
} else {
- m_new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(m_new_tile, TT(), IsRoadTT() ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0));
+ m_new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(m_new_tile, TT(), IsRoadTT() ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0));
if (IsTram() && m_new_td_bits == TRACKDIR_BIT_NONE) {
/* GetTileTrackStatus() returns 0 for single tram bits.
@@ -350,7 +351,18 @@ protected:
RailType rail_type = GetTileRailType(m_new_tile);
if (!HasBit(m_railtypes, rail_type)) {
/* incompatible rail type */
- m_err = EC_RAIL_TYPE;
+ m_err = EC_RAIL_ROAD_TYPE;
+ return false;
+ }
+ }
+
+ /* road transport is possible only on compatible road types */
+ if (IsRoadTT()) {
+ const RoadVehicle *v = RoadVehicle::From(m_veh);
+ RoadType roadtype = GetRoadType(m_new_tile, GetRoadTramType(v->roadtype));
+ if (!HasBit(v->compatible_roadtypes, roadtype)) {
+ /* incompatible road type */
+ m_err = EC_RAIL_ROAD_TYPE;
return false;
}
}
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp
index 36f66b5a9..2cf333890 100644
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -43,6 +43,7 @@ struct AyStarUserData {
TransportType type;
RailTypes railtypes;
RoadTypes roadtypes;
+ uint subtype;
};
/** Indices into AyStarNode.userdata[] */
@@ -719,7 +720,7 @@ static DiagDirection GetDepotDirection(TileIndex tile, TransportType type)
static DiagDirection GetSingleTramBit(TileIndex tile)
{
if (IsNormalRoadTile(tile)) {
- RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
+ RoadBits rb = GetRoadBits(tile, RTT_TRAM);
switch (rb) {
case ROAD_NW: return DIAGDIR_NW;
case ROAD_SW: return DIAGDIR_SW;
@@ -747,7 +748,7 @@ static DiagDirection GetTileSingleEntry(TileIndex tile, TransportType type, uint
if (type == TRANSPORT_ROAD) {
if (IsStandardRoadStopTile(tile)) return GetRoadStopDir(tile);
- if (HasBit(subtype, ROADTYPE_TRAM)) return GetSingleTramBit(tile);
+ if ((RoadTramType)subtype == RTT_TRAM) return GetSingleTramBit(tile);
}
return INVALID_DIAGDIR;
@@ -785,13 +786,24 @@ static bool CanEnterTile(TileIndex tile, DiagDirection dir, AyStarUserData *user
if (!CanEnterTileOwnerCheck(user->owner, tile, dir)) return false;
/* check correct rail type (mono, maglev, etc) */
- if (user->type == TRANSPORT_RAIL) {
- RailType rail_type = GetTileRailType(tile);
- if (!HasBit(user->railtypes, rail_type)) return false;
+ switch (user->type) {
+ case TRANSPORT_RAIL: {
+ RailType rail_type = GetTileRailType(tile);
+ if (!HasBit(user->railtypes, rail_type)) return false;
+ break;
+ }
+
+ case TRANSPORT_ROAD: {
+ RoadType road_type = GetRoadType(tile, (RoadTramType)user->subtype);
+ if (!HasBit(user->roadtypes, road_type)) return false;
+ break;
+ }
+
+ default: break;
}
/* Depots, standard roadstops and single tram bits can only be entered from one direction */
- DiagDirection single_entry = GetTileSingleEntry(tile, user->type, user->roadtypes);
+ DiagDirection single_entry = GetTileSingleEntry(tile, user->type, user->subtype);
if (single_entry != INVALID_DIAGDIR && single_entry != ReverseDiagDir(dir)) return false;
return true;
@@ -813,7 +825,7 @@ static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, TileIndex src_t
{
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype));
- if (trackdirbits == TRACKDIR_BIT_NONE && type == TRANSPORT_ROAD && HasBit(subtype, ROADTYPE_TRAM)) {
+ if (trackdirbits == TRACKDIR_BIT_NONE && type == TRANSPORT_ROAD && (RoadTramType)subtype == RTT_TRAM) {
/* GetTileTrackStatus() returns 0 for single tram bits.
* As we cannot change it there (easily) without breaking something, change it here */
switch (GetSingleTramBit(dst_tile)) {
@@ -863,7 +875,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
/* Information about the vehicle: TransportType (road/rail/water) and SubType (compatible rail/road types) */
TransportType type = user->type;
- uint subtype = user->roadtypes;
+ uint subtype = user->subtype;
/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
aystar->num_neighbours = 0;
@@ -894,11 +906,11 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
/* We leave src_tile in src_exitdir and reach dst_tile */
dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(src_exitdir));
- if (dst_tile != INVALID_TILE && !CanEnterTile(dst_tile, src_exitdir, user)) dst_tile = INVALID_TILE;
+ if (dst_tile != INVALID_TILE && IsNormalRoadTile(dst_tile) && !CanEnterTile(dst_tile, src_exitdir, user)) dst_tile = INVALID_TILE;
if (dst_tile == INVALID_TILE) {
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
- if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return;
+ if (type != TRANSPORT_ROAD || (RoadTramType)subtype == RTT_TRAM) return;
dst_tile = src_tile;
src_trackdir = ReverseTrackdir(src_trackdir);
@@ -908,7 +920,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
if (trackdirbits == TRACKDIR_BIT_NONE) {
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
- if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return;
+ if (type != TRANSPORT_ROAD || (RoadTramType)subtype == RTT_TRAM) return;
dst_tile = src_tile;
src_trackdir = ReverseTrackdir(src_trackdir);
@@ -1120,7 +1132,7 @@ FindDepotData NPFRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_penal
{
Trackdir trackdir = v->GetVehicleTrackdir();
- AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes };
+ AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes, GetRoadTramType(v->roadtype) };
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, INVALID_TILE, INVALID_TRACKDIR, false, nullptr, &user, 0, max_penalty);
if (ftd.best_bird_dist != 0) return FindDepotData();
@@ -1140,7 +1152,7 @@ Trackdir NPFRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDir
NPFFillWithOrderData(&fstd, v);
Trackdir trackdir = DiagDirToDiagTrackdir(enterdir);
- AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes };
+ AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes, GetRoadTramType(v->roadtype) };
NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, &user);
assert(ftd.best_trackdir != INVALID_TRACKDIR);
@@ -1163,7 +1175,7 @@ Track NPFShipChooseTrack(const Ship *v, bool &path_found)
NPFFillWithOrderData(&fstd, v);
- AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE };
+ AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE, 0 };
NPFFoundTargetData ftd = NPFRouteToStationOrTile(v->tile, trackdir, true, &fstd, &user);
assert(ftd.best_trackdir != INVALID_TRACKDIR);
@@ -1188,7 +1200,7 @@ bool NPFShipCheckReverse(const Ship *v)
assert(trackdir != INVALID_TRACKDIR);
assert(trackdir_rev != INVALID_TRACKDIR);
- AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE };
+ AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE, 0 };
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, v->tile, trackdir_rev, false, &fstd, &user);
/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
@@ -1206,7 +1218,7 @@ FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_penalty)
fstd.reserve_path = false;
assert(trackdir != INVALID_TRACKDIR);
- AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE };
+ AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE, 0 };
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, &user, NPF_INFINITE_PENALTY, max_penalty);
if (ftd.best_bird_dist != 0) return FindDepotData();
@@ -1235,7 +1247,7 @@ bool NPFTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir trackd
/* perform a breadth first search. Target is nullptr,
* since we are just looking for any safe tile...*/
- AyStarUserData user = { v->owner, TRANSPORT_RAIL, railtypes, ROADTYPES_NONE };
+ AyStarUserData user = { v->owner, TRANSPORT_RAIL, railtypes, ROADTYPES_NONE, 0 };
return NPFRouteInternal(&start1, true, nullptr, false, &fstd, NPFFindSafeTile, NPFCalcZero, &user, 0, true).res_okay;
}
@@ -1252,7 +1264,7 @@ bool NPFTrainCheckReverse(const Train *v)
assert(trackdir != INVALID_TRACKDIR);
assert(trackdir_rev != INVALID_TRACKDIR);
- AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE };
+ AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE, 0 };
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, &user);
/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
@@ -1266,7 +1278,7 @@ Track NPFTrainChooseTrack(const Train *v, bool &path_found, bool reserve_track,
PBSTileInfo origin = FollowTrainReservation(v);
assert(IsValidTrackdir(origin.trackdir));
- AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE };
+ AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE, 0 };
NPFFoundTargetData ftd = NPFRouteToStationOrTile(origin.tile, origin.trackdir, true, &fstd, &user);
if (target != nullptr) {
diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp
index 6c1c3ca7a..9613fd079 100644
--- a/src/pathfinder/yapf/yapf_costrail.hpp
+++ b/src/pathfinder/yapf/yapf_costrail.hpp
@@ -496,7 +496,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
if (!tf_local.Follow(cur.tile, cur.td)) {
assert(tf_local.m_err != TrackFollower::EC_NONE);
/* Can't move to the next tile (EOL?). */
- if (tf_local.m_err == TrackFollower::EC_RAIL_TYPE) {
+ if (tf_local.m_err == TrackFollower::EC_RAIL_ROAD_TYPE) {
end_segment_reason |= ESRB_RAIL_TYPE;
} else {
end_segment_reason |= ESRB_DEAD_END;
diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp
index 9e206115f..3935ba18d 100644
--- a/src/pathfinder/yapf/yapf_road.cpp
+++ b/src/pathfinder/yapf/yapf_road.cpp
@@ -249,7 +249,7 @@ public:
} else {
m_dest_station = INVALID_STATION;
m_destTile = v->dest_tile;
- m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
+ m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype)));
}
}
@@ -367,7 +367,7 @@ public:
/* our source tile will be the next vehicle tile (should be the given one) */
TileIndex src_tile = tile;
/* get available trackdirs on the start tile */
- TrackdirBits src_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes));
+ TrackdirBits src_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype)));
/* select reachable trackdirs only */
src_trackdirs &= DiagdirReachesTrackdirs(enterdir);
@@ -449,7 +449,7 @@ public:
/* set origin (tile, trackdir) */
TileIndex src_tile = v->tile;
Trackdir src_td = v->GetVehicleTrackdir();
- if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->compatible_roadtypes)), src_td)) {
+ if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, this->IsTram() ? RTT_TRAM : RTT_ROAD)), src_td)) {
/* sometimes the roadveh is not on the road (it resides on non-existing track)
* how should we handle that situation? */
return false;
@@ -529,7 +529,7 @@ FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_dist
{
TileIndex tile = v->tile;
Trackdir trackdir = v->GetVehicleTrackdir();
- if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes)), trackdir)) {
+ if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype))), trackdir)) {
return FindDepotData();
}