Changeset - r23440:7b9a736249f0
[Not reviewed]
master
0 5 0
Michael Lutz - 5 years ago 2019-03-10 08:12:47
michi@icosahedron.de
Feature: Railtype flags to allow/disallow 90 degree curves. (#7352)
5 files changed with 43 insertions and 15 deletions:
0 comments (0 inline, 0 general)
src/pathfinder/follow_track.hpp
Show inline comments
 
@@ -157,7 +157,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;
src/pathfinder/npf/npf.cpp
Show inline comments
 
@@ -803,12 +803,13 @@ static bool CanEnterTile(TileIndex tile,
 
 * 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));
 

	
 
@@ -836,7 +837,9 @@ static TrackdirBits GetDriveableTrackdir
 
	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) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
 
	if (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);
 

	
 
@@ -877,7 +880,7 @@ static void NPFFollowTrack(AyStar *aysta
 
	if (CheckIgnoreFirstTile(&current->path)) {
 
		/* 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);
 
@@ -901,7 +904,7 @@ static void NPFFollowTrack(AyStar *aysta
 
			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 */
 
@@ -910,7 +913,7 @@ static void NPFFollowTrack(AyStar *aysta
 
			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);
 
		}
 
	}
 

	
src/pbs.cpp
Show inline comments
 
@@ -400,7 +400,7 @@ bool IsSafeWaitingPosition(const Train *
 

	
 
	/* 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 *
 

	
 
	/* 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));
 
}
src/rail.h
Show inline comments
 
@@ -21,6 +21,7 @@
 
#include "strings_type.h"
 
#include "date_type.h"
 
#include "signal_type.h"
 
#include "settings_type.h"
 

	
 
/** Railtype flags. */
 
enum RailTypeFlags {
 
@@ -28,12 +29,16 @@ enum RailTypeFlags {
 
	RTF_NO_LEVEL_CROSSING = 1,                           ///< Bit number for disallowing level crossings.
 
	RTF_HIDDEN            = 2,                           ///< Bit number for hiding from selection.
 
	RTF_NO_SPRITE_COMBINE = 3,                           ///< Bit number for using non-combined junctions.
 
	RTF_ALLOW_90DEG       = 4,                           ///< Bit number for always allowed 90 degree turns, regardless of setting.
 
	RTF_DISALLOW_90DEG    = 5,                           ///< Bit number for never allowed 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_HIDDEN            = 1 << RTF_HIDDEN,            ///< Value for hiding from selection.
 
	RTFB_NO_SPRITE_COMBINE = 1 << RTF_NO_SPRITE_COMBINE, ///< Value for using non-combined junctions.
 
	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 never allowed 90 degree turns, regardless of setting.
 
};
 
DECLARE_ENUM_AS_BIT_SET(RailTypeFlags)
 

	
 
@@ -342,6 +347,26 @@ static inline bool RailNoLevelCrossings(
 
}
 

	
 
/**
 
 * Test if 90 degree turns are disallowed 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 disallowed 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.
 
 * @return The cost multiplier.
src/train_cmd.cpp
Show inline comments
 
@@ -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);
 
@@ -2339,7 +2339,7 @@ static PBSTileInfo ExtendTrainReservatio
 
			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;
 
		}
 
@@ -2391,7 +2391,7 @@ static PBSTileInfo ExtendTrainReservatio
 
	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);
 
		}
 
@@ -2626,7 +2626,7 @@ static Track ChooseTrainTrack(Train *v, 
 
		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));
 
		}
 

	
 
@@ -2718,7 +2718,7 @@ bool TryPathReserve(Train *v, bool mark_
 
	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);
 
@@ -3139,7 +3139,7 @@ bool TrainController(Train *v, Vehicle *
 
				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));
 
@@ -3711,7 +3711,7 @@ static bool TrainCheckIfLineEnds(Train *
 

	
 
	/* 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));
 
	}
 

	
0 comments (0 inline, 0 general)