Rework ChoosePylonPosition to simplify the loop
[openttd/fttd.git] / src / cargopacket.h
blob2ce5cbdbb3f220324c641ccd1fa5a8544c0d2b9c
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file cargopacket.h Base class for cargo packets. */
12 #ifndef CARGOPACKET_H
13 #define CARGOPACKET_H
15 #include "core/pool_type.hpp"
16 #include "economy_type.h"
17 #include "station_type.h"
18 #include "order_type.h"
19 #include "cargo_type.h"
20 #include "vehicle_type.h"
21 #include "core/multimap.hpp"
22 #include "saveload/saveload_data.h"
23 #include <list>
25 /** Unique identifier for a single cargo packet. */
26 typedef uint32 CargoPacketID;
27 struct CargoPacket;
29 struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets()
31 template <class Tinst, class Tcont> class CargoList;
32 class StationCargoList; // forward-declare, so we can use it in VehicleCargoList.
33 extern const struct SaveLoad *GetCargoPacketDesc();
35 typedef uint32 TileOrStationID;
37 /**
38 * Container for cargo from the same location and time.
40 struct CargoPacket : PooledItem <CargoPacket, CargoPacketID, 1024, 0xFFF000, PT_NORMAL, true, false> {
41 private:
42 Money feeder_share; ///< Value of feeder pickup to be paid for on delivery of cargo.
43 uint16 count; ///< The amount of cargo in this packet.
44 byte days_in_transit; ///< Amount of days this packet has been in transit.
45 CargoSource source; ///< Source of cargo.
46 StationID source_st; ///< The station where the cargo came from first.
47 TileIndex source_xy; ///< The origin of the cargo (first station in feeder chain).
48 union {
49 TileOrStationID loaded_at_xy; ///< Location where this cargo has been loaded into the vehicle.
50 TileOrStationID next_station; ///< Station where the cargo wants to go next.
53 /** The CargoList caches, thus needs to know about it. */
54 template <class Tinst, class Tcont> friend class CargoList;
55 friend class VehicleCargoList;
56 friend class StationCargoList;
57 /** We want this to be saved, right? */
58 friend const struct SaveLoad *GetCargoPacketDesc();
59 public:
60 /** Maximum number of items in a single cargo packet. */
61 static const uint16 MAX_COUNT = UINT16_MAX;
63 CargoPacket();
64 CargoPacket (const struct Station *st, uint16 count, SourceType source_type, SourceID source_id);
65 CargoPacket (uint16 count, byte days_in_transit, StationID source_st, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share = 0);
66 CargoPacket (const CargoPacket &cp, uint16 count, Money share);
68 /** Destroy the packet. */
69 ~CargoPacket() { }
71 CargoPacket *Split(uint new_size);
72 void Merge(CargoPacket *cp);
73 void Reduce(uint count);
75 /**
76 * Try to merge another packet into this one, if the total count allows it.
77 * @param cp Packet to merge.
78 * @return Whether merging was possible (and done).
80 bool TryMerge (CargoPacket *cp)
82 if (this->count + cp->count > MAX_COUNT) return false;
83 this->Merge (cp);
84 return true;
87 /**
88 * Sets the tile where the packet was loaded last.
89 * @param load_place Tile where the packet was loaded last.
91 void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
93 /**
94 * Sets the station where the packet is supposed to go next.
95 * @param next_station Next station the packet should go to.
97 void SetNextStation(StationID next_station) { this->next_station = next_station; }
99 /**
100 * Adds some feeder share to the packet.
101 * @param new_share Feeder share to be added.
103 void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
106 * Gets the number of 'items' in this packet.
107 * @return Item count.
109 inline uint16 Count() const
111 return this->count;
115 * Gets the amount of money already paid to earlier vehicles in
116 * the feeder chain.
117 * @return Feeder share.
119 inline Money FeederShare() const
121 return this->feeder_share;
125 * Gets part of the amount of money already paid to earlier vehicles in
126 * the feeder chain.
127 * @param part Amount of cargo to get the share for.
128 * @return Feeder share for the given amount of cargo.
130 inline Money FeederShare(uint part) const
132 return this->feeder_share * part / static_cast<uint>(this->count);
136 * Gets the number of days this cargo has been in transit.
137 * This number isn't really in days, but in 2.5 days (CARGO_AGING_TICKS = 185 ticks) and
138 * it is capped at 255.
139 * @return Length this cargo has been in transit.
141 inline byte DaysInTransit() const
143 return this->days_in_transit;
147 * Gets the source of the cargo.
148 * @return Source of the cargo.
150 inline const CargoSource &Source() const
152 return this->source;
156 * Gets the ID of the station where the cargo was loaded for the first time.
157 * @return StationID.
159 inline StationID SourceStation() const
161 return this->source_st;
165 * Gets the coordinates of the cargo's source station.
166 * @return Source station's coordinates.
168 inline TileIndex SourceStationXY() const
170 return this->source_xy;
174 * Gets the coordinates of the cargo's last loading station.
175 * @return Last loading station's coordinates.
177 inline TileIndex LoadedAtXY() const
179 return this->loaded_at_xy;
183 * Gets the ID of station the cargo wants to go next.
184 * @return Next station for this packets.
186 inline StationID NextStation() const
188 return this->next_station;
191 static void InvalidateAllFrom(SourceType src_type, SourceID src);
192 static void InvalidateAllFrom(StationID sid);
193 static void AfterLoad(const SavegameTypeVersion *stv);
197 * Iterate over all _valid_ cargo packets from the given start.
198 * @param var Variable used as "iterator".
199 * @param start Cargo packet ID of the first packet to iterate over.
201 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
204 * Iterate over all _valid_ cargo packets from the begin of the pool.
205 * @param var Variable used as "iterator".
207 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
210 * Simple collection class for a list of cargo packets.
211 * @tparam Tinst Actual instantiation of this cargo list.
213 template <class Tinst, class Tcont>
214 class CargoList {
215 public:
216 /** The iterator for our container. */
217 typedef typename Tcont::iterator Iterator;
218 /** The reverse iterator for our container. */
219 typedef typename Tcont::reverse_iterator ReverseIterator;
220 /** The const iterator for our container. */
221 typedef typename Tcont::const_iterator ConstIterator;
222 /** The const reverse iterator for our container. */
223 typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
225 /** Kind of actions that could be done with packets on move. */
226 enum MoveToAction {
227 MTA_BEGIN = 0,
228 MTA_TRANSFER = 0, ///< Transfer the cargo to the station.
229 MTA_DELIVER, ///< Deliver the cargo to some town or industry.
230 MTA_KEEP, ///< Keep the cargo in the vehicle.
231 MTA_LOAD, ///< Load the cargo from the station.
232 MTA_END,
233 NUM_MOVE_TO_ACTION = MTA_END
236 protected:
237 uint count; ///< Cache for the number of cargo entities.
238 uint cargo_days_in_transit; ///< Cache for the sum of number of days in transit of each entity; comparable to man-hours.
240 Tcont packets; ///< The cargo packets in this list.
242 void AddToCache(const CargoPacket *cp);
244 void RemoveFromCache(const CargoPacket *cp, uint count);
246 public:
247 /** Create the cargo list. */
248 CargoList() : count(0), cargo_days_in_transit(0), packets()
252 ~CargoList();
254 void OnCleanPool();
257 * Returns a pointer to the cargo packet list (so you can iterate over it etc).
258 * @return Pointer to the packet list.
260 inline const Tcont *Packets() const
262 return &this->packets;
266 * Returns average number of days in transit for a cargo entity.
267 * @return The before mentioned number.
269 inline uint DaysInTransit() const
271 return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
274 void InvalidateCache();
277 typedef std::list<CargoPacket *> CargoPacketList;
280 * CargoList that is used for vehicles.
282 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
283 protected:
284 /** The (direct) parent of this class. */
285 typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
287 Money feeder_share; ///< Cache for the feeder share.
288 uint action_counts[NUM_MOVE_TO_ACTION]; ///< Counts of cargo to be transfered, delivered, kept and loaded.
291 * Assert that the designation counts add up.
293 inline void AssertCountConsistency() const
295 assert(this->action_counts[MTA_KEEP] +
296 this->action_counts[MTA_DELIVER] +
297 this->action_counts[MTA_TRANSFER] +
298 this->action_counts[MTA_LOAD] == this->count);
301 void AddToCache(const CargoPacket *cp);
302 void RemoveFromCache(const CargoPacket *cp, uint count);
304 void AddToMeta(const CargoPacket *cp, MoveToAction action);
305 void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
307 static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
308 StationID current_station, bool accepted,
309 const StationIDStack &next_station);
311 public:
312 VehicleCargoList() : feeder_share(0)
314 memset (this->action_counts, 0, sizeof(this->action_counts));
317 /** The station cargo list needs to control the unloading. */
318 friend class StationCargoList;
319 /** The super class ought to know what it's doing. */
320 friend class CargoList<VehicleCargoList, CargoPacketList>;
321 /** The vehicles have a cargo list (and we want that saved). */
322 friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
325 * Returns source of the first cargo packet in this list.
326 * @return The before mentioned source.
328 inline StationID Source() const
330 return this->count == 0 ? INVALID_STATION : this->packets.front()->SourceStation();
334 * Returns total sum of the feeder share for all packets.
335 * @return The before mentioned number.
337 inline Money FeederShare() const
339 return this->feeder_share;
343 * Returns the amount of cargo designated for a given purpose.
344 * @param action Action the cargo is designated for.
345 * @return Amount of cargo designated for the given action.
347 inline uint ActionCount(MoveToAction action) const
349 return this->action_counts[action];
353 * Returns sum of cargo on board the vehicle (ie not only
354 * reserved).
355 * @return Cargo on board the vehicle.
357 inline uint StoredCount() const
359 return this->count - this->action_counts[MTA_LOAD];
363 * Returns sum of cargo, including reserved cargo.
364 * @return Sum of cargo.
366 inline uint TotalCount() const
368 return this->count;
372 * Returns sum of reserved cargo.
373 * @return Sum of reserved cargo.
375 inline uint ReservedCount() const
377 return this->action_counts[MTA_LOAD];
381 * Returns sum of cargo to be moved out of the vehicle at the current station.
382 * @return Cargo to be moved.
384 inline uint UnloadCount() const
386 return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
390 * Returns the sum of cargo to be kept in the vehicle at the current station.
391 * @return Cargo to be kept or loaded.
393 inline uint RemainingCount() const
395 return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
398 void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
400 void AgeCargo();
402 void InvalidateCache();
404 void SetTransferLoadPlace(TileIndex xy);
406 bool Stage (bool accepted, StationID current_station,
407 const StationIDStack &next_station, uint8 order_flags,
408 const GoodsEntry *ge, CargoPayment *payment);
411 * Marks all cargo in the vehicle as to be kept. This is mostly useful for
412 * loading old savegames. When loading is aborted the reserved cargo has
413 * to be returned first.
415 inline void KeepAll()
417 this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
418 this->action_counts[MTA_KEEP] = this->count;
422 * Marks cargo previously set to load or deliver as to be kept.
423 * @param from Previous designation of cargo (MTA_LOAD or MTA_DELIVER).
424 * @param max_move Maximum amount of cargo to reassign.
426 void Keep (MoveToAction from, uint max_move = UINT_MAX)
428 assert (from == MTA_DELIVER || from == MTA_LOAD);
429 max_move = min (this->action_counts[from], max_move);
430 this->action_counts[from] -= max_move;
431 this->action_counts[MTA_KEEP] += max_move;
434 /* Methods for moving cargo around. First parameter is always maximum
435 * amount of cargo to be moved. Second parameter is destination (if
436 * applicable), return value is amount of cargo actually moved. */
438 void Transfer (void);
439 uint Return (StationCargoList *dest, uint max_move = UINT_MAX);
440 uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
441 uint Shift(uint max_move, VehicleCargoList *dest);
442 uint Truncate(uint max_move = UINT_MAX);
443 void Reroute (StationID avoid, StationID avoid2, const GoodsEntry *ge);
444 void Reattach (VehicleCargoList *dest, uint max_move = UINT_MAX);
447 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
448 typedef std::map<StationID, uint> StationCargoAmountMap;
451 * CargoList that is used for stations.
453 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
454 protected:
455 /** The (direct) parent of this class. */
456 typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
458 uint reserved_count; ///< Amount of cargo being reserved for loading.
460 public:
461 /** The super class ought to know what it's doing. */
462 friend class CargoList<StationCargoList, StationCargoPacketMap>;
463 /** The stations, via GoodsEntry, have a CargoList. */
464 friend const struct SaveLoad *GetGoodsDesc();
466 friend class VehicleCargoList;
468 uint ShiftCargo (VehicleCargoList *dest, uint max_move,
469 TileIndex load_place, const StationIDStack &next, bool load);
471 void Append(CargoPacket *cp, StationID next);
474 * Check for cargo headed for a specific station.
475 * @param next Station the cargo is headed for.
476 * @return If there is any cargo for that station.
478 inline bool HasCargoFor (const StationIDStack &next) const
480 for (StationIDStack::const_iterator iter (next.begin()); iter != next.end(); iter++) {
481 if (this->packets.find (*iter) != this->packets.end()) return true;
483 /* Packets for INVALID_STTION can go anywhere. */
484 return this->packets.find(INVALID_STATION) != this->packets.end();
488 * Returns source of the first cargo packet in this list.
489 * @return The before mentioned source.
491 inline StationID Source() const
493 return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->SourceStation();
497 * Returns sum of cargo still available for loading at the sation.
498 * (i.e. not counting cargo which is already reserved for loading)
499 * @return Cargo on board the vehicle.
501 inline uint AvailableCount() const
503 return this->count;
507 * Returns sum of cargo reserved for loading onto vehicles.
508 * @return Cargo reserved for loading.
510 inline uint ReservedCount() const
512 return this->reserved_count;
516 * Returns total count of cargo at the station, including
517 * cargo which is already reserved for loading.
518 * @return Total cargo count.
520 inline uint TotalCount() const
522 return this->count + this->reserved_count;
525 /* Methods for moving cargo around. First parameter is always maximum
526 * amount of cargo to be moved. Second parameter is destination (if
527 * applicable), return value is amount of cargo actually moved. */
530 * Reserves cargo for loading onto the vehicle.
531 * @param max_move Maximum amount of cargo to reserve.
532 * @param dest VehicleCargoList to reserve for.
533 * @param load_place Tile index of the current station.
534 * @param next Next station(s) the loading vehicle will visit.
535 * @return Amount of cargo actually reserved.
537 uint Reserve (uint max_move, VehicleCargoList *dest,
538 TileIndex load_place, const StationIDStack &next)
540 return this->ShiftCargo (dest, max_move, load_place, next, false);
543 uint Load (uint max_move, VehicleCargoList *dest, TileIndex load_place, const StationIDStack &next);
544 uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
545 void Reroute (StationID avoid, StationID avoid2, const GoodsEntry *ge);
548 #endif /* CARGOPACKET_H */