mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
Departures: Split some parts of MakeDepartureList into separate functions
This commit is contained in:
parent
2edf361d59
commit
da3b8dfb97
@ -461,6 +461,115 @@ static void GetDepartureCandidateOrderDatesFromVehicle(std::vector<OrderDate> &n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DepartureViaTerminusState {
|
||||||
|
/* We keep track of potential via stations along the way. If we call at a station immediately after going via it, then it is the via station. */
|
||||||
|
StationID candidate_via = INVALID_STATION;
|
||||||
|
StationID pending_via = INVALID_STATION;
|
||||||
|
StationID pending_via2 = INVALID_STATION;
|
||||||
|
|
||||||
|
/* We only need to consider each order at most once. */
|
||||||
|
bool found_terminus = false;
|
||||||
|
|
||||||
|
bool CheckOrder(const Vehicle *v, Departure *d, const Order *order, DepartureOrderDestinationDetector source, DepartureCallingSettings calling_settings);
|
||||||
|
bool HandleCallingPoint(Departure *d, const Order *order, CallAt c);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the order terminus and via states.
|
||||||
|
* @return true to stop at this order
|
||||||
|
*/
|
||||||
|
bool DepartureViaTerminusState::CheckOrder(const Vehicle *v, Departure *d, const Order *order, DepartureOrderDestinationDetector source, DepartureCallingSettings calling_settings)
|
||||||
|
{
|
||||||
|
/* If we reach the original station again, then use it as the terminus. */
|
||||||
|
if (order->GetType() == OT_GOTO_STATION &&
|
||||||
|
source.OrderMatches(order) &&
|
||||||
|
(order->GetUnloadType() != OUFB_NO_UNLOAD ||
|
||||||
|
calling_settings.show_all_stops) &&
|
||||||
|
(((order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) || ((d->order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0))) {
|
||||||
|
/* If we're not calling anywhere, then skip this departure. */
|
||||||
|
this->found_terminus = (d->calling_at.size() > 0);
|
||||||
|
return true;
|
||||||
|
} else if (order->GetType() == OT_GOTO_WAYPOINT && source.OrderMatches(order)) {
|
||||||
|
/* If we're not calling anywhere, then skip this departure. */
|
||||||
|
this->found_terminus = (d->calling_at.size() > 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we're going via this station. */
|
||||||
|
if ((order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
|
||||||
|
order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) &&
|
||||||
|
order->GetType() == OT_GOTO_STATION &&
|
||||||
|
d->via == INVALID_STATION) {
|
||||||
|
this->candidate_via = (StationID)order->GetDestination();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order->GetType() == OT_LABEL && order->GetLabelSubType() == OLST_DEPARTURES_VIA && d->via == INVALID_STATION && this->pending_via == INVALID_STATION) {
|
||||||
|
this->pending_via = (StationID)order->GetDestination();
|
||||||
|
const Order *next = v->orders->GetNext(order);
|
||||||
|
if (next->GetType() == OT_LABEL && next->GetLabelSubType() == OLST_DEPARTURES_VIA && (StationID)next->GetDestination() != this->pending_via) {
|
||||||
|
this->pending_via2 = (StationID)next->GetDestination();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order->GetType() == OT_LABEL && order->GetLabelSubType() == OLST_DEPARTURES_REMOVE_VIA && !d->calling_at.empty()) {
|
||||||
|
d->remove_vias.push_back({ (StationID)order->GetDestination(), (uint)(d->calling_at.size() - 1) });
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DepartureViaTerminusState::HandleCallingPoint(Departure *d, const Order *order, CallAt c)
|
||||||
|
{
|
||||||
|
/* If this order's station is already in the calling, then the previous called at station is the terminus. */
|
||||||
|
if (std::find(d->calling_at.begin(), d->calling_at.end(), c) != d->calling_at.end()) {
|
||||||
|
this->found_terminus = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If appropriate, add the station to the calling at list and make it the candidate terminus. */
|
||||||
|
if ((order->GetType() == OT_GOTO_STATION ||
|
||||||
|
order->GetType() == OT_IMPLICIT) &&
|
||||||
|
order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
|
||||||
|
order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
|
||||||
|
if (d->via == INVALID_STATION && pending_via != INVALID_STATION) {
|
||||||
|
d->via = this->pending_via;
|
||||||
|
d->via2 = this->pending_via2;
|
||||||
|
}
|
||||||
|
if (d->via == INVALID_STATION && this->candidate_via == (StationID)order->GetDestination()) {
|
||||||
|
d->via = (StationID)order->GetDestination();
|
||||||
|
}
|
||||||
|
d->terminus = c;
|
||||||
|
d->calling_at.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we unload all at this station, then it is the terminus. */
|
||||||
|
if (order->GetType() == OT_GOTO_STATION &&
|
||||||
|
order->GetUnloadType() == OUFB_UNLOAD) {
|
||||||
|
if (d->calling_at.size() > 0) {
|
||||||
|
this->found_terminus = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether this order is an ignorable calling point.
|
||||||
|
*/
|
||||||
|
static bool IsIgnorableCallingAtOrder(const Order *order, DepartureCallingSettings calling_settings)
|
||||||
|
{
|
||||||
|
if ((order->GetUnloadType() == OUFB_NO_UNLOAD &&
|
||||||
|
!calling_settings.show_all_stops) ||
|
||||||
|
(order->GetType() != OT_GOTO_STATION &&
|
||||||
|
order->GetType() != OT_IMPLICIT) ||
|
||||||
|
order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
|
||||||
|
order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute an up-to-date list of departures for a station.
|
* Compute an up-to-date list of departures for a station.
|
||||||
* @param source the station/etc to compute the departures of
|
* @param source the station/etc to compute the departures of
|
||||||
@ -565,22 +674,17 @@ DepartureList MakeDepartureList(DepartureOrderDestinationDetector source, const
|
|||||||
/* A departure goes via a station if it is the first station for which the vehicle has an order to go via or non-stop via. */
|
/* A departure goes via a station if it is the first station for which the vehicle has an order to go via or non-stop via. */
|
||||||
/* Multiple departures on the same journey may go via different stations. That a departure can go via at most one station is intentional. */
|
/* Multiple departures on the same journey may go via different stations. That a departure can go via at most one station is intentional. */
|
||||||
|
|
||||||
/* We keep track of potential via stations along the way. If we call at a station immediately after going via it, then it is the via station. */
|
DepartureViaTerminusState via_state{};
|
||||||
StationID candidate_via = INVALID_STATION;
|
|
||||||
StationID pending_via = INVALID_STATION;
|
|
||||||
StationID pending_via2 = INVALID_STATION;
|
|
||||||
|
|
||||||
/* Go through the order list, looping if necessary, to find a terminus. */
|
/* Go through the order list, looping if necessary, to find a terminus. */
|
||||||
/* Get the next order, which may be the vehicle's first order. */
|
/* Get the next order, which may be the vehicle's first order. */
|
||||||
order = lod.v->orders->GetNext(order);
|
order = lod.v->orders->GetNext(order);
|
||||||
/* We only need to consider each order at most once. */
|
|
||||||
bool found_terminus = false;
|
|
||||||
CallAt c = CallAt((StationID)order->GetDestination(), d->scheduled_tick);
|
CallAt c = CallAt((StationID)order->GetDestination(), d->scheduled_tick);
|
||||||
for (uint i = order_iteration_limit; i > 0; --i) {
|
for (uint i = order_iteration_limit; i > 0; --i) {
|
||||||
/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
|
/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
|
||||||
if (order == lod.order) {
|
if (order == lod.order) {
|
||||||
/* If we're not calling anywhere, then skip this departure. */
|
/* If we're not calling anywhere, then skip this departure. */
|
||||||
found_terminus = (d->calling_at.size() > 0);
|
via_state.found_terminus = (d->calling_at.size() > 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,40 +718,7 @@ DepartureList MakeDepartureList(DepartureOrderDestinationDetector source, const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we reach the original station again, then use it as the terminus. */
|
if (via_state.CheckOrder(lod.v, d, order, source, calling_settings)) break;
|
||||||
if (order->GetType() == OT_GOTO_STATION &&
|
|
||||||
source.OrderMatches(order) &&
|
|
||||||
(order->GetUnloadType() != OUFB_NO_UNLOAD ||
|
|
||||||
calling_settings.show_all_stops) &&
|
|
||||||
(((order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) || ((lod.order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0))) {
|
|
||||||
/* If we're not calling anywhere, then skip this departure. */
|
|
||||||
found_terminus = (d->calling_at.size() > 0);
|
|
||||||
break;
|
|
||||||
} else if (order->GetType() == OT_GOTO_WAYPOINT && source.OrderMatches(order)) {
|
|
||||||
/* If we're not calling anywhere, then skip this departure. */
|
|
||||||
found_terminus = (d->calling_at.size() > 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we're going via this station. */
|
|
||||||
if ((order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
|
|
||||||
order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) &&
|
|
||||||
order->GetType() == OT_GOTO_STATION &&
|
|
||||||
d->via == INVALID_STATION) {
|
|
||||||
candidate_via = (StationID)order->GetDestination();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (order->GetType() == OT_LABEL && order->GetLabelSubType() == OLST_DEPARTURES_VIA && d->via == INVALID_STATION && pending_via == INVALID_STATION) {
|
|
||||||
pending_via = (StationID)order->GetDestination();
|
|
||||||
const Order *next = lod.v->orders->GetNext(order);
|
|
||||||
if (next->GetType() == OT_LABEL && next->GetLabelSubType() == OLST_DEPARTURES_VIA && (StationID)next->GetDestination() != pending_via) {
|
|
||||||
pending_via2 = (StationID)next->GetDestination();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (order->GetType() == OT_LABEL && order->GetLabelSubType() == OLST_DEPARTURES_REMOVE_VIA && !d->calling_at.empty()) {
|
|
||||||
d->remove_vias.push_back({ (StationID)order->GetDestination(), (uint)(d->calling_at.size() - 1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.scheduled_tick != 0 && (order->GetTravelTime() != 0 || order->IsTravelTimetabled())) {
|
if (c.scheduled_tick != 0 && (order->GetTravelTime() != 0 || order->IsTravelTimetabled())) {
|
||||||
c.scheduled_tick += order->GetTravelTime(); /* TODO smart terminal may not work correctly */
|
c.scheduled_tick += order->GetTravelTime(); /* TODO smart terminal may not work correctly */
|
||||||
@ -658,47 +729,13 @@ DepartureList MakeDepartureList(DepartureOrderDestinationDetector source, const
|
|||||||
c.station = (StationID)order->GetDestination();
|
c.station = (StationID)order->GetDestination();
|
||||||
|
|
||||||
/* We're not interested in this order any further if we're not calling at it. */
|
/* We're not interested in this order any further if we're not calling at it. */
|
||||||
if ((order->GetUnloadType() == OUFB_NO_UNLOAD &&
|
if (IsIgnorableCallingAtOrder(order, calling_settings)) {
|
||||||
!calling_settings.show_all_stops) ||
|
|
||||||
(order->GetType() != OT_GOTO_STATION &&
|
|
||||||
order->GetType() != OT_IMPLICIT) ||
|
|
||||||
order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
|
|
||||||
order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) {
|
|
||||||
if (c.scheduled_tick != 0) c.scheduled_tick += order->GetWaitTime();
|
if (c.scheduled_tick != 0) c.scheduled_tick += order->GetWaitTime();
|
||||||
order = lod.v->orders->GetNext(order);
|
order = lod.v->orders->GetNext(order);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this order's station is already in the calling, then the previous called at station is the terminus. */
|
if (via_state.HandleCallingPoint(d, order, c)) break;
|
||||||
if (std::find(d->calling_at.begin(), d->calling_at.end(), c) != d->calling_at.end()) {
|
|
||||||
found_terminus = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If appropriate, add the station to the calling at list and make it the candidate terminus. */
|
|
||||||
if ((order->GetType() == OT_GOTO_STATION ||
|
|
||||||
order->GetType() == OT_IMPLICIT) &&
|
|
||||||
order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
|
|
||||||
order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
|
|
||||||
if (d->via == INVALID_STATION && pending_via != INVALID_STATION) {
|
|
||||||
d->via = pending_via;
|
|
||||||
d->via2 = pending_via2;
|
|
||||||
}
|
|
||||||
if (d->via == INVALID_STATION && candidate_via == (StationID)order->GetDestination()) {
|
|
||||||
d->via = (StationID)order->GetDestination();
|
|
||||||
}
|
|
||||||
d->terminus = c;
|
|
||||||
d->calling_at.push_back(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we unload all at this station, then it is the terminus. */
|
|
||||||
if (order->GetType() == OT_GOTO_STATION &&
|
|
||||||
order->GetUnloadType() == OUFB_UNLOAD) {
|
|
||||||
if (d->calling_at.size() > 0) {
|
|
||||||
found_terminus = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.scheduled_tick != 0) c.scheduled_tick += order->GetWaitTime();
|
if (c.scheduled_tick != 0) c.scheduled_tick += order->GetWaitTime();
|
||||||
|
|
||||||
@ -706,7 +743,7 @@ DepartureList MakeDepartureList(DepartureOrderDestinationDetector source, const
|
|||||||
order = lod.v->orders->GetNext(order);
|
order = lod.v->orders->GetNext(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found_terminus) {
|
if (via_state.found_terminus) {
|
||||||
/* Add the departure to the result list. */
|
/* Add the departure to the result list. */
|
||||||
bool duplicate = false;
|
bool duplicate = false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user