+ BlockRef &first = cur_blocks.front();
+ BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back());
+ BlockRef next = last.next();
+ const Block::Endpoint &first_ep = first.block->get_endpoints()[first.entry];
+ const Block::Endpoint &next_ep = next.block->get_endpoints()[next.entry];
+ if(!r->has_track(*next_ep.track))
+ {
+ Route *lead = Route::find(*next_ep.track, next_ep.track_ep, *r);
+ create_lead_route(lead, lead);
+ routes.push_front(lead);
+ }
+ else if(!r->has_track(*first_ep.track))
+ routes.push_front(create_lead_route(0, r));
+ }
+
+ reserve_more();
+
+ signal_route_changed.emit(get_route());
+}
+
+void Train::go_to(Track &to)
+{
+ for(list<BlockRef>::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
+ if(i->block->has_track(to))
+ {
+ signal_arrived.emit();
+ set_route(0);
+ return;
+ }
+
+ free_noncritical_blocks();
+
+ BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back());
+ BlockRef next = last.next();
+ const Block::Endpoint &ep = next.block->get_endpoints()[next.entry];
+
+ Route *route = Route::find(*ep.track, ep.track_ep, to);
+ create_lead_route(route, route);
+ 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;
+
+ int path = -1;
+ unsigned from_ep = 0;
+ list<RouteRef>::iterator route = routes.begin();
+ Block *block = cur_blocks.back().block;
+ unsigned entry = cur_blocks.back().entry;
+ set<const Track *> visited;
+
+ // Follow our routes to find out where we're entering the turnout
+ while(1)
+ {
+ Block *link = block->get_link(block->traverse(entry, route->route));
+ entry = link->get_endpoint_by_link(*block);
+ block = link;
+
+ const Block::Endpoint &entry_ep = block->get_endpoints()[entry];
+
+ if(visited.count(entry_ep.track))
+ return false;
+ visited.insert(entry_ep.track);
+
+ if(!advance_route(route, *entry_ep.track))
+ return false;
+
+ if(entry_ep.track==&from)
+ {
+ if(block->get_train()==this && !free_block(*block))
+ return false;
+
+ from_ep = entry_ep.track_ep;
+ path = route->route->get_turnout(from.get_turnout_id());
+ break;
+ }
+ }
+
+ // Check that more than one path is available
+ unsigned ep_paths = from.get_type().get_endpoints()[from_ep].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!=path)
+ {
+ path = i;
+ break;
+ }
+
+ Track *track = from.get_link(from.traverse(from_ep, path));
+ if(!track)
+ return false;
+
+ unsigned ep = track->get_endpoint_by_link(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());
+ Route *diversion = 0;
+ try
+ {
+ diversion = Route::find(*track, ep, tracks);
+ }
+ catch(const Msp::Exception &)
+ {
+ return false;