}
}
-void BlockAllocator::start_from(const BlockIter &block)
+bool BlockAllocator::start_from(const BlockIter &block)
{
if(!block)
throw invalid_argument("BlockAllocator::start_from");
+ float remaining_length = 0;
+ unsigned n_vehs = train.get_n_vehicles();
+ for(unsigned i=0; i<n_vehs; ++i)
+ remaining_length += train.get_vehicle(i).get_type().get_length();
+
clear();
- reserve_block(block);
+
+ BlockList blocks_to_reserve;
+ for(BlockIter b=block; b; b=b.next())
+ {
+ if(b->get_train())
+ break;
+ blocks_to_reserve.push_back(b);
+ for(TrackIter t=b.track_iter(); (t && &t->get_block()==&*b); t=t.next())
+ remaining_length -= t->get_type().get_path_length(t->get_active_path());
+ if(remaining_length<=0)
+ break;
+ }
+
+ if(remaining_length>0)
+ return false;
+
+ for(BlockList::iterator i=blocks_to_reserve.begin(); i!=blocks_to_reserve.end(); ++i)
+ {
+ blocks.push_back(*i);
+ try
+ {
+ (*i)->reserve(&train);
+ }
+ catch(...)
+ {
+ blocks.pop_back();
+ while(i!=blocks_to_reserve.begin())
+ {
+ blocks.pop_back();
+ (*--i)->reserve(0);
+ }
+ throw;
+ }
+ }
+
+ return true;
}
void BlockAllocator::rewind_to(const Block &block)
void set_active(bool);
bool is_active() const { return active; }
- void start_from(const BlockIter &);
+ bool start_from(const BlockIter &);
void rewind_to(const Block &);
void clear();
bool empty() const { return blocks.empty(); }
(*i)->message(msg);
}
-void Train::place(const BlockIter &block)
+bool Train::place(const BlockIter &block)
{
if(!block)
throw invalid_argument("Train::place");
if(controller->get_speed())
throw logic_error("moving");
- allocator.start_from(block);
accurate_position = false;
last_entry_block = BlockIter();
- if(reverse)
- vehicles.front()->place(block.reverse().track_iter(), VehiclePlacement::FRONT_BUFFER);
+ if(allocator.start_from(block))
+ {
+ if(reverse)
+ vehicles.front()->place(block.reverse().track_iter(), VehiclePlacement::FRONT_BUFFER);
+ else
+ vehicles.back()->place(block.track_iter(), VehiclePlacement::BACK_BUFFER);
+ return true;
+ }
else
- vehicles.back()->place(block.track_iter(), VehiclePlacement::BACK_BUFFER);
+ {
+ unplace();
+ return false;
+ }
}
void Train::unplace()
return 0;
}
- void place(const BlockIter &);
+ bool place(const BlockIter &);
void unplace();
bool is_placed() const { return !allocator.empty(); }
void stop_at(Block *);