Rework ChoosePylonPosition to simplify the loop
[openttd/fttd.git] / src / roadstop_base.h
blob299618bc56a6c3037bffe5d350fbbb657291fe4b
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 roadstop_base.h Base class for roadstops. */
12 #ifndef ROADSTOP_BASE_H
13 #define ROADSTOP_BASE_H
15 #include "core/pool_type.hpp"
16 #include "core/bitmath_func.hpp"
17 #include "map/station.h"
19 /** A Stop for a Road Vehicle */
20 struct RoadStop : PooledItem <RoadStop, RoadStopID, 32, 64000> {
21 enum RoadStopStatusFlags {
22 RSSFB_BAY0_FREE = 0, ///< Non-zero when bay 0 is free
23 RSSFB_BAY1_FREE = 1, ///< Non-zero when bay 1 is free
24 RSSFB_BAY_COUNT = 2, ///< Max. number of bays
25 RSSFB_BASE_ENTRY = 6, ///< Non-zero when the entries on this road stop are the primary, i.e. the ones to delete
26 RSSFB_ENTRY_BUSY = 7, ///< Non-zero when roadstop entry is busy
29 /** Container for both entry points of a drive-through road stop. */
30 struct Platform {
31 private:
32 uint length; ///< The length of the stop in tile 'units'
33 uint occupied_east; ///< The amount of occupied stop in tile 'units' to the east
34 uint occupied_west; ///< The amount of occupied stop in tile 'units' to the west
36 public:
37 friend struct RoadStop; ///< Oh yeah, the road stop may play with me.
39 /** Create a platform. */
40 CONSTEXPR Platform()
41 : length(0), occupied_east(), occupied_west()
45 /**
46 * Get the length of this drive through stop.
47 * @return the length in tile units.
49 inline uint GetLength() const
51 return this->length;
54 /**
55 * Get the amount of occupied space in a given direction.
56 * @param dir The direction to get the occupied space for.
57 * @return the occupied space in tile units.
59 inline uint GetOccupied (DiagDirection dir) const
61 return HasBit ((int)dir, 1) ? this->occupied_west : this->occupied_east;
64 private:
65 /**
66 * Get a pointer to the occupied field in a given direction.
67 * @param dir The direction to get the occupied pointer for.
68 * @return A pointer to the occupied field in the given direction.
70 inline uint *GetOccupiedPtr (DiagDirection dir)
72 return HasBit ((int)dir, 1) ? &this->occupied_west : &this->occupied_east;
75 public:
76 void Rebuild (TileIndex tile);
79 TileIndex xy; ///< Position on the map
80 byte status; ///< Current status of the Stop, @see RoadStopSatusFlag. Access using *Bay and *Busy functions.
81 struct RoadStop *next; ///< Next stop of the given type at this station
82 private:
83 Platform *platform; ///< Platform data for drive-through stops
85 public:
86 /** Initializes a RoadStop */
87 inline RoadStop(TileIndex tile = INVALID_TILE) :
88 xy(tile),
89 status((1 << RSSFB_BAY_COUNT) - 1)
90 { }
92 ~RoadStop();
94 /**
95 * Checks whether there is a free bay in this road stop
96 * @return is at least one bay free?
98 inline bool HasFreeBay() const
100 return GB(this->status, 0, RSSFB_BAY_COUNT) != 0;
104 * Checks whether the given bay is free in this road stop
105 * @param nr bay to check
106 * @return is given bay free?
108 inline bool IsFreeBay(uint nr) const
110 assert(nr < RSSFB_BAY_COUNT);
111 return HasBit(this->status, nr);
115 * Checks whether the entrance of the road stop is occupied by a vehicle
116 * @return is entrance busy?
118 inline bool IsEntranceBusy() const
120 return HasBit(this->status, RSSFB_ENTRY_BUSY);
124 * Makes an entrance occupied or free
125 * @param busy If true, marks busy; free otherwise.
127 inline void SetEntranceBusy(bool busy)
129 SB(this->status, RSSFB_ENTRY_BUSY, 1, busy);
133 * Get the drive through road stop platform struct.
134 * @return the platform
136 inline const Platform *GetPlatform (void) const
138 return this->platform;
141 void MakeDriveThrough();
142 void ClearDriveThrough();
145 * Add the length of a vehicle to the occupied length in the platform.
146 * @param dir The direction of the vehicle.
147 * @param length The vehicle length to add.
149 void EnterDriveThrough (DiagDirection dir, uint length)
151 assert (IsDriveThroughStopTile (this->xy));
153 /* We cannot assert on occupied < length because of the
154 * remote possibility that RVs are running through each
155 * other when trying to prevent an infinite jam. */
156 *this->platform->GetOccupiedPtr(dir) += length;
160 * Subtract the length of a vehicle from the occupied length in the platform.
161 * @param dir The direction of the vehicle.
162 * @param length The vehicle length to subtract.
164 void LeaveDriveThrough (DiagDirection dir, uint length)
166 assert (IsDriveThroughStopTile (this->xy));
168 uint *p = this->platform->GetOccupiedPtr (dir);
169 assert (*p >= length);
170 *p -= length;
173 static RoadStop *GetByTile(TileIndex tile, RoadStopType type);
175 static bool IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next);
177 /** Rebuild the vehicles and other metadata on this stop. */
178 void Rebuild (void)
180 assert (HasBit (this->status, RSSFB_BASE_ENTRY));
182 this->platform->Rebuild (this->xy);
185 void CheckIntegrity (void) const;
188 * Allocates a bay
189 * @return the allocated bay number, or -1 if all are busy
191 inline int AllocateBay()
193 /* Find the first free bay. If the bit is set, the bay is free. */
194 for (uint bay = 0; bay < RSSFB_BAY_COUNT; bay++) {
195 if (HasBit (this->status, bay)) {
196 ClrBit (this->status, bay);
197 return bay;
201 return -1;
205 * Frees the given bay
206 * @param nr the number of the bay to free
208 inline void FreeBay(uint nr)
210 assert(nr < RSSFB_BAY_COUNT);
211 SetBit(this->status, nr);
215 #define FOR_ALL_ROADSTOPS_FROM(var, start) FOR_ALL_ITEMS_FROM(RoadStop, roadstop_index, var, start)
216 #define FOR_ALL_ROADSTOPS(var) FOR_ALL_ROADSTOPS_FROM(var, 0)
218 #endif /* ROADSTOP_BASE_H */