OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

station_base.h
Go to the documentation of this file.
1 /* $Id: station_base.h 26891 2014-09-21 16:19:52Z fonsinchen $ */
2
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 */
9
12 #ifndef STATION_BASE_H
13 #define STATION_BASE_H
14
15 #include "core/random_func.hpp"
16 #include "base_station_base.h"
17 #include "newgrf_airport.h"
18 #include "cargopacket.h"
19 #include "industry_type.h"
20 #include "linkgraph/linkgraph_type.h"
21 #include "newgrf_storage.h"
22 #include <map>
23
24 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
25 extern StationPool _station_pool;
26
27 static const byte INITIAL_STATION_RATING = 175;
28
36 class FlowStat {
37 public:
38 typedef std::map<uint32, StationID> SharesMap;
39
45 inline FlowStat() {NOT_REACHED();}
46
53 inline FlowStat(StationID st, uint flow, bool restricted = false)
54 {
55 assert(flow > 0);
56 this->shares[flow] = st;
57 this->unrestricted = restricted ? 0 : flow;
58 }
59
68 inline void AppendShare(StationID st, uint flow, bool restricted = false)
69 {
70 assert(flow > 0);
71 this->shares[(--this->shares.end())->first + flow] = st;
72 if (!restricted) this->unrestricted += flow;
73 }
74
75 uint GetShare(StationID st) const;
76
77 void ChangeShare(StationID st, int flow);
78
79 void RestrictShare(StationID st);
80
81 void ReleaseShare(StationID st);
82
83 void ScaleToMonthly(uint runtime);
84
90 inline const SharesMap *GetShares() const { return &this->shares; }
91
96 inline uint GetUnrestricted() const { return this->unrestricted; }
97
103 inline void SwapShares(FlowStat &other)
104 {
105 this->shares.swap(other.shares);
106 Swap(this->unrestricted, other.unrestricted);
107 }
108
117 inline StationID GetViaWithRestricted(bool &is_restricted) const
118 {
119 assert(!this->shares.empty());
120 uint rand = RandomRange((--this->shares.end())->first);
121 is_restricted = rand >= this->unrestricted;
122 return this->shares.upper_bound(rand)->second;
123 }
124
132 inline StationID GetVia() const
133 {
134 assert(!this->shares.empty());
135 return this->unrestricted > 0 ?
136 this->shares.upper_bound(RandomRange(this->unrestricted))->second :
137 INVALID_STATION;
138 }
139
140 StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
141
142 void Invalidate();
143
144 private:
145 SharesMap shares;
146 uint unrestricted;
147 };
148
150 class FlowStatMap : public std::map<StationID, FlowStat> {
151 public:
152 uint GetFlow() const;
153 uint GetFlowVia(StationID via) const;
154 uint GetFlowFrom(StationID from) const;
155 uint GetFlowFromVia(StationID from, StationID via) const;
156
157 void AddFlow(StationID origin, StationID via, uint amount);
158 void PassOnFlow(StationID origin, StationID via, uint amount);
159 StationIDStack DeleteFlows(StationID via);
160 void RestrictFlows(StationID via);
161 void ReleaseFlows(StationID via);
162 void FinalizeLocalConsumption(StationID self);
163 };
164
168 struct GoodsEntry {
170 enum GoodsEntryStatus {
175 GES_ACCEPTANCE,
176
185 GES_RATING,
186
191 GES_EVER_ACCEPTED,
192
197 GES_LAST_MONTH,
198
203 GES_CURRENT_MONTH,
204
209 GES_ACCEPTED_BIGTICK,
210 };
211
212 GoodsEntry() :
213 status(0),
214 time_since_pickup(255),
215 rating(INITIAL_STATION_RATING),
216 last_speed(0),
217 last_age(255),
218 amount_fract(0),
219 link_graph(INVALID_LINK_GRAPH),
220 node(INVALID_NODE),
221 max_waiting_cargo(0)
222 {}
223
224 byte status;
225
231 byte time_since_pickup;
232
233 byte rating;
234
244 byte last_speed;
245
250 byte last_age;
251
252 byte amount_fract;
253 StationCargoList cargo;
254
255 LinkGraphID link_graph;
256 NodeID node;
257 FlowStatMap flows;
258 uint max_waiting_cargo;
259
265 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
266
271 inline bool HasRating() const
272 {
273 return HasBit(this->status, GES_RATING);
274 }
275
281 inline StationID GetVia(StationID source) const
282 {
283 FlowStatMap::const_iterator flow_it(this->flows.find(source));
284 return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
285 }
286
295 inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
296 {
297 FlowStatMap::const_iterator flow_it(this->flows.find(source));
298 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
299 }
300 };
301
303 struct Airport : public TileArea {
304 Airport() : TileArea(INVALID_TILE, 0, 0) {}
305
306 uint64 flags;
307 byte type;
308 byte layout;
309 DirectionByte rotation;
310
311 PersistentStorage *psa;
312
318 const AirportSpec *GetSpec() const
319 {
320 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
321 return AirportSpec::Get(this->type);
322 }
323
330 const AirportFTAClass *GetFTA() const
331 {
332 return this->GetSpec()->fsm;
333 }
334
336 inline bool HasHangar() const
337 {
338 return this->GetSpec()->nof_depots > 0;
339 }
340
349 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
350 {
351 const AirportSpec *as = this->GetSpec();
352 switch (this->rotation) {
353 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
354
355 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
356
357 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
358
359 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
360
361 default: NOT_REACHED();
362 }
363 }
364
371 inline TileIndex GetHangarTile(uint hangar_num) const
372 {
373 const AirportSpec *as = this->GetSpec();
374 for (uint i = 0; i < as->nof_depots; i++) {
375 if (as->depot_table[i].hangar_num == hangar_num) {
376 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
377 }
378 }
379 NOT_REACHED();
380 }
381
388 inline Direction GetHangarExitDirection(TileIndex tile) const
389 {
390 const AirportSpec *as = this->GetSpec();
391 const HangarTileTable *htt = GetHangarDataByTile(tile);
392 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
393 }
394
401 inline uint GetHangarNum(TileIndex tile) const
402 {
403 const HangarTileTable *htt = GetHangarDataByTile(tile);
404 return htt->hangar_num;
405 }
406
408 inline uint GetNumHangars() const
409 {
410 uint num = 0;
411 uint counted = 0;
412 const AirportSpec *as = this->GetSpec();
413 for (uint i = 0; i < as->nof_depots; i++) {
414 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
415 num++;
416 SetBit(counted, as->depot_table[i].hangar_num);
417 }
418 }
419 return num;
420 }
421
422 private:
429 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
430 {
431 const AirportSpec *as = this->GetSpec();
432 for (uint i = 0; i < as->nof_depots; i++) {
433 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
434 return as->depot_table + i;
435 }
436 }
437 NOT_REACHED();
438 }
439 };
440
441 typedef SmallVector<Industry *, 2> IndustryVector;
442
444 struct Station FINAL : SpecializedStation<Station, false> {
445 public:
446 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
447 {
448 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
449 }
450
451 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
452
453 RoadStop *bus_stops;
454 TileArea bus_station;
455 RoadStop *truck_stops;
456 TileArea truck_station;
457
458 Airport airport;
459 TileIndex dock_tile;
460
461 IndustryType indtype;
462
463 StationHadVehicleOfTypeByte had_vehicle_of_type;
464
465 byte time_since_load;
466 byte time_since_unload;
467
468 byte last_vehicle_type;
469 std::list<Vehicle *> loading_vehicles;
470 GoodsEntry goods[NUM_CARGO];
471 uint32 always_accepted;
472
473 IndustryVector industries_near;
474
475 Station(TileIndex tile = INVALID_TILE);
476 ~Station();
477
478 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
479
480 void MarkTilesDirty(bool cargo_change) const;
481
482 void UpdateVirtCoord();
483
484 /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
485 /* virtual */ uint GetPlatformLength(TileIndex tile) const;
486 void RecomputeIndustriesNear();
487 static void RecomputeIndustriesNearForAll();
488
489 uint GetCatchmentRadius() const;
490 Rect GetCatchmentRect() const;
491
492 /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
493 {
494 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
495 }
496
497 inline bool TileBelongsToAirport(TileIndex tile) const
498 {
499 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
500 }
501
502 /* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
503
504 /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
505 };
506
507 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
508
510 class AirportTileIterator : public OrthogonalTileIterator {
511 private:
512 const Station *st;
513
514 public:
519 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
520 {
521 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
522 }
523
524 inline TileIterator& operator ++()
525 {
526 (*this).OrthogonalTileIterator::operator++();
527 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
528 (*this).OrthogonalTileIterator::operator++();
529 }
530 return *this;
531 }
532
533 virtual TileIterator *Clone() const
534 {
535 return new AirportTileIterator(*this);
536 }
537 };
538
539 #endif /* STATION_BASE_H */