2 |
2 |
3 #include "../../stdafx.h" |
3 #include "../../stdafx.h" |
4 #include "../../openttd.h" |
4 #include "../../openttd.h" |
5 #include "../../bridge_map.h" |
5 #include "../../bridge_map.h" |
6 #include "../../debug.h" |
6 #include "../../debug.h" |
7 #include "../../functions.h" |
7 #include "../../command_func.h" |
8 #include "../../map.h" |
|
9 #include "../../tile.h" |
|
10 #include "../../command.h" |
|
11 #include "trolly.h" |
8 #include "trolly.h" |
12 #include "../../depot.h" |
9 #include "../../depot.h" |
13 #include "../../tunnel_map.h" |
10 #include "../../tunnel_map.h" |
14 #include "../../bridge.h" |
11 #include "../../bridge.h" |
|
12 #include "../../tunnelbridge_map.h" |
15 #include "../ai.h" |
13 #include "../ai.h" |
|
14 #include "../../variables.h" |
|
15 #include "../../player_base.h" |
|
16 #include "../../player_func.h" |
|
17 |
16 |
18 |
17 #define TEST_STATION_NO_DIR 0xFF |
19 #define TEST_STATION_NO_DIR 0xFF |
18 |
20 |
19 // Tests if a station can be build on the given spot |
21 // Tests if a station can be build on the given spot |
20 // TODO: make it train compatible |
22 // TODO: make it train compatible |
25 if (dir == TEST_STATION_NO_DIR) { |
27 if (dir == TEST_STATION_NO_DIR) { |
26 CommandCost ret; |
28 CommandCost ret; |
27 // TODO: currently we only allow spots that can be access from al 4 directions... |
29 // TODO: currently we only allow spots that can be access from al 4 directions... |
28 // should be fixed!!! |
30 // should be fixed!!! |
29 for (dir = 0; dir < 4; dir++) { |
31 for (dir = 0; dir < 4; dir++) { |
30 ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST); |
32 ret = AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST); |
31 if (CmdSucceeded(ret)) return true; |
33 if (CmdSucceeded(ret)) return true; |
32 } |
34 } |
33 return false; |
35 return false; |
34 } |
36 } |
35 |
37 |
36 // return true if command succeeded, so the inverse of CmdFailed() |
38 // return true if command succeeded, so the inverse of CmdFailed() |
37 return CmdSucceeded(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST)); |
39 return CmdSucceeded(AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST)); |
38 } |
40 } |
39 |
41 |
40 |
42 |
41 static bool IsRoad(TileIndex tile) |
43 static bool IsRoad(TileIndex tile) |
42 { |
44 { |
43 return |
45 return |
44 // MP_ROAD, but not a road depot? |
46 // MP_ROAD, but not a road depot? |
45 (IsTileType(tile, MP_ROAD) && !IsTileDepotType(tile, TRANSPORT_ROAD)) || |
47 (IsTileType(tile, MP_ROAD) && !IsTileDepotType(tile, TRANSPORT_ROAD)) || |
46 (IsTileType(tile, MP_TUNNELBRIDGE) && ( |
48 (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD); |
47 (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) || |
|
48 (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_ROAD) |
|
49 )); |
|
50 } |
49 } |
51 |
50 |
52 |
51 |
53 // Checks if a tile 'a' is between the tiles 'b' and 'c' |
52 // Checks if a tile 'a' is between the tiles 'b' and 'c' |
54 #define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c)) |
53 #define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c)) |
232 // We do this simply by just building the tile! |
231 // We do this simply by just building the tile! |
233 |
232 |
234 // If the next step is a bridge, we have to enter it the right way |
233 // If the next step is a bridge, we have to enter it the right way |
235 if (!PathFinderInfo->rail_or_road && IsRoad(atile)) { |
234 if (!PathFinderInfo->rail_or_road && IsRoad(atile)) { |
236 if (IsTileType(atile, MP_TUNNELBRIDGE)) { |
235 if (IsTileType(atile, MP_TUNNELBRIDGE)) { |
237 if (IsTunnel(atile)) { |
236 if (GetTunnelBridgeDirection(atile) != i) continue; |
238 if (GetTunnelDirection(atile) != i) continue; |
|
239 } else { |
|
240 if (GetBridgeRampDirection(atile) != i) continue; |
|
241 } |
|
242 } |
237 } |
243 } |
238 } |
244 |
239 |
245 if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 || |
240 if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 || |
246 (AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) { |
241 (AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) { |
362 } |
357 } |
363 |
358 |
364 |
359 |
365 extern Foundation GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c |
360 extern Foundation GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c |
366 extern Foundation GetRoadFoundation(Slope tileh, RoadBits bits); // XXX function declaration in .c |
361 extern Foundation GetRoadFoundation(Slope tileh, RoadBits bits); // XXX function declaration in .c |
367 extern Foundation GetBridgeFoundation(Slope tileh, Axis); // XXX function declaration in .c |
|
368 enum BridgeFoundation { |
|
369 BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12, |
|
370 }; |
|
371 |
362 |
372 // The most important function: it calculates the g-value |
363 // The most important function: it calculates the g-value |
373 static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent) |
364 static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent) |
374 { |
365 { |
375 Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target; |
366 Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target; |
406 // especially they essentially block the ability to connect or cross the road |
397 // especially they essentially block the ability to connect or cross the road |
407 // from one side. |
398 // from one side. |
408 if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) { |
399 if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) { |
409 // Skip if the tile was from a bridge or tunnel |
400 // Skip if the tile was from a bridge or tunnel |
410 if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) { |
401 if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) { |
|
402 static const uint32 SLOPED_TILEHS = (1 << SLOPE_NW) | (1 << SLOPE_SW) | (1 << SLOPE_SE) | (1 << SLOPE_NE); |
411 if (PathFinderInfo->rail_or_road) { |
403 if (PathFinderInfo->rail_or_road) { |
412 Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile))); |
404 Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile))); |
413 // Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information.. |
405 if (IsInclinedFoundation(f) || (!IsFoundation(f) && HasBit(SLOPED_TILEHS, parent_tileh))) { |
414 if (IsInclinedFoundation(f) || (!IsFoundation(f) && HasBit(BRIDGE_NO_FOUNDATION, parent_tileh))) { |
|
415 res += AI_PATHFINDER_TILE_GOES_UP_PENALTY; |
406 res += AI_PATHFINDER_TILE_GOES_UP_PENALTY; |
416 } else { |
407 } else { |
417 res += AI_PATHFINDER_FOUNDATION_PENALTY; |
408 res += AI_PATHFINDER_FOUNDATION_PENALTY; |
418 } |
409 } |
419 } else { |
410 } else { |
420 if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) { |
411 if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) { |
421 Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)); |
412 Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)); |
422 if (IsInclinedFoundation(f) || (!IsFoundation(f) && HasBit(BRIDGE_NO_FOUNDATION, parent_tileh))) { |
413 if (IsInclinedFoundation(f) || (!IsFoundation(f) && HasBit(SLOPED_TILEHS, parent_tileh))) { |
423 res += AI_PATHFINDER_TILE_GOES_UP_PENALTY; |
414 res += AI_PATHFINDER_TILE_GOES_UP_PENALTY; |
424 } else { |
415 } else { |
425 res += AI_PATHFINDER_FOUNDATION_PENALTY; |
416 res += AI_PATHFINDER_FOUNDATION_PENALTY; |
426 } |
417 } |
427 } |
418 } |
442 if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) { |
433 if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) { |
443 // That means for every length a penalty |
434 // That means for every length a penalty |
444 res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile); |
435 res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile); |
445 // Check if we are going up or down, first for the starting point |
436 // Check if we are going up or down, first for the starting point |
446 // In user_data[0] is at the 8th bit the direction |
437 // In user_data[0] is at the 8th bit the direction |
447 if (!HasBit(BRIDGE_NO_FOUNDATION, parent_tileh)) { |
438 if (!HasBridgeFlatRamp(parent_tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY; |
448 if (IsLeveledFoundation(GetBridgeFoundation(parent_tileh, (Axis)((current->user_data[0] >> 8) & 1)))) { |
|
449 res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY; |
|
450 } |
|
451 } |
|
452 // Second for the end point |
439 // Second for the end point |
453 if (!HasBit(BRIDGE_NO_FOUNDATION, tileh)) { |
440 if (!HasBridgeFlatRamp(tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY; |
454 if (IsLeveledFoundation(GetBridgeFoundation(tileh, (Axis)((current->user_data[0] >> 8) & 1)))) { |
|
455 res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY; |
|
456 } |
|
457 } |
|
458 if (parent_tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY; |
|
459 if (tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY; |
|
460 } |
441 } |
461 |
442 |
462 // To prevent the AI from taking the fastest way in tiles, but not the fastest way |
443 // To prevent the AI from taking the fastest way in tiles, but not the fastest way |
463 // in speed, we have to give a good penalty to direction changing |
444 // in speed, we have to give a good penalty to direction changing |
464 // This way, we get almost the fastest way in tiles, and a very good speed on the track |
445 // This way, we get almost the fastest way in tiles, and a very good speed on the track |