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()==█
+}
+
+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;
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);
}
{
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;