+ (*i)->break_links();
+
+ list<Track *> flext;
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ {
+ if((*i)->get_flex())
+ flext.push_back(*i);
+ else
+ {
+ for(set<Track *>::iterator j=i; j!=tracks.end(); ++j)
+ if(j!=i)
+ (*i)->snap_to(**j, true);
+ }
+ }
+
+ for(list<Track *>::iterator i=flext.begin(); i!=flext.end(); ++i)
+ for(set<Track *>::iterator j=tracks.begin(); j!=tracks.end(); ++j)
+ if(*j!=*i)
+ (*i)->snap_to(**j, true);
+}
+
+void Layout::check_routes()
+{
+ for(map<string, Route *>::iterator i=routes.begin(); i!=routes.end(); ++i)
+ {
+ if(i->second->is_temporary())
+ continue;
+
+ /* We must copy the turnout map, since adding tracks to the route will
+ (temporarily) mess it up */
+ const map<unsigned, int> turnouts = i->second->get_turnouts();
+
+ // Find any turnout in the route
+ Track *track = 0;
+ unsigned trk_path = 0;
+ for(set<Track *>::const_iterator j=tracks.begin(); j!=tracks.end(); ++j)
+ {
+ map<unsigned, int>::const_iterator k = turnouts.find((*j)->get_turnout_id());
+ if(k!=turnouts.end())
+ {
+ track = *j;
+ trk_path = k->second;
+ break;
+ }
+ }
+
+ if(!track)
+ continue;
+
+ // Find an applicable endpoint
+ const vector<Endpoint> &eps = track->get_type().get_endpoints();
+ unsigned ep = 0;
+ for(unsigned j=0; j<eps.size(); ++j)
+ if(eps[j].paths&(1<<trk_path))
+ {
+ ep = j;
+ break;
+ }
+
+ Track *start = 0;
+ while(1)
+ {
+ // Traverse the track and get the next one
+ if(track->get_type().get_endpoints().size()<2)
+ break;
+ unsigned out_ep = track->traverse(ep, trk_path);
+ Track *next = track->get_links()[out_ep];
+ if(!next || next == start)
+ break;
+
+ ep = next->get_endpoint_by_link(*track);
+ if(next->get_type().is_turnout())
+ {
+ // Select correct path across the turnout, or break if we hit an unknown turnout
+ map<unsigned, int>::const_iterator j = turnouts.find(next->get_turnout_id());
+ if(j==turnouts.end())
+ break;
+ trk_path = j->second;
+ }
+ else
+ {
+ trk_path = 0;
+
+ /* Start adding tracks when we find the first non-turnout. This
+ prevents the occurrence of ambiguities while adding the tracks */
+ if(!start)
+ start = next;
+ }
+
+ if(start)
+ i->second->add_track(*next);
+
+ track = next;
+ }
+ }
+}
+
+void Layout::sensor_event(unsigned addr, bool state)
+{
+ if(state)
+ {
+ for(set<Block *>::iterator i=blocks.begin(); i!=blocks.end(); ++i)
+ if((*i)->get_sensor_id()==addr)
+ {
+ if(!(*i)->get_train())
+ emergency(format("Unreserved sensor %d triggered", addr));
+ break;
+ }
+ }