X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrainrouteplanner.cpp;h=5bffec1d899c535fc295bf2847faea29d7a2987d;hb=ace4d2175dce7364ff094b8dd44c53e47ba395b1;hp=dbe6035499c9e61663b2f6337448c35e5518b9d2;hpb=9976acc82d98c8aecde0152a72be8cc8882e35ff;p=r2c2.git diff --git a/source/libr2c2/trainrouteplanner.cpp b/source/libr2c2/trainrouteplanner.cpp index dbe6035..5bffec1 100644 --- a/source/libr2c2/trainrouteplanner.cpp +++ b/source/libr2c2/trainrouteplanner.cpp @@ -29,7 +29,11 @@ TrainRoutePlanner::TrainRoutePlanner(Layout &layout): TrainRoutePlanner::~TrainRoutePlanner() { - delete thread; + if(thread) + { + thread->join(); + delete thread; + } } TrainRoutePlanner::Result TrainRoutePlanner::plan() @@ -55,9 +59,13 @@ TrainRoutePlanner::Result TrainRoutePlanner::check() { if(result==PENDING && goal) { + if(thread) + { + thread->join(); + delete thread; + thread = 0; + } finalize_plan(); - delete thread; - thread = 0; } return result; @@ -206,6 +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()), router(train->get_ai_of_type()), destination(0), has_duration(false) @@ -213,15 +222,18 @@ TrainRoutePlanner::TrainRoutingInfo::TrainRoutingInfo(Train &t): if(router) { destination = router->get_destination(); - waypoints.resize(router->get_n_waypoints()); - metrics.resize(waypoints.size()+1); - metrics[0] = &router->get_metric(-1); - for(unsigned i=0; iget_waypoint(i); - metrics[i+1] = &router->get_metric(i); + waypoints.resize(router->get_n_waypoints()); + metrics.resize(waypoints.size()+1); + metrics[0] = &router->get_metric(-1); + for(unsigned i=0; iget_waypoint(i); + metrics[i+1] = &router->get_metric(i); + } + has_duration = router->get_trip_duration(); } - has_duration = router->get_trip_duration(); } // If no maximum speed is specified, use a sensible default @@ -261,6 +273,7 @@ TrainRoutePlanner::OccupiedTrack::~OccupiedTrack() TrainRoutePlanner::TrainRoutingState::TrainRoutingState(TrainRoutingInfo &inf): info(&inf), + critical(true), occupied_tracks(0), state(MOVING), delay(info->router->get_departure_delay()), @@ -296,6 +309,7 @@ TrainRoutePlanner::TrainRoutingState::TrainRoutingState(const TrainRoutingState info(other.info), track(other.track), path(other.path), + critical(other.critical), occupied_tracks(other.occupied_tracks), offset(other.offset), back_offset(other.back_offset), @@ -350,6 +364,9 @@ bool TrainRoutePlanner::TrainRoutingState::check_arrival() waypoint = -1; } + if(info->first_noncritical->has_track(*track)) + critical = false; + return false; } @@ -358,20 +375,37 @@ void TrainRoutePlanner::TrainRoutingState::advance(float distance) offset += distance; back_offset += distance; - OccupiedTrack *last_occ = occupied_tracks; - for(unsigned n=occupied_tracks->n_tracks; n>1; --n) - last_occ = last_occ->next; + unsigned count_to_free = 0; + unsigned last_sensor_addr = 0; + float distance_after_sensor = 0; + OccupiedTrack *occ = occupied_tracks; + for(unsigned n=occupied_tracks->n_tracks; n>0; --n) + { + if(unsigned saddr = occ->track->get_sensor_address()) + { + if(saddr!=last_sensor_addr) + { + count_to_free = 0; + distance_after_sensor = 0; + } + last_sensor_addr = saddr; + } - // XXX What if there's multiple tracks to remove? - if(back_offset>last_occ->path_length) + ++count_to_free; + distance_after_sensor += occ->path_length; + + occ = occ->next; + } + + if(count_to_free && back_offset>distance_after_sensor) { - back_offset -= last_occ->path_length; + back_offset -= distance_after_sensor; if(occupied_tracks->refcount>1) { --occupied_tracks->refcount; occupied_tracks = new OccupiedTrack(*occupied_tracks); } - --occupied_tracks->n_tracks; + occupied_tracks->n_tracks -= count_to_free; } distance_traveled += distance; @@ -464,15 +498,26 @@ void TrainRoutePlanner::RoutingStep::create_successors(list &new_st train.advance_track(0); const TrackType::Endpoint &next_entry_ep = next_track.endpoint(); - for(unsigned i=0; next_entry_ep.paths>>i; ++i) - if(next_entry_ep.has_path(i)) - { - train.path = i; - train.update_estimate(); - next.update_estimate(); - if(next.is_viable()) - new_steps.push_back(next); - } + if(train.critical) + { + train.path = train.track->get_type().coerce_path(train.track.entry(), train.track->get_active_path()); + train.update_estimate(); + next.update_estimate(); + if(next.is_viable()) + new_steps.push_back(next); + } + else + { + for(unsigned i=0; next_entry_ep.paths>>i; ++i) + if(next_entry_ep.has_path(i)) + { + train.path = i; + train.update_estimate(); + next.update_estimate(); + if(next.is_viable()) + new_steps.push_back(next); + } + } new_steps.sort(); for(list::iterator i=new_steps.begin(); ++i!=new_steps.end(); ) @@ -481,7 +526,7 @@ void TrainRoutePlanner::RoutingStep::create_successors(list &new_st i->update_estimate(); } - if(next_entry_ep.paths!=next_track->get_type().get_paths()) + if(next_entry_ep.paths!=next_track->get_type().get_paths() && !train.critical) { RoutingStep wait(this); wait.advance(dt);