]> git.tdb.fi Git - r2c2.git/commitdiff
Move path coercion to TrackType
authorMikko Rasa <tdb@tdb.fi>
Thu, 10 Apr 2014 19:01:54 +0000 (22:01 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 10 Apr 2014 19:29:07 +0000 (22:29 +0300)
source/libr2c2/blockallocator.cpp
source/libr2c2/tracktype.cpp
source/libr2c2/tracktype.h

index ed32193f3e1d116b65b557d9bb8619f82dc0bf41..88fb12e8145baaf3f4e636311f9664b5a0a86e1d 100644 (file)
@@ -253,26 +253,16 @@ void BlockAllocator::reserve_more()
                }
                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;
+                               }
                        }
                }
 
index 7a1f27ad5adcc69ee282a028d10755dabf68d37a..59b8f9ca275b4fe508b94fe77c32ec220ab83472 100644 (file)
@@ -44,6 +44,36 @@ unsigned TrackType::get_n_paths() const
        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;
index 64efe8c1907f27541d08af89a2898aa4c02040ac..56d164f1b652a308a58a7ec1b0cf7505d6491631 100644 (file)
@@ -56,6 +56,7 @@ public:
        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;