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 
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 AddFeederShare(Money new_share) { this->feeder_share += new_share; }
00090 
00095   inline uint16 Count() const
00096   {
00097     return this->count;
00098   }
00099 
00105   inline Money FeederShare() const
00106   {
00107     return this->feeder_share;
00108   }
00109 
00116   inline Money FeederShare(uint part) const
00117   {
00118     return this->feeder_share * part / static_cast<uint>(this->count);
00119   }
00120 
00127   inline byte DaysInTransit() const
00128   {
00129     return this->days_in_transit;
00130   }
00131 
00136   inline SourceType SourceSubsidyType() const
00137   {
00138     return this->source_type;
00139   }
00140 
00145   inline SourceID SourceSubsidyID() const
00146   {
00147     return this->source_id;
00148   }
00149 
00154   inline SourceID SourceStation() const
00155   {
00156     return this->source;
00157   }
00158 
00163   inline TileIndex SourceStationXY() const
00164   {
00165     return this->source_xy;
00166   }
00167 
00172   inline TileIndex LoadedAtXY() const
00173   {
00174     return this->loaded_at_xy;
00175   }
00176 
00181   inline StationID NextStation() const
00182   {
00183     return this->next_station;
00184   }
00185 
00186   static void InvalidateAllFrom(SourceType src_type, SourceID src);
00187   static void InvalidateAllFrom(StationID sid);
00188   static void AfterLoad();
00189 };
00190 
00196 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
00197 
00202 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
00203 
00208 template <class Tinst, class Tcont>
00209 class CargoList {
00210 public:
00212   typedef typename Tcont::iterator Iterator;
00214   typedef typename Tcont::reverse_iterator ReverseIterator;
00216   typedef typename Tcont::const_iterator ConstIterator;
00218   typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
00219 
00221   enum MoveToAction {
00222     MTA_BEGIN = 0,
00223     MTA_TRANSFER = 0, 
00224     MTA_DELIVER,      
00225     MTA_KEEP,         
00226     MTA_LOAD,         
00227     MTA_END,
00228     NUM_MOVE_TO_ACTION = MTA_END
00229   };
00230 
00231 protected:
00232   uint count;                 
00233   uint cargo_days_in_transit; 
00234 
00235   Tcont packets;              
00236 
00237   void AddToCache(const CargoPacket *cp);
00238 
00239   void RemoveFromCache(const CargoPacket *cp, uint count);
00240 
00241   static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
00242 
00243 public:
00245   CargoList() {}
00246 
00247   ~CargoList();
00248 
00249   void OnCleanPool();
00250 
00255   inline const Tcont *Packets() const
00256   {
00257     return &this->packets;
00258   }
00259 
00264   inline uint DaysInTransit() const
00265   {
00266     return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
00267   }
00268 
00269   void InvalidateCache();
00270 };
00271 
00272 typedef std::list<CargoPacket *> CargoPacketList;
00273 
00277 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
00278 protected:
00280   typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
00281 
00282   Money feeder_share;                     
00283   uint action_counts[NUM_MOVE_TO_ACTION]; 
00284 
00285   template<class Taction>
00286   void ShiftCargo(Taction action);
00287 
00288   template<class Taction>
00289   void PopCargo(Taction action);
00290 
00294   inline void AssertCountConsistency() const
00295   {
00296     assert(this->action_counts[MTA_KEEP] +
00297         this->action_counts[MTA_DELIVER] +
00298         this->action_counts[MTA_TRANSFER] +
00299         this->action_counts[MTA_LOAD] == this->count);
00300   }
00301 
00302   void AddToCache(const CargoPacket *cp);
00303   void RemoveFromCache(const CargoPacket *cp, uint count);
00304 
00305   void AddToMeta(const CargoPacket *cp, MoveToAction action);
00306   void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
00307 
00308 public:
00310   friend class StationCargoList;
00312   friend class CargoList<VehicleCargoList, CargoPacketList>;
00314   friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
00315 
00316   friend class CargoShift;
00317   friend class CargoTransfer;
00318   friend class CargoDelivery;
00319   template<class Tsource>
00320   friend class CargoRemoval;
00321   friend class CargoReturn;
00322 
00327   inline StationID Source() const
00328   {
00329     return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
00330   }
00331 
00336   inline Money FeederShare() const
00337   {
00338     return this->feeder_share;
00339   }
00340 
00346   inline uint ActionCount(MoveToAction action) const
00347   {
00348     return this->action_counts[action];
00349   }
00350 
00356   inline uint StoredCount() const
00357   {
00358     return this->count - this->action_counts[MTA_LOAD];
00359   }
00360 
00365   inline uint TotalCount() const
00366   {
00367     return this->count;
00368   }
00369 
00374   inline uint ReservedCount() const
00375   {
00376     return this->action_counts[MTA_LOAD];
00377   }
00378 
00383   inline uint UnloadCount() const
00384   {
00385     return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
00386   }
00387 
00392   inline uint RemainingCount() const
00393   {
00394     return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
00395   }
00396 
00397   void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
00398 
00399   void AgeCargo();
00400 
00401   void InvalidateCache();
00402 
00403   void SetTransferLoadPlace(TileIndex xy);
00404 
00405   bool Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
00406 
00412   inline void KeepAll()
00413   {
00414     this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
00415     this->action_counts[MTA_KEEP] = this->count;
00416   }
00417 
00418   /* Methods for moving cargo around. First parameter is always maximum
00419    * amount of cargo to be moved. Second parameter is destination (if
00420    * applicable), return value is amount of cargo actually moved. */
00421 
00422   uint Reassign(uint max_move, MoveToAction from, MoveToAction to);
00423   uint Return(uint max_move, StationCargoList *dest, StationID next_station);
00424   uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
00425   uint Shift(uint max_move, VehicleCargoList *dest);
00426   uint Truncate(uint max_move = UINT_MAX);
00427 
00435   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00436   {
00437     return cp1->source_xy    == cp2->source_xy &&
00438         cp1->days_in_transit == cp2->days_in_transit &&
00439         cp1->source_type     == cp2->source_type &&
00440         cp1->source_id       == cp2->source_id &&
00441         cp1->loaded_at_xy    == cp2->loaded_at_xy;
00442   }
00443 };
00444 
00445 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
00446 typedef std::map<StationID, uint> StationCargoAmountMap;
00447 
00451 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
00452 protected:
00454   typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
00455 
00456   uint reserved_count; 
00457 
00458 public:
00460   friend class CargoList<StationCargoList, StationCargoPacketMap>;
00462   friend const struct SaveLoad *GetGoodsDesc();
00463 
00464   friend class CargoLoad;
00465   friend class CargoTransfer;
00466   template<class Tsource>
00467   friend class CargoRemoval;
00468   friend class CargoReservation;
00469   friend class CargoReturn;
00470   friend class CargoReroute;
00471 
00472   static void InvalidateAllFrom(SourceType src_type, SourceID src);
00473 
00474   template<class Taction>
00475   bool ShiftCargo(Taction &action, StationID next);
00476 
00477   template<class Taction>
00478   uint ShiftCargo(Taction action, StationID next, bool include_invalid);
00479 
00480   void Append(CargoPacket *cp, StationID next);
00481 
00487   inline bool HasCargoFor(StationID next) const
00488   {
00489     return this->packets.find(next) != this->packets.end();
00490   }
00491 
00496   inline StationID Source() const
00497   {
00498     return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
00499   }
00500 
00506   inline uint AvailableCount() const
00507   {
00508     return this->count;
00509   }
00510 
00515   inline uint ReservedCount() const
00516   {
00517     return this->reserved_count;
00518   }
00519 
00525   inline uint TotalCount() const
00526   {
00527     return this->count + this->reserved_count;
00528   }
00529 
00530   /* Methods for moving cargo around. First parameter is always maximum
00531    * amount of cargo to be moved. Second parameter is destination (if
00532    * applicable), return value is amount of cargo actually moved. */
00533 
00534   uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
00535   uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
00536   uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
00537   uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00538 
00546   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00547   {
00548     return cp1->source_xy    == cp2->source_xy &&
00549         cp1->days_in_transit == cp2->days_in_transit &&
00550         cp1->source_type     == cp2->source_type &&
00551         cp1->source_id       == cp2->source_id;
00552   }
00553 };
00554 
00555 #endif /* CARGOPACKET_H */