}
else
{
- const TrackType::Endpoint &entry_ep = track.endpoint();
unsigned path = track->get_active_path();
- if(!entry_ep.has_path(path))
+ if(!track.endpoint().has_path(path))
{
- const TrackType::Endpoint &exit_ep = track.reverse().endpoint();
- if(entry_ep.has_common_paths(exit_ep))
+ path = track->get_type().coerce_path(track.entry(), path);
+ track->set_active_path(path);
+ if(track->is_path_changing())
{
- unsigned mask = entry_ep.paths&exit_ep.paths;
- for(path=0; mask>1; ++path, mask>>=1) ;
-
- track->set_active_path(path);
- if(track->is_path_changing())
- {
- pending_block = &*block;
- break;
- }
- }
- else
- // XXX Do something here
+ pending_block = &*block;
break;
+ }
}
}
return n;
}
+unsigned TrackType::coerce_path(unsigned entry, unsigned path) const
+{
+ const Endpoint &ep = get_endpoint(entry);
+ if(ep.has_path(path))
+ return path;
+
+ unsigned paths = get_paths();
+ if(paths>>(1<<state_bits))
+ {
+ /* There are more paths than can be expressed with state_bits, so
+ multiple paths are set at once. See if one of the alternatives fits. */
+ unsigned step = 1<<state_bits;
+ for(unsigned p=path+step; paths>>p; p+=step)
+ if(ep.has_path(p))
+ return p;
+ }
+
+ // Find an endpoint that's connected to the entry and has the requested path
+ for(vector<Endpoint>::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
+ if(i->has_path(path) && i->has_common_paths(ep))
+ {
+ unsigned p = 1;
+ for(unsigned m=i->paths&ep.paths; m>>p; ++p) ;
+ return p-1;
+ }
+
+ // TODO crossings fall here
+ throw logic_error("TrackType::coerce_path");
+}
+
bool TrackType::is_turnout() const
{
return endpoints.size()>2;
float get_path_length(int) const;
unsigned get_paths() const;
unsigned get_n_paths() const;
+ unsigned coerce_path(unsigned, unsigned) const;
unsigned get_state_bits() const { return state_bits; }
bool is_turnout() const;
bool is_dead_end() const;