npf.c
changeset 1463 a9b4664cef34
parent 1460 ebd1cfae9588
child 1464 266d3b0ee2c8
equal deleted inserted replaced
1462:f487048c5748 1463:a9b4664cef34
    30 };
    30 };
    31 
    31 
    32 /* Maps a trackdir to the trackdirs that can be reached from it (ie, when
    32 /* Maps a trackdir to the trackdirs that can be reached from it (ie, when
    33  * entering the next tile */
    33  * entering the next tile */
    34 const uint16 _trackdir_reaches_trackdirs[14] = {
    34 const uint16 _trackdir_reaches_trackdirs[14] = {
    35 0x1009, 0x0016, 0x1009, 0x0016, 0x0520, 0x0016, 0, 0,
    35 	0x1009, 0x0016, 0x1009, 0x0016, 0x0520, 0x0016, 0, 0,
    36 0x0520, 0x2A00, 0x2A00, 0x0520, 0x2A00, 0x1009
    36 	0x0520, 0x2A00, 0x2A00, 0x0520, 0x2A00, 0x1009
    37 };
    37 };
    38 
    38 
    39 /* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
    39 /* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
    40 const uint16 _trackdir_crosses_trackdirs[14] = {
    40 const uint16 _trackdir_crosses_trackdirs[14] = {
    41 0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C, 0, 0,
    41 	0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C, 0, 0,
    42 0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C
    42 	0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C
    43 };
    43 };
    44 
    44 
    45 /* Maps a track to all tracks that make 90 deg turns with it. */
    45 /* Maps a track to all tracks that make 90 deg turns with it. */
    46 const byte _track_crosses_tracks[6] = {
    46 const byte _track_crosses_tracks[6] = {
    47 	0x2, /* Track 1 -> Track 2 */
    47 	0x2, /* Track 1 -> Track 2 */
    93 /* The cost of each trackdir. A diagonal piece is the full NPF_TILE_LENGTH,
    93 /* The cost of each trackdir. A diagonal piece is the full NPF_TILE_LENGTH,
    94  * the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071
    94  * the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071
    95  */
    95  */
    96 #define NPF_STRAIGHT_LENGTH (uint)(NPF_TILE_LENGTH * 0.7071)
    96 #define NPF_STRAIGHT_LENGTH (uint)(NPF_TILE_LENGTH * 0.7071)
    97 static const uint _trackdir_length[14] = {
    97 static const uint _trackdir_length[14] = {
    98 NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, 0, 0,
    98 	NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH,
    99 NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH
    99 	0, 0,
       
   100 	NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH
   100 };
   101 };
   101 
   102 
   102 uint NTPHash(uint key1, uint key2)
   103 uint NTPHash(uint key1, uint key2)
   103 {
   104 {
   104 	return PATHFIND_HASH_TILE(key1);
   105 	return PATHFIND_HASH_TILE(key1);
   116 	const Station* st = GetStation(station);
   117 	const Station* st = GetStation(station);
   117 
   118 
   118 	int x1,x2,x3,tx;
   119 	int x1,x2,x3,tx;
   119 	int y1,y2,y3,ty;
   120 	int y1,y2,y3,ty;
   120 
   121 
   121 	x1 = TileX(st->train_tile);			y1 = TileY(st->train_tile);			// topmost corner of station
   122 	x1 = TileX(st->train_tile);  y1 = TileY(st->train_tile);  // topmost corner of station
   122 	x2 = x1 + st->trainst_w - 1; 		y2 = y1 + st->trainst_h - 1;		// lowermost corner of station
   123 	x2 = x1 + st->trainst_w - 1; y2 = y1 + st->trainst_h - 1; // lowermost corner of station
   123 	x3 = TileX(tile); 							y3 = TileY(tile);								// tile we take the distance from
   124 	x3 = TileX(tile);            y3 = TileY(tile);            // tile we take the distance from
   124 
   125 
   125 	// we are going the aim for the x coordinate of the closest corner
   126 	// we are going the aim for the x coordinate of the closest corner
   126 	// but if we are between those coordinates, we will aim for our own x coordinate
   127 	// but if we are between those coordinates, we will aim for our own x coordinate
   127 	if (x3 < x1)
   128 	if (x3 < x1)
   128 		tx = x1;
   129 		tx = x1;
   160 
   161 
   161 	if (dist < ftd->best_bird_dist) {
   162 	if (dist < ftd->best_bird_dist) {
   162 		ftd->best_bird_dist = dist;
   163 		ftd->best_bird_dist = dist;
   163 		ftd->best_trackdir = current->user_data[NPF_TRACKDIR_CHOICE];
   164 		ftd->best_trackdir = current->user_data[NPF_TRACKDIR_CHOICE];
   164 	}
   165 	}
   165 	#ifdef NPF_DEBUG
   166 #ifdef NPF_DEBUG
   166 	debug("Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist);
   167 	debug("Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist);
   167 	#endif
   168 #endif
   168 	return dist;
   169 	return dist;
   169 }
   170 }
   170 
   171 
   171 /* Calcs the heuristic to the target station or tile. Almost the same as above
   172 /* Calcs the heuristic to the target station or tile. Almost the same as above
   172  * function, but calculates the distance to train stations with
   173  * function, but calculates the distance to train stations with
   189 
   190 
   190 	if (dist < ftd->best_bird_dist) {
   191 	if (dist < ftd->best_bird_dist) {
   191 		ftd->best_bird_dist = dist;
   192 		ftd->best_bird_dist = dist;
   192 		ftd->best_trackdir = current->user_data[NPF_TRACKDIR_CHOICE];
   193 		ftd->best_trackdir = current->user_data[NPF_TRACKDIR_CHOICE];
   193 	}
   194 	}
   194 	#ifdef NPF_DEBUG
   195 #ifdef NPF_DEBUG
   195 	debug("Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist);
   196 	debug("Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist);
   196 	#endif
   197 #endif
   197 	return dist;
   198 	return dist;
   198 }
   199 }
   199 
   200 
   200 
   201 
   201 /* Fills AyStarNode.user_data[NPF_TRACKDIRCHOICE] with the chosen direction to
   202 /* Fills AyStarNode.user_data[NPF_TRACKDIRCHOICE] with the chosen direction to
   206 	if (parent->path.parent == NULL) {
   207 	if (parent->path.parent == NULL) {
   207 		byte trackdir = current->direction;
   208 		byte trackdir = current->direction;
   208 		/* This is a first order decision, so we'd better save the
   209 		/* This is a first order decision, so we'd better save the
   209 		 * direction we chose */
   210 		 * direction we chose */
   210 		current->user_data[NPF_TRACKDIR_CHOICE] = trackdir;
   211 		current->user_data[NPF_TRACKDIR_CHOICE] = trackdir;
   211 		#ifdef NPF_DEBUG
   212 #ifdef NPF_DEBUG
   212 		debug("Saving trackdir: %#x", trackdir);
   213 		debug("Saving trackdir: %#x", trackdir);
   213 		#endif
   214 #endif
   214 	} else {
   215 	} else {
   215 		/* We've already made the decision, so just save our parent's
   216 		/* We've already made the decision, so just save our parent's
   216 		 * decision */
   217 		 * decision */
   217 		current->user_data[NPF_TRACKDIR_CHOICE] = parent->path.node.user_data[NPF_TRACKDIR_CHOICE];
   218 		current->user_data[NPF_TRACKDIR_CHOICE] = parent->path.node.user_data[NPF_TRACKDIR_CHOICE];
   218 	}
   219 	}
   303 	cost += NPFSlopeCost(current);
   304 	cost += NPFSlopeCost(current);
   304 
   305 
   305 	/* Check for turns */
   306 	/* Check for turns */
   306 	//TODO
   307 	//TODO
   307 
   308 
   308 	#ifdef NPF_MARKROUTE
   309 #ifdef NPF_MARKROUTE
   309 	NPFMarkTile(tile);
   310 	NPFMarkTile(tile);
   310 	#endif
   311 #endif
   311 	#ifdef NPF_DEBUG
   312 #ifdef NPF_DEBUG
   312 	debug("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost);
   313 	debug("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost);
   313 	#endif
   314 #endif
   314 	return cost;
   315 	return cost;
   315 }
   316 }
   316 
   317 
   317 
   318 
   318 /* Determine the cost of this node, for railway tracks */
   319 /* Determine the cost of this node, for railway tracks */
   387 		 * exactly once, on its end tile (if it's a station) and it
   388 		 * exactly once, on its end tile (if it's a station) and it
   388 		 * will therefore not make a difference. */
   389 		 * will therefore not make a difference. */
   389 		cost += _patches.npf_rail_station_penalty;
   390 		cost += _patches.npf_rail_station_penalty;
   390 	}
   391 	}
   391 
   392 
   392 	#ifdef NPF_MARKROUTE
   393 #ifdef NPF_MARKROUTE
   393 	NPFMarkTile(tile);
   394 	NPFMarkTile(tile);
   394 	#endif
   395 #endif
   395 	#ifdef NPF_DEBUG
   396 #ifdef NPF_DEBUG
   396 	debug("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost);
   397 	debug("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost);
   397 	#endif
   398 #endif
   398 	return cost;
   399 	return cost;
   399 }
   400 }
   400 
   401 
   401 /* Will find any depot */
   402 /* Will find any depot */
   402 int32 NPFFindDepot(AyStar* as, AyStarNode *node) {
   403 int32 NPFFindDepot(AyStar* as, AyStarNode *node) {
   459 	int i = 0;
   460 	int i = 0;
   460 	uint trackdirs, ts;
   461 	uint trackdirs, ts;
   461 	TransportType type = aystar->user_data[NPF_TYPE];
   462 	TransportType type = aystar->user_data[NPF_TYPE];
   462 	/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
   463 	/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
   463 	aystar->num_neighbours = 0;
   464 	aystar->num_neighbours = 0;
   464 	#ifdef NPF_DEBUG
   465 #ifdef NPF_DEBUG
   465 	debug("Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile);
   466 	debug("Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile);
   466 	#endif
   467 #endif
   467 
   468 
   468 	/* Find dest tile */
   469 	/* Find dest tile */
   469 	if (IsTileType(src_tile, MP_TUNNELBRIDGE) && (_map5[src_tile] & 0xF0)==0 && (_map5[src_tile] & 3) == src_exitdir) {
   470 	if (IsTileType(src_tile, MP_TUNNELBRIDGE) && (_map5[src_tile] & 0xF0)==0 && (_map5[src_tile] & 3) == src_exitdir) {
   470 		/* This is a tunnel. We know this tunnel is our type,
   471 		/* This is a tunnel. We know this tunnel is our type,
   471 		 * otherwise we wouldn't have got here. It is also facing us,
   472 		 * otherwise we wouldn't have got here. It is also facing us,
   527 	} else {
   528 	} else {
   528 		ts = GetTileTrackStatus(dst_tile, type);
   529 		ts = GetTileTrackStatus(dst_tile, type);
   529 	}
   530 	}
   530 	trackdirs = ts & 0x3F3F; /* Filter out signal status and the unused bits */
   531 	trackdirs = ts & 0x3F3F; /* Filter out signal status and the unused bits */
   531 
   532 
   532 	#ifdef NPF_DEBUG
   533 #ifdef NPF_DEBUG
   533 	debug("Next node: (%d, %d) [%d], possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirs);
   534 	debug("Next node: (%d, %d) [%d], possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirs);
   534 	#endif
   535 #endif
   535 	/* Select only trackdirs we can reach from our current trackdir */
   536 	/* Select only trackdirs we can reach from our current trackdir */
   536 	trackdirs &= _trackdir_reaches_trackdirs[src_trackdir];
   537 	trackdirs &= _trackdir_reaches_trackdirs[src_trackdir];
   537 	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) /* Filter out trackdirs that would make 90 deg turns for trains */
   538 	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) /* Filter out trackdirs that would make 90 deg turns for trains */
   538 		trackdirs &= ~_trackdir_crosses_trackdirs[src_trackdir];
   539 		trackdirs &= ~_trackdir_crosses_trackdirs[src_trackdir];
   539 	#ifdef NPF_DEBUG
   540 #ifdef NPF_DEBUG
   540 	debug("After filtering: (%d, %d), possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), trackdirs);
   541 	debug("After filtering: (%d, %d), possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), trackdirs);
   541 	#endif
   542 #endif
   542 
   543 
   543 	/* Enumerate possible track */
   544 	/* Enumerate possible track */
   544 	while (trackdirs != 0) {
   545 	while (trackdirs != 0) {
   545 		byte dst_trackdir;
   546 		byte dst_trackdir;
   546 		dst_trackdir =  FindFirstBit2x64(trackdirs);
   547 		dst_trackdir =  FindFirstBit2x64(trackdirs);
   547 		trackdirs = KillFirstBit2x64(trackdirs);
   548 		trackdirs = KillFirstBit2x64(trackdirs);
   548 		#ifdef NPF_DEBUG
   549 #ifdef NPF_DEBUG
   549 		debug("Expanded into trackdir: %d, remaining trackdirs: %#x", dst_trackdir, trackdirs);
   550 		debug("Expanded into trackdir: %d, remaining trackdirs: %#x", dst_trackdir, trackdirs);
   550 		#endif
   551 #endif
   551 
   552 
   552 		/* Check for oneway signal against us */
   553 		/* Check for oneway signal against us */
   553 		if (IsTileType(dst_tile, MP_RAILWAY) && (_map5[dst_tile]&0xC0) == 0x40) {
   554 		if (IsTileType(dst_tile, MP_RAILWAY) && (_map5[dst_tile]&0xC0) == 0x40) {
   554 			// the tile has a signal
   555 			// the tile has a signal
   555 			byte signal_present = _map3_lo[dst_tile];
   556 			byte signal_present = _map3_lo[dst_tile];
   779 	return best_result;
   780 	return best_result;
   780 }
   781 }
   781 
   782 
   782 void InitializeNPF(void)
   783 void InitializeNPF(void)
   783 {
   784 {
   784 		init_AyStar(&_npf_aystar, NTPHash, 1024);
   785 	init_AyStar(&_npf_aystar, NTPHash, 1024);
   785 		_npf_aystar.loops_per_tick = 0;
   786 	_npf_aystar.loops_per_tick = 0;
   786 		_npf_aystar.max_path_cost = 0;
   787 	_npf_aystar.max_path_cost = 0;
   787 		_npf_aystar.max_search_nodes = 0;
   788 	_npf_aystar.max_search_nodes = 0;
   788 		/*
   789 #if 0
   789 		init_AyStar(&_train_find_station, NTPHash, 1024);
   790 	init_AyStar(&_train_find_station, NTPHash, 1024);
   790 		init_AyStar(&_train_find_depot, NTPHash, 1024);
   791 	init_AyStar(&_train_find_depot, NTPHash, 1024);
   791 		init_AyStar(&_road_find_station, NTPHash, 1024);
   792 	init_AyStar(&_road_find_station, NTPHash, 1024);
   792 		init_AyStar(&_road_find_depot, NTPHash, 1024);
   793 	init_AyStar(&_road_find_depot, NTPHash, 1024);
   793 
   794 
   794 		_train_find_station.loops_per_tick = 0;
   795 	_train_find_station.loops_per_tick = 0;
   795 		_train_find_depot.loops_per_tick = 0;
   796 	_train_find_depot.loops_per_tick = 0;
   796 		_road_find_station.loops_per_tick = 0;
   797 	_road_find_station.loops_per_tick = 0;
   797 		_road_find_depot.loops_per_tick = 0;
   798 	_road_find_depot.loops_per_tick = 0;
   798 
   799 
   799 		_train_find_station.max_path_cost = 0;
   800 	_train_find_station.max_path_cost = 0;
   800 		_train_find_depot.max_path_cost = 0;
   801 	_train_find_depot.max_path_cost = 0;
   801 		_road_find_station.max_path_cost = 0;
   802 	_road_find_station.max_path_cost = 0;
   802 		_road_find_depot.max_path_cost = 0;
   803 	_road_find_depot.max_path_cost = 0;
   803 
   804 
   804 		_train_find_station.max_search_nodes = 0;
   805 	_train_find_station.max_search_nodes = 0;
   805 		_train_find_depot.max_search_nodes = 0;
   806 	_train_find_depot.max_search_nodes = 0;
   806 		_road_find_station.max_search_nodes = 0;
   807 	_road_find_station.max_search_nodes = 0;
   807 		_road_find_depot.max_search_nodes = 0;
   808 	_road_find_depot.max_search_nodes = 0;
   808 
   809 
   809 		_train_find_station.CalculateG = NPFRailPathCost;
   810 	_train_find_station.CalculateG = NPFRailPathCost;
   810 		_train_find_depot.CalculateG = NPFRailPathCost;
   811 	_train_find_depot.CalculateG = NPFRailPathCost;
   811 		_road_find_station.CalculateG = NPFRoadPathCost;
   812 	_road_find_station.CalculateG = NPFRoadPathCost;
   812 		_road_find_depot.CalculateG = NPFRoadPathCost;
   813 	_road_find_depot.CalculateG = NPFRoadPathCost;
   813 
   814 
   814 		_train_find_station.CalculateH = NPFCalcStationHeuristic;
   815 	_train_find_station.CalculateH = NPFCalcStationHeuristic;
   815 		_train_find_depot.CalculateH = NPFCalcStationHeuristic;
   816 	_train_find_depot.CalculateH = NPFCalcStationHeuristic;
   816 		_road_find_station.CalculateH = NPFCalcStationHeuristic;
   817 	_road_find_station.CalculateH = NPFCalcStationHeuristic;
   817 		_road_find_depot.CalculateH = NPFCalcStationHeuristic;
   818 	_road_find_depot.CalculateH = NPFCalcStationHeuristic;
   818 
   819 
   819 		_train_find_station.EndNodeCheck = NPFFindStationOrTile;
   820 	_train_find_station.EndNodeCheck = NPFFindStationOrTile;
   820 		_train_find_depot.EndNodeCheck = NPFFindStationOrTile;
   821 	_train_find_depot.EndNodeCheck = NPFFindStationOrTile;
   821 		_road_find_station.EndNodeCheck = NPFFindStationOrTile;
   822 	_road_find_station.EndNodeCheck = NPFFindStationOrTile;
   822 		_road_find_depot.EndNodeCheck = NPFFindStationOrTile;
   823 	_road_find_depot.EndNodeCheck = NPFFindStationOrTile;
   823 
   824 
   824 		_train_find_station.FoundEndNode = NPFSaveTargetData;
   825 	_train_find_station.FoundEndNode = NPFSaveTargetData;
   825 		_train_find_depot.FoundEndNode = NPFSaveTargetData;
   826 	_train_find_depot.FoundEndNode = NPFSaveTargetData;
   826 		_road_find_station.FoundEndNode = NPFSaveTargetData;
   827 	_road_find_station.FoundEndNode = NPFSaveTargetData;
   827 		_road_find_depot.FoundEndNode = NPFSaveTargetData;
   828 	_road_find_depot.FoundEndNode = NPFSaveTargetData;
   828 
   829 
   829 		_train_find_station.GetNeighbours = NPFFollowTrack;
   830 	_train_find_station.GetNeighbours = NPFFollowTrack;
   830 		_train_find_depot.GetNeighbours = NPFFollowTrack;
   831 	_train_find_depot.GetNeighbours = NPFFollowTrack;
   831 		_road_find_station.GetNeighbours = NPFFollowTrack;
   832 	_road_find_station.GetNeighbours = NPFFollowTrack;
   832 		_road_find_depot.GetNeighbours = NPFFollowTrack;
   833 	_road_find_depot.GetNeighbours = NPFFollowTrack;
   833 		*/
   834 #endif
   834 }
   835 }
   835 
   836 
   836 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) {
   837 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) {
   837 	/* Ships don't really reach their stations, but the tile in front. So don't
   838 	/* Ships don't really reach their stations, but the tile in front. So don't
   838 	 * save the station id for ships. For roadvehs we don't store it either,
   839 	 * save the station id for ships. For roadvehs we don't store it either,