summaryrefslogtreecommitdiff
path: root/src/cargodest_base.h
blob: 8d71e2f8fa131ac6f5aeee36a1b97fb9714bb82a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* $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 <http://www.gnu.org/licenses/>.
 */

/** @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<uint32>   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<CargoLink, 8> 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<CargoSourceSink *>(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<RouteLink, RouteLinkID, 512, 262144> 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 */