src/ai/trolly/pathfinder.cpp
branchNewGRF_ports
changeset 6872 1c4a4a609f85
parent 6871 5a9dc001e1ad
child 6877 889301acc299
equal deleted inserted replaced
6871:5a9dc001e1ad 6872:1c4a4a609f85
     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