77 uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3); |
80 uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3); |
78 uint dir_2 = 2 ^ dir_1; |
81 uint dir_2 = 2 ^ dir_1; |
79 |
82 |
80 return HasBit(r1, dir_1) && HasBit(r2, dir_2); |
83 return HasBit(r1, dir_1) && HasBit(r2, dir_2); |
81 } |
84 } |
|
85 |
|
86 /* Helper functions for AIRoad::CanBuildConnectedRoadParts(). */ |
|
87 |
|
88 /** |
|
89 * Check whether the given existing bits the start and end part can be build. |
|
90 * As the function assumes the bits being build on a slope that does not |
|
91 * allow level foundations all of the existing parts will always be in |
|
92 * a straight line. This also needs to hold for the start and end parts, |
|
93 * otherwise it is for sure not valid. Finally a check will be done to |
|
94 * determine whether the existing road parts match the to-be-build parts. |
|
95 * As they can only be placed in one direction, just checking the start |
|
96 * part with the first existing part is enough. |
|
97 * @param existing The existing road parts. |
|
98 * @param start The part that should be build first. |
|
99 * @param end The part that will be build second. |
|
100 * @return True if and only if the road bits can be build. |
|
101 */ |
|
102 static bool CheckAutoExpandedRoadBits(const Array *existing, int32 start, int32 end) |
|
103 { |
|
104 return (start + end == 0) && (existing->size == 0 || existing->array[0] == start || existing->array[0] == end); |
|
105 } |
|
106 |
|
107 /** |
|
108 * Lookup function for building road parts when building on slopes is disabled. |
|
109 * @param slope The slope of the tile to examine. |
|
110 * @param existing The existing road parts. |
|
111 * @param start The part that should be build first. |
|
112 * @param end The part that will be build second. |
|
113 * @return 0 when the build parts do not connect, 1 when they do connect once |
|
114 * they are build or 2 when building the first part automatically |
|
115 * builds the second part. |
|
116 */ |
|
117 static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array *existing, int32 start, int32 end) |
|
118 { |
|
119 switch (slope) { |
|
120 /* Flat slopes can always be build. */ |
|
121 case SLOPE_FLAT: |
|
122 return 1; |
|
123 |
|
124 /* Only 4 of the slopes can be build upon. Testing the existing bits is |
|
125 * necessary because these bits can be something else when the settings |
|
126 * in the game have been changed. |
|
127 */ |
|
128 case SLOPE_NE: case SLOPE_SW: |
|
129 return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing->size == 0 ? 2 : 1) : 0; |
|
130 case SLOPE_SE: case SLOPE_NW: |
|
131 return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing->size == 0 ? 2 : 1) : 0; |
|
132 |
|
133 /* Any other tile cannot be built on. */ |
|
134 default: |
|
135 return 0; |
|
136 } |
|
137 } |
|
138 |
|
139 /** |
|
140 * Rotate a neighbour bit a single time clockwise. |
|
141 * @param neighbour The neighbour. |
|
142 * @return The rotate neighbour data. |
|
143 */ |
|
144 static int32 RotateNeighbour(int32 neighbour) |
|
145 { |
|
146 switch (neighbour) { |
|
147 case -2: return -1; |
|
148 case -1: return 2; |
|
149 case 1: return -2; |
|
150 case 2: return 1; |
|
151 default: NOT_REACHED(); |
|
152 } |
|
153 } |
|
154 |
|
155 /** |
|
156 * Convert a neighbour to a road bit representation for easy internal use. |
|
157 * @param neighbour The neighbour. |
|
158 * @return The bits representing the direction. |
|
159 */ |
|
160 static RoadBits NeighbourToRoadBits(int32 neighbour) |
|
161 { |
|
162 switch (neighbour) { |
|
163 case -2: return ROAD_NW; |
|
164 case -1: return ROAD_NE; |
|
165 case 2: return ROAD_SE; |
|
166 case 1: return ROAD_SW; |
|
167 default: NOT_REACHED(); |
|
168 } |
|
169 } |
|
170 |
|
171 /** |
|
172 * Lookup function for building road parts when building on slopes is enabled. |
|
173 * @param slope The slope of the tile to examine. |
|
174 * @param existing The existing neighbours. |
|
175 * @param start The part that should be build first. |
|
176 * @param end The part that will be build second. |
|
177 * @return 0 when the build parts do not connect, 1 when they do connect once |
|
178 * they are build or 2 when building the first part automatically |
|
179 * builds the second part. |
|
180 */ |
|
181 static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start, int32 end) |
|
182 { |
|
183 if (::IsSteepSlope(slope)) { |
|
184 switch (slope) { |
|
185 /* On steep slopes one can only build straight roads that will be |
|
186 * automatically expanded to a straight road. Just check that the existing |
|
187 * road parts are in the same direction. */ |
|
188 case SLOPE_STEEP_S: |
|
189 case SLOPE_STEEP_W: |
|
190 case SLOPE_STEEP_N: |
|
191 case SLOPE_STEEP_E: |
|
192 return CheckAutoExpandedRoadBits(existing, start, end) ? (existing->size == 0 ? 2 : 1) : 0; |
|
193 |
|
194 /* All other slopes are invalid slopes!. */ |
|
195 default: |
|
196 return -1; |
|
197 } |
|
198 } |
|
199 |
|
200 /* The slope is not steep. Furthermore lots of slopes are generally the |
|
201 * same but are only rotated. So to reduce the amount of lookup work that |
|
202 * needs to be done the data is made uniform. This means rotating the |
|
203 * existing parts and updating the slope. */ |
|
204 static const ::Slope base_slopes[] = { |
|
205 SLOPE_FLAT, SLOPE_W, SLOPE_W, SLOPE_SW, |
|
206 SLOPE_W, SLOPE_EW, SLOPE_SW, SLOPE_WSE, |
|
207 SLOPE_W, SLOPE_SW, SLOPE_EW, SLOPE_WSE, |
|
208 SLOPE_SW, SLOPE_WSE, SLOPE_WSE}; |
|
209 static const byte base_rotates[] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 2, 3, 2, 2, 1}; |
|
210 |
|
211 if (slope >= (::Slope)lengthof(base_slopes)) { |
|
212 /* This slope is an invalid slope, so ignore it. */ |
|
213 return -1; |
|
214 } |
|
215 byte base_rotate = base_rotates[slope]; |
|
216 slope = base_slopes[slope]; |
|
217 |
|
218 /* Some slopes don't need rotating, so return early when we know we do |
|
219 * not need to rotate. */ |
|
220 switch (slope) { |
|
221 case SLOPE_FLAT: |
|
222 /* Flat slopes can always be build. */ |
|
223 return 1; |
|
224 |
|
225 case SLOPE_EW: |
|
226 case SLOPE_WSE: |
|
227 /* A slope similar to a SLOPE_EW or SLOPE_WSE will always cause |
|
228 * foundations which makes them accessible from all sides. */ |
|
229 return 1; |
|
230 |
|
231 case SLOPE_W: |
|
232 case SLOPE_SW: |
|
233 /* A slope for which we need perform some calculations. */ |
|
234 break; |
|
235 |
|
236 default: |
|
237 /* An invalid slope. */ |
|
238 return -1; |
|
239 } |
|
240 |
|
241 /* Now perform the actual rotation. */ |
|
242 for (int j = 0; j < base_rotate; j++) { |
|
243 for (int i = 0; i < existing->size; i++) { |
|
244 existing->array[i] = RotateNeighbour(existing->array[i]); |
|
245 } |
|
246 start = RotateNeighbour(start); |
|
247 end = RotateNeighbour(end); |
|
248 } |
|
249 |
|
250 /* Create roadbits out of the data for easier handling. */ |
|
251 RoadBits start_roadbits = NeighbourToRoadBits(start); |
|
252 RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end); |
|
253 RoadBits existing_roadbits = ROAD_NONE; |
|
254 for (int i = 0; i < existing->size; i++) { |
|
255 existing_roadbits |= NeighbourToRoadBits(existing->array[i]); |
|
256 } |
|
257 |
|
258 switch (slope) { |
|
259 case SLOPE_W: |
|
260 /* A slope similar to a SLOPE_W. */ |
|
261 switch (new_roadbits) { |
|
262 case 6: // ROAD_SE | ROAD_SW: |
|
263 case 9: // ROAD_NE | ROAD_NW: |
|
264 case 12: // ROAD_NE | ROAD_SE: |
|
265 /* Cannot build anything with a turn from the low side. */ |
|
266 return 0; |
|
267 |
|
268 case 5: // ROAD_SE | ROAD_NW: |
|
269 case 10: // ROAD_NE | ROAD_SW: |
|
270 /* A 'sloped' tile is going to be build. */ |
|
271 if ((existing_roadbits | new_roadbits) != new_roadbits) { |
|
272 /* There is already a foundation on the tile, or at least |
|
273 * another slope that is not compatible with the new one. */ |
|
274 return 0; |
|
275 } |
|
276 /* If the start is in the low part, it is automatically |
|
277 * building the second part too. */ |
|
278 return ((start_roadbits & (ROAD_NE | ROAD_SE)) && !(existing_roadbits & (ROAD_SW | ROAD_NW))) ? 2 : 1; |
|
279 |
|
280 default: |
|
281 /* Roadbits causing a foundation are going to be build. |
|
282 * When the existing roadbits are slopes (the lower bits |
|
283 * are used), this cannot be done. */ |
|
284 if ((existing_roadbits | new_roadbits) == new_roadbits) return 1; |
|
285 return (existing_roadbits & (ROAD_NE | ROAD_SE)) ? 0 : 1; |
|
286 } |
|
287 |
|
288 case SLOPE_SW: |
|
289 /* A slope similar to a SLOPE_SW. */ |
|
290 switch (new_roadbits) { |
|
291 case 9: // ROAD_NE | ROAD_NW: |
|
292 case 12: // ROAD_NE | ROAD_SE: |
|
293 /* Cannot build anything with a turn from the low side. */ |
|
294 return 0; |
|
295 |
|
296 case 10: // ROAD_NE | ROAD_SW: |
|
297 /* A 'sloped' tile is going to be build. */ |
|
298 if ((existing_roadbits | new_roadbits) != new_roadbits) { |
|
299 /* There is already a foundation on the tile, or at least |
|
300 * another slope that is not compatible with the new one. */ |
|
301 return 0; |
|
302 } |
|
303 /* If the start is in the low part, it is automatically |
|
304 * building the second part too. */ |
|
305 return ((start_roadbits & ROAD_NE) && !(existing_roadbits & ROAD_SW)) ? 2 : 1; |
|
306 |
|
307 default: |
|
308 /* Roadbits causing a foundation are going to be build. |
|
309 * When the existing roadbits are slopes (the lower bits |
|
310 * are used), this cannot be done. */ |
|
311 return (existing_roadbits & ROAD_NE) ? 0 : 1; |
|
312 } |
|
313 |
|
314 default: |
|
315 NOT_REACHED(); |
|
316 } |
|
317 } |
|
318 |
|
319 /** |
|
320 * Normalise all input data so we can easily handle it without needing |
|
321 * to call the API lots of times or create large if-elseif-elseif-else |
|
322 * constructs. |
|
323 * In this case it means that a TileXY(0, -1) becomes -2 and TileXY(0, 1) |
|
324 * becomes 2. TileXY(-1, 0) and TileXY(1, 0) stay respectively -1 and 1. |
|
325 * Any other value means that it is an invalid tile offset. |
|
326 * @param tile The tile to normalise. |
|
327 * @return True if and only if the tile offset is valid. |
|
328 */ |
|
329 static bool NormaliseTileOffset(int32 *tile) |
|
330 { |
|
331 if (*tile == 1 || *tile == -1) return true; |
|
332 if (*tile == ::TileDiffXY(0, -1)) { |
|
333 *tile = -2; |
|
334 return true; |
|
335 } |
|
336 if (*tile == ::TileDiffXY(0, 1)) { |
|
337 *tile = 2; |
|
338 return true; |
|
339 } |
|
340 return false; |
|
341 } |
|
342 |
|
343 /* static */ int32 AIRoad::CanBuildConnectedRoadParts(AITile::Slope slope_, Array *existing, TileIndex start_, TileIndex end_) |
|
344 { |
|
345 ::Slope slope = (::Slope)slope_; |
|
346 int32 start = start_; |
|
347 int32 end = end_; |
|
348 |
|
349 /* The start tile and end tile cannot be the same tile either. */ |
|
350 if (start == end) return -1; |
|
351 |
|
352 for (int i = 0; i < existing->size; i++) { |
|
353 if (!NormaliseTileOffset(&existing->array[i])) return -1; |
|
354 } |
|
355 |
|
356 if (!NormaliseTileOffset(&start)) return -1; |
|
357 if (!NormaliseTileOffset(&end)) return -1; |
|
358 |
|
359 /* Without build on slopes the characteristics are vastly different, so use |
|
360 * a different helper function (one that is much simpler). */ |
|
361 return _settings_game.construction.build_on_slopes ? LookupWithBuildOnSlopes(slope, existing, start, end) : LookupWithoutBuildOnSlopes(slope, existing, start, end); |
|
362 } |
|
363 |
|
364 /* static */ int32 AIRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end) |
|
365 { |
|
366 if (!::IsValidTile(tile) || !::IsValidTile(start) || !::IsValidTile(end)) return -1; |
|
367 if (::DistanceManhattan(tile, start) != 1 || ::DistanceManhattan(tile, end) != 1) return -1; |
|
368 |
|
369 static const TileIndex neighbours[] = {::TileDiffXY(-1, 0), ::TileDiffXY(1, 0), ::TileDiffXY(0, -1), ::TileDiffXY(0, 1)}; |
|
370 Array *existing = (Array*)alloca(sizeof(Array) + lengthof(neighbours) * sizeof(int32)); |
|
371 existing->size = 0; |
|
372 |
|
373 for (uint i = 0; i < lengthof(neighbours); i++) { |
|
374 if (AIRoad::AreRoadTilesConnected(tile, tile + neighbours[i])) existing->array[existing->size++] = neighbours[i]; |
|
375 } |
|
376 |
|
377 return AIRoad::CanBuildConnectedRoadParts(AITile::GetSlope(tile), existing, start - tile, end - tile); |
|
378 } |
|
379 |
82 |
380 |
83 /* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile) |
381 /* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile) |
84 { |
382 { |
85 if (!::IsValidTile(tile)) return false; |
383 if (!::IsValidTile(tile)) return false; |
86 |
384 |