cargopacket.h

Go to the documentation of this file.
00001 /* $Id$ */
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 #ifndef CARGOPACKET_H
00013 #define CARGOPACKET_H
00014 
00015 #include "core/pool_type.hpp"
00016 #include "economy_type.h"
00017 #include "station_type.h"
00018 #include "order_type.h"
00019 #include "cargo_type.h"
00020 #include "vehicle_type.h"
00021 #include "core/multimap.hpp"
00022 #include <list>
00023 
00025 typedef uint32 CargoPacketID;
00026 struct CargoPacket;
00027 
00029 typedef Pool<CargoPacket, CargoPacketID, 1024, 0xFFF000, PT_NORMAL, true, false> CargoPacketPool;
00031 extern CargoPacketPool _cargopacket_pool;
00032 
00033 struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets()
00034 
00035 template <class Tinst, class Tcont> class CargoList;
00036 class StationCargoList; // forward-declare, so we can use it in VehicleCargoList.
00037 extern const struct SaveLoad *GetCargoPacketDesc();
00038 
00042 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
00043 private:
00044   Money feeder_share;         
00045   uint16 count;               
00046   byte days_in_transit;       
00047   SourceTypeByte source_type; 
00048   SourceID source_id;         
00049   StationID source;           
00050   TileIndex source_xy;        
00051   union {
00052     TileIndex loaded_at_xy; 
00053     StationID next_station; 
00054   };
00055 
00057   template <class Tinst, class Tcont> friend class CargoList;
00058   friend class VehicleCargoList;
00059   friend class StationCargoList;
00061   friend const struct SaveLoad *GetCargoPacketDesc();
00062 public:
00064   static const uint16 MAX_COUNT = UINT16_MAX;
00065 
00066   CargoPacket();
00067   CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
00068   CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share = 0, SourceType source_type = ST_INDUSTRY, SourceID source_id = INVALID_SOURCE);
00069 
00071   ~CargoPacket() { }
00072 
00073   CargoPacket *Split(uint new_size);
00074   void Merge(CargoPacket *cp);
00075   void Reduce(uint count);
00076 
00081   void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
00082 
00087   void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
00088 
00093   inline uint16 Count() const
00094   {
00095     return this->count;
00096   }
00097 
00103   inline Money FeederShare() const
00104   {
00105     return this->feeder_share;
00106   }
00107 
00114   inline Money FeederShare(uint part) const
00115   {
00116     return this->feeder_share * part / static_cast<uint>(this->count);
00117   }
00118 
00125   inline byte DaysInTransit() const
00126   {
00127     return this->days_in_transit;
00128   }
00129 
00134   inline SourceType SourceSubsidyType() const
00135   {
00136     return this->source_type;
00137   }
00138 
00143   inline SourceID SourceSubsidyID() const
00144   {
00145     return this->source_id;
00146   }
00147 
00152   inline SourceID SourceStation() const
00153   {
00154     return this->source;
00155   }
00156 
00161   inline TileIndex SourceStationXY() const
00162   {
00163     return this->source_xy;
00164   }
00165 
00170   inline TileIndex LoadedAtXY() const
00171   {
00172     return this->loaded_at_xy;
00173   }
00174 
00179   inline StationID NextStation() const
00180   {
00181     return this->next_station;
00182   }
00183 
00184   static void InvalidateAllFrom(SourceType src_type, SourceID src);
00185   static void InvalidateAllFrom(StationID sid);
00186   static void AfterLoad();
00187 };
00188 
00194 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
00195 
00200 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
00201 
00206 template <class Tinst, class Tcont>
00207 class CargoList {
00208 public:
00210   typedef typename Tcont::iterator Iterator;
00212   typedef typename Tcont::reverse_iterator ReverseIterator;
00214   typedef typename Tcont::const_iterator ConstIterator;
00216   typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
00217 
00219   enum MoveToAction {
00220     MTA_BEGIN = 0,
00221     MTA_TRANSFER = 0, 
00222     MTA_DELIVER,      
00223     MTA_KEEP,         
00224     MTA_LOAD,         
00225     MTA_END,
00226     NUM_MOVE_TO_ACTION = MTA_END
00227   };
00228 
00229 protected:
00230   uint count;                 
00231   uint cargo_days_in_transit; 
00232 
00233   Tcont packets;              
00234 
00235   void AddToCache(const CargoPacket *cp);
00236 
00237   void RemoveFromCache(const CargoPacket *cp, uint count);
00238 
00239   static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
00240 
00241 public:
00243   CargoList() {}
00244 
00245   ~CargoList();
00246 
00247   void OnCleanPool();
00248 
00253   inline const Tcont *Packets() const
00254   {
00255     return &this->packets;
00256   }
00257 
00262   inline bool Empty() const
00263   {
00264     return this->count == 0;
00265   }
00266 
00271   inline uint Count() const
00272   {
00273     return this->count;
00274   }
00275 
00280   inline uint DaysInTransit() const
00281   {
00282     return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
00283   }
00284 
00285   void InvalidateCache();
00286 };
00287 
00288 typedef std::list<CargoPacket *> CargoPacketList;
00289 
00293 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
00294 protected:
00296   typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
00297 
00298   Money feeder_share;                     
00299   uint action_counts[NUM_MOVE_TO_ACTION]; 
00300 
00301   template<class Taction>
00302   void ShiftCargo(Taction action);
00303 
00304   template<class Taction>
00305   void PopCargo(Taction action);
00306 
00310   inline void AssertCountConsistency() const
00311   {
00312     assert(this->action_counts[MTA_KEEP] +
00313         this->action_counts[MTA_DELIVER] +
00314         this->action_counts[MTA_TRANSFER] +
00315         this->action_counts[MTA_LOAD] == this->count);
00316   }
00317 
00318   void AddToCache(const CargoPacket *cp);
00319   void RemoveFromCache(const CargoPacket *cp, uint count);
00320 
00321   void AddToMeta(const CargoPacket *cp, MoveToAction action);
00322   void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
00323 
00324 public:
00326   friend class StationCargoList;
00328   friend class CargoList<VehicleCargoList, CargoPacketList>;
00330   friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
00331 
00332   friend class CargoShift;
00333   friend class CargoTransfer;
00334   friend class CargoDelivery;
00335   template<class Tsource>
00336   friend class CargoRemoval;
00337   friend class CargoReturn;
00338 
00343   inline StationID Source() const
00344   {
00345     return this->Empty() ? INVALID_STATION : this->packets.front()->source;
00346   }
00347 
00352   inline Money FeederShare() const
00353   {
00354     return this->feeder_share;
00355   }
00356 
00362   inline uint ActionCount(MoveToAction action) const
00363   {
00364     return this->action_counts[action];
00365   }
00366 
00372   inline uint OnboardCount() const
00373   {
00374     return this->count - this->action_counts[MTA_LOAD];
00375   }
00376 
00381   inline uint UnloadCount() const
00382   {
00383     return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
00384   }
00385 
00390   inline uint RemainingCount() const
00391   {
00392     return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
00393   }
00394 
00395   void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
00396 
00397   void AgeCargo();
00398 
00399   void InvalidateCache();
00400 
00401   void SetTransferLoadPlace(TileIndex xy);
00402 
00403   bool Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
00404 
00410   inline void KeepAll()
00411   {
00412     this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
00413     this->action_counts[MTA_KEEP] = this->count;
00414   }
00415 
00416   /* Methods for moving cargo around. First parameter is always maximum
00417    * amount of cargo to be moved. Second parameter is destination (if
00418    * applicable), return value is amount of cargo actually moved. */
00419 
00420   uint Reassign(uint max_move, MoveToAction from, MoveToAction to);
00421   uint Return(uint max_move, StationCargoList *dest, StationID next_station);
00422   uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
00423   uint Shift(uint max_move, VehicleCargoList *dest);
00424   uint Truncate(uint max_move = UINT_MAX);
00425 
00433   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00434   {
00435     return cp1->source_xy    == cp2->source_xy &&
00436         cp1->days_in_transit == cp2->days_in_transit &&
00437         cp1->source_type     == cp2->source_type &&
00438         cp1->source_id       == cp2->source_id &&
00439         cp1->loaded_at_xy    == cp2->loaded_at_xy;
00440   }
00441 };
00442 
00443 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
00444 typedef std::map<StationID, uint> StationCargoAmountMap;
00445 
00449 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
00450 protected:
00452   typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
00453 
00454   uint reserved_count; 
00455 
00456 public:
00458   friend class CargoList<StationCargoList, StationCargoPacketMap>;
00460   friend const struct SaveLoad *GetGoodsDesc();
00461 
00462   friend class CargoLoad;
00463   friend class CargoTransfer;
00464   template<class Tsource>
00465   friend class CargoRemoval;
00466   friend class CargoReservation;
00467   friend class CargoReturn;
00468   friend class CargoReroute;
00469 
00470   static void InvalidateAllFrom(SourceType src_type, SourceID src);
00471 
00472   template<class Taction>
00473   bool ShiftCargo(Taction &action, StationID next);
00474 
00475   template<class Taction>
00476   uint ShiftCargo(Taction action, StationID next, bool include_invalid);
00477 
00478   void Append(CargoPacket *cp, StationID next);
00479 
00485   inline bool HasCargoFor(StationID next) const
00486   {
00487     return this->packets.find(next) != this->packets.end();
00488   }
00489 
00494   inline StationID Source() const
00495   {
00496     return this->Empty() ? INVALID_STATION : this->packets.begin()->second.front()->source;
00497   }
00498 
00503   inline uint ReservedCount() const
00504   {
00505     return this->reserved_count;
00506   }
00507 
00513   inline uint TotalCount() const
00514   {
00515     return this->count + this->reserved_count;
00516   }
00517 
00518   /* Methods for moving cargo around. First parameter is always maximum
00519    * amount of cargo to be moved. Second parameter is destination (if
00520    * applicable), return value is amount of cargo actually moved. */
00521 
00522   uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
00523   uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
00524   uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
00525   uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00526 
00534   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00535   {
00536     return cp1->source_xy    == cp2->source_xy &&
00537         cp1->days_in_transit == cp2->days_in_transit &&
00538         cp1->source_type     == cp2->source_type &&
00539         cp1->source_id       == cp2->source_id;
00540   }
00541 };
00542 
00543 #endif /* CARGOPACKET_H */