cargopacket.h

Go to the documentation of this file.
00001 /* $Id: cargopacket.h 25900 2013-10-22 16:15:59Z fonsinchen $ */
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 
00039 typedef uint32 TileOrStationID;
00040 
00044 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
00045 private:
00046   Money feeder_share;         
00047   uint16 count;               
00048   byte days_in_transit;       
00049   SourceTypeByte source_type; 
00050   SourceID source_id;         
00051   StationID source;           
00052   TileIndex source_xy;        
00053   union {
00054     TileOrStationID loaded_at_xy; 
00055     TileOrStationID next_station; 
00056   };
00057 
00059   template <class Tinst, class Tcont> friend class CargoList;
00060   friend class VehicleCargoList;
00061   friend class StationCargoList;
00063   friend const struct SaveLoad *GetCargoPacketDesc();
00064 public:
00066   static const uint16 MAX_COUNT = UINT16_MAX;
00067 
00068   CargoPacket();
00069   CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
00070   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);
00071 
00073   ~CargoPacket() { }
00074 
00075   CargoPacket *Split(uint new_size);
00076   void Merge(CargoPacket *cp);
00077   void Reduce(uint count);
00078 
00083   void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
00084 
00089   void SetNextStation(StationID next_station) { this->next_station = next_station; }
00090 
00095   void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
00096 
00101   inline uint16 Count() const
00102   {
00103     return this->count;
00104   }
00105 
00111   inline Money FeederShare() const
00112   {
00113     return this->feeder_share;
00114   }
00115 
00122   inline Money FeederShare(uint part) const
00123   {
00124     return this->feeder_share * part / static_cast<uint>(this->count);
00125   }
00126 
00133   inline byte DaysInTransit() const
00134   {
00135     return this->days_in_transit;
00136   }
00137 
00142   inline SourceType SourceSubsidyType() const
00143   {
00144     return this->source_type;
00145   }
00146 
00151   inline SourceID SourceSubsidyID() const
00152   {
00153     return this->source_id;
00154   }
00155 
00160   inline SourceID SourceStation() const
00161   {
00162     return this->source;
00163   }
00164 
00169   inline TileIndex SourceStationXY() const
00170   {
00171     return this->source_xy;
00172   }
00173 
00178   inline TileIndex LoadedAtXY() const
00179   {
00180     return this->loaded_at_xy;
00181   }
00182 
00187   inline StationID NextStation() const
00188   {
00189     return this->next_station;
00190   }
00191 
00192   static void InvalidateAllFrom(SourceType src_type, SourceID src);
00193   static void InvalidateAllFrom(StationID sid);
00194   static void AfterLoad();
00195 };
00196 
00202 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
00203 
00208 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
00209 
00214 template <class Tinst, class Tcont>
00215 class CargoList {
00216 public:
00218   typedef typename Tcont::iterator Iterator;
00220   typedef typename Tcont::reverse_iterator ReverseIterator;
00222   typedef typename Tcont::const_iterator ConstIterator;
00224   typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
00225 
00227   enum MoveToAction {
00228     MTA_BEGIN = 0,
00229     MTA_TRANSFER = 0, 
00230     MTA_DELIVER,      
00231     MTA_KEEP,         
00232     MTA_LOAD,         
00233     MTA_END,
00234     NUM_MOVE_TO_ACTION = MTA_END
00235   };
00236 
00237 protected:
00238   uint count;                 
00239   uint cargo_days_in_transit; 
00240 
00241   Tcont packets;              
00242 
00243   void AddToCache(const CargoPacket *cp);
00244 
00245   void RemoveFromCache(const CargoPacket *cp, uint count);
00246 
00247   static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
00248 
00249 public:
00251   CargoList() {}
00252 
00253   ~CargoList();
00254 
00255   void OnCleanPool();
00256 
00261   inline const Tcont *Packets() const
00262   {
00263     return &this->packets;
00264   }
00265 
00270   inline uint DaysInTransit() const
00271   {
00272     return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
00273   }
00274 
00275   void InvalidateCache();
00276 };
00277 
00278 typedef std::list<CargoPacket *> CargoPacketList;
00279 
00283 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
00284 protected:
00286   typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
00287 
00288   Money feeder_share;                     
00289   uint action_counts[NUM_MOVE_TO_ACTION]; 
00290 
00291   template<class Taction>
00292   void ShiftCargo(Taction action);
00293 
00294   template<class Taction>
00295   void PopCargo(Taction action);
00296 
00300   inline void AssertCountConsistency() const
00301   {
00302     assert(this->action_counts[MTA_KEEP] +
00303         this->action_counts[MTA_DELIVER] +
00304         this->action_counts[MTA_TRANSFER] +
00305         this->action_counts[MTA_LOAD] == this->count);
00306   }
00307 
00308   void AddToCache(const CargoPacket *cp);
00309   void RemoveFromCache(const CargoPacket *cp, uint count);
00310 
00311   void AddToMeta(const CargoPacket *cp, MoveToAction action);
00312   void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
00313 
00314   static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
00315       StationID current_station, bool accepted, StationIDStack next_station);
00316 
00317 public:
00319   friend class StationCargoList;
00321   friend class CargoList<VehicleCargoList, CargoPacketList>;
00323   friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
00324 
00325   friend class CargoShift;
00326   friend class CargoTransfer;
00327   friend class CargoDelivery;
00328   template<class Tsource>
00329   friend class CargoRemoval;
00330   friend class CargoReturn;
00331   friend class VehicleCargoReroute;
00332 
00337   inline StationID Source() const
00338   {
00339     return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
00340   }
00341 
00346   inline Money FeederShare() const
00347   {
00348     return this->feeder_share;
00349   }
00350 
00356   inline uint ActionCount(MoveToAction action) const
00357   {
00358     return this->action_counts[action];
00359   }
00360 
00366   inline uint StoredCount() const
00367   {
00368     return this->count - this->action_counts[MTA_LOAD];
00369   }
00370 
00375   inline uint TotalCount() const
00376   {
00377     return this->count;
00378   }
00379 
00384   inline uint ReservedCount() const
00385   {
00386     return this->action_counts[MTA_LOAD];
00387   }
00388 
00393   inline uint UnloadCount() const
00394   {
00395     return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
00396   }
00397 
00402   inline uint RemainingCount() const
00403   {
00404     return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
00405   }
00406 
00407   void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
00408 
00409   void AgeCargo();
00410 
00411   void InvalidateCache();
00412 
00413   void SetTransferLoadPlace(TileIndex xy);
00414 
00415   bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
00416 
00422   inline void KeepAll()
00423   {
00424     this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
00425     this->action_counts[MTA_KEEP] = this->count;
00426   }
00427 
00428   /* Methods for moving cargo around. First parameter is always maximum
00429    * amount of cargo to be moved. Second parameter is destination (if
00430    * applicable), return value is amount of cargo actually moved. */
00431 
00432   uint Reassign(uint max_move, MoveToAction from, MoveToAction to);
00433   uint Return(uint max_move, StationCargoList *dest, StationID next_station);
00434   uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
00435   uint Shift(uint max_move, VehicleCargoList *dest);
00436   uint Truncate(uint max_move = UINT_MAX);
00437   uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00438 
00446   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00447   {
00448     return cp1->source_xy    == cp2->source_xy &&
00449         cp1->days_in_transit == cp2->days_in_transit &&
00450         cp1->source_type     == cp2->source_type &&
00451         cp1->source_id       == cp2->source_id &&
00452         cp1->loaded_at_xy    == cp2->loaded_at_xy;
00453   }
00454 };
00455 
00456 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
00457 typedef std::map<StationID, uint> StationCargoAmountMap;
00458 
00462 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
00463 protected:
00465   typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
00466 
00467   uint reserved_count; 
00468 
00469 public:
00471   friend class CargoList<StationCargoList, StationCargoPacketMap>;
00473   friend const struct SaveLoad *GetGoodsDesc();
00474 
00475   friend class CargoLoad;
00476   friend class CargoTransfer;
00477   template<class Tsource>
00478   friend class CargoRemoval;
00479   friend class CargoReservation;
00480   friend class CargoReturn;
00481   friend class StationCargoReroute;
00482 
00483   static void InvalidateAllFrom(SourceType src_type, SourceID src);
00484 
00485   template<class Taction>
00486   bool ShiftCargo(Taction &action, StationID next);
00487 
00488   template<class Taction>
00489   uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid);
00490 
00491   void Append(CargoPacket *cp, StationID next);
00492 
00498   inline bool HasCargoFor(StationIDStack next) const
00499   {
00500     while (!next.IsEmpty()) {
00501       if (this->packets.find(next.Pop()) != this->packets.end()) return true;
00502     }
00503     /* Packets for INVALID_STTION can go anywhere. */
00504     return this->packets.find(INVALID_STATION) != this->packets.end();
00505   }
00506 
00511   inline StationID Source() const
00512   {
00513     return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
00514   }
00515 
00521   inline uint AvailableCount() const
00522   {
00523     return this->count;
00524   }
00525 
00530   inline uint ReservedCount() const
00531   {
00532     return this->reserved_count;
00533   }
00534 
00540   inline uint TotalCount() const
00541   {
00542     return this->count + this->reserved_count;
00543   }
00544 
00545   /* Methods for moving cargo around. First parameter is always maximum
00546    * amount of cargo to be moved. Second parameter is destination (if
00547    * applicable), return value is amount of cargo actually moved. */
00548 
00549   uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
00550   uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
00551   uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
00552   uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00553 
00561   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00562   {
00563     return cp1->source_xy    == cp2->source_xy &&
00564         cp1->days_in_transit == cp2->days_in_transit &&
00565         cp1->source_type     == cp2->source_type &&
00566         cp1->source_id       == cp2->source_id;
00567   }
00568 };
00569 
00570 #endif /* CARGOPACKET_H */