mirror of https://github.com/OpenTTD/OpenTTD
(svn r18535) -Fix [FS#2722]: don't account for path reservation costs when entering a signal block via a 'block' signal. This way you won't get double penalties, both red signals and reservation costs, for the block signalled tracks
parent
f051ef01e3
commit
c5159055e3
|
@ -66,6 +66,7 @@ enum NPFNodeFlag {
|
||||||
NPF_FLAG_3RD_SIGNAL, ///< Used to mark that three signals were seen, rail only
|
NPF_FLAG_3RD_SIGNAL, ///< Used to mark that three signals were seen, rail only
|
||||||
NPF_FLAG_REVERSE, ///< Used to mark that this node was reached from the second start node, if applicable
|
NPF_FLAG_REVERSE, ///< Used to mark that this node was reached from the second start node, if applicable
|
||||||
NPF_FLAG_LAST_SIGNAL_RED, ///< Used to mark that the last signal on this path was red
|
NPF_FLAG_LAST_SIGNAL_RED, ///< Used to mark that the last signal on this path was red
|
||||||
|
NPF_FLAG_LAST_SIGNAL_BLOCK, ///< Used to mark that the last signal on this path was a block signal
|
||||||
NPF_FLAG_IGNORE_START_TILE, ///< Used to mark that the start tile is invalid, and searching should start from the second tile on
|
NPF_FLAG_IGNORE_START_TILE, ///< Used to mark that the start tile is invalid, and searching should start from the second tile on
|
||||||
NPF_FLAG_TARGET_RESERVED, ///< Used to mark that the possible reservation target is already reserved
|
NPF_FLAG_TARGET_RESERVED, ///< Used to mark that the possible reservation target is already reserved
|
||||||
NPF_FLAG_IGNORE_RESERVED, ///< Used to mark that reserved tiles should be considered impassable
|
NPF_FLAG_IGNORE_RESERVED, ///< Used to mark that reserved tiles should be considered impassable
|
||||||
|
@ -272,7 +273,7 @@ static uint NPFReservedTrackCost(AyStarNode *current)
|
||||||
TrackBits track = TrackToTrackBits(TrackdirToTrack(current->direction));
|
TrackBits track = TrackToTrackBits(TrackdirToTrack(current->direction));
|
||||||
TrackBits res = GetReservedTrackbits(tile);
|
TrackBits res = GetReservedTrackbits(tile);
|
||||||
|
|
||||||
if (NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL) || ((res & track) == TRACK_BIT_NONE && !TracksOverlap(res | track))) return 0;
|
if (NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL) || NPFGetFlag(current, NPF_FLAG_LAST_SIGNAL_BLOCK) || ((res & track) == TRACK_BIT_NONE && !TracksOverlap(res | track))) return 0;
|
||||||
|
|
||||||
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
||||||
DiagDirection exitdir = TrackdirToExitdir(current->direction);
|
DiagDirection exitdir = TrackdirToExitdir(current->direction);
|
||||||
|
@ -463,6 +464,7 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
|
||||||
/* Check for signals */
|
/* Check for signals */
|
||||||
if (IsTileType(tile, MP_RAILWAY)) {
|
if (IsTileType(tile, MP_RAILWAY)) {
|
||||||
if (HasSignalOnTrackdir(tile, trackdir)) {
|
if (HasSignalOnTrackdir(tile, trackdir)) {
|
||||||
|
SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir));
|
||||||
/* Ordinary track with signals */
|
/* Ordinary track with signals */
|
||||||
if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_RED) {
|
if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_RED) {
|
||||||
/* Signal facing us is red */
|
/* Signal facing us is red */
|
||||||
|
@ -471,7 +473,6 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
|
||||||
* encounter, if it is red */
|
* encounter, if it is red */
|
||||||
|
|
||||||
/* Is this a presignal exit or combo? */
|
/* Is this a presignal exit or combo? */
|
||||||
SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir));
|
|
||||||
if (!IsPbsSignal(sigtype)) {
|
if (!IsPbsSignal(sigtype)) {
|
||||||
if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) {
|
if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) {
|
||||||
/* Penalise exit and combo signals differently (heavier) */
|
/* Penalise exit and combo signals differently (heavier) */
|
||||||
|
@ -496,6 +497,7 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
|
||||||
} else {
|
} else {
|
||||||
NPFSetFlag(current, NPF_FLAG_SEEN_SIGNAL, true);
|
NPFSetFlag(current, NPF_FLAG_SEEN_SIGNAL, true);
|
||||||
}
|
}
|
||||||
|
NPFSetFlag(current, NPF_FLAG_LAST_SIGNAL_BLOCK, !IsPbsSignal(sigtype));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasPbsSignalOnTrackdir(tile, ReverseTrackdir(trackdir)) && !NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL)) {
|
if (HasPbsSignalOnTrackdir(tile, ReverseTrackdir(trackdir)) && !NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL)) {
|
||||||
|
|
|
@ -169,6 +169,7 @@ public:
|
||||||
FORCEINLINE int ReservationCost(Node& n, TileIndex tile, Trackdir trackdir, int skipped)
|
FORCEINLINE int ReservationCost(Node& n, TileIndex tile, Trackdir trackdir, int skipped)
|
||||||
{
|
{
|
||||||
if (n.m_num_signals_passed >= m_sig_look_ahead_costs.Size() / 2) return 0;
|
if (n.m_num_signals_passed >= m_sig_look_ahead_costs.Size() / 2) return 0;
|
||||||
|
if (!IsPbsSignal(n.m_last_signal_type)) return 0;
|
||||||
|
|
||||||
if (IsRailStationTile(tile) && IsAnyStationTileReserved(tile, trackdir, skipped)) {
|
if (IsRailStationTile(tile) && IsAnyStationTileReserved(tile, trackdir, skipped)) {
|
||||||
return Yapf().PfGetSettings().rail_pbs_station_penalty * (skipped + 1);
|
return Yapf().PfGetSettings().rail_pbs_station_penalty * (skipped + 1);
|
||||||
|
@ -194,6 +195,10 @@ public:
|
||||||
} else {
|
} else {
|
||||||
if (has_signal_along) {
|
if (has_signal_along) {
|
||||||
SignalState sig_state = GetSignalStateByTrackdir(tile, trackdir);
|
SignalState sig_state = GetSignalStateByTrackdir(tile, trackdir);
|
||||||
|
SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir));
|
||||||
|
|
||||||
|
n.m_last_signal_type = sig_type;
|
||||||
|
|
||||||
/* cache the look-ahead polynomial constant only if we didn't pass more signals than the look-ahead limit is */
|
/* cache the look-ahead polynomial constant only if we didn't pass more signals than the look-ahead limit is */
|
||||||
int look_ahead_cost = (n.m_num_signals_passed < m_sig_look_ahead_costs.Size()) ? m_sig_look_ahead_costs.Data()[n.m_num_signals_passed] : 0;
|
int look_ahead_cost = (n.m_num_signals_passed < m_sig_look_ahead_costs.Size()) ? m_sig_look_ahead_costs.Data()[n.m_num_signals_passed] : 0;
|
||||||
if (sig_state != SIGNAL_STATE_RED) {
|
if (sig_state != SIGNAL_STATE_RED) {
|
||||||
|
@ -205,7 +210,6 @@ public:
|
||||||
cost -= look_ahead_cost;
|
cost -= look_ahead_cost;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir));
|
|
||||||
/* we have a red signal in our direction
|
/* we have a red signal in our direction
|
||||||
* was it first signal which is two-way? */
|
* was it first signal which is two-way? */
|
||||||
if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) {
|
if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) {
|
||||||
|
@ -389,11 +393,12 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
||||||
/* Slope cost. */
|
/* Slope cost. */
|
||||||
segment_cost += Yapf().SlopeCost(cur.tile, cur.td);
|
segment_cost += Yapf().SlopeCost(cur.tile, cur.td);
|
||||||
|
|
||||||
|
/* Signal cost (routine can modify segment data). */
|
||||||
|
segment_cost += Yapf().SignalCost(n, cur.tile, cur.td);
|
||||||
|
|
||||||
/* Reserved tiles. */
|
/* Reserved tiles. */
|
||||||
segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, tf->m_tiles_skipped);
|
segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, tf->m_tiles_skipped);
|
||||||
|
|
||||||
/* Signal cost (routine can modify segment data). */
|
|
||||||
segment_cost += Yapf().SignalCost(n, cur.tile, cur.td);
|
|
||||||
end_segment_reason = segment.m_end_segment_reason;
|
end_segment_reason = segment.m_end_segment_reason;
|
||||||
|
|
||||||
/* Tests for 'potential target' reasons to close the segment. */
|
/* Tests for 'potential target' reasons to close the segment. */
|
||||||
|
|
|
@ -206,6 +206,7 @@ struct CYapfRailNodeT
|
||||||
} flags_s;
|
} flags_s;
|
||||||
} flags_u;
|
} flags_u;
|
||||||
SignalType m_last_red_signal_type;
|
SignalType m_last_red_signal_type;
|
||||||
|
SignalType m_last_signal_type;
|
||||||
|
|
||||||
FORCEINLINE void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
|
FORCEINLINE void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
|
||||||
{
|
{
|
||||||
|
@ -215,10 +216,22 @@ struct CYapfRailNodeT
|
||||||
m_num_signals_passed = 0;
|
m_num_signals_passed = 0;
|
||||||
flags_u.m_inherited_flags = 0;
|
flags_u.m_inherited_flags = 0;
|
||||||
m_last_red_signal_type = SIGTYPE_NORMAL;
|
m_last_red_signal_type = SIGTYPE_NORMAL;
|
||||||
|
/* We use PBS as initial signal type because if we are in
|
||||||
|
* a PBS section and need to route, i.e. we're at a safe
|
||||||
|
* waiting point of a station, we need to account for the
|
||||||
|
* reservation costs. If we are in a normal block then we
|
||||||
|
* should be alone in there and as such the reservation
|
||||||
|
* costs should be 0 anyway. If there would be another
|
||||||
|
* train in the block, i.e. passing signals at danger
|
||||||
|
* then avoiding that train with help of the reservation
|
||||||
|
* costs is not a bad thing, actually it would probably
|
||||||
|
* be a good thing to do. */
|
||||||
|
m_last_signal_type = SIGTYPE_PBS;
|
||||||
} else {
|
} else {
|
||||||
m_num_signals_passed = parent->m_num_signals_passed;
|
m_num_signals_passed = parent->m_num_signals_passed;
|
||||||
flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
|
flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
|
||||||
m_last_red_signal_type = parent->m_last_red_signal_type;
|
m_last_red_signal_type = parent->m_last_red_signal_type;
|
||||||
|
m_last_signal_type = parent->m_last_signal_type;
|
||||||
}
|
}
|
||||||
flags_u.flags_s.m_choice_seen |= is_choice;
|
flags_u.flags_s.m_choice_seen |= is_choice;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue