00001
00002
00003 #include "../../stdafx.h"
00004 #include "../../openttd.h"
00005 #include "../../bridge_map.h"
00006 #include "../../debug.h"
00007 #include "../../command_func.h"
00008 #include "trolly.h"
00009 #include "../../depot.h"
00010 #include "../../tunnel_map.h"
00011 #include "../../bridge.h"
00012 #include "../../tunnelbridge_map.h"
00013 #include "../ai.h"
00014 #include "../../variables.h"
00015 #include "../../player_base.h"
00016 #include "../../player_func.h"
00017 #include "../../tunnelbridge.h"
00018
00019
00020 #define TEST_STATION_NO_DIR 0xFF
00021
00022
00023
00024 static bool TestCanBuildStationHere(TileIndex tile, byte dir)
00025 {
00026 Player *p = GetPlayer(_current_player);
00027
00028 if (dir == TEST_STATION_NO_DIR) {
00029 CommandCost ret;
00030
00031
00032 for (dir = 0; dir < 4; dir++) {
00033 ret = AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST);
00034 if (CmdSucceeded(ret)) return true;
00035 }
00036 return false;
00037 }
00038
00039
00040 return CmdSucceeded(AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST));
00041 }
00042
00043
00044 static bool IsRoad(TileIndex tile)
00045 {
00046 return
00047
00048 (IsTileType(tile, MP_ROAD) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
00049 (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD);
00050 }
00051
00052
00053
00054 #define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
00055
00056
00057
00058 static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
00059 {
00060 const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
00061
00062
00063 if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
00064 if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
00065 if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
00066 if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
00067 return AYSTAR_FOUND_END_NODE;
00068
00069 return AYSTAR_DONE;
00070 }
00071
00072
00073
00074
00075 static uint AiPathFinder_Hash(uint key1, uint key2)
00076 {
00077 return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
00078 }
00079
00080
00081
00082 static void AyStar_AiPathFinder_Free(AyStar *aystar)
00083 {
00084 AyStarMain_Free(aystar);
00085 delete aystar;
00086 }
00087
00088
00089 static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
00090 static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
00091 static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
00092 static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
00093
00094
00095
00096 AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
00097 {
00098 PathNode start_node;
00099 uint x;
00100 uint y;
00101
00102 AyStar *result = new AyStar();
00103 init_AyStar(result, AiPathFinder_Hash, 1 << 10);
00104
00105 result->CalculateG = AyStar_AiPathFinder_CalculateG;
00106 result->CalculateH = AyStar_AiPathFinder_CalculateH;
00107 result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
00108 result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
00109 result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
00110
00111 result->free = AyStar_AiPathFinder_Free;
00112
00113
00114 result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
00115 result->max_path_cost = 0;
00116 result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
00117
00118
00119 result->user_target = PathFinderInfo;
00120
00121
00122 start_node.parent = NULL;
00123 start_node.node.direction = 0;
00124 start_node.node.user_data[0] = 0;
00125
00126
00127 for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
00128 for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
00129 start_node.node.tile = TileXY(x, y);
00130 result->addstart(result, &start_node.node, 0);
00131 }
00132 }
00133
00134 return result;
00135 }
00136
00137
00138
00139 void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
00140 {
00141 PathNode start_node;
00142 uint x;
00143 uint y;
00144
00145 aystar->clear(aystar);
00146
00147
00148 aystar->user_target = PathFinderInfo;
00149
00150
00151 start_node.parent = NULL;
00152 start_node.node.direction = 0;
00153 start_node.node.user_data[0] = 0;
00154 start_node.node.tile = PathFinderInfo->start_tile_tl;
00155
00156
00157 for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
00158 for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
00159 TileIndex tile = TileXY(x, y);
00160
00161 if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) continue;
00162 if (!TestCanBuildStationHere(tile, TEST_STATION_NO_DIR)) continue;
00163 start_node.node.tile = tile;
00164 aystar->addstart(aystar, &start_node.node, 0);
00165 }
00166 }
00167 }
00168
00169
00170
00171 static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
00172 {
00173 const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
00174 int r, r2;
00175
00176 if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
00177
00178 r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDiagDir(PathFinderInfo->end_direction));
00179 r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDiagDir(PathFinderInfo->end_direction));
00180 } else {
00181
00182 r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
00183 r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
00184 }
00185
00186 if (r2 < r) r = r2;
00187 return r * AI_PATHFINDER_H_MULTIPLER;
00188 }
00189
00190
00191
00192 static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
00193 {
00194 Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
00195 uint i = 0;
00196 PathNode *parent = ¤t->path;
00197
00198 do {
00199 PathFinderInfo->route_extra[i] = parent->node.user_data[0];
00200 PathFinderInfo->route[i++] = parent->node.tile;
00201 if (i > lengthof(PathFinderInfo->route)) {
00202
00203 DEBUG(ai, 0, "No more space in pathfinder route[] array");
00204 PathFinderInfo->route_length = -1;
00205 return;
00206 }
00207 parent = parent->parent;
00208 } while (parent != NULL);
00209 PathFinderInfo->route_length = i;
00210 DEBUG(ai, 1, "Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
00211 }
00212
00213
00214
00215 static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
00216 {
00217 CommandCost ret;
00218 int dir;
00219
00220 Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
00221
00222 aystar->num_neighbours = 0;
00223
00224
00225 for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
00226 TileIndex ctile = current->path.node.tile;
00227 TileIndex atile = ctile + TileOffsByDiagDir(i);
00228
00229 if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
00230 TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
00231
00232
00233
00234
00235 if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
00236 if (IsTileType(atile, MP_TUNNELBRIDGE)) {
00237 if (GetTunnelBridgeDirection(atile) != i) continue;
00238 }
00239 }
00240
00241 if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
00242 (AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
00243
00244
00245 if ((uint)i != (current->path.node.user_data[0] >> 8)) continue;
00246 }
00247 dir = 0;
00248
00249
00250 if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
00251
00252 if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
00253
00254 if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
00255
00256 continue;
00257 }
00258 }
00259 } else if (current->path.node.user_data[0] == 0) {
00260 if (PathFinderInfo->rail_or_road) {
00261
00262 dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
00263 ret = AI_DoCommand(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
00264 if (CmdFailed(ret)) continue;
00265 #ifdef AI_PATHFINDER_NO_90DEGREES_TURN
00266 if (current->path.parent->parent != NULL) {
00267
00268 int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
00269 if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
00270 continue;
00271 }
00272 }
00273 #endif
00274 } else {
00275
00276 dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
00277 if (IsRoad(ctile)) {
00278 if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
00279
00280 dir = 0;
00281 } else {
00282
00283 if ((GetAnyRoadBits(ctile, ROADTYPE_ROAD) & dir) != dir) {
00284
00285 dir &= ~GetAnyRoadBits(ctile, ROADTYPE_ROAD);
00286 } else {
00287 dir = 0;
00288 }
00289 }
00290 }
00291
00292 if (dir != 0) {
00293 ret = AI_DoCommand(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
00294 if (CmdFailed(ret)) continue;
00295 }
00296 }
00297 }
00298
00299
00300 aystar->neighbours[aystar->num_neighbours].tile = atile;
00301 aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
00302 aystar->neighbours[aystar->num_neighbours++].direction = 0;
00303 }
00304 }
00305
00306
00307 if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
00308
00309 DiagDirection dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
00310
00311 TileIndex tile = current->path.node.tile;
00312 TileIndex new_tile = tile;
00313 Slope tileh = GetTileSlope(tile, NULL);
00314
00315
00316
00317 if (tileh != SLOPE_FLAT ||
00318 (PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_ROAD)) ||
00319 (!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_RAILWAY))) {
00320 for (;;) {
00321 new_tile += TileOffsByDiagDir(dir);
00322
00323
00324 if (!CheckBridge_Stuff(0, GetTunnelBridgeLength(tile, new_tile))) break;
00325
00326
00327 if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
00328
00329
00330 ret = AI_DoCommand(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
00331 if (CmdFailed(ret)) continue;
00332
00333 aystar->neighbours[aystar->num_neighbours].tile = new_tile;
00334 aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
00335 aystar->neighbours[aystar->num_neighbours++].direction = 0;
00336
00337 if (aystar->num_neighbours == 11) break;
00338 }
00339 }
00340
00341
00342
00343
00344 if (tileh == InclinedSlope(dir)) {
00345
00346 ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
00347 tileh = GetTileSlope(_build_tunnel_endtile, NULL);
00348 if (CmdSucceeded(ret) && IsInclinedSlope(tileh)) {
00349 aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
00350 aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
00351 aystar->neighbours[aystar->num_neighbours++].direction = 0;
00352 }
00353 }
00354 }
00355 }
00356
00357
00358 extern Foundation GetRailFoundation(Slope tileh, TrackBits bits);
00359 extern Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
00360
00361
00362 static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
00363 {
00364 Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
00365 int res = 0;
00366 Slope tileh = GetTileSlope(current->tile, NULL);
00367 Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
00368
00369
00370 if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
00371
00372 if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction) {
00373
00374 return AYSTAR_INVALID_NODE;
00375 }
00376
00377 return 0;
00378 }
00379
00380
00381 res += AI_PATHFINDER_PENALTY;
00382
00383 if (!PathFinderInfo->rail_or_road) {
00384
00385
00386 if (IsRoad(current->tile)) {
00387 res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) {
00398
00399 if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
00400 if (PathFinderInfo->rail_or_road) {
00401 Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)));
00402 if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
00403 res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
00404 } else {
00405 res += AI_PATHFINDER_FOUNDATION_PENALTY;
00406 }
00407 } else {
00408 if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) {
00409 Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
00410 if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
00411 res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
00412 } else {
00413 res += AI_PATHFINDER_FOUNDATION_PENALTY;
00414 }
00415 }
00416 }
00417 }
00418 }
00419
00420
00421 if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
00422 int r;
00423
00424
00425 r = AI_PATHFINDER_TUNNEL_PENALTY * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
00426 res += r + (r >> 8);
00427 }
00428
00429
00430 if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
00431
00432 res += AI_PATHFINDER_BRIDGE_PENALTY * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
00433
00434
00435 if (!HasBridgeFlatRamp(parent_tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
00436
00437 if (!HasBridgeFlatRamp(tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
00438 }
00439
00440
00441
00442
00443 if (!PathFinderInfo->rail_or_road) {
00444 if (parent->path.parent != NULL &&
00445 AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
00446
00447 if (IsRoad(parent->path.node.tile)) {
00448 res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
00449 } else {
00450 res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
00451 }
00452 }
00453 } else {
00454
00455
00456 if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
00457 int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
00458 int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
00459
00460 if (dir1 > 1) res -= AI_PATHFINDER_DIAGONAL_BONUS;
00461
00462
00463 if (dir1 != dir2) {
00464
00465 if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
00466
00467 res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
00468 }
00469 if (parent->path.parent->parent->parent != NULL) {
00470 int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
00471
00472 if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
00473 res += AI_PATHFINDER_CURVE_PENALTY;
00474 }
00475 }
00476 }
00477 }
00478 }
00479
00480 return (res < 0) ? 0 : res;
00481 }