+ 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)
+ {
+ for(list<RouteRef>::iterator i=route; (end==routes.end() && i!=routes.end()); ++i)
+ if(i->route->has_track(*track))
+ end = i;
+
+ if(end!=routes.end())
+ break;
+ else if(!diversion->has_track(*track))
+ throw LogicError("Pathfinder returned a bad route");
+
+ track = track.next(diversion->get_path(*track));
+ }
+
+ if(route==end)
+ // We are rejoining the same route we diverted from, duplicate it
+ routes.insert(end, *route);