2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 /** @file rail.cpp Implementation of rail specific functions. */
11 #include "station_map.h"
12 #include "tunnelbridge_map.h"
13 #include "timer/timer_game_calendar.h"
14 #include "company_func.h"
15 #include "company_base.h"
16 #include "engine_base.h"
18 #include "safeguards.h"
20 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
21 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
22 * direction along with the trackdir */
23 extern const uint8_t _signal_along_trackdir
[TRACKDIR_END
] = {
24 0x8, 0x8, 0x8, 0x2, 0x4, 0x1, 0, 0,
25 0x4, 0x4, 0x4, 0x1, 0x8, 0x2
28 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
29 * direction against the trackdir */
30 extern const uint8_t _signal_against_trackdir
[TRACKDIR_END
] = {
31 0x4, 0x4, 0x4, 0x1, 0x8, 0x2, 0, 0,
32 0x8, 0x8, 0x8, 0x2, 0x4, 0x1
35 /* Maps a Track to the bits that store the status of the two signals that can
36 * be present on the given track */
37 extern const uint8_t _signal_on_track
[] = {
38 0xC, 0xC, 0xC, 0x3, 0xC, 0x3
41 /* Maps a diagonal direction to the all trackdirs that are connected to any
42 * track entering in this direction (including those making 90 degree turns)
44 extern const TrackdirBits _exitdir_reaches_trackdirs
[] = {
45 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_LEFT_N
, // DIAGDIR_NE
46 TRACKDIR_BIT_Y_SE
| TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_UPPER_E
, // DIAGDIR_SE
47 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_RIGHT_S
, // DIAGDIR_SW
48 TRACKDIR_BIT_Y_NW
| TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_LOWER_W
// DIAGDIR_NW
51 extern const Trackdir _next_trackdir
[TRACKDIR_END
] = {
52 TRACKDIR_X_NE
, TRACKDIR_Y_SE
, TRACKDIR_LOWER_E
, TRACKDIR_UPPER_E
, TRACKDIR_RIGHT_S
, TRACKDIR_LEFT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
,
53 TRACKDIR_X_SW
, TRACKDIR_Y_NW
, TRACKDIR_LOWER_W
, TRACKDIR_UPPER_W
, TRACKDIR_RIGHT_N
, TRACKDIR_LEFT_N
56 /* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
57 extern const TrackdirBits _track_crosses_trackdirs
[TRACK_END
] = {
58 TRACKDIR_BIT_Y_SE
| TRACKDIR_BIT_Y_NW
, // TRACK_X
59 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_X_SW
, // TRACK_Y
60 TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_LEFT_S
, // TRACK_UPPER
61 TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_LEFT_S
, // TRACK_LOWER
62 TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_LOWER_E
, // TRACK_LEFT
63 TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_LOWER_E
// TRACK_RIGHT
66 /* Maps a track to all tracks that make 90 deg turns with it. */
67 extern const TrackBits _track_crosses_tracks
[] = {
68 TRACK_BIT_Y
, // TRACK_X
69 TRACK_BIT_X
, // TRACK_Y
70 TRACK_BIT_VERT
, // TRACK_UPPER
71 TRACK_BIT_VERT
, // TRACK_LOWER
72 TRACK_BIT_HORZ
, // TRACK_LEFT
73 TRACK_BIT_HORZ
// TRACK_RIGHT
76 /* Maps a trackdir to the (4-way) direction the tile is exited when following
78 extern const DiagDirection _trackdir_to_exitdir
[TRACKDIR_END
] = {
79 DIAGDIR_NE
, DIAGDIR_SE
, DIAGDIR_NE
, DIAGDIR_SE
, DIAGDIR_SW
, DIAGDIR_SE
, DIAGDIR_NE
, DIAGDIR_NE
,
80 DIAGDIR_SW
, DIAGDIR_NW
, DIAGDIR_NW
, DIAGDIR_SW
, DIAGDIR_NW
, DIAGDIR_NE
,
83 extern const Trackdir _track_exitdir_to_trackdir
[][DIAGDIR_END
] = {
84 {TRACKDIR_X_NE
, INVALID_TRACKDIR
, TRACKDIR_X_SW
, INVALID_TRACKDIR
},
85 {INVALID_TRACKDIR
, TRACKDIR_Y_SE
, INVALID_TRACKDIR
, TRACKDIR_Y_NW
},
86 {TRACKDIR_UPPER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_UPPER_W
},
87 {INVALID_TRACKDIR
, TRACKDIR_LOWER_E
, TRACKDIR_LOWER_W
, INVALID_TRACKDIR
},
88 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LEFT_S
, TRACKDIR_LEFT_N
},
89 {TRACKDIR_RIGHT_N
, TRACKDIR_RIGHT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
}
92 extern const Trackdir _track_enterdir_to_trackdir
[][DIAGDIR_END
] = {
93 {TRACKDIR_X_NE
, INVALID_TRACKDIR
, TRACKDIR_X_SW
, INVALID_TRACKDIR
},
94 {INVALID_TRACKDIR
, TRACKDIR_Y_SE
, INVALID_TRACKDIR
, TRACKDIR_Y_NW
},
95 {INVALID_TRACKDIR
, TRACKDIR_UPPER_E
, TRACKDIR_UPPER_W
, INVALID_TRACKDIR
},
96 {TRACKDIR_LOWER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LOWER_W
},
97 {TRACKDIR_LEFT_N
, TRACKDIR_LEFT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
},
98 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_RIGHT_S
, TRACKDIR_RIGHT_N
}
101 extern const Trackdir _track_direction_to_trackdir
[][DIR_END
] = {
102 {INVALID_TRACKDIR
, TRACKDIR_X_NE
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_X_SW
, INVALID_TRACKDIR
, INVALID_TRACKDIR
},
103 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_Y_SE
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_Y_NW
},
104 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_UPPER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_UPPER_W
, INVALID_TRACKDIR
},
105 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LOWER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LOWER_W
, INVALID_TRACKDIR
},
106 {TRACKDIR_LEFT_N
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LEFT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
},
107 {TRACKDIR_RIGHT_N
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_RIGHT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
}
110 extern const Trackdir _dir_to_diag_trackdir
[] = {
111 TRACKDIR_X_NE
, TRACKDIR_Y_SE
, TRACKDIR_X_SW
, TRACKDIR_Y_NW
,
114 extern const TrackBits _corner_to_trackbits
[] = {
115 TRACK_BIT_LEFT
, TRACK_BIT_LOWER
, TRACK_BIT_RIGHT
, TRACK_BIT_UPPER
,
118 extern const TrackdirBits _uphill_trackdirs
[] = {
119 TRACKDIR_BIT_NONE
, ///< 0 SLOPE_FLAT
120 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_NW
, ///< 1 SLOPE_W -> inclined for diagonal track
121 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_SE
, ///< 2 SLOPE_S -> inclined for diagonal track
122 TRACKDIR_BIT_X_SW
, ///< 3 SLOPE_SW
123 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_SE
, ///< 4 SLOPE_E -> inclined for diagonal track
124 TRACKDIR_BIT_NONE
, ///< 5 SLOPE_EW
125 TRACKDIR_BIT_Y_SE
, ///< 6 SLOPE_SE
126 TRACKDIR_BIT_NONE
, ///< 7 SLOPE_WSE -> leveled
127 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_NW
, ///< 8 SLOPE_N -> inclined for diagonal track
128 TRACKDIR_BIT_Y_NW
, ///< 9 SLOPE_NW
129 TRACKDIR_BIT_NONE
, ///< 10 SLOPE_NS
130 TRACKDIR_BIT_NONE
, ///< 11 SLOPE_NWS -> leveled
131 TRACKDIR_BIT_X_NE
, ///< 12 SLOPE_NE
132 TRACKDIR_BIT_NONE
, ///< 13 SLOPE_ENW -> leveled
133 TRACKDIR_BIT_NONE
, ///< 14 SLOPE_SEN -> leveled
134 TRACKDIR_BIT_NONE
, ///< 15 invalid
135 TRACKDIR_BIT_NONE
, ///< 16 invalid
136 TRACKDIR_BIT_NONE
, ///< 17 invalid
137 TRACKDIR_BIT_NONE
, ///< 18 invalid
138 TRACKDIR_BIT_NONE
, ///< 19 invalid
139 TRACKDIR_BIT_NONE
, ///< 20 invalid
140 TRACKDIR_BIT_NONE
, ///< 21 invalid
141 TRACKDIR_BIT_NONE
, ///< 22 invalid
142 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_SE
, ///< 23 SLOPE_STEEP_S -> inclined for diagonal track
143 TRACKDIR_BIT_NONE
, ///< 24 invalid
144 TRACKDIR_BIT_NONE
, ///< 25 invalid
145 TRACKDIR_BIT_NONE
, ///< 26 invalid
146 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_NW
, ///< 27 SLOPE_STEEP_W -> inclined for diagonal track
147 TRACKDIR_BIT_NONE
, ///< 28 invalid
148 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_NW
, ///< 29 SLOPE_STEEP_N -> inclined for diagonal track
149 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_SE
, ///< 30 SLOPE_STEEP_E -> inclined for diagonal track
153 * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
155 RailType
GetTileRailType(Tile tile
)
157 switch (GetTileType(tile
)) {
159 return GetRailType(tile
);
162 /* rail/road crossing */
163 if (IsLevelCrossing(tile
)) return GetRailType(tile
);
167 if (HasStationRail(tile
)) return GetRailType(tile
);
170 case MP_TUNNELBRIDGE
:
171 if (GetTunnelBridgeTransportType(tile
) == TRANSPORT_RAIL
) return GetRailType(tile
);
177 return INVALID_RAILTYPE
;
181 * Finds out if a company has a certain buildable railtype available.
182 * @param company the company in question
183 * @param railtype requested RailType
184 * @return true if company has requested RailType available
186 bool HasRailTypeAvail(const CompanyID company
, const RailType railtype
)
188 return !HasBit(_railtypes_hidden_mask
, railtype
) && HasBit(Company::Get(company
)->avail_railtypes
, railtype
);
192 * Test if any buildable railtype is available for a company.
193 * @param company the company in question
194 * @return true if company has any RailTypes available
196 bool HasAnyRailTypesAvail(const CompanyID company
)
198 return (Company::Get(company
)->avail_railtypes
& ~_railtypes_hidden_mask
) != 0;
202 * Validate functions for rail building.
203 * @param rail the railtype to check.
204 * @return true if the current company may build the rail.
206 bool ValParamRailType(const RailType rail
)
208 return rail
< RAILTYPE_END
&& HasRailTypeAvail(_current_company
, rail
);
212 * Add the rail types that are to be introduced at the given date.
213 * @param current The currently available railtypes.
214 * @param date The date for the introduction comparisons.
215 * @return The rail types that should be available when date
216 * introduced rail types are taken into account as well.
218 RailTypes
AddDateIntroducedRailTypes(RailTypes current
, TimerGameCalendar::Date date
)
220 RailTypes rts
= current
;
222 for (RailType rt
= RAILTYPE_BEGIN
; rt
!= RAILTYPE_END
; rt
++) {
223 const RailTypeInfo
*rti
= GetRailTypeInfo(rt
);
224 /* Unused rail type. */
225 if (rti
->label
== 0) continue;
227 /* Not date introduced. */
228 if (!IsInsideMM(rti
->introduction_date
, 0, CalendarTime::MAX_DATE
.base())) continue;
230 /* Not yet introduced at this date. */
231 if (rti
->introduction_date
> date
) continue;
233 /* Have we introduced all required railtypes? */
234 RailTypes required
= rti
->introduction_required_railtypes
;
235 if ((rts
& required
) != required
) continue;
237 rts
|= rti
->introduces_railtypes
;
240 /* When we added railtypes we need to run this method again; the added
241 * railtypes might enable more rail types to become introduced. */
242 return rts
== current
? rts
: AddDateIntroducedRailTypes(rts
, date
);
246 * Get the rail types the given company can build.
247 * @param company the company to get the rail types for.
248 * @param introduces If true, include rail types introduced by other rail types
249 * @return the rail types.
251 RailTypes
GetCompanyRailTypes(CompanyID company
, bool introduces
)
253 RailTypes rts
= RAILTYPES_NONE
;
255 for (const Engine
*e
: Engine::IterateType(VEH_TRAIN
)) {
256 const EngineInfo
*ei
= &e
->info
;
258 if (HasBit(ei
->climates
, _settings_game
.game_creation
.landscape
) &&
259 (HasBit(e
->company_avail
, company
) || TimerGameCalendar::date
>= e
->intro_date
+ CalendarTime::DAYS_IN_YEAR
)) {
260 const RailVehicleInfo
*rvi
= &e
->u
.rail
;
262 if (rvi
->railveh_type
!= RAILVEH_WAGON
) {
263 assert(rvi
->railtype
< RAILTYPE_END
);
265 rts
|= GetRailTypeInfo(rvi
->railtype
)->introduces_railtypes
;
267 SetBit(rts
, rvi
->railtype
);
273 if (introduces
) return AddDateIntroducedRailTypes(rts
, TimerGameCalendar::date
);
278 * Get list of rail types, regardless of company availability.
279 * @param introduces If true, include rail types introduced by other rail types
280 * @return the rail types.
282 RailTypes
GetRailTypes(bool introduces
)
284 RailTypes rts
= RAILTYPES_NONE
;
286 for (const Engine
*e
: Engine::IterateType(VEH_TRAIN
)) {
287 const EngineInfo
*ei
= &e
->info
;
288 if (!HasBit(ei
->climates
, _settings_game
.game_creation
.landscape
)) continue;
290 const RailVehicleInfo
*rvi
= &e
->u
.rail
;
291 if (rvi
->railveh_type
!= RAILVEH_WAGON
) {
292 assert(rvi
->railtype
< RAILTYPE_END
);
294 rts
|= GetRailTypeInfo(rvi
->railtype
)->introduces_railtypes
;
296 SetBit(rts
, rvi
->railtype
);
301 if (introduces
) return AddDateIntroducedRailTypes(rts
, CalendarTime::MAX_DATE
);
306 * Get the rail type for a given label.
307 * @param label the railtype label.
308 * @param allow_alternate_labels Search in the alternate label lists as well.
309 * @return the railtype.
311 RailType
GetRailTypeByLabel(RailTypeLabel label
, bool allow_alternate_labels
)
313 if (label
== 0) return INVALID_RAILTYPE
;
315 /* Loop through each rail type until the label is found */
316 for (RailType r
= RAILTYPE_BEGIN
; r
!= RAILTYPE_END
; r
++) {
317 const RailTypeInfo
*rti
= GetRailTypeInfo(r
);
318 if (rti
->label
== label
) return r
;
321 if (allow_alternate_labels
) {
322 /* Test if any rail type defines the label as an alternate. */
323 for (RailType r
= RAILTYPE_BEGIN
; r
!= RAILTYPE_END
; r
++) {
324 const RailTypeInfo
*rti
= GetRailTypeInfo(r
);
325 if (std::find(rti
->alternate_labels
.begin(), rti
->alternate_labels
.end(), label
) != rti
->alternate_labels
.end()) return r
;
329 /* No matching label was found, so it is invalid */
330 return INVALID_RAILTYPE
;