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
bool Train::free_block(Block &block)
{
- float margin = 10*layout.get_catalogue().get_scale();
- if(get_reserved_distance_until(&block, false)<controller->get_braking_distance()*1.3+margin)
+ if(get_reserved_distance_until(&block, false)<controller->get_braking_distance()*1.3)
return false;
unsigned nsens = 0;
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)
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
}
// Move blocks up to the next sensor to our current blocks
+ for(BlockList::iterator j=cur_blocks_end; j!=end; ++j)
+ signal_advanced.emit(**j);
cur_blocks_end = end;
// Try to get more blocks if we're moving
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;
if(real_speed[i].weight)
{
last = i;
- if(real_speed[i].speed<real)
- low = i;
- else
+ if(real_speed[i].speed>=real)
high = i;
+ else if(real_speed[i].speed>real_speed[low].speed)
+ low = i;
}
if(!high)
{
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;