]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/train.cpp
Ensure that turnout tracks have a turnout id
[r2c2.git] / source / libr2c2 / train.cpp
index b7dc2470c4c1a98e98e5aae789c39e4130e1f31f..7224247b5c4aaf26e8ad950d533113b24773e75b 100644 (file)
@@ -6,6 +6,7 @@
 #include <msp/time/units.h>
 #include <msp/time/utils.h>
 #include "aicontrol.h"
+#include "block.h"
 #include "catalogue.h"
 #include "driver.h"
 #include "layout.h"
@@ -13,6 +14,7 @@
 #include "simplecontroller.h"
 #include "speedquantizer.h"
 #include "timetable.h"
+#include "trackcircuit.h"
 #include "trackiter.h"
 #include "tracktype.h"
 #include "train.h"
@@ -60,7 +62,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p):
        layout.get_driver().signal_loco_speed.connect(sigc::mem_fun(this, &Train::loco_speed_event));
        layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event));
 
-       layout.signal_block_state_changed.connect(sigc::mem_fun(this, &Train::block_state_changed));
+       layout.signal_sensor_state_changed.connect(sigc::mem_fun(this, &Train::sensor_state_changed));
 
        layout.get_driver().signal_halt.connect(sigc::mem_fun(this, &Train::halt_event));
 
@@ -232,7 +234,7 @@ void Train::stop_at(Block *block)
 
 bool Train::free_block(Block &block)
 {
-       if(get_reserved_distance_until(&block, false)<controller->get_braking_distance()*1.3)
+       if(get_reserved_distance_until(&block)<controller->get_braking_distance()*1.3)
                return false;
 
        return allocator.release_from(block);
@@ -252,53 +254,21 @@ void Train::free_noncritical_blocks()
        float margin = 10*layout.get_catalogue().get_scale();
        float min_dist = controller->get_braking_distance()*1.3+margin;
 
-       Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front());
-
-       TrackIter track = veh.get_track_iter();
-       BlockIter block = allocator.first();
-       const BlockIter &last_cur = allocator.last_current();
-       const BlockIter &last = allocator.last();
-       bool in_rsv = false;
-       while(!block->has_track(*track))
-       {
-               if(&*block==&*last_cur)
-                       in_rsv = true;
-               if(&*block==&*last)
-                       break;
-               block = block.next();
-       }
-
-       float dist = veh.get_offset();
-       if(reverse)
-               track.reverse();
-       else
-               dist = track->get_type().get_path_length(track->get_active_path())-dist;
-       dist -= veh.get_type().get_length()/2;
-
-       bool nsens = 0;
-       while(1)
+       BlockIter i = allocator.last_current().next();
+       float dist = 0;
+       bool sensor_seen = false;
+       for(; i->get_train()==this; i=i.next())
        {
-               track = track.next();
-
-               if(!block->has_track(*track))
+               if(dist>min_dist && sensor_seen)
                {
-                       if(&*block==&*last_cur)
-                               in_rsv = true;
-                       if(&*block==&*last)
-                               return;
-                       block = block.next();
-
-                       if(dist>min_dist && nsens>0)
-                       {
-                               allocator.release_from(*block);
-                               return;
-                       }
-
-                       if(in_rsv && block->get_sensor_id())
-                               ++nsens;
+                       allocator.release_from(*i);
+                       return;
                }
 
-               dist += track->get_type().get_path_length(track->get_active_path());
+               dist += i->get_path_length(i.entry());
+
+               if(i->get_sensor_id())
+                       sensor_seen = true;
        }
 }
 
@@ -312,7 +282,7 @@ float Train::get_reserved_distance() const
        if(next && next->get_type().is_turnout())
                margin = 15*layout.get_catalogue().get_scale();
 
-       return max(get_reserved_distance_until(0, false)-margin, 0.0f);
+       return max(get_reserved_distance_until(0)-margin, 0.0f);
 }
 
 void Train::reserve_more()
@@ -386,14 +356,6 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt)
                        }
                }
        }
-
-       if(!allocator.empty() && !allocator.first()->get_sensor_id())
-       {
-               float dist = get_reserved_distance_until(&*allocator.first(), true);
-
-               if(dist>10*layout.get_catalogue().get_scale())
-                       allocator.release_until(*allocator.first());
-       }
 }
 
 void Train::save(list<DataFile::Statement> &st) const
@@ -468,9 +430,15 @@ void Train::loco_func_event(unsigned addr, unsigned func, bool state)
        }
 }
 
-void Train::block_state_changed(Block &block, Block::State state)
+void Train::sensor_state_changed(Sensor &sensor, Sensor::State state)
 {
-       if(block.get_train()==this && state==Block::MAYBE_ACTIVE)
+       Block *block = 0;
+       if(TrackCircuit *tc = dynamic_cast<TrackCircuit *>(&sensor))
+               block = &tc->get_block();
+       else
+               return;
+
+       if(block->get_train()==this && state==Sensor::MAYBE_ACTIVE)
        {
                if(last_entry_block)
                {
@@ -478,7 +446,7 @@ void Train::block_state_changed(Block &block, Block::State state)
                        if(pure_speed && speed_quantizer && current_speed_step>0)
                                travel_distance = 0;
 
-                       for(BlockIter i=last_entry_block; &*i!=&block; i=i.next())
+                       for(BlockIter i=last_entry_block; &*i!=block; i=i.next())
                        {
                                if(i->get_sensor_id())
                                        return;
@@ -495,7 +463,7 @@ void Train::block_state_changed(Block &block, Block::State state)
                        }
                }
 
-               last_entry_block = allocator.iter_for(block);
+               last_entry_block = allocator.iter_for(*block);
                last_entry_time = Time::now();
                pure_speed = true;
                accurate_position = true;
@@ -521,65 +489,44 @@ void Train::halt_event(bool h)
                accurate_position = false;
 }
 
-float Train::get_reserved_distance_until(const Block *until_block, bool back) const
+float Train::get_reserved_distance_until(const Block *until_block) const
 {
        if(allocator.empty())
                return 0;
 
-       Vehicle &veh = *(reverse!=back ? vehicles.back() : vehicles.front());
-       const VehicleType &vtype = veh.get_type();
+       Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front());
 
        TrackIter track = veh.get_track_iter();
        if(!track)  // XXX Probably unnecessary
                return 0;
 
-       const BlockIter &first = allocator.first();
-       const BlockIter &last = allocator.last();
-       BlockIter block = first;
-       while(!block->has_track(*track))
-       {
-               if(&*block==&*last)
-                       return 0;
-               block = block.next();
-       }
+       BlockIter block = track.block_iter();
        if(&*block==until_block)
                return 0;
 
-       if(back)
-               block = block.reverse();
-
+       // Account for the vehicle's offset on its current track
        float result = veh.get_offset();
-       if(reverse!=back)
+       if(reverse)
                track = track.reverse();
        else
                result = track->get_type().get_path_length(track->get_active_path())-result;
-       result -= vtype.get_length()/2;
+       result -= veh.get_type().get_length()/2;
 
-       while(1)
-       {
-               track = track.next();
-               if(!track)
-                       break;
+       // Count remaining distance in the vehicle's current block
+       for(track=track.next(); &track->get_block()==&*block; track=track.next())
+               result += track->get_type().get_path_length(track->get_active_path());
 
-               if(!block->has_track(*track))
-               {
-                       if(back)
-                       {
-                               if(&*block==&*first)
-                                       break;
-                       }
-                       else
-                       {
-                               if(&*block==&*last)
-                                       break;
-                       }
-                       block = block.next();
+       const BlockIter &last = allocator.last();
+       if(&*block==&*last)
+               return result;
 
-                       if(&*block==until_block)
-                               break;
-               }
+       // Count any remaining blocks
+       for(block=block.next(); (&*block!=until_block && block->get_train()==this); block=block.next())
+       {
+               result += block->get_path_length(block.entry());
 
-               result += track->get_type().get_path_length(track->get_active_path());
+               if(&*block==&*last)
+                       break;
        }
 
        return result;