/* $Id$ */
/*
* This file is part of OpenTTD.
* 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.
* 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.
* 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 .
*/
/** @file cargodest_base.h Classes and types for entities having cargo destinations. */
#ifndef CARGODEST_BASE_H
#define CARGODEST_BASE_H
#include "cargodest_type.h"
#include "cargo_type.h"
#include "town_type.h"
#include "core/smallvec_type.hpp"
#include "core/pool_type.hpp"
#include "order_type.h"
#include "station_type.h"
#include "company_type.h"
#include "vehicle_type.h"
struct CargoSourceSink;
/** Information about a demand link for cargo. */
struct CargoLink {
CargoSourceSink *dest; ///< Destination of the link.
TransportedCargoStat amount; ///< Transported cargo statistics.
uint weight; ///< Weight of this link.
byte weight_mod; ///< Weight modifier.
CargoLink(CargoSourceSink *d, byte mod) : dest(d), weight(1), weight_mod(mod) {}
/* Compare two cargo links for inequality. */
bool operator !=(const CargoLink &other) const
{
return other.dest != dest;
}
};
/** An entity producing or accepting cargo with a destination. */
struct CargoSourceSink {
/** List of destinations for each cargo type. */
SmallVector cargo_links[NUM_CARGO];
/** Sum of the destination weights for each cargo type. */
uint cargo_links_weight[NUM_CARGO];
/** NOSAVE: Desired link count for each cargo. */
uint16 num_links_expected[NUM_CARGO];
/** NOSAVE: Incoming link count for each cargo. */
uint num_incoming_links[NUM_CARGO];
virtual ~CargoSourceSink();
/** Get the type of this entity. */
virtual SourceType GetType() const = 0;
/** Get the source ID corresponding with this entity. */
virtual SourceID GetID() const = 0;
/**
* Test if a demand link to a destination exists.
* @param cid Cargo type for which a link should be searched.
* @param dest Destination to search for.
* @return True if a link to the destination is present.
*/
bool HasLinkTo(CargoID cid, const CargoSourceSink *dest) const
{
return this->cargo_links[cid].Contains(CargoLink(const_cast(dest), 1));
}
/** Is this cargo accepted? */
virtual bool AcceptsCargo(CargoID cid) const = 0;
/** Is this cargo produced? */
virtual bool SuppliesCargo(CargoID cid) const = 0;
/** Get the link weight for this as a destination for a specific cargo. */
virtual uint GetDestinationWeight(CargoID cid, byte weight_mod) const = 0;
CargoLink *GetRandomLink(CargoID cid, bool allow_self);
/** Create the special cargo links for a cargo if not already present. */
virtual void CreateSpecialLinks(CargoID cid);
/** Get a random destination tile index for this cargo. */
virtual TileArea GetTileForDestination(CargoID cid) = 0;
void SaveCargoSourceSink();
void LoadCargoSourceSink();
void PtrsCargoSourceSink();
};
/** Pool of route links. */
typedef Pool RouteLinkPool;
extern RouteLinkPool _routelink_pool;
/** Holds information about a route service between two stations. */
struct RouteLink : public RouteLinkPool::PoolItem<&_routelink_pool> {
private:
friend const struct SaveLoad *GetRouteLinkDescription(); ///< Saving and loading of route links.
friend void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner);
friend void AgeRouteLinks(Station *st);
StationID dest; ///< Destination station id.
OrderID prev_order; ///< Id of the order the vehicle had when arriving at the origin.
OrderID next_order; ///< Id of the order the vehicle will leave the station with.
OwnerByte owner; ///< Owner of the vehicle of the link.
VehicleTypeByte vtype; ///< Vehicle type traveling this link.
uint32 travel_time; ///< Average travel duration of this link.
uint16 wait_time; ///< Days since the last vehicle traveled this link.
public:
/** Constructor */
RouteLink(StationID dest = INVALID_STATION, OrderID prev_order = INVALID_ORDER, OrderID next_order = INVALID_ORDER, Owner owner = INVALID_OWNER, uint32 travel_time = 0, VehicleType vtype = VEH_INVALID)
: dest(dest), prev_order(prev_order), next_order(next_order), travel_time(travel_time), wait_time(0)
{
this->owner = owner;
this->vtype = vtype;
}
~RouteLink();
/** Get the target station of this link. */
inline StationID GetDestination() const { return this->dest; }
/** Get the order id that lead to the origin station. */
inline OrderID GetOriginOrderId() const { return this->prev_order; }
/** Get the order id that lead to the destination station. */
inline OrderID GetDestOrderId() const { return this->next_order; }
/** Get the owner of this link. */
inline Owner GetOwner() const { return this->owner; }
/** Get the type of the vehicles on this link. */
inline VehicleType GetVehicleType() const { return this->vtype; }
/** Get the travel time of this link. */
inline uint32 GetTravelTime() const { return this->travel_time; }
/** Get the wait time at the origin station. */
inline uint16 GetWaitTime() const { return this->wait_time; }
/** Update the destination of the route link. */
inline void SetDestination(StationID dest_id, OrderID dest_order_id)
{
this->dest = dest_id;
this->next_order = dest_order_id;
}
/** Update the travel time with a new travel time. */
void UpdateTravelTime(uint32 new_time)
{
/* Weighted average so that a single late vehicle will not skew the time. */
this->travel_time = (3 * this->travel_time + new_time) / 4;
}
/** A vehicle arrived at the origin of the link, reset waiting time. */
void VehicleArrived()
{
this->wait_time = 0;
}
};
/**
* Iterate over all valid route links from a given start.
* @param var The variable to use as the "iterator".
* @param start The #RouteLinkID to start the iteration from.
*/
#define FOR_ALL_ROUTELINKS_FROM(var, start) FOR_ALL_ITEMS_FROM(RouteLink, routelink_index, var, start)
/**
* Iterate over all valid route links.
* @param var The variable to use as the "iterator".
*/
#define FOR_ALL_ROUTELINKS(var) FOR_ALL_ROUTELINKS_FROM(var, 0)
#endif /* CARGODEST_BASE_H */