+void Train::free_noncritical_blocks()
+{
+ if(blocks.empty())
+ return;
+
+ if(controller->get_speed()==0)
+ {
+ release_blocks(cur_blocks_end, blocks.end());
+ return;
+ }
+
+ 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(), veh.get_entry());
+ BlockList::iterator block = blocks.begin();
+ bool in_rsv = false;
+ while(block!=blocks.end() && !(*block)->has_track(*track))
+ {
+ ++block;
+ if(block==cur_blocks_end)
+ in_rsv = true;
+ }
+
+ 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)
+ {
+ track = track.next();
+
+ if(!(*block)->has_track(*track))
+ {
+ ++block;
+ if(block==cur_blocks_end)
+ in_rsv = true;
+ if(block==blocks.end())
+ return;
+
+ if(dist>min_dist && nsens>0)
+ {
+ release_blocks(block, blocks.end());
+ return;
+ }
+
+ if(in_rsv && (*block)->get_sensor_id())
+ ++nsens;
+ }
+
+ dist += track->get_type().get_path_length(track->get_active_path());
+ }
+}
+