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) {