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);
}
bool is_placed() const { return !allocator.empty(); }
void stop_at(Block *);
bool is_block_critical(const Block &) const;
- BlockIter get_first_noncritical_block() const;
+ BlockIter get_last_critical_block() const;
+private:
+ BlockIter check_critical_blocks(const Block *) const;
+public:
void refresh_blocks_from(Block &);
const BlockAllocator &get_block_allocator() const { return allocator; }
float get_reserved_distance() const;
TrainRoutePlanner::TrainRoutingInfo::TrainRoutingInfo(Train &t):
train(&t),
speed(train->get_maximum_speed()),
- first_noncritical(train->get_first_noncritical_block().block()),
+ first_noncritical(train->get_last_critical_block().next().block()),
router(train->get_ai_of_type<TrainRouter>()),
waypoints(router ? router->get_n_waypoints() : 0),
has_duration(false)
void TrainRouter::route_changed()
{
- BlockIter fncb = train.get_first_noncritical_block();
+ BlockIter fncb = train.get_last_critical_block().next();
arrival = ON_THE_WAY;
reserving_route = routes.begin();
if(routes.empty() || !train.is_placed())
return false;
- BlockIter fncb = train.get_first_noncritical_block();
- TrackIter next_track = fncb.track_iter();
+ BlockIter lcb = train.get_last_critical_block();
+ TrackIter last_track_rev = lcb.reverse().track_iter();
unsigned count = 0;
- for(TrackIter i=next_track.flip(); (i && i->get_block().get_train()==&train); i=i.next())
+ for(TrackIter i=last_track_rev; (i && i->get_block().get_train()==&train); i=i.next())
{
if(routes.front()->has_track(*i))
++count;
else if(count>0)
{
if(count==routes.front()->get_tracks().size())
- next_track = i.flip();
+ last_track_rev = i;
break;
}
}
- if(!routes.front()->has_track(*next_track) && !routes.front()->has_track(*next_track.flip()))
+ TrackIter next_track = last_track_rev.flip();
+ if(!routes.front()->has_track(*last_track_rev) && !routes.front()->has_track(*next_track))
{
Route *pf = Route::find(next_track, *routes.front());
if(!pf)
}
Route *lead = 0;
- for(TrackIter i=next_track.flip(); (i && i->get_block().get_train()==&train); i=i.next())
+ for(TrackIter i=last_track_rev; (i && i->get_block().get_train()==&train); i=i.next())
{
if(!lead && !routes.front()->has_track(*i))
{