Avoid setting a route that can't be reached
Stop timetable if route can't be set
Put diversion route in RefPtr so it gets cleaned if we bail out
+ if(!train.set_route(*i))
+ engineer.set_status("Could not set route");
}
else
train.set_route(0);
}
else
train.set_route(0);
{
pick_conn.disconnect();
{
pick_conn.disconnect();
- try
- {
- train.go_to(*track);
- }
- catch(const Exception &e)
- {
- engineer.set_status(e.what());
- }
+ if(!train.go_to(*track))
+ engineer.set_status("Could not set route");
- if(!final)
- throw InvalidParameterValue("Could not find a route");
-
list<Track *> result;
for(Node *node=final; node; node=node->prev)
result.push_front(node->track);
list<Track *> result;
for(Node *node=final; node; node=node->prev)
result.push_front(node->track);
{
list<Track *> tracks = dijkstra(from, ep, goal);
{
list<Track *> tracks = dijkstra(from, ep, goal);
+ if(tracks.empty())
+ return 0;
+
Route *route = new Route(from.get_layout());
for(list<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
route->add_track(**i);
Route *route = new Route(from.get_layout());
for(list<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
route->add_track(**i);
switch(row.type)
{
case GOTO:
switch(row.type)
{
case GOTO:
- train.go_to(**parse_location(row.get_param<string>(0)).get_tracks().begin());
+ if(!train.go_to(**parse_location(row.get_param<string>(0)).get_tracks().begin()))
+ set_enabled(false);
break;
case TRAVEL:
pending_block = &parse_location(row.get_param<string>(0));
break;
case TRAVEL:
pending_block = &parse_location(row.get_param<string>(0));
train.set_control("reverse", !train.get_control("reverse"));
break;
case ROUTE:
train.set_control("reverse", !train.get_control("reverse"));
break;
case ROUTE:
- train.set_route(&train.get_layout().get_route(row.get_param<string>(0)));
+ if(!train.set_route(&train.get_layout().get_route(row.get_param<string>(0))))
+ set_enabled(false);
-void Train::set_route(const Route *r)
+bool Train::set_route(const Route *r)
{
free_noncritical_blocks();
{
free_noncritical_blocks();
- routes.clear();
- if(r)
- routes.push_back(r);
- end_of_route = false;
-
if(r && !cur_blocks.empty())
{
TrackIter first = cur_blocks.front().track_iter();
TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter();
if(!r->has_track(*next))
{
if(r && !cur_blocks.empty())
{
TrackIter first = cur_blocks.front().track_iter();
TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter();
if(!r->has_track(*next))
{
- Route *lead = Route::find(*next, next.entry(), *r);
+ lead = Route::find(*next, next.entry(), *r);
+ if(!lead)
+ return false;
create_lead_route(lead, lead);
routes.push_front(lead);
}
else if(!r->has_track(*first))
create_lead_route(lead, lead);
routes.push_front(lead);
}
else if(!r->has_track(*first))
- routes.push_front(create_lead_route(0, r));
+ lead = create_lead_route(0, r);
+ routes.clear();
+ if(lead)
+ routes.push_back(lead);
+ if(r)
+ routes.push_back(r);
+ end_of_route = false;
+
reserve_more();
signal_route_changed.emit(get_route());
reserve_more();
signal_route_changed.emit(get_route());
-void Train::go_to(Track &to)
+bool Train::go_to(Track &to)
{
for(BlockList::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
if((*i)->has_track(to))
{
signal_arrived.emit();
{
for(BlockList::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
if((*i)->has_track(to))
{
signal_arrived.emit();
- set_route(0);
- return;
}
free_noncritical_blocks();
}
free_noncritical_blocks();
TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter();
Route *route = Route::find(*next, next.entry(), to);
TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter();
Route *route = Route::find(*next, next.entry(), to);
+ if(!route)
+ return false;
create_lead_route(route, route);
create_lead_route(route, route);
+ return set_route(route);
}
bool Train::divert(Track &from)
}
bool Train::divert(Track &from)
set<Track *> tracks;
for(list<RouteRef>::iterator i=routes.begin(); i!=routes.end(); ++i)
tracks.insert(i->route->get_tracks().begin(), i->route->get_tracks().end());
set<Track *> tracks;
for(list<RouteRef>::iterator i=routes.begin(); i!=routes.end(); ++i)
tracks.insert(i->route->get_tracks().begin(), i->route->get_tracks().end());
- Route *diversion = 0;
- try
- {
- diversion = Route::find(*track, ep, tracks);
- }
- catch(const Msp::Exception &)
- {
+ RefPtr<Route> diversion = Route::find(*track, ep, tracks);
+ if(!diversion)
diversion->set_name("Diversion");
diversion->add_track(from);
diversion->set_turnout(from.get_turnout_id(), path);
if(!is_valid_diversion(*diversion, from, from_ep))
diversion->set_name("Diversion");
diversion->add_track(from);
diversion->set_turnout(from.get_turnout_id(), path);
if(!is_valid_diversion(*diversion, from, from_ep))
// Follow the diversion route until we get back to the original route
list<RouteRef>::iterator end = routes.end();
// Follow the diversion route until we get back to the original route
list<RouteRef>::iterator end = routes.end();
if(end!=routes.end())
break;
else if(!diversion->has_track(*track))
if(end!=routes.end())
break;
else if(!diversion->has_track(*track))
- throw Exception("Pathfinder returned a bad route");
+ throw LogicError("Pathfinder returned a bad route");
unsigned tid = track->get_turnout_id();
track = track.next(tid ? diversion->get_turnout(tid) : 0);
unsigned tid = track->get_turnout_id();
track = track.next(tid ? diversion->get_turnout(tid) : 0);
++route;
routes.erase(route, end);
}
++route;
routes.erase(route, end);
}
- routes.insert(end, RouteRef(diversion, from.get_turnout_id()));
+ routes.insert(end, RouteRef(diversion.release(), from.get_turnout_id()));
void set_timetable(Timetable *);
Timetable *get_timetable() { return timetable; }
void set_timetable(Timetable *);
Timetable *get_timetable() { return timetable; }
- void set_route(const Route *);
- void go_to(Track &);
+ bool set_route(const Route *);
+ bool go_to(Track &);
bool divert(Track &);
const Route *get_route() const;
void place(Block &, unsigned);
bool divert(Track &);
const Route *get_route() const;
void place(Block &, unsigned);