X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrain.cpp;h=ea4599fa9545eb2465d9ba2d0a1a5c85efc583d5;hb=2c0a478641a10a739557d055f80354a28936ced1;hp=dd7139f864824c7aac2e80b1eea4f8c40691c6ab;hpb=1ff06c5bc46a677fa389ef86c6b26664368f1653;p=r2c2.git diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index dd7139f..ea4599f 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -21,6 +21,7 @@ Distributed under the GPL #include "train.h" #include "vehicle.h" #include "vehicletype.h" +#include "zone.h" using namespace std; using namespace Msp; @@ -47,6 +48,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p): protocol(p), priority(0), yielding_to(0), + preceding_train(0), cur_blocks_end(blocks.end()), clear_blocks_end(blocks.end()), pending_block(0), @@ -74,7 +76,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p): layout.add_train(*this); - layout.get_driver().add_loco(address, protocol); + layout.get_driver().add_loco(address, protocol, loco_type); layout.get_driver().signal_loco_speed.connect(sigc::mem_fun(this, &Train::loco_speed_event)); layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event)); @@ -184,10 +186,7 @@ void Train::set_function(unsigned func, bool state) { if(!loco_type.get_functions().count(func)) throw InvalidParameterValue("Invalid function"); - if(func<5) - layout.get_driver().set_loco_function(address, func, state); - else - layout.get_driver().set_loco_function(address+1, func-4, state); + layout.get_driver().set_loco_function(address, func, state); } float Train::get_control(const string &ctrl) const @@ -266,6 +265,35 @@ bool Train::go_to(Track &to) return set_route(route); } +bool Train::go_to(const Zone &to) +{ + set tracks; + for(BlockList::const_iterator i=blocks.begin(); i!=blocks.end(); ++i) + tracks.insert((*i)->get_tracks().begin(), (*i)->get_tracks().end()); + + const Zone::TrackSet &ztracks = to.get_tracks(); + unsigned union_size = 0; + for(Zone::TrackSet::const_iterator i=ztracks.begin(); i!=ztracks.end(); ++i) + union_size += tracks.count(*i); + + if(union_size==tracks.size() || union_size==ztracks.size()) + { + signal_arrived.emit(); + return set_route(0); + } + + free_noncritical_blocks(); + + TrackIter next = blocks.back().next().track_iter(); + + Route *route = Route::find(next, to); + if(!route) + return false; + create_lead_route(route, route); + route->add_tracks(ztracks); + return set_route(route); +} + bool Train::divert(Track &from) { if(!from.get_turnout_id()) @@ -415,8 +443,7 @@ void Train::unplace() bool Train::free_block(Block &block) { - float margin = 10*layout.get_catalogue().get_scale(); - if(get_reserved_distance_until(&block, false)get_braking_distance()*1.3+margin) + if(get_reserved_distance_until(&block, false)get_braking_distance()*1.3) return false; unsigned nsens = 0; @@ -506,7 +533,15 @@ int Train::get_entry_to_block(Block &block) const float Train::get_reserved_distance() const { - return get_reserved_distance_until(0, false); + if(blocks.empty()) + return 0; + + float margin = 0; + TrackIter next = blocks.back().next().track_iter(); + if(next && next->get_type().is_turnout()) + margin = 15*layout.get_catalogue().get_scale(); + + return max(get_reserved_distance_until(0, false)-margin, 0.0f); } void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) @@ -647,11 +682,13 @@ void Train::control_changed(const Controller::Control &ctrl) signal_control_changed.emit(ctrl.name, ctrl.value); } -void Train::loco_speed_event(unsigned addr, unsigned speed, bool) +void Train::loco_speed_event(unsigned addr, unsigned speed, bool rev) { if(addr==address) { current_speed_step = speed; + if(rev!=reverse) + layout.get_driver().set_loco_reverse(address, reverse); speed_changing = false; pure_speed = false; } @@ -659,10 +696,8 @@ void Train::loco_speed_event(unsigned addr, unsigned speed, bool) void Train::loco_func_event(unsigned addr, unsigned func, bool state) { - if(addr==address || (addr==address+1 && loco_type.get_max_function()>4)) + if(addr==address) { - if(addr==address+1) - func += 4; if(state) functions |= 1<get_endpoints().size()<2) { if(!blocking_train) + { good_end = blocks.end(); + end_of_route = true; + } break; } @@ -922,10 +963,15 @@ void Train::reserve_more() bool entry_conflict = (block.entry()==other_exit); bool exit_conflict = (exit==static_cast(other_entry)); if(!entry_conflict && !last->get_turnout_id()) + { /* The other train is not coming to the blocks we're holding, so we can keep them. */ good_end = blocks.end(); + if(static_cast(other_entry)==block.entry()) + preceding_train = other_train; + } + int other_prio = other_train->get_priority(); if(!entry_conflict && !exit_conflict && other_priois_active())) // We are blocked, but there's a diversion possibility try_divert = true; @@ -1143,10 +1189,10 @@ unsigned Train::find_speed_step(float real) const if(real_speed[i].weight) { last = i; - if(real_speed[i].speed=real) high = i; + else if(real_speed[i].speed>real_speed[low].speed) + low = i; } if(!high) { @@ -1257,7 +1303,7 @@ bool Train::is_valid_diversion(const Route &diversion, const TrackIter &from) track1 = track1.next(path); - if(track1.looped()) + if(!track1 || track1.looped()) return false; } @@ -1275,6 +1321,8 @@ bool Train::is_valid_diversion(const Route &diversion, const TrackIter &from) bool ok = (track2!=from && diversion.has_track(*track2)); track2 = track2.next(path); + if(!track2) + return false; if(ok) break;