+bool TrainRoutePlanner::RoutingStep::update_states()
+{
+ bool changes = false;
+ for(vector<TrainRoutingState>::iterator i=trains.begin(); i!=trains.end(); ++i)
+ {
+ if(i->state==ARRIVED)
+ continue;
+
+ TrainState old_state = i->state;
+
+ TrackIter next_track = i->track.next(i->path);
+ if(next_track)
+ {
+ i->blocked_by = get_occupant(*next_track);
+ if(i->blocked_by>=0)
+ i->state = BLOCKED;
+ else if(i->state==BLOCKED)
+ i->state = MOVING;
+ }
+ else
+ i->state = BLOCKED;
+
+ if(i->state!=old_state)
+ changes = true;
+ }
+
+ return changes;
+}
+
+bool TrainRoutePlanner::RoutingStep::check_deadlocks() const
+{
+ for(unsigned i=0; i<trains.size(); ++i)
+ {
+ const TrainRoutingState &train = trains[i];
+ if(train.state!=BLOCKED)
+ continue;
+
+ if(train.blocked_by<0)
+ return true;
+
+ if(trains[train.blocked_by].blocked_by==static_cast<int>(i))
+ return true;
+ }
+
+ return false;
+}
+
+int TrainRoutePlanner::RoutingStep::get_occupant(Track &track) const
+{
+ for(unsigned i=0; i<trains.size(); ++i)
+ if(trains[i].is_occupied(track))
+ return i;
+
+ return -1;
+}
+
+int TrainRoutePlanner::RoutingStep::find_next_train() const
+{
+ Time::TimeDelta min_dt;
+ int next_train = -1;
+ for(unsigned i=0; i<trains.size(); ++i)
+ if(trains[i].state==MOVING)
+ {
+ Time::TimeDelta dt = trains[i].get_time_to_next_track();
+ if(dt<min_dt || next_train<0)
+ {
+ min_dt = dt;
+ next_train = i;
+ }
+ }
+
+ return next_train;
+}
+