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 road.cpp Generic road related functions. */
13 #include "water_map.h"
15 #include "company_func.h"
16 #include "company_base.h"
17 #include "engine_base.h"
18 #include "timer/timer_game_calendar.h"
19 #include "landscape.h"
21 #include "road_func.h"
24 #include "safeguards.h"
27 * Return if the tile is a valid tile for a crossing.
29 * @param tile the current tile
30 * @param ax the axis of the road over the rail
31 * @return true if it is a valid tile
33 static bool IsPossibleCrossing(const TileIndex tile
, Axis ax
)
35 return (IsTileType(tile
, MP_RAILWAY
) &&
36 GetRailTileType(tile
) == RAIL_TILE_NORMAL
&&
37 GetTrackBits(tile
) == (ax
== AXIS_X
? TRACK_BIT_Y
: TRACK_BIT_X
) &&
38 std::get
<0>(GetFoundationSlope(tile
)) == SLOPE_FLAT
);
42 * Clean up unnecessary RoadBits of a planned tile.
43 * @param tile current tile
44 * @param org_rb planned RoadBits
45 * @return optimised RoadBits
47 RoadBits
CleanUpRoadBits(const TileIndex tile
, RoadBits org_rb
)
49 if (!IsValidTile(tile
)) return ROAD_NONE
;
50 for (DiagDirection dir
= DIAGDIR_BEGIN
; dir
< DIAGDIR_END
; dir
++) {
51 const TileIndex neighbor_tile
= TileAddByDiagDir(tile
, dir
);
53 /* Get the Roadbit pointing to the neighbor_tile */
54 const RoadBits target_rb
= DiagDirToRoadBits(dir
);
56 /* If the roadbit is in the current plan */
57 if (org_rb
& target_rb
) {
58 bool connective
= false;
59 const RoadBits mirrored_rb
= MirrorRoadBits(target_rb
);
61 if (IsValidTile(neighbor_tile
)) {
62 switch (GetTileType(neighbor_tile
)) {
63 /* Always connective ones */
64 case MP_CLEAR
: case MP_TREES
:
68 /* The conditionally connective ones */
72 if (IsNormalRoadTile(neighbor_tile
)) {
73 /* Always connective */
76 const RoadBits neighbor_rb
= GetAnyRoadBits(neighbor_tile
, RTT_ROAD
) | GetAnyRoadBits(neighbor_tile
, RTT_TRAM
);
78 /* Accept only connective tiles */
79 connective
= (neighbor_rb
& mirrored_rb
) != ROAD_NONE
;
84 connective
= IsPossibleCrossing(neighbor_tile
, DiagDirToAxis(dir
));
88 /* Check for real water tile */
89 connective
= !IsWater(neighbor_tile
);
92 /* The definitely not connective ones */
97 /* If the neighbor tile is inconnective, remove the planned road connection to it */
98 if (!connective
) org_rb
^= target_rb
;
106 * Finds out, whether given company has a given RoadType available for construction.
107 * @param company ID of company
108 * @param roadtypet RoadType to test
109 * @return true if company has the requested RoadType available
111 bool HasRoadTypeAvail(const CompanyID company
, RoadType roadtype
)
113 if (company
== OWNER_DEITY
|| company
== OWNER_TOWN
|| _game_mode
== GM_EDITOR
|| _generating_world
) {
114 const RoadTypeInfo
*rti
= GetRoadTypeInfo(roadtype
);
115 if (rti
->label
== 0) return false;
117 /* Not yet introduced at this date. */
118 if (IsInsideMM(rti
->introduction_date
, 0, CalendarTime::MAX_DATE
.base()) && rti
->introduction_date
> TimerGameCalendar::date
) return false;
121 * Do not allow building hidden road types, except when a town may build it.
122 * The GS under deity mode, as well as anybody in the editor builds roads that are
123 * owned by towns. So if a town may build it, it should be buildable by them too.
125 return (rti
->flags
& ROTFB_HIDDEN
) == 0 || (rti
->flags
& ROTFB_TOWN_BUILD
) != 0;
127 const Company
*c
= Company::GetIfValid(company
);
128 if (c
== nullptr) return false;
129 return HasBit(c
->avail_roadtypes
& ~_roadtypes_hidden_mask
, roadtype
);
133 static RoadTypes
GetMaskForRoadTramType(RoadTramType rtt
)
135 return rtt
== RTT_TRAM
? _roadtypes_type
: ~_roadtypes_type
;
139 * Test if any buildable RoadType is available for a company.
140 * @param company the company in question
141 * @return true if company has any RoadTypes available
143 bool HasAnyRoadTypesAvail(CompanyID company
, RoadTramType rtt
)
145 return (Company::Get(company
)->avail_roadtypes
& ~_roadtypes_hidden_mask
& GetMaskForRoadTramType(rtt
)) != ROADTYPES_NONE
;
149 * Validate functions for rail building.
150 * @param roadtype road type to check.
151 * @return true if the current company may build the road.
153 bool ValParamRoadType(RoadType roadtype
)
155 return roadtype
< ROADTYPE_END
&& HasRoadTypeAvail(_current_company
, roadtype
);
159 * Add the road types that are to be introduced at the given date.
161 * @param current The currently available roadtypes.
162 * @param date The date for the introduction comparisons.
163 * @return The road types that should be available when date
164 * introduced road types are taken into account as well.
166 RoadTypes
AddDateIntroducedRoadTypes(RoadTypes current
, TimerGameCalendar::Date date
)
168 RoadTypes rts
= current
;
170 for (RoadType rt
= ROADTYPE_BEGIN
; rt
!= ROADTYPE_END
; rt
++) {
171 const RoadTypeInfo
*rti
= GetRoadTypeInfo(rt
);
172 /* Unused road type. */
173 if (rti
->label
== 0) continue;
175 /* Not date introduced. */
176 if (!IsInsideMM(rti
->introduction_date
, 0, CalendarTime::MAX_DATE
.base())) continue;
178 /* Not yet introduced at this date. */
179 if (rti
->introduction_date
> date
) continue;
181 /* Have we introduced all required roadtypes? */
182 RoadTypes required
= rti
->introduction_required_roadtypes
;
183 if ((rts
& required
) != required
) continue;
185 rts
|= rti
->introduces_roadtypes
;
188 /* When we added roadtypes we need to run this method again; the added
189 * roadtypes might enable more rail types to become introduced. */
190 return rts
== current
? rts
: AddDateIntroducedRoadTypes(rts
, date
);
194 * Get the road types the given company can build.
195 * @param company the company to get the road types for.
196 * @param introduces If true, include road types introduced by other road types
197 * @return the road types.
199 RoadTypes
GetCompanyRoadTypes(CompanyID company
, bool introduces
)
201 RoadTypes rts
= ROADTYPES_NONE
;
203 for (const Engine
*e
: Engine::IterateType(VEH_ROAD
)) {
204 const EngineInfo
*ei
= &e
->info
;
206 if (HasBit(ei
->climates
, _settings_game
.game_creation
.landscape
) &&
207 (HasBit(e
->company_avail
, company
) || TimerGameCalendar::date
>= e
->intro_date
+ CalendarTime::DAYS_IN_YEAR
)) {
208 const RoadVehicleInfo
*rvi
= &e
->u
.road
;
209 assert(rvi
->roadtype
< ROADTYPE_END
);
211 rts
|= GetRoadTypeInfo(rvi
->roadtype
)->introduces_roadtypes
;
213 SetBit(rts
, rvi
->roadtype
);
218 if (introduces
) return AddDateIntroducedRoadTypes(rts
, TimerGameCalendar::date
);
223 * Get list of road types, regardless of company availability.
224 * @param introduces If true, include road types introduced by other road types
225 * @return the road types.
227 RoadTypes
GetRoadTypes(bool introduces
)
229 RoadTypes rts
= ROADTYPES_NONE
;
231 for (const Engine
*e
: Engine::IterateType(VEH_ROAD
)) {
232 const EngineInfo
*ei
= &e
->info
;
233 if (!HasBit(ei
->climates
, _settings_game
.game_creation
.landscape
)) continue;
235 const RoadVehicleInfo
*rvi
= &e
->u
.road
;
236 assert(rvi
->roadtype
< ROADTYPE_END
);
238 rts
|= GetRoadTypeInfo(rvi
->roadtype
)->introduces_roadtypes
;
240 SetBit(rts
, rvi
->roadtype
);
244 if (introduces
) return AddDateIntroducedRoadTypes(rts
, CalendarTime::MAX_DATE
);
249 * Get the road type for a given label.
250 * @param label the roadtype label.
251 * @param allow_alternate_labels Search in the alternate label lists as well.
252 * @return the roadtype.
254 RoadType
GetRoadTypeByLabel(RoadTypeLabel label
, bool allow_alternate_labels
)
256 if (label
== 0) return INVALID_ROADTYPE
;
258 /* Loop through each road type until the label is found */
259 for (RoadType r
= ROADTYPE_BEGIN
; r
!= ROADTYPE_END
; r
++) {
260 const RoadTypeInfo
*rti
= GetRoadTypeInfo(r
);
261 if (rti
->label
== label
) return r
;
264 if (allow_alternate_labels
) {
265 /* Test if any road type defines the label as an alternate. */
266 for (RoadType r
= ROADTYPE_BEGIN
; r
!= ROADTYPE_END
; r
++) {
267 const RoadTypeInfo
*rti
= GetRoadTypeInfo(r
);
268 if (std::find(rti
->alternate_labels
.begin(), rti
->alternate_labels
.end(), label
) != rti
->alternate_labels
.end()) return r
;
272 /* No matching label was found, so it is invalid */
273 return INVALID_ROADTYPE
;