]> git.tdb.fi Git - r2c2.git/commitdiff
Reserve enough blocks for the entire train when placing
authorMikko Rasa <tdb@tdb.fi>
Fri, 9 Aug 2013 10:30:30 +0000 (13:30 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 9 Aug 2013 10:30:30 +0000 (13:30 +0300)
source/libr2c2/blockallocator.cpp
source/libr2c2/blockallocator.h
source/libr2c2/train.cpp
source/libr2c2/train.h

index 547415aa965173ad5eeb68fb0966eceb6aff000c..2e816775f7dfa7c86683a559e3f1f638e436b33f 100644 (file)
@@ -60,13 +60,53 @@ void BlockAllocator::set_active(bool a)
        }
 }
 
-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)
index f5af90e585a4913554645cb189ee61d9fea32b17..fe05603e0e0c997d56058a7904a72afb3dc34fe1 100644 (file)
@@ -48,7 +48,7 @@ public:
        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(); }
index 95b78b567c9498ba687c05bbd445082d252ad065..07461b80a9558ecc4000c176bf73565e4c6d922b 100644 (file)
@@ -185,21 +185,29 @@ void Train::ai_message(const TrainAI::Message &msg)
                (*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()
index 3aaf6b14137cf8401489c39918fbba135107a011..340537a89a401242fd08cabb2c004459892ec36e 100644 (file)
@@ -112,7 +112,7 @@ public:
                return 0;
        }
 
-       void place(const BlockIter &);
+       bool place(const BlockIter &);
        void unplace();
        bool is_placed() const { return !allocator.empty(); }
        void stop_at(Block *);