Initial implementation of PBS entry signal condition variable.
TODO: see how the efficiency of this can be improved.
This commit is contained in:
@@ -189,12 +189,88 @@ private:
|
||||
IsRestrictedSignal(tile);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to retrieve the previous signal, as required
|
||||
* This is not run all the time as it is somewhat expensive and most restrictions will not test for the previous signal
|
||||
*/
|
||||
static TileIndex TraceRestrictPreviousSignalCallback(const Train *v, const void *node_ptr)
|
||||
{
|
||||
const Node *node = static_cast<const Node *>(node_ptr);
|
||||
for (;;) {
|
||||
TileIndex last_signal_tile = node->m_segment->m_last_signal_tile;
|
||||
if (last_signal_tile != INVALID_TILE) {
|
||||
Trackdir last_signal_trackdir = node->m_segment->m_last_signal_td;
|
||||
if (HasPbsSignalOnTrackdir(last_signal_tile, last_signal_trackdir)) {
|
||||
return last_signal_tile;
|
||||
} else {
|
||||
return INVALID_TILE;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->m_parent) {
|
||||
node = node->m_parent;
|
||||
} else {
|
||||
// scan forwards from vehicle position, for the case that train is waiting at/approaching PBS signal
|
||||
|
||||
/*
|
||||
* TODO: can this be made more efficient?
|
||||
* This track scan will have been performed upstack, however extracting the entry signal
|
||||
* during that scan and passing it through to this point would likely require relatively
|
||||
* invasive changes to the pathfinder code, or at least an extra param on a number of wrapper
|
||||
* functions between there and here, which would be best avoided.
|
||||
*/
|
||||
|
||||
TileIndex origin_tile = node->GetTile();
|
||||
Trackdir origin_trackdir = node->GetTrackdir();
|
||||
|
||||
TileIndex tile = v->tile;
|
||||
Trackdir trackdir = v->GetVehicleTrackdir();
|
||||
|
||||
CFollowTrackRail ft(v);
|
||||
|
||||
TileIndex candidate_tile = INVALID_TILE;
|
||||
|
||||
for (;;) {
|
||||
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir)) {
|
||||
if (HasPbsSignalOnTrackdir(tile, trackdir)) {
|
||||
// found PBS signal
|
||||
candidate_tile = tile;
|
||||
} else {
|
||||
// wrong type of signal
|
||||
candidate_tile = INVALID_TILE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tile == origin_tile && trackdir == origin_trackdir) {
|
||||
// reached pathfinder origin
|
||||
return candidate_tile;
|
||||
}
|
||||
|
||||
// advance to next tile
|
||||
if (!ft.Follow(tile, trackdir)) {
|
||||
// ran out of track
|
||||
return INVALID_TILE;
|
||||
}
|
||||
|
||||
if (KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
// reached a junction tile
|
||||
return INVALID_TILE;
|
||||
}
|
||||
|
||||
tile = ft.m_new_tile;
|
||||
trackdir = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
// returns true if dead end bit has been set
|
||||
inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out)
|
||||
{
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir));
|
||||
if (prog) {
|
||||
prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir), out);
|
||||
prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir, &TraceRestrictPreviousSignalCallback, &n), out);
|
||||
if (out.flags & TRPRF_DENY) {
|
||||
n.m_segment->m_end_segment_reason |= ESRB_DEAD_END;
|
||||
return true;
|
||||
|
Reference in New Issue
Block a user