X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrainrouteplanner.cpp;h=5bffec1d899c535fc295bf2847faea29d7a2987d;hb=ace4d2175dce7364ff094b8dd44c53e47ba395b1;hp=163bb281eacd019997e8975802f670a0d904ce6f;hpb=dd41422054c277b44059d5d2d127ce34a2c2119f;p=r2c2.git diff --git a/source/libr2c2/trainrouteplanner.cpp b/source/libr2c2/trainrouteplanner.cpp index 163bb28..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; @@ -427,6 +461,7 @@ TrainRoutePlanner::RoutingStep::RoutingStep(): TrainRoutePlanner::RoutingStep::RoutingStep(const RoutingStep *p): time(p->time), + penalty(p->penalty), cost_estimate(p->cost_estimate), trains(p->trains), prev(p) @@ -463,21 +498,41 @@ 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(); ) + { + i->penalty += 5*Time::sec; + 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); wait.trains[train_index].state = WAITING; + wait.penalty += 15*Time::sec; + wait.update_estimate(); if(wait.is_viable()) new_steps.push_back(wait); } @@ -573,7 +628,7 @@ void TrainRoutePlanner::RoutingStep::advance(const Time::TimeDelta &dt) void TrainRoutePlanner::RoutingStep::update_estimate() { - cost_estimate = Time::zero; + cost_estimate = penalty; for(vector::const_iterator i=trains.begin(); i!=trains.end(); ++i) if(i->remaining_estimate>=0) cost_estimate += i->wait_time+((i->distance_traveled+i->remaining_estimate)/i->info->speed)*Time::sec;