]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/train.cpp
Remember the states of locomotive functions
[r2c2.git] / source / libr2c2 / train.cpp
index 858cbbc9e8c8d093971af814a3acb049717ffc37..43723779fbb89f2cfba327659f81aa4410883a38 100644 (file)
@@ -241,33 +241,53 @@ void Train::stop_at(Block *block)
 
 bool Train::is_block_critical(const Block &block) const
 {
-       return get_reserved_distance_until(&block)<=controller->get_braking_distance()*1.3;
+       if(allocator.is_block_current(block))
+               return true;
+
+       BlockIter i = check_critical_blocks(&block);
+       return i.block()==&block;
+}
+
+BlockIter Train::get_last_critical_block() const
+{
+       return check_critical_blocks(0);
 }
 
-BlockIter Train::get_first_noncritical_block() const
+BlockIter Train::check_critical_blocks(const Block *check) const
 {
        if(allocator.empty())
                return BlockIter();
 
-       BlockIter i = allocator.last_current().next();
+       BlockIter i = allocator.last_current();
 
        if(controller->get_speed()==0)
                return i;
 
+       BlockIter last = allocator.last();
+       if(i.block()==last.block())
+               return i;
+
        float margin = 10*layout.get_catalogue().get_scale();
        float min_dist = controller->get_braking_distance()*1.3+margin;
 
        float dist = 0;
        bool sensor_seen = false;
-       for(; i->get_train()==this; i=i.next())
+       i = i.next();
+       while(i.block()!=last.block() && i.block()!=check)
        {
-               if(dist>min_dist && sensor_seen)
-                       return i;
-
                dist += i->get_path_length(i.entry());
 
                if(i->get_sensor_address())
                        sensor_seen = true;
+
+               if(dist>min_dist && sensor_seen)
+                       break;
+
+               BlockIter j = i.next();
+               if(j->get_train()!=this)
+                       break;
+
+               i = j;
        }
 
        return i;
@@ -276,7 +296,7 @@ BlockIter Train::get_first_noncritical_block() const
 void Train::refresh_blocks_from(Block &block)
 {
        if(is_block_critical(block))
-               allocator.rewind_to(*get_first_noncritical_block());
+               allocator.rewind_to(*get_last_critical_block().next());
        else
                allocator.rewind_to(block);
 }
@@ -397,6 +417,10 @@ void Train::save(list<DataFile::Statement> &st) const
                st.push_back(ss);
        }
 
+       const VehicleType::FunctionMap &func_map = loco_type.get_functions();
+       for(VehicleType::FunctionMap::const_iterator i=func_map.begin(); i!=func_map.end(); ++i)
+               st.push_back((DataFile::Statement("function"), i->first, static_cast<bool>(functions&(1<<i->first))));
+
        // XXX Need more generic way of saving AI state
        for(list<TrainAI *>::const_iterator i=ais.begin(); i!=ais.end(); ++i)
        {
@@ -573,6 +597,7 @@ Train::Loader::Loader(Train &t):
        blocks_valid(true)
 {
        add("blocks",      &Loader::blocks);
+       add("function",    &Loader::function);
        add("name",        &Loader::name);
        add("quantized_speed",  &Loader::quantized_speed);
        add("router",      &Loader::router);
@@ -595,6 +620,11 @@ void Train::Loader::blocks()
        load_sub(obj.allocator);
 }
 
+void Train::Loader::function(unsigned f, bool s)
+{
+       obj.set_function(f, s);
+}
+
 void Train::Loader::name(const string &n)
 {
        obj.set_name(n);