The previous attempt didn't release any blocks if the last vehicle was
still behind the last active sensor, which is almost always the case. And
if it did manage to release anything, it would have released too much.
/* Sensors aren't guaranteed to be detriggered in order. Go through the
block list and locate the first sensor that's still active. */
/* Sensors aren't guaranteed to be detriggered in order. Go through the
block list and locate the first sensor that's still active. */
- Sensor *last_inactive = 0;
- for(BlockList::iterator i=blocks.begin(); (i!=cur_blocks_end && i->block()!=&veh_block); ++i)
+ BlockList::iterator end = blocks.end();
+ for(BlockList::iterator i=blocks.begin(); i!=cur_blocks_end; ++i)
- if(Sensor *sensor = (*i)->get_sensor())
- sensors.push_back(sensor);
+ /* Collect all sensors from the block in the order they are expected to
+ detrigger. */
for(TrackIter j=i->track_iter(); (j && &j->get_block()==block); j=j.next())
if(!j->get_attachments().empty())
{
for(TrackIter j=i->track_iter(); (j && &j->get_block()==block); j=j.next())
if(!j->get_attachments().empty())
{
sensors.push_back(gate);
}
sensors.push_back(gate);
}
- for(list<Sensor *>::const_iterator j=sensors.begin(); j!=sensors.end(); ++j)
+ if(Sensor *sensor = (*i)->get_sensor())
+ sensors.push_back(sensor);
+
+ /* See if any sensor is still active, and record the position of the
+ last inactive sensor. */
+ bool active_sensor = false;
+ for(list<Sensor *>::const_iterator j=sensors.begin(); (!active_sensor && j!=sensors.end()); ++j)
+ active_sensor = true;
+ else
+ end = i;
+ }
+
+ // Stop if we encounter an active sensor or the train's last vehicle
+ if(block==&veh_block || active_sensor)
+ {
+ if(end!=blocks.end())
- if(last_inactive)
- {
- if(dynamic_cast<BeamGate *>(*j))
- ++i;
- release_blocks_begin(i);
- }
- return;
+ /* If the last inactive sensor was in an earlier block, release
+ that block as well. */
+ if(i!=end)
+ ++end;
+ release_blocks_begin(end);
- else
- last_inactive = *j;