1 /*
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/>.
6  */
7 
8 /** @file road.cpp Generic road related functions. */
9 
10 #include "stdafx.h"
11 #include "rail_map.h"
12 #include "road_map.h"
13 #include "water_map.h"
14 #include "genworld.h"
15 #include "company_func.h"
16 #include "company_base.h"
17 #include "engine_base.h"
18 #include "date_func.h"
19 #include "landscape.h"
20 #include "road.h"
21 #include "road_func.h"
22 #include "roadveh.h"
23 
24 #include "safeguards.h"
25 
26 /**
27  * Return if the tile is a valid tile for a crossing.
28  *
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
32  */
IsPossibleCrossing(const TileIndex tile,Axis ax)33 static bool IsPossibleCrossing(const TileIndex tile, Axis ax)
34 {
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 		GetFoundationSlope(tile) == SLOPE_FLAT);
39 }
40 
41 /**
42  * Clean up unnecessary RoadBits of a planned tile.
43  * @param tile current tile
44  * @param org_rb planned RoadBits
45  * @return optimised RoadBits
46  */
CleanUpRoadBits(const TileIndex tile,RoadBits org_rb)47 RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
48 {
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);
52 
53 		/* Get the Roadbit pointing to the neighbor_tile */
54 		const RoadBits target_rb = DiagDirToRoadBits(dir);
55 
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);
60 
61 			if (IsValidTile(neighbor_tile)) {
62 				switch (GetTileType(neighbor_tile)) {
63 					/* Always connective ones */
64 					case MP_CLEAR: case MP_TREES:
65 						connective = true;
66 						break;
67 
68 					/* The conditionally connective ones */
69 					case MP_TUNNELBRIDGE:
70 					case MP_STATION:
71 					case MP_ROAD:
72 						if (IsNormalRoadTile(neighbor_tile)) {
73 							/* Always connective */
74 							connective = true;
75 						} else {
76 							const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, RTT_ROAD) | GetAnyRoadBits(neighbor_tile, RTT_TRAM);
77 
78 							/* Accept only connective tiles */
79 							connective = (neighbor_rb & mirrored_rb) != ROAD_NONE;
80 						}
81 						break;
82 
83 					case MP_RAILWAY:
84 						connective = IsPossibleCrossing(neighbor_tile, DiagDirToAxis(dir));
85 						break;
86 
87 					case MP_WATER:
88 						/* Check for real water tile */
89 						connective = !IsWater(neighbor_tile);
90 						break;
91 
92 					/* The definitely not connective ones */
93 					default: break;
94 				}
95 			}
96 
97 			/* If the neighbor tile is inconnective, remove the planned road connection to it */
98 			if (!connective) org_rb ^= target_rb;
99 		}
100 	}
101 
102 	return org_rb;
103 }
104 
105 /**
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
110  */
HasRoadTypeAvail(const CompanyID company,RoadType roadtype)111 bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype)
112 {
113 	if (company == OWNER_DEITY || company == OWNER_TOWN || _game_mode == GM_EDITOR || _generating_world) {
114 		return true; // TODO: should there be a proper check?
115 	} else {
116 		const Company *c = Company::GetIfValid(company);
117 		if (c == nullptr) return false;
118 		return HasBit(c->avail_roadtypes & ~_roadtypes_hidden_mask, roadtype);
119 	}
120 }
121 
GetMaskForRoadTramType(RoadTramType rtt)122 static RoadTypes GetMaskForRoadTramType(RoadTramType rtt)
123 {
124 	return rtt == RTT_TRAM ? _roadtypes_type : ~_roadtypes_type;
125 }
126 
127 /**
128  * Test if any buildable RoadType is available for a company.
129  * @param company the company in question
130  * @return true if company has any RoadTypes available
131  */
HasAnyRoadTypesAvail(CompanyID company,RoadTramType rtt)132 bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt)
133 {
134 	return (Company::Get(company)->avail_roadtypes & ~_roadtypes_hidden_mask & GetMaskForRoadTramType(rtt)) != ROADTYPES_NONE;
135 }
136 
137 /**
138  * Validate functions for rail building.
139  * @param roadtype road type to check.
140  * @return true if the current company may build the road.
141  */
ValParamRoadType(RoadType roadtype)142 bool ValParamRoadType(RoadType roadtype)
143 {
144 	return roadtype != INVALID_ROADTYPE && HasRoadTypeAvail(_current_company, roadtype);
145 }
146 
147 /**
148  * Add the road types that are to be introduced at the given date.
149  * @param rt      Roadtype
150  * @param current The currently available roadtypes.
151  * @param date    The date for the introduction comparisons.
152  * @return The road types that should be available when date
153  *         introduced road types are taken into account as well.
154  */
AddDateIntroducedRoadTypes(RoadTypes current,Date date)155 RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date)
156 {
157 	RoadTypes rts = current;
158 
159 	for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
160 		const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
161 		/* Unused road type. */
162 		if (rti->label == 0) continue;
163 
164 		/* Not date introduced. */
165 		if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
166 
167 		/* Not yet introduced at this date. */
168 		if (rti->introduction_date > date) continue;
169 
170 		/* Have we introduced all required roadtypes? */
171 		RoadTypes required = rti->introduction_required_roadtypes;
172 		if ((rts & required) != required) continue;
173 
174 		rts |= rti->introduces_roadtypes;
175 	}
176 
177 	/* When we added roadtypes we need to run this method again; the added
178 	 * roadtypes might enable more rail types to become introduced. */
179 	return rts == current ? rts : AddDateIntroducedRoadTypes(rts, date);
180 }
181 
182 /**
183  * Get the road types the given company can build.
184  * @param company the company to get the road types for.
185  * @param introduces If true, include road types introduced by other road types
186  * @return the road types.
187  */
GetCompanyRoadTypes(CompanyID company,bool introduces)188 RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces)
189 {
190 	RoadTypes rts = ROADTYPES_NONE;
191 
192 	for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
193 		const EngineInfo *ei = &e->info;
194 
195 		if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
196 				(HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) {
197 			const RoadVehicleInfo *rvi = &e->u.road;
198 			assert(rvi->roadtype < ROADTYPE_END);
199 			if (introduces) {
200 				rts |= GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes;
201 			} else {
202 				SetBit(rts, rvi->roadtype);
203 			}
204 		}
205 	}
206 
207 	if (introduces) return AddDateIntroducedRoadTypes(rts, _date);
208 	return rts;
209 }
210 
211 /**
212  * Get list of road types, regardless of company availability.
213  * @param introduces If true, include road types introduced by other road types
214  * @return the road types.
215  */
GetRoadTypes(bool introduces)216 RoadTypes GetRoadTypes(bool introduces)
217 {
218 	RoadTypes rts = ROADTYPES_NONE;
219 
220 	for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
221 		const EngineInfo *ei = &e->info;
222 		if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) continue;
223 
224 		const RoadVehicleInfo *rvi = &e->u.road;
225 		assert(rvi->roadtype < ROADTYPE_END);
226 		if (introduces) {
227 			rts |= GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes;
228 		} else {
229 			SetBit(rts, rvi->roadtype);
230 		}
231 	}
232 
233 	if (introduces) return AddDateIntroducedRoadTypes(rts, MAX_DAY);
234 	return rts;
235 }
236 
237 /**
238  * Get the road type for a given label.
239  * @param label the roadtype label.
240  * @param allow_alternate_labels Search in the alternate label lists as well.
241  * @return the roadtype.
242  */
GetRoadTypeByLabel(RoadTypeLabel label,bool allow_alternate_labels)243 RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
244 {
245 	/* Loop through each road type until the label is found */
246 	for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) {
247 		const RoadTypeInfo *rti = GetRoadTypeInfo(r);
248 		if (rti->label == label) return r;
249 	}
250 
251 	if (allow_alternate_labels) {
252 		/* Test if any road type defines the label as an alternate. */
253 		for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) {
254 			const RoadTypeInfo *rti = GetRoadTypeInfo(r);
255 			if (std::find(rti->alternate_labels.begin(), rti->alternate_labels.end(), label) != rti->alternate_labels.end()) return r;
256 		}
257 	}
258 
259 	/* No matching label was found, so it is invalid */
260 	return INVALID_ROADTYPE;
261 }
262 
263 /**
264  * Returns the available RoadSubTypes for the provided RoadType
265  * If the given company is valid then will be returned a list of the available sub types at the current date, while passing
266  * a deity company will make all the sub types available
267  * @param rt the RoadType to filter
268  * @param c the company ID to check the roadtype against
269  * @param any_date whether to return only currently introduced roadtypes or also future ones
270  * @returns the existing RoadSubTypes
271  */
ExistingRoadTypes(CompanyID c)272 RoadTypes ExistingRoadTypes(CompanyID c)
273 {
274 	/* Check only players which can actually own vehicles, editor and gamescripts are considered deities */
275 	if (c < OWNER_END) {
276 		const Company *company = Company::GetIfValid(c);
277 		if (company != nullptr) return company->avail_roadtypes;
278 	}
279 
280 	RoadTypes known_roadtypes = ROADTYPES_NONE;
281 
282 	/* Find used roadtypes */
283 	for (Engine *e : Engine::IterateType(VEH_ROAD)) {
284 		/* Check if the roadtype can be used in the current climate */
285 		if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
286 
287 		/* Check whether available for all potential companies */
288 		if (e->company_avail != (CompanyMask)-1) continue;
289 
290 		known_roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
291 	}
292 
293 	/* Get the date introduced roadtypes as well. */
294 	known_roadtypes = AddDateIntroducedRoadTypes(known_roadtypes, MAX_DAY);
295 
296 	return known_roadtypes;
297 }
298