12 #include "../../stdafx.h"
13 #include "../../network/network.h"
14 #include "../../viewport_func.h"
15 #include "../../ship.h"
16 #include "../../roadstop_base.h"
17 #include "../pathfinder_func.h"
18 #include "../pathfinder_type.h"
19 #include "../follow_track.hpp"
22 #include "../../safeguards.h"
28 static const uint NPF_HASH_HALFMASK = (1 << NPF_HASH_HALFBITS) - 1;
81 #define NPF_STRAIGHT_LENGTH (uint)(NPF_TILE_LENGTH * STRAIGHT_TRACK_LENGTH)
93 return HasBit(node->user_data[NPF_NODE_FLAGS], flag);
101 SB(node->user_data[NPF_NODE_FLAGS], flag, 1, value);
115 const uint straightTracks = 2 *
min(dx, dy);
120 const uint diagTracks = dx + dy - straightTracks;
137 uint part1 =
TileX(key1) & NPF_HASH_HALFMASK;
138 uint part2 =
TileY(key1) & NPF_HASH_HALFMASK;
142 return ((part1 << NPF_HASH_HALFBITS | part2) + (NPF_HASH_SIZE * key2 /
TRACKDIR_END)) % NPF_HASH_SIZE;
174 DEBUG(npf, 4,
"Calculating H for: (%d, %d). Result: %d",
TileX(current->tile),
TileY(current->tile), dist);
176 if (dist < ftd->best_bird_dist) {
177 ftd->best_bird_dist = dist;
189 if (parent->path.
parent == NULL) {
190 Trackdir trackdir = current->direction;
194 DEBUG(npf, 6,
"Saving trackdir: 0x%X", trackdir);
204 static uint NPFTunnelCost(
AyStarNode *current)
220 static inline uint NPFBridgeCost(
AyStarNode *current)
235 int dx4 = (x2 - x1) / 4;
236 int dy4 = (y2 - y1) / 4;
241 int z1 = GetSlopePixelZ(x1 + dx4, y1 + dy4);
242 int z2 = GetSlopePixelZ(x2 - dx4, y2 - dy4);
254 static uint NPFReservedTrackCost(
AyStarNode *current)
277 #ifndef NO_DEBUG_MESSAGES
305 Trackdir trackdir = current->direction;
307 cost = _trackdir_length[trackdir];
331 cost =
IsTunnel(tile) ? NPFTunnelCost(current) : NPFBridgeCost(current);
367 cost += NPFSlopeCost(current);
376 DEBUG(npf, 4,
"Calculating G for: (%d, %d). Result: %d",
TileX(current->tile),
TileY(current->tile), cost);
385 Trackdir trackdir = current->direction;
393 cost =
IsTunnel(tile) ? NPFTunnelCost(current) : NPFBridgeCost(current);
397 cost = _trackdir_length[trackdir];
423 while (ft.Follow(t, td)) {
424 assert(t != ft.m_new_tile);
464 if (!IsPbsSignal(sigtype)) {
501 new_node.path.node = *current;
507 cost += NPFSlopeCost(current);
525 cost += NPFReservedTrackCost(current);
528 DEBUG(npf, 4,
"Calculating G for: (%d, %d). Result: %d",
TileX(current->tile),
TileY(current->tile), cost);
596 bool first_run =
true;
597 for (; start != end; start = start->
parent) {
619 ftd->
node = current->path.node;
627 ftd->
node = target->node;
636 ftd->
node.tile = end_tile;
787 if (!
HasBit(railtypes, rail_type))
return false;
830 DEBUG(npf, 4,
"Next node: (%d, %d) [%d], possible trackdirs: 0x%X",
TileX(dst_tile),
TileY(dst_tile), dst_tile, trackdirbits);
838 DEBUG(npf, 6,
"After filtering: (%d, %d), possible trackdirs: 0x%X",
TileX(dst_tile),
TileY(dst_tile), trackdirbits);
853 Trackdir src_trackdir = current->path.node.direction;
854 TileIndex src_tile = current->path.node.tile;
867 aystar->num_neighbours = 0;
868 DEBUG(npf, 4,
"Expanding: (%d, %d, %d) [%d]",
TileX(src_tile),
TileY(src_tile), src_trackdir, src_tile);
875 if (ignore_src_tile) {
883 }
else if (
ForceReverse(src_tile, src_exitdir, type, subtype)) {
904 if (trackdirbits == 0) {
928 while (trackdirbits != 0) {
930 DEBUG(npf, 5,
"Expanded into trackdir: %d, remaining trackdirs: 0x%X", dst_trackdir, trackdirbits);
941 AyStarNode *neighbour = &aystar->neighbours[i];
942 neighbour->tile = dst_tile;
943 neighbour->direction = dst_trackdir;
945 neighbour->user_data[NPF_NODE_FLAGS] = current->path.node.user_data[NPF_NODE_FLAGS];
946 NPFFillTrackdirChoice(neighbour, current);
950 aystar->num_neighbours = i;
963 static NPFFoundTargetData NPFRouteInternal(
AyStarNode *start1,
bool ignore_start_tile1,
AyStarNode *start2,
bool ignore_start_tile2,
NPFFindStationOrTileData *target,
AyStar_EndNodeCheck target_proc,
AyStar_CalculateH heuristic_proc,
TransportType type, uint sub_type,
Owner owner,
RailTypes railtypes, uint reverse_penalty)
969 _npf_aystar.CalculateH = heuristic_proc;
970 _npf_aystar.EndNodeCheck = target_proc;
972 _npf_aystar.GetNeighbours = NPFFollowTrack;
974 default: NOT_REACHED();
975 case TRANSPORT_RAIL: _npf_aystar.CalculateG = NPFRailPathCost;
break;
976 case TRANSPORT_ROAD: _npf_aystar.CalculateG = NPFRoadPathCost;
break;
977 case TRANSPORT_WATER: _npf_aystar.CalculateG = NPFWaterPathCost;
break;
982 start1->user_data[NPF_NODE_FLAGS] = 0;
985 if (start2 != NULL) {
987 start2->user_data[NPF_NODE_FLAGS] = 0;
999 _npf_aystar.user_path = &result;
1002 _npf_aystar.user_target = target;
1005 _npf_aystar.user_data[
NPF_TYPE] = type;
1007 _npf_aystar.user_data[
NPF_OWNER] = owner;
1011 r = _npf_aystar.
Main();
1015 if (target != NULL) {
1016 DEBUG(npf, 1,
"Could not find route to tile 0x%X from 0x%X.", target->
dest_coords, start1->tile);
1019 DEBUG(npf, 1,
"Could not find route to a depot from tile 0x%X.", start1->tile);
1029 static NPFFoundTargetData NPFRouteToStationOrTileTwoWay(
TileIndex tile1,
Trackdir trackdir1,
bool ignore_start_tile1,
TileIndex tile2,
Trackdir trackdir2,
bool ignore_start_tile2,
NPFFindStationOrTileData *target,
TransportType type, uint sub_type,
Owner owner,
RailTypes railtypes)
1034 start1.tile = tile1;
1035 start2.tile = tile2;
1039 start1.direction = trackdir1;
1040 start2.direction = trackdir2;
1043 return NPFRouteInternal(&start1, ignore_start_tile1, (
IsValidTile(tile2) ? &start2 : NULL), ignore_start_tile2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, sub_type, owner, railtypes, 0);
1051 return NPFRouteToStationOrTileTwoWay(tile, trackdir, ignore_start_tile,
INVALID_TILE,
INVALID_TRACKDIR,
false, target, type, sub_type, owner, railtypes);
1061 static NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(
TileIndex tile1,
Trackdir trackdir1,
bool ignore_start_tile1,
TileIndex tile2,
Trackdir trackdir2,
bool ignore_start_tile2,
NPFFindStationOrTileData *target,
TransportType type, uint sub_type,
Owner owner,
RailTypes railtypes, uint reverse_penalty)
1066 start1.tile = tile1;
1067 start2.tile = tile2;
1071 start1.direction = trackdir1;
1072 start2.direction = trackdir2;
1077 return NPFRouteInternal(&start1, ignore_start_tile1, (
IsValidTile(tile2) ? &start2 : NULL), ignore_start_tile2, target, NPFFindDepot, NPFCalcZero, type, sub_type, owner, railtypes, reverse_penalty);
1080 void InitializeNPF()
1082 static bool first_init =
true;
1087 _npf_aystar.
Clear();
1126 NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->
tile, trackdir,
false, v->
tile,
ReverseTrackdir(trackdir),
false, NULL,
TRANSPORT_ROAD, v->compatible_roadtypes, v->
owner,
INVALID_RAILTYPES, 0);
1142 NPFFillWithOrderData(&fstd, v);
1170 NPFFillWithOrderData(&fstd, v);
1188 NPFFillWithOrderData(&fstd, v);
1195 ftd = NPFRouteToStationOrTileTwoWay(v->
tile, trackdir,
false, v->
tile, trackdir_rev,
false, &fstd,
TRANSPORT_WATER, 0, v->
owner,
INVALID_RAILTYPES);
1209 fstd.reserve_path =
false;
1212 NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->
tile, trackdir,
false, last->
tile, trackdir_rev,
false, &fstd,
TRANSPORT_RAIL, 0, v->
owner, v->compatible_railtypes,
NPF_INFINITE_PENALTY);
1236 start1.direction = trackdir;
1239 RailTypes railtypes = v->compatible_railtypes;
1244 return NPFRouteInternal(&start1,
true, NULL,
false, &fstd,
NPFFindSafeTile, NPFCalcZero,
TRANSPORT_RAIL, 0, v->
owner, railtypes, 0).
res_okay;
1253 NPFFillWithOrderData(&fstd, v);
1260 ftd = NPFRouteToStationOrTileTwoWay(v->
tile, trackdir,
false, last->
tile, trackdir_rev,
false, &fstd,
TRANSPORT_RAIL, 0, v->
owner, v->compatible_railtypes);
1268 NPFFillWithOrderData(&fstd, v, reserve_track);
1275 if (target != NULL) {