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/>.
10 /** @file rail.cpp Implementation of rail specific functions. */
13 #include "station_map.h"
14 #include "tunnelbridge_map.h"
15 #include "date_func.h"
16 #include "company_func.h"
17 #include "company_base.h"
18 #include "engine_base.h"
20 #include "safeguards.h"
22 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
23 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
24 * direction along with the trackdir */
25 extern const byte _signal_along_trackdir
[TRACKDIR_END
] = {
26 0x8, 0x8, 0x8, 0x2, 0x4, 0x1, 0, 0,
27 0x4, 0x4, 0x4, 0x1, 0x8, 0x2
30 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
31 * direction against the trackdir */
32 extern const byte _signal_against_trackdir
[TRACKDIR_END
] = {
33 0x4, 0x4, 0x4, 0x1, 0x8, 0x2, 0, 0,
34 0x8, 0x8, 0x8, 0x2, 0x4, 0x1
37 /* Maps a Track to the bits that store the status of the two signals that can
38 * be present on the given track */
39 extern const byte _signal_on_track
[] = {
40 0xC, 0xC, 0xC, 0x3, 0xC, 0x3
43 /* Maps a diagonal direction to the all trackdirs that are connected to any
44 * track entering in this direction (including those making 90 degree turns)
46 extern const TrackdirBits _exitdir_reaches_trackdirs
[] = {
47 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_LEFT_N
, // DIAGDIR_NE
48 TRACKDIR_BIT_Y_SE
| TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_UPPER_E
, // DIAGDIR_SE
49 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_RIGHT_S
, // DIAGDIR_SW
50 TRACKDIR_BIT_Y_NW
| TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_LOWER_W
// DIAGDIR_NW
53 extern const Trackdir _next_trackdir
[TRACKDIR_END
] = {
54 TRACKDIR_X_NE
, TRACKDIR_Y_SE
, TRACKDIR_LOWER_E
, TRACKDIR_UPPER_E
, TRACKDIR_RIGHT_S
, TRACKDIR_LEFT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
,
55 TRACKDIR_X_SW
, TRACKDIR_Y_NW
, TRACKDIR_LOWER_W
, TRACKDIR_UPPER_W
, TRACKDIR_RIGHT_N
, TRACKDIR_LEFT_N
58 /* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
59 extern const TrackdirBits _track_crosses_trackdirs
[TRACK_END
] = {
60 TRACKDIR_BIT_Y_SE
| TRACKDIR_BIT_Y_NW
, // TRACK_X
61 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_X_SW
, // TRACK_Y
62 TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_LEFT_S
, // TRACK_UPPER
63 TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_LEFT_S
, // TRACK_LOWER
64 TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_LOWER_E
, // TRACK_LEFT
65 TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_LOWER_E
// TRACK_RIGHT
68 /* Maps a track to all tracks that make 90 deg turns with it. */
69 extern const TrackBits _track_crosses_tracks
[] = {
70 TRACK_BIT_Y
, // TRACK_X
71 TRACK_BIT_X
, // TRACK_Y
72 TRACK_BIT_VERT
, // TRACK_UPPER
73 TRACK_BIT_VERT
, // TRACK_LOWER
74 TRACK_BIT_HORZ
, // TRACK_LEFT
75 TRACK_BIT_HORZ
// TRACK_RIGHT
78 /* Maps a trackdir to the (4-way) direction the tile is exited when following
80 extern const DiagDirection _trackdir_to_exitdir
[TRACKDIR_END
] = {
81 DIAGDIR_NE
, DIAGDIR_SE
, DIAGDIR_NE
, DIAGDIR_SE
, DIAGDIR_SW
, DIAGDIR_SE
, DIAGDIR_NE
, DIAGDIR_NE
,
82 DIAGDIR_SW
, DIAGDIR_NW
, DIAGDIR_NW
, DIAGDIR_SW
, DIAGDIR_NW
, DIAGDIR_NE
,
85 extern const Trackdir _track_exitdir_to_trackdir
[][DIAGDIR_END
] = {
86 {TRACKDIR_X_NE
, INVALID_TRACKDIR
, TRACKDIR_X_SW
, INVALID_TRACKDIR
},
87 {INVALID_TRACKDIR
, TRACKDIR_Y_SE
, INVALID_TRACKDIR
, TRACKDIR_Y_NW
},
88 {TRACKDIR_UPPER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_UPPER_W
},
89 {INVALID_TRACKDIR
, TRACKDIR_LOWER_E
, TRACKDIR_LOWER_W
, INVALID_TRACKDIR
},
90 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LEFT_S
, TRACKDIR_LEFT_N
},
91 {TRACKDIR_RIGHT_N
, TRACKDIR_RIGHT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
}
94 extern const Trackdir _track_enterdir_to_trackdir
[][DIAGDIR_END
] = {
95 {TRACKDIR_X_NE
, INVALID_TRACKDIR
, TRACKDIR_X_SW
, INVALID_TRACKDIR
},
96 {INVALID_TRACKDIR
, TRACKDIR_Y_SE
, INVALID_TRACKDIR
, TRACKDIR_Y_NW
},
97 {INVALID_TRACKDIR
, TRACKDIR_UPPER_E
, TRACKDIR_UPPER_W
, INVALID_TRACKDIR
},
98 {TRACKDIR_LOWER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LOWER_W
},
99 {TRACKDIR_LEFT_N
, TRACKDIR_LEFT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
},
100 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_RIGHT_S
, TRACKDIR_RIGHT_N
}
103 extern const Trackdir _track_direction_to_trackdir
[][DIR_END
] = {
104 {INVALID_TRACKDIR
, TRACKDIR_X_NE
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_X_SW
, INVALID_TRACKDIR
, INVALID_TRACKDIR
},
105 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_Y_SE
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_Y_NW
},
106 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_UPPER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_UPPER_W
, INVALID_TRACKDIR
},
107 {INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LOWER_E
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LOWER_W
, INVALID_TRACKDIR
},
108 {TRACKDIR_LEFT_N
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_LEFT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
},
109 {TRACKDIR_RIGHT_N
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, TRACKDIR_RIGHT_S
, INVALID_TRACKDIR
, INVALID_TRACKDIR
, INVALID_TRACKDIR
}
112 extern const Trackdir _dir_to_diag_trackdir
[] = {
113 TRACKDIR_X_NE
, TRACKDIR_Y_SE
, TRACKDIR_X_SW
, TRACKDIR_Y_NW
,
116 extern const TrackBits _corner_to_trackbits
[] = {
117 TRACK_BIT_LEFT
, TRACK_BIT_LOWER
, TRACK_BIT_RIGHT
, TRACK_BIT_UPPER
,
120 extern const TrackdirBits _uphill_trackdirs
[] = {
121 TRACKDIR_BIT_NONE
, ///< 0 SLOPE_FLAT
122 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_NW
, ///< 1 SLOPE_W -> inclined for diagonal track
123 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_SE
, ///< 2 SLOPE_S -> inclined for diagonal track
124 TRACKDIR_BIT_X_SW
, ///< 3 SLOPE_SW
125 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_SE
, ///< 4 SLOPE_E -> inclined for diagonal track
126 TRACKDIR_BIT_NONE
, ///< 5 SLOPE_EW
127 TRACKDIR_BIT_Y_SE
, ///< 6 SLOPE_SE
128 TRACKDIR_BIT_NONE
, ///< 7 SLOPE_WSE -> leveled
129 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_NW
, ///< 8 SLOPE_N -> inclined for diagonal track
130 TRACKDIR_BIT_Y_NW
, ///< 9 SLOPE_NW
131 TRACKDIR_BIT_NONE
, ///< 10 SLOPE_NS
132 TRACKDIR_BIT_NONE
, ///< 11 SLOPE_NWS -> leveled
133 TRACKDIR_BIT_X_NE
, ///< 12 SLOPE_NE
134 TRACKDIR_BIT_NONE
, ///< 13 SLOPE_ENW -> leveled
135 TRACKDIR_BIT_NONE
, ///< 14 SLOPE_SEN -> leveled
136 TRACKDIR_BIT_NONE
, ///< 15 invalid
137 TRACKDIR_BIT_NONE
, ///< 16 invalid
138 TRACKDIR_BIT_NONE
, ///< 17 invalid
139 TRACKDIR_BIT_NONE
, ///< 18 invalid
140 TRACKDIR_BIT_NONE
, ///< 19 invalid
141 TRACKDIR_BIT_NONE
, ///< 20 invalid
142 TRACKDIR_BIT_NONE
, ///< 21 invalid
143 TRACKDIR_BIT_NONE
, ///< 22 invalid
144 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_SE
, ///< 23 SLOPE_STEEP_S -> inclined for diagonal track
145 TRACKDIR_BIT_NONE
, ///< 24 invalid
146 TRACKDIR_BIT_NONE
, ///< 25 invalid
147 TRACKDIR_BIT_NONE
, ///< 26 invalid
148 TRACKDIR_BIT_X_SW
| TRACKDIR_BIT_Y_NW
, ///< 27 SLOPE_STEEP_W -> inclined for diagonal track
149 TRACKDIR_BIT_NONE
, ///< 28 invalid
150 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_NW
, ///< 29 SLOPE_STEEP_N -> inclined for diagonal track
151 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_Y_SE
, ///< 30 SLOPE_STEEP_E -> inclined for diagonal track
155 * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
157 RailType
GetTileRailType(TileIndex tile
)
159 switch (GetTileType(tile
)) {
161 return GetRailType(tile
);
164 /* rail/road crossing */
165 if (IsLevelCrossing(tile
)) return GetRailType(tile
);
169 if (HasStationRail(tile
)) return GetRailType(tile
);
172 case MP_TUNNELBRIDGE
:
173 if (GetTunnelBridgeTransportType(tile
) == TRANSPORT_RAIL
) return GetRailType(tile
);
179 return INVALID_RAILTYPE
;
183 * Finds out if a company has a certain railtype available
184 * @param company the company in question
185 * @param railtype requested RailType
186 * @return true if company has requested RailType available
188 bool HasRailtypeAvail(const CompanyID company
, const RailType railtype
)
190 return HasBit(Company::Get(company
)->avail_railtypes
, railtype
);
194 * Validate functions for rail building.
195 * @param rail the railtype to check.
196 * @return true if the current company may build the rail.
198 bool ValParamRailtype(const RailType rail
)
200 return rail
< RAILTYPE_END
&& HasRailtypeAvail(_current_company
, rail
);
204 * Returns the "best" railtype a company can build.
205 * As the AI doesn't know what the BEST one is, we have our own priority list
206 * here. When adding new railtypes, modify this function
207 * @param company the company "in action"
208 * @return The "best" railtype a company has available
210 RailType
GetBestRailtype(const CompanyID company
)
212 if (HasRailtypeAvail(company
, RAILTYPE_MAGLEV
)) return RAILTYPE_MAGLEV
;
213 if (HasRailtypeAvail(company
, RAILTYPE_MONO
)) return RAILTYPE_MONO
;
214 if (HasRailtypeAvail(company
, RAILTYPE_ELECTRIC
)) return RAILTYPE_ELECTRIC
;
215 return RAILTYPE_RAIL
;
219 * Add the rail types that are to be introduced at the given date.
220 * @param current The currently available railtypes.
221 * @param date The date for the introduction comparisons.
222 * @return The rail types that should be available when date
223 * introduced rail types are taken into account as well.
225 RailTypes
AddDateIntroducedRailTypes(RailTypes current
, Date date
)
227 RailTypes rts
= current
;
229 for (RailType rt
= RAILTYPE_BEGIN
; rt
!= RAILTYPE_END
; rt
++) {
230 const RailtypeInfo
*rti
= GetRailTypeInfo(rt
);
231 /* Unused rail type. */
232 if (rti
->label
== 0) continue;
234 /* Not date introduced. */
235 if (!IsInsideMM(rti
->introduction_date
, 0, MAX_DAY
)) continue;
237 /* Not yet introduced at this date. */
238 if (rti
->introduction_date
> date
) continue;
240 /* Have we introduced all required railtypes? */
241 RailTypes required
= rti
->introduction_required_railtypes
;
242 if ((rts
& required
) != required
) continue;
244 rts
|= rti
->introduces_railtypes
;
247 /* When we added railtypes we need to run this method again; the added
248 * railtypes might enable more rail types to become introduced. */
249 return rts
== current
? rts
: AddDateIntroducedRailTypes(rts
, date
);
253 * Get the rail types the given company can build.
254 * @param c the company to get the rail types for.
255 * @return the rail types.
257 RailTypes
GetCompanyRailtypes(CompanyID company
)
259 RailTypes rts
= RAILTYPES_NONE
;
262 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_TRAIN
) {
263 const EngineInfo
*ei
= &e
->info
;
265 if (HasBit(ei
->climates
, _settings_game
.game_creation
.landscape
) &&
266 (HasBit(e
->company_avail
, company
) || _date
>= e
->intro_date
+ DAYS_IN_YEAR
)) {
267 const RailVehicleInfo
*rvi
= &e
->u
.rail
;
269 if (rvi
->railveh_type
!= RAILVEH_WAGON
) {
270 assert(rvi
->railtype
< RAILTYPE_END
);
271 rts
|= GetRailTypeInfo(rvi
->railtype
)->introduces_railtypes
;
276 return AddDateIntroducedRailTypes(rts
, _date
);
280 * Get the rail type for a given label.
281 * @param label the railtype label.
282 * @param allow_alternate_labels Search in the alternate label lists as well.
283 * @return the railtype.
285 RailType
GetRailTypeByLabel(RailTypeLabel label
, bool allow_alternate_labels
)
287 /* Loop through each rail type until the label is found */
288 for (RailType r
= RAILTYPE_BEGIN
; r
!= RAILTYPE_END
; r
++) {
289 const RailtypeInfo
*rti
= GetRailTypeInfo(r
);
290 if (rti
->label
== label
) return r
;
293 if (allow_alternate_labels
) {
294 /* Test if any rail type defines the label as an alternate. */
295 for (RailType r
= RAILTYPE_BEGIN
; r
!= RAILTYPE_END
; r
++) {
296 const RailtypeInfo
*rti
= GetRailTypeInfo(r
);
297 if (rti
->alternate_labels
.Contains(label
)) return r
;
301 /* No matching label was found, so it is invalid */
302 return INVALID_RAILTYPE
;