+ free_noncritical_blocks();
+
+ Route *lead = 0;
+ if(r && !blocks.empty())
+ {
+ TrackIter first = blocks.front().track_iter();
+ TrackIter next = blocks.back().next().track_iter();
+ if(!r->has_track(*next))
+ {
+ lead = Route::find(next, *r);
+ if(!lead)
+ return false;
+ create_lead_route(lead, lead);
+ routes.push_front(lead);
+ }
+ else if(!r->has_track(*first))
+ 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());
+
+ return true;
+}
+
+bool Train::go_to(Track &to)
+{
+ for(BlockList::const_iterator i=blocks.begin(); i!=cur_blocks_end; ++i)
+ if((*i)->has_track(to))
+ {
+ signal_arrived.emit();
+ return set_route(0);
+ }
+
+ free_noncritical_blocks();
+
+ TrackIter next = blocks.back().next().track_iter();
+
+ Route *route = Route::find(next, to);
+ if(!route)
+ return false;
+ create_lead_route(route, route);
+ return set_route(route);
+}
+
+bool Train::divert(Track &from)
+{
+ if(!from.get_turnout_id())
+ throw InvalidParameterValue("Can't divert from a non-turnout");
+ if(routes.empty())
+ return false;
+
+ unsigned path = 0;
+ unsigned entry = 0;
+ list<RouteRef>::iterator route = routes.begin();
+
+ // Follow our routes to find out where we're entering the turnout
+ for(TrackLoopIter track = blocks.front().track_iter();;)
+ {
+ if(!advance_route(route, *track))
+ return false;
+
+ if(&*track==&from)
+ {
+ Block &block = track->get_block();
+ if(block.get_train()==this && !free_block(block))
+ return false;
+
+ int route_path = route->route->get_turnout(from.get_turnout_id());
+
+ // Check that more than one path is available
+ unsigned ep_paths = track->get_type().get_endpoints()[track.entry()].paths;
+ if(!(ep_paths&(ep_paths-1)))
+ return false;
+
+ // Choose some other path
+ for(int i=0; ep_paths>>i; ++i)
+ if((ep_paths&(1<<i)) && i!=route_path)
+ {
+ path = i;
+ break;
+ }
+
+ entry = track.entry();
+ break;
+ }
+
+ track = track.next(route->route->get_path(*track));
+
+ if(!track || track.looped())
+ return false;
+ }
+
+ TrackIter track = TrackIter(&from, entry).next(path);
+ if(!track)
+ return false;
+
+ 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());
+ RefPtr<Route> diversion = Route::find(track, tracks);
+ if(!diversion)
+ return false;
+
+ diversion->set_name("Diversion");
+ diversion->add_track(from);
+ diversion->set_turnout(from.get_turnout_id(), path);
+
+ if(!is_valid_diversion(*diversion, TrackIter(&from, entry)))
+ return false;
+
+ // Follow the diversion route until we get back to the original route
+ list<RouteRef>::iterator end = routes.end();
+ while(1)