Last active
August 12, 2018 10:32
-
-
Save michicc/8d16426de023d015ce4f16d85d77a606 to your computer and use it in GitHub Desktop.
Railtype flag for 90 deg curves.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 58b42eaa40c6ec8a242ba64054f50c31d62a9e3e Mon Sep 17 00:00:00 2001 | |
From: Michael Lutz <michi@icosahedron.de> | |
Date: Sat, 28 Jul 2018 18:07:41 +0200 | |
Subject: Feature: Railtype flags to allow/disallow 90 degree curves. | |
--- | |
src/pathfinder/follow_track.hpp | 2 +- | |
src/pathfinder/npf/npf.cpp | 14 +++++++++----- | |
src/pbs.cpp | 4 ++-- | |
src/rail.h | 25 +++++++++++++++++++++++++ | |
src/train_cmd.cpp | 14 +++++++------- | |
5 files changed, 44 insertions(+), 15 deletions(-) | |
diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp | |
index 70f148de3..fd431a49b 100644 | |
--- a/src/pathfinder/follow_track.hpp | |
+++ b/src/pathfinder/follow_track.hpp | |
@@ -153,7 +153,7 @@ struct CFollowTrackT | |
return false; | |
} | |
- if (!Allow90degTurns()) { | |
+ if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(m_old_tile), GetTileRailType(m_new_tile), !Allow90degTurns()))) { | |
m_new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(m_old_td); | |
if (m_new_td_bits == TRACKDIR_BIT_NONE) { | |
m_err = EC_90DEG; | |
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp | |
index 3218d8314..211a1f7b7 100644 | |
--- a/src/pathfinder/npf/npf.cpp | |
+++ b/src/pathfinder/npf/npf.cpp | |
@@ -798,12 +798,13 @@ static bool CanEnterTile(TileIndex tile, DiagDirection dir, AyStarUserData *user | |
* One-way-roads are taken into account. Signals are not tested. | |
* | |
* @param dst_tile The tile of interest. | |
+ * @param src_tile The originating tile. | |
* @param src_trackdir The direction the vehicle is currently moving. | |
* @param type The transporttype of the vehicle. | |
* @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle. | |
* @return The Trackdirs the vehicle can continue moving on. | |
*/ | |
-static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_trackdir, TransportType type, uint subtype) | |
+static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, TileIndex src_tile, Trackdir src_trackdir, TransportType type, uint subtype) | |
{ | |
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype)); | |
@@ -831,7 +832,10 @@ static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_tr | |
trackdirbits &= TrackdirReachesTrackdirs(src_trackdir); | |
/* Filter out trackdirs that would make 90 deg turns for trains */ | |
- if (_settings_game.pf.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir); | |
+ if ((type == TRANSPORT_WATER && _settings_game.pf.forbid_90_deg) || | |
+ (type == TRANSPORT_RAIL && Rail90DegTurnDisallowed(GetTileRailType(src_tile), GetTileRailType(dst_tile)))) { | |
+ trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir); | |
+ } | |
DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits); | |
@@ -874,7 +878,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) | |
if (ignore_src_tile) { | |
/* Do not perform any checks that involve src_tile */ | |
dst_tile = src_tile + TileOffsByDiagDir(src_exitdir); | |
- trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); | |
+ trackdirbits = GetDriveableTrackdirBits(dst_tile, src_tile, src_trackdir, type, subtype); | |
} else if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(src_tile) == src_exitdir) { | |
/* We drive through the wormhole and arrive on the other side */ | |
dst_tile = GetOtherTunnelBridgeEnd(src_tile); | |
@@ -898,7 +902,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) | |
src_trackdir = ReverseTrackdir(src_trackdir); | |
} | |
- trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); | |
+ trackdirbits = GetDriveableTrackdirBits(dst_tile, src_tile, src_trackdir, type, subtype); | |
if (trackdirbits == TRACKDIR_BIT_NONE) { | |
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */ | |
@@ -907,7 +911,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) | |
dst_tile = src_tile; | |
src_trackdir = ReverseTrackdir(src_trackdir); | |
- trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); | |
+ trackdirbits = GetDriveableTrackdirBits(dst_tile, src_tile, src_trackdir, type, subtype); | |
} | |
} | |
diff --git a/src/pbs.cpp b/src/pbs.cpp | |
index 6bb35a696..44b5b069b 100644 | |
--- a/src/pbs.cpp | |
+++ b/src/pbs.cpp | |
@@ -400,7 +400,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo | |
/* Check for reachable tracks. */ | |
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir); | |
- if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir); | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile), forbid_90deg)) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir); | |
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) return include_line_end; | |
if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) { | |
@@ -445,7 +445,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo | |
/* Check for reachable tracks. */ | |
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir); | |
- if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir); | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile), forbid_90deg)) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir); | |
return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits)); | |
} | |
diff --git a/src/rail.h b/src/rail.h | |
index 1bc403d7f..245ba67c4 100644 | |
--- a/src/rail.h | |
+++ b/src/rail.h | |
@@ -21,15 +21,20 @@ | |
#include "strings_type.h" | |
#include "date_type.h" | |
#include "signal_type.h" | |
+#include "settings_type.h" | |
/** Railtype flags. */ | |
enum RailTypeFlags { | |
RTF_CATENARY = 0, ///< Bit number for drawing a catenary. | |
RTF_NO_LEVEL_CROSSING = 1, ///< Bit number for disallowing level crossings. | |
+ RTF_ALLOW_90DEG = 2, ///< Bit number for always allowed 90 degree turns, regardless of setting. | |
+ RTF_DISALLOW_90DEG = 3, ///< Bit number for always disallowed 90 degree turns, regardless of setting. | |
RTFB_NONE = 0, ///< All flags cleared. | |
RTFB_CATENARY = 1 << RTF_CATENARY, ///< Value for drawing a catenary. | |
RTFB_NO_LEVEL_CROSSING = 1 << RTF_NO_LEVEL_CROSSING, ///< Value for disallowing level crossings. | |
+ RTFB_ALLOW_90DEG = 1 << RTF_ALLOW_90DEG, ///< Value for always allowed 90 degree turns, regardless of setting. | |
+ RTFB_DISALLOW_90DEG = 1 << RTF_DISALLOW_90DEG, ///< Value for always allowed 90 degree turns, regardless of setting. | |
}; | |
DECLARE_ENUM_AS_BIT_SET(RailTypeFlags) | |
@@ -336,6 +341,26 @@ static inline bool RailNoLevelCrossings(RailType rt) | |
return HasBit(GetRailTypeInfo(rt)->flags, RTF_NO_LEVEL_CROSSING); | |
} | |
+/** | |
+ * Test if 90 degree turns are allowed between two railtypes. | |
+ * @param rt1 First railtype to test for. | |
+ * @param rt2 Second railtype to test for. | |
+ * @param def Default value to use if the rail type doesn't specify anything. | |
+ * @return True if 90 degree turns are allowed between the two rail types. | |
+ */ | |
+static inline bool Rail90DegTurnDisallowed(RailType rt1, RailType rt2, bool def = _settings_game.pf.forbid_90_deg) | |
+{ | |
+ if (rt1 == INVALID_RAILTYPE || rt2 == INVALID_RAILTYPE) return def; | |
+ | |
+ const RailtypeInfo *rti1 = GetRailTypeInfo(rt1); | |
+ const RailtypeInfo *rti2 = GetRailTypeInfo(rt2); | |
+ | |
+ bool rt1_90deg = HasBit(rti1->flags, RTF_DISALLOW_90DEG) || (!HasBit(rti1->flags, RTF_ALLOW_90DEG) && def); | |
+ bool rt2_90deg = HasBit(rti2->flags, RTF_DISALLOW_90DEG) || (!HasBit(rti2->flags, RTF_ALLOW_90DEG) && def); | |
+ | |
+ return rt1_90deg || rt2_90deg; | |
+} | |
+ | |
/** | |
* Returns the cost of building the specified railtype. | |
* @param railtype The railtype being built. | |
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp | |
index 60a7b2ca9..8bb146e2c 100644 | |
--- a/src/train_cmd.cpp | |
+++ b/src/train_cmd.cpp | |
@@ -2100,7 +2100,7 @@ static void CheckNextTrainTile(Train *v) | |
if (HasPbsSignalOnTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) { | |
/* If the next tile is a PBS signal, try to make a reservation. */ | |
TrackBits tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits); | |
- if (_settings_game.pf.forbid_90_deg) { | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) { | |
tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.m_old_td)); | |
} | |
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, NULL, false); | |
@@ -2341,7 +2341,7 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, | |
if (HasOnewaySignalBlockingTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) break; | |
} | |
- if (_settings_game.pf.forbid_90_deg) { | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) { | |
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td); | |
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) break; | |
} | |
@@ -2393,7 +2393,7 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, | |
while (tile != stopped || cur_td != stopped_td) { | |
if (!ft.Follow(tile, cur_td)) break; | |
- if (_settings_game.pf.forbid_90_deg) { | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) { | |
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td); | |
assert(ft.m_new_td_bits != TRACKDIR_BIT_NONE); | |
} | |
@@ -2628,7 +2628,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, | |
DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir); | |
TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir); | |
TrackBits reachable = TrackdirBitsToTrackBits((TrackdirBits)(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0))) & DiagdirReachesTracks(exitdir); | |
- if (_settings_game.pf.forbid_90_deg) { | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(res_dest.tile), GetTileRailType(next_tile))) { | |
reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir)); | |
} | |
@@ -2720,7 +2720,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay) | |
TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir); | |
TrackBits reachable = TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(GetTileTrackStatus(new_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTrackdirs(exitdir)); | |
- if (_settings_game.pf.forbid_90_deg) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir)); | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir)); | |
bool res_made = false; | |
ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck); | |
@@ -3141,7 +3141,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) | |
TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs); | |
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); | |
- if (_settings_game.pf.forbid_90_deg && prev == NULL) { | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(gp.old_tile), GetTileRailType(gp.new_tile)) && prev == NULL) { | |
/* We allow wagons to make 90 deg turns, because forbid_90_deg | |
* can be switched on halfway a turn */ | |
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track)); | |
@@ -3713,7 +3713,7 @@ static bool TrainCheckIfLineEnds(Train *v, bool reverse) | |
/* mask unreachable track bits if we are forbidden to do 90deg turns */ | |
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); | |
- if (_settings_game.pf.forbid_90_deg) { | |
+ if (Rail90DegTurnDisallowed(GetTileRailType(v->tile), GetTileRailType(tile))) { | |
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track)); | |
} | |
-- | |
2.17.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tried this, but generated s crash when a train was leaving the station. I sent the crash report to @michicc
-Snail