#include "train.h"
#include "vehicle.h"
#include "vehicletype.h"
+#include "zone.h"
using namespace std;
using namespace Msp;
protocol(p),
priority(0),
yielding_to(0),
+ preceding_train(0),
cur_blocks_end(blocks.end()),
clear_blocks_end(blocks.end()),
pending_block(0),
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));
{
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
return set_route(route);
}
+bool Train::go_to(const Zone &to)
+{
+ set<Track *> 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())
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;
}
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<<func;
else
BlockIter start = blocks.back();
pending_block = 0;
+ preceding_train = 0;
// See how many sensor blocks and how much track we already have
unsigned nsens = 0;
if(!block || block->get_endpoints().size()<2)
{
if(!blocking_train)
+ {
good_end = blocks.end();
+ end_of_route = true;
+ }
break;
}
bool entry_conflict = (block.entry()==other_exit);
bool exit_conflict = (exit==static_cast<unsigned>(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<unsigned>(other_entry)==block.entry())
+ preceding_train = other_train;
+ }
+
int other_prio = other_train->get_priority();
if(!entry_conflict && !exit_conflict && other_prio<priority)
contested_blocks.push_back(block);
continue;
}
- else if(divert_track && (entry_conflict || exit_conflict))
+ else if(divert_track && (entry_conflict || exit_conflict || !other_train->is_active()))
// We are blocked, but there's a diversion possibility
try_divert = true;
track1 = track1.next(path);
- if(track1.looped())
+ if(!track1 || track1.looped())
return false;
}
bool ok = (track2!=from && diversion.has_track(*track2));
track2 = track2.next(path);
+ if(!track2)
+ return false;
if(ok)
break;