cargopacket.cpp

Go to the documentation of this file.
00001 /* $Id: cargopacket.cpp 21863 2011-01-19 20:40:27Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "core/pool_func.hpp"
00014 #include "economy_base.h"
00015 
00016 /* Initialize the cargopacket-pool */
00017 CargoPacketPool _cargopacket_pool("CargoPacket");
00018 INSTANTIATE_POOL_METHODS(CargoPacket)
00019 
00020 
00023 void InitializeCargoPackets()
00024 {
00025   _cargopacket_pool.CleanPool();
00026 }
00027 
00031 CargoPacket::CargoPacket()
00032 {
00033   this->source_type = ST_INDUSTRY;
00034   this->source_id   = INVALID_SOURCE;
00035 }
00036 
00048 CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) :
00049   feeder_share(0),
00050   count(count),
00051   days_in_transit(0),
00052   source_id(source_id),
00053   source(source),
00054   source_xy(source_xy),
00055   loaded_at_xy(0)
00056 {
00057   assert(count != 0);
00058   this->source_type  = source_type;
00059 }
00060 
00075 CargoPacket::CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share, SourceType source_type, SourceID source_id) :
00076     feeder_share(feeder_share),
00077     count(count),
00078     days_in_transit(days_in_transit),
00079     source_id(source_id),
00080     source(source),
00081     source_xy(source_xy),
00082     loaded_at_xy(loaded_at_xy)
00083 {
00084   assert(count != 0);
00085   this->source_type = source_type;
00086 }
00087 
00093 FORCEINLINE CargoPacket *CargoPacket::Split(uint new_size)
00094 {
00095   Money fs = this->feeder_share * new_size / static_cast<uint>(this->count);
00096   CargoPacket *cp_new = new CargoPacket(new_size, this->days_in_transit, this->source, this->source_xy, this->loaded_at_xy, fs, this->source_type, this->source_id);
00097   this->feeder_share -= fs;
00098   this->count -= new_size;
00099   return cp_new;
00100 }
00101 
00106 FORCEINLINE void CargoPacket::Merge(CargoPacket *cp)
00107 {
00108   this->count += cp->count;
00109   this->feeder_share += cp->feeder_share;
00110   delete cp;
00111 }
00112 
00118 /* static */ void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
00119 {
00120   CargoPacket *cp;
00121   FOR_ALL_CARGOPACKETS(cp) {
00122     if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
00123   }
00124 }
00125 
00130 /* static */ void CargoPacket::InvalidateAllFrom(StationID sid)
00131 {
00132   CargoPacket *cp;
00133   FOR_ALL_CARGOPACKETS(cp) {
00134     if (cp->source == sid) cp->source = INVALID_STATION;
00135   }
00136 }
00137 
00138 /*
00139  *
00140  * Cargo list implementation
00141  *
00142  */
00143 
00147 template <class Tinst>
00148 CargoList<Tinst>::~CargoList()
00149 {
00150   for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
00151     delete *it;
00152   }
00153 }
00154 
00160 template <class Tinst>
00161 void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp)
00162 {
00163   this->count                 -= cp->count;
00164   this->cargo_days_in_transit -= cp->days_in_transit * cp->count;
00165 }
00166 
00172 template <class Tinst>
00173 void CargoList<Tinst>::AddToCache(const CargoPacket *cp)
00174 {
00175   this->count                 += cp->count;
00176   this->cargo_days_in_transit += cp->days_in_transit * cp->count;
00177 }
00178 
00187 template <class Tinst>
00188 void CargoList<Tinst>::Append(CargoPacket *cp)
00189 {
00190   assert(cp != NULL);
00191   static_cast<Tinst *>(this)->AddToCache(cp);
00192 
00193   for (List::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
00194     CargoPacket *icp = *it;
00195     if (Tinst::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
00196       icp->Merge(cp);
00197       return;
00198     }
00199   }
00200 
00201   /* The packet could not be merged with another one */
00202   this->packets.push_back(cp);
00203 }
00204 
00210 template <class Tinst>
00211 void CargoList<Tinst>::Truncate(uint max_remaining)
00212 {
00213   for (Iterator it(packets.begin()); it != packets.end(); /* done during loop*/) {
00214     CargoPacket *cp = *it;
00215     if (max_remaining == 0) {
00216       /* Nothing should remain, just remove the packets. */
00217       this->packets.erase(it++);
00218       static_cast<Tinst *>(this)->RemoveFromCache(cp);
00219       delete cp;
00220       continue;
00221     }
00222 
00223     uint local_count = cp->count;
00224     if (local_count > max_remaining) {
00225       uint diff = local_count - max_remaining;
00226       this->count -= diff;
00227       this->cargo_days_in_transit -= cp->days_in_transit * diff;
00228       cp->count = max_remaining;
00229       max_remaining = 0;
00230     } else {
00231       max_remaining -= local_count;
00232     }
00233     ++it;
00234   }
00235 }
00236 
00258 template <class Tinst>
00259 template <class Tother_inst>
00260 bool CargoList<Tinst>::MoveTo(Tother_inst *dest, uint max_move, MoveToAction mta, CargoPayment *payment, uint data)
00261 {
00262   assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
00263   assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
00264 
00265   Iterator it(this->packets.begin());
00266   while (it != this->packets.end() && max_move > 0) {
00267     CargoPacket *cp = *it;
00268     if (cp->source == data && mta == MTA_FINAL_DELIVERY) {
00269       /* Skip cargo that originated from this station. */
00270       ++it;
00271       continue;
00272     }
00273 
00274     if (cp->count <= max_move) {
00275       /* Can move the complete packet */
00276       max_move -= cp->count;
00277       this->packets.erase(it++);
00278       static_cast<Tinst *>(this)->RemoveFromCache(cp);
00279       switch(mta) {
00280         case MTA_FINAL_DELIVERY:
00281           payment->PayFinalDelivery(cp, cp->count);
00282           delete cp;
00283           continue; // of the loop
00284 
00285         case MTA_CARGO_LOAD:
00286           cp->loaded_at_xy = data;
00287           break;
00288 
00289         case MTA_TRANSFER:
00290           cp->feeder_share += payment->PayTransfer(cp, cp->count);
00291           break;
00292 
00293         case MTA_UNLOAD:
00294           break;
00295       }
00296       dest->Append(cp);
00297       continue;
00298     }
00299 
00300     /* Can move only part of the packet */
00301     if (mta == MTA_FINAL_DELIVERY) {
00302       /* Final delivery doesn't need package splitting. */
00303       payment->PayFinalDelivery(cp, max_move);
00304 
00305       /* Remove the delivered data from the cache */
00306       uint left = cp->count - max_move;
00307       cp->count = max_move;
00308       static_cast<Tinst *>(this)->RemoveFromCache(cp);
00309 
00310       /* Final delivery payment pays the feeder share, so we have to
00311        * reset that so it is not 'shown' twice for partial unloads. */
00312       cp->feeder_share = 0;
00313       cp->count = left;
00314     } else {
00315       /* But... the rest needs package splitting. */
00316       CargoPacket *cp_new = cp->Split(max_move);
00317 
00318       static_cast<Tinst *>(this)->RemoveFromCache(cp_new); // this reflects the changes in cp.
00319 
00320       if (mta == MTA_TRANSFER) {
00321         /* Add the feeder share before inserting in dest. */
00322         cp_new->feeder_share += payment->PayTransfer(cp_new, max_move);
00323       } else if (mta == MTA_CARGO_LOAD) {
00324         cp_new->loaded_at_xy = data;
00325       }
00326 
00327       dest->Append(cp_new);
00328     }
00329 
00330     max_move = 0;
00331   }
00332 
00333   return it != packets.end();
00334 }
00335 
00337 template <class Tinst>
00338 void CargoList<Tinst>::InvalidateCache()
00339 {
00340   this->count = 0;
00341   this->cargo_days_in_transit = 0;
00342 
00343   for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00344     static_cast<Tinst *>(this)->AddToCache(*it);
00345   }
00346 }
00347 
00353 void VehicleCargoList::RemoveFromCache(const CargoPacket *cp)
00354 {
00355   this->feeder_share -= cp->feeder_share;
00356   this->Parent::RemoveFromCache(cp);
00357 }
00358 
00364 void VehicleCargoList::AddToCache(const CargoPacket *cp)
00365 {
00366   this->feeder_share += cp->feeder_share;
00367   this->Parent::AddToCache(cp);
00368 }
00369 
00373 void VehicleCargoList::AgeCargo()
00374 {
00375   for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00376     CargoPacket *cp = *it;
00377     /* If we're at the maximum, then we can't increase no more. */
00378     if (cp->days_in_transit == 0xFF) continue;
00379 
00380     cp->days_in_transit++;
00381     this->cargo_days_in_transit += cp->count;
00382   }
00383 }
00384 
00386 void VehicleCargoList::InvalidateCache()
00387 {
00388   this->feeder_share = 0;
00389   this->Parent::InvalidateCache();
00390 }
00391 
00392 /*
00393  * We have to instantiate everything we want to be usable.
00394  */
00395 template class CargoList<VehicleCargoList>;
00396 template class CargoList<StationCargoList>;
00397 
00399 template bool CargoList<VehicleCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00401 template bool CargoList<VehicleCargoList>::MoveTo(StationCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00403 template bool CargoList<StationCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);

Generated on Thu Jan 20 22:57:32 2011 for OpenTTD by  doxygen 1.6.1