]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/train.cpp
Add a timetable command to travel past a turnout
[r2c2.git] / source / libr2c2 / train.cpp
index 28976838fcf7da9c699ed11b8b461cdab566fd41..1447ca58df834c86f7a14d27610e0959bb38c560 100644 (file)
@@ -443,8 +443,7 @@ void Train::unplace()
 
 bool Train::free_block(Block &block)
 {
-       float margin = 10*layout.get_catalogue().get_scale();
-       if(get_reserved_distance_until(&block, false)<controller->get_braking_distance()*1.3+margin)
+       if(get_reserved_distance_until(&block, false)<controller->get_braking_distance()*1.3)
                return false;
 
        unsigned nsens = 0;
@@ -534,7 +533,15 @@ int Train::get_entry_to_block(Block &block) const
 
 float Train::get_reserved_distance() const
 {
-       return get_reserved_distance_until(0, false);
+       if(blocks.empty())
+               return 0;
+
+       float margin = 0;
+       TrackIter next = blocks.back().next().track_iter();
+       if(next->get_type().is_turnout())
+               margin = 15*layout.get_catalogue().get_scale();
+
+       return max(get_reserved_distance_until(0, false)-margin, 0.0f);
 }
 
 void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt)
@@ -675,11 +682,13 @@ void Train::control_changed(const Controller::Control &ctrl)
        signal_control_changed.emit(ctrl.name, ctrl.value);
 }
 
-void Train::loco_speed_event(unsigned addr, unsigned speed, bool)
+void Train::loco_speed_event(unsigned addr, unsigned speed, bool rev)
 {
        if(addr==address)
        {
                current_speed_step = speed;
+               if(rev!=reverse)
+                       layout.get_driver().set_loco_reverse(address, reverse);
                speed_changing = false;
                pure_speed = false;
        }
@@ -773,6 +782,8 @@ void Train::sensor_event(unsigned addr, bool state)
                        }
 
                        // Move blocks up to the next sensor to our current blocks
+                       for(BlockList::iterator j=cur_blocks_end; j!=end; ++j)
+                               signal_advanced.emit(**j);
                        cur_blocks_end = end;
 
                        // Try to get more blocks if we're moving
@@ -872,7 +883,10 @@ void Train::reserve_more()
                if(!block || block->get_endpoints().size()<2)
                {
                        if(!blocking_train)
+                       {
                                good_end = blocks.end();
+                               end_of_route = true;
+                       }
                        break;
                }
 
@@ -976,7 +990,7 @@ void Train::reserve_more()
                                contested_blocks.push_back(block);
                                continue;
                        }
-                       else if(divert_track && (entry_conflict || exit_conflict))
+                       else if(divert_track && (entry_conflict || exit_conflict || !other_train->is_active()))
                                // We are blocked, but there's a diversion possibility
                                try_divert = true;
 
@@ -1175,10 +1189,10 @@ unsigned Train::find_speed_step(float real) const
                if(real_speed[i].weight)
                {
                        last = i;
-                       if(real_speed[i].speed<real)
-                               low = i;
-                       else
+                       if(real_speed[i].speed>=real)
                                high = i;
+                       else if(real_speed[i].speed>real_speed[low].speed)
+                               low = i;
                }
        if(!high)
        {
@@ -1289,7 +1303,7 @@ bool Train::is_valid_diversion(const Route &diversion, const TrackIter &from)
 
                track1 = track1.next(path);
 
-               if(track1.looped())
+               if(!track1 || track1.looped())
                        return false;
        }
 
@@ -1307,6 +1321,8 @@ bool Train::is_valid_diversion(const Route &diversion, const TrackIter &from)
                bool ok = (track2!=from && diversion.has_track(*track2));
 
                track2 = track2.next(path);
+               if(!track2)
+                       return false;
 
                if(ok)
                        break;