Destination is really just a special case of a waypoint, so there's no
point in keeping it separate. It just adds duplicated logic, which was
about to get worse with some upcoming new features.
- train.ai_message(Message("set-destination", i->target));
+ train.ai_message(Message("add-waypoint", i->target));
break;
}
else if(i->type==DEPART)
break;
}
else if(i->type==DEPART)
for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
{
TrainRoutingInfo info(*i->second);
for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
{
TrainRoutingInfo info(*i->second);
+ if(!info.waypoints.empty())
routed_trains.push_back(info);
}
}
routed_trains.push_back(info);
}
}
speed(train->get_maximum_speed()),
first_noncritical(train->get_first_noncritical_block().block()),
router(train->get_ai_of_type<TrainRouter>()),
speed(train->get_maximum_speed()),
first_noncritical(train->get_first_noncritical_block().block()),
router(train->get_ai_of_type<TrainRouter>()),
+ waypoints(router ? router->get_n_waypoints() : 0),
- destination = router->get_destination();
- if(destination)
+ metrics.resize(waypoints.size());
+ for(unsigned i=0; i<waypoints.size(); ++i)
- waypoints.resize(router->get_n_waypoints());
- metrics.resize(waypoints.size()+1);
- metrics[0] = &router->get_metric(-1);
- for(unsigned i=0; i<waypoints.size(); ++i)
- {
- waypoints[i] = &router->get_waypoint(i);
- metrics[i+1] = &router->get_metric(i);
- }
- has_duration = router->get_trip_duration();
+ waypoints[i] = &router->get_waypoint(i);
+ metrics[i] = &router->get_metric(i);
+ has_duration = router->get_trip_duration();
}
// If no maximum speed is specified, use a sensible default
}
// If no maximum speed is specified, use a sensible default
state(MOVING),
delay(info->router->get_departure_delay()),
duration(info->router->get_trip_duration()),
state(MOVING),
delay(info->router->get_departure_delay()),
duration(info->router->get_trip_duration()),
- waypoint(info->waypoints.empty() ? -1 : 0),
blocked_by(-1)
{
const Vehicle *veh = &info->train->get_vehicle(0);
blocked_by(-1)
{
const Vehicle *veh = &info->train->get_vehicle(0);
{
TrackIter next_track = track.next(path);
{
TrackIter next_track = track.next(path);
- if(waypoint<0 && info->destination->has_track(*track) && !info->destination->has_track(*next_track))
- {
- state = ARRIVED;
- return true;
- }
- else if(waypoint>=0 && info->waypoints[waypoint]->has_track(*track) && !info->waypoints[waypoint]->has_track(*next_track))
+ const TrackChain *wp_chain = info->waypoints[waypoint];
+ if(wp_chain->has_track(*track) && !wp_chain->has_track(*next_track))
- ++waypoint;
- if(waypoint>=static_cast<int>(info->waypoints.size()))
- waypoint = -1;
+ if(waypoint+1<info->waypoints.size())
+ ++waypoint;
+ else
+ {
+ state = ARRIVED;
+ return true;
+ }
}
if(info->first_noncritical->has_track(*track))
}
if(info->first_noncritical->has_track(*track))
void TrainRoutePlanner::TrainRoutingState::update_estimate()
{
TrackIter iter = track.reverse(path);
void TrainRoutePlanner::TrainRoutingState::update_estimate()
{
TrackIter iter = track.reverse(path);
- float distance = info->metrics[waypoint+1]->get_distance_from(*iter.track(), iter.entry());
+ float distance = info->metrics[waypoint]->get_distance_from(*iter.track(), iter.entry());
distance += track->get_type().get_path_length(path)-offset;
remaining_estimate = distance;
}
distance += track->get_type().get_path_length(path)-offset;
remaining_estimate = distance;
}
float speed;
Block *first_noncritical;
TrainRouter *router;
float speed;
Block *first_noncritical;
TrainRouter *router;
- const TrackChain *destination;
std::vector<const TrackChain *> waypoints;
std::vector<const TrainRouteMetric *> metrics;
bool has_duration;
std::vector<const TrackChain *> waypoints;
std::vector<const TrainRouteMetric *> metrics;
bool has_duration;
TrainState state;
Msp::Time::TimeDelta delay;
Msp::Time::TimeDelta duration;
TrainState state;
Msp::Time::TimeDelta delay;
Msp::Time::TimeDelta duration;
float distance_traveled;
float remaining_estimate;
Msp::Time::TimeDelta wait_time;
float distance_traveled;
float remaining_estimate;
Msp::Time::TimeDelta wait_time;
TrainAI(t),
priority(0),
arrival(ON_THE_WAY),
TrainAI(t),
priority(0),
arrival(ON_THE_WAY),
- destination(0),
- destination_changed(false),
+ waypoints_changed(false),
metrics_stale(false),
current_sequence(0),
sequence_check_pending(false)
metrics_stale(false),
current_sequence(0),
sequence_check_pending(false)
waypoints.clear();
sequence_points.clear();
current_sequence = 0;
waypoints.clear();
sequence_points.clear();
current_sequence = 0;
void TrainRouter::set_destination(const TrackChain &d)
{
void TrainRouter::set_destination(const TrackChain &d)
{
- destination = &d;
- destination_changed = true;
+ if(waypoints.empty())
+ waypoints.push_back(&d);
+ else
+ waypoints.back() = &d;
+ waypoints_changed = true;
metrics_stale = true;
}
void TrainRouter::add_waypoint(const TrackChain &wp)
{
waypoints.push_back(&wp);
metrics_stale = true;
}
void TrainRouter::add_waypoint(const TrackChain &wp)
{
waypoints.push_back(&wp);
- destination_changed = true;
+ waypoints_changed = true;
const TrainRouteMetric &TrainRouter::get_metric(int index) const
{
const TrainRouteMetric &TrainRouter::get_metric(int index) const
{
throw logic_error("no metrics");
else if(metrics_stale)
throw logic_error("metrics are stale");
if(index<0)
throw logic_error("no metrics");
else if(metrics_stale)
throw logic_error("metrics are stale");
if(index<0)
- return *metrics.front();
+ return *metrics.back();
else if(static_cast<unsigned>(index)>=waypoints.size())
throw out_of_range("TrainRouter::get_metric");
else
else if(static_cast<unsigned>(index)>=waypoints.size())
throw out_of_range("TrainRouter::get_metric");
else
- return *metrics[index+1];
+ return *metrics[index];
}
void TrainRouter::set_departure_delay(const Time::TimeDelta &d)
{
delay = d;
}
void TrainRouter::set_departure_delay(const Time::TimeDelta &d)
{
delay = d;
- destination_changed = true;
+ waypoints_changed = true;
}
void TrainRouter::set_trip_duration(const Time::TimeDelta &d)
}
void TrainRouter::set_trip_duration(const Time::TimeDelta &d)
else if(duration)
duration = max(duration-dt, Time::zero);
else if(duration)
duration = max(duration-dt, Time::zero);
- if(destination_changed && !planner)
+ if(waypoints_changed && !planner)
start_planning(train.get_layout());
if(planner && planner->check()!=TrainRoutePlanner::PENDING)
{
start_planning(train.get_layout());
if(planner && planner->check()!=TrainRoutePlanner::PENDING)
{
- destination_changed = false;
+ waypoints_changed = false;
if(planner->get_result()==TrainRoutePlanner::COMPLETE)
{
const list<Route *> &planned_routes = planner->get_routes_for(train);
if(planner->get_result()==TrainRoutePlanner::COMPLETE)
{
const list<Route *> &planned_routes = planner->get_routes_for(train);
if(arrival==RESERVED_TO_END && !train.get_speed())
{
if(arrival==RESERVED_TO_END && !train.get_speed())
{
- signal_arrived.emit(destination);
- signal_event.emit(Message("arrived", destination));
+ signal_arrived.emit(waypoints.back());
+ signal_event.emit(Message("arrived", waypoints.back()));
arrival = ARRIVED;
}
else if(arrival==ARRIVED && !train.get_block_allocator().is_active())
arrival = ARRIVED;
}
else if(arrival==ARRIVED && !train.get_block_allocator().is_active())
{
BlockIter b_iter = train.get_block_allocator().iter_for(block);
{
BlockIter b_iter = train.get_block_allocator().iter_for(block);
{
// A waypoint is considered reached when the train has advanced through it.
const TrackChain &wp = *waypoints.front();
{
// A waypoint is considered reached when the train has advanced through it.
const TrackChain &wp = *waypoints.front();
- metrics.push_back(new TrainRouteMetric(*destination));
for(vector<const TrackChain *>::const_iterator i=waypoints.begin(); i!=waypoints.end(); ++i)
metrics.push_back(new TrainRouteMetric(**i));
for(vector<const TrackChain *>::const_iterator i=waypoints.begin(); i!=waypoints.end(); ++i)
metrics.push_back(new TrainRouteMetric(**i));
- for(unsigned i=metrics.size(); --i>0; )
- metrics[i]->chain_to(*metrics[(i+1)%metrics.size()]);
+ for(unsigned i=metrics.size()-1; i-->0; )
+ metrics[i]->chain_to(*metrics[i+1]);
}
bool TrainRouter::create_lead_route()
}
bool TrainRouter::create_lead_route()
RouteList routes;
RouteList::iterator reserving_route;
ArrivalState arrival;
RouteList routes;
RouteList::iterator reserving_route;
ArrivalState arrival;
- const TrackChain *destination;
std::vector<const TrackChain *> waypoints;
std::vector<const TrackChain *> waypoints;
- bool destination_changed;
+ bool waypoints_changed;
std::vector<TrainRouteMetric *> metrics;
bool metrics_stale;
std::list<SequencePoint> sequence_points;
std::vector<TrainRouteMetric *> metrics;
bool metrics_stale;
std::list<SequencePoint> sequence_points;
public:
void set_destination(const TrackChain &);
public:
void set_destination(const TrackChain &);
- const TrackChain *get_destination() const { return destination; }
+ const TrackChain *get_destination() const { return waypoints.empty() ? 0 : waypoints.back(); }
void add_waypoint(const TrackChain &);
unsigned get_n_waypoints() const { return waypoints.size(); }
const TrackChain &get_waypoint(unsigned) const;
void add_waypoint(const TrackChain &);
unsigned get_n_waypoints() const { return waypoints.size(); }
const TrackChain &get_waypoint(unsigned) const;