]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/trainroutemetric.cpp
Don't crash if a train has no router
[r2c2.git] / source / libr2c2 / trainroutemetric.cpp
index 1fc4fcea2389d917ecaa90627791801dc0ee46e2..6577c84c7ff1ee732be6cb31cb4de305b319aac8 100644 (file)
@@ -9,22 +9,28 @@ namespace R2C2 {
 
 TrainRouteMetric::TrainRouteMetric(const TrackChain &tc, TrackChain::Direction dir)
 {
-       /* Initialize goals for tracks in the target chain.  We travel outwards from
-       the target in the search phase so the iters appear to point the wrong way. */
-       TrackChain::Direction reverse_dir = (dir==TrackChain::DOWN ? TrackChain::UP : TrackChain::DOWN);
-       const TrackChain::TrackSet &ctracks = tc.get_tracks();
-       for(TrackChain::TrackSet::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i)
+       vector<TrackIter> ends;
+       if(dir==TrackChain::UNSPECIFIED)
        {
-               if(dir==TrackChain::UNSPECIFIED)
+               for(unsigned i=0; i<2; ++i)
+                       if(TrackIter end = tc.get_end(i))
+                               ends.push_back(end);
+       }
+       else if(TrackIter end = tc.get_end(dir))
+               ends.push_back(end);
+
+       /* Initialize goals for the ends of the target chain.  We travel away from
+       the goals in the search phase so the iters appear to point the wrong way. */
+       for(vector<TrackIter>::const_iterator i=ends.begin(); i!=ends.end(); ++i)
+       {
+               const TrackType::Endpoint &ep = i->endpoint();
+               unsigned nls = (*i)->get_n_link_slots();
+               for(unsigned j=0; j<nls; ++j)
                {
-                       unsigned nls = (*i)->get_n_link_slots();
-                       for(unsigned j=0; j<nls; ++j)
-                               if(Track *link = (*i)->get_link(j))
-                                       if(!ctracks.count(link))
-                                               goals.push_back(TrackIter(*i, j));
+                       TrackIter iter(i->track(), j);
+                       if(ep.has_common_paths(iter.endpoint()))
+                               goals.push_back(iter);
                }
-               else if(TrackIter iter = tc.iter_for(**i, reverse_dir))
-                       goals.push_back(iter);
        }
 
        list<TrackIter> queue;
@@ -44,6 +50,8 @@ TrainRouteMetric::TrainRouteMetric(const TrackChain &tc, TrackChain::Direction d
                const Data &data = tracks[Key(track.track(), track.entry())];
 
                const TrackType::Endpoint &ep = track.endpoint();
+
+               float multiplier = get_travel_multiplier(*track, track.entry());
                for(unsigned i=0; ep.paths>>i; ++i)
                        if(ep.has_path(i))
                        {
@@ -52,7 +60,7 @@ TrainRouteMetric::TrainRouteMetric(const TrackChain &tc, TrackChain::Direction d
                                        continue;
 
                                Data &target = tracks[Key(next.track(), next.entry())];
-                               float dist = data.distance+track->get_type().get_path_length(i);
+                               float dist = data.distance+track->get_type().get_path_length(i)*multiplier;
                                if(target.distance<0 || target.distance>dist)
                                {
                                        target = Data(dist, data.goal);
@@ -93,6 +101,15 @@ float TrainRouteMetric::get_distance_from(const Track &track, unsigned exit) con
        return i->second.distance+i->second.goal->base_distance;
 }
 
+float TrainRouteMetric::get_travel_multiplier(const Track &track, unsigned exit) const
+{
+       int pref = track.get_preferred_exit();
+       if(pref>=0 && exit!=static_cast<unsigned>(pref))
+               return 5;
+
+       return 1;
+}
+
 
 TrainRouteMetric::Goal::Goal():
        base_distance(0)