]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/train.cpp
Fix critical block logic
[r2c2.git] / source / libr2c2 / train.cpp
index 6ba868461b6da2eb5e995673053eada3f55a6369..b1fbc6a76ebb1bf4ad02f85d981f465fef1a1759 100644 (file)
@@ -5,13 +5,11 @@
 #include <msp/strings/format.h>
 #include <msp/time/units.h>
 #include <msp/time/utils.h>
-#include "aicontrol.h"
 #include "beamgate.h"
 #include "block.h"
 #include "catalogue.h"
 #include "driver.h"
 #include "layout.h"
-#include "route.h"
 #include "simplecontroller.h"
 #include "speedquantizer.h"
 #include "timetable.h"
@@ -22,7 +20,6 @@
 #include "trainrouter.h"
 #include "vehicle.h"
 #include "vehicletype.h"
-#include "zone.h"
 
 using namespace std;
 using namespace Msp;
@@ -244,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;
@@ -279,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);
 }
@@ -301,12 +318,9 @@ void Train::tick(const Time::TimeDelta &dt)
 {
        if(stop_timeout)
        {
-               stop_timeout -= dt;
+               stop_timeout = max(stop_timeout-dt, Time::zero);
                if(stop_timeout<=Time::zero)
-               {
                        allocator.set_active(false);
-                       stop_timeout = Time::TimeDelta();
-               }
        }
 
        travel_time += dt;