From ecd7af790bd3ab7c7e768f68968379e1feea56a9 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 12 Feb 2015 16:46:45 +0200 Subject: [PATCH] Fix critical block logic First noncritical block is not reliable, as it could be outside of the train's allocated blocks and not guaranteed to set to a consistent path. Worse, the get_first_noncritical_block function could return a block on the other side of a turnout which is changing path, and is_block_critical used completely different logic. --- source/libr2c2/train.cpp | 36 +++++++++++++++++++++------- source/libr2c2/train.h | 5 +++- source/libr2c2/trainrouteplanner.cpp | 2 +- source/libr2c2/trainrouter.cpp | 15 ++++++------ 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index 858cbbc..b1fbc6a 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -241,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()==█ +} + +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; @@ -276,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); } diff --git a/source/libr2c2/train.h b/source/libr2c2/train.h index 113af0e..dff9aae 100644 --- a/source/libr2c2/train.h +++ b/source/libr2c2/train.h @@ -121,7 +121,10 @@ public: 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; diff --git a/source/libr2c2/trainrouteplanner.cpp b/source/libr2c2/trainrouteplanner.cpp index 9bed406..9f19ffc 100644 --- a/source/libr2c2/trainrouteplanner.cpp +++ b/source/libr2c2/trainrouteplanner.cpp @@ -214,7 +214,7 @@ void TrainRoutePlanner::finalize_plan() 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()), waypoints(router ? router->get_n_waypoints() : 0), has_duration(false) diff --git a/source/libr2c2/trainrouter.cpp b/source/libr2c2/trainrouter.cpp index d95bdff..3d8b9d4 100644 --- a/source/libr2c2/trainrouter.cpp +++ b/source/libr2c2/trainrouter.cpp @@ -83,7 +83,7 @@ void TrainRouter::use_planned_route() 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(); @@ -438,23 +438,24 @@ bool TrainRouter::create_lead_route() 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) @@ -464,7 +465,7 @@ bool TrainRouter::create_lead_route() } 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)) { -- 2.45.2