npf.c
changeset 2006 9d5d7fd428c2
parent 1983 4fcefeef2feb
child 2008 cdb444f6d43c
equal deleted inserted replaced
2005:2fe1516d45c5 2006:9d5d7fd428c2
   232 			if ((_map5[tile] & 0xF0)==0) {
   232 			if ((_map5[tile] & 0xF0)==0) {
   233 				cost = NPFTunnelCost(current);
   233 				cost = NPFTunnelCost(current);
   234 				break;
   234 				break;
   235 			}
   235 			}
   236 			/* Fall through if above if is false, it is a bridge
   236 			/* Fall through if above if is false, it is a bridge
   237 			 * then. We treat that as ordinary rail */
   237 			 * then. We treat that as ordinary road */
   238 		case MP_STREET:
   238 		case MP_STREET:
   239 			cost = NPF_TILE_LENGTH;
   239 			cost = NPF_TILE_LENGTH;
       
   240 			/* Increase the cost for level crossings */
       
   241 			if ((_map5[tile] & 0xF0) == 0x10)
       
   242 				cost += _patches.npf_crossing_penalty;
   240 			break;
   243 			break;
   241 		default:
   244 		default:
   242 			break;
   245 			break;
   243 	}
   246 	}
   244 
   247 
   522 	 * that I can enter the tunnel from a tile below the tunnel entrance. This
   525 	 * that I can enter the tunnel from a tile below the tunnel entrance. This
   523 	 * solves the problem of vehicles wanting to drive off a tunnel entrance */
   526 	 * solves the problem of vehicles wanting to drive off a tunnel entrance */
   524 	if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && (_map5[dst_tile] & 0xF0) == 0 && GetTileZ(dst_tile) < GetTileZ(src_tile))
   527 	if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && (_map5[dst_tile] & 0xF0) == 0 && GetTileZ(dst_tile) < GetTileZ(src_tile))
   525 		return;
   528 		return;
   526 
   529 
   527 	/* check correct rail type (mono, maglev, etc)
   530 	/* check correct rail type (mono, maglev, etc) */
   528 	 * XXX: This now compares with the previous tile, which should not pose a
       
   529 	 * problem, but it might be nicer to compare with the first tile, or even
       
   530 	 * the type of the vehicle... Maybe an NPF_RAILTYPE userdata sometime? */
       
   531 	if (type == TRANSPORT_RAIL) {
   531 	if (type == TRANSPORT_RAIL) {
   532 		RailType src_type = GetTileRailType(src_tile, src_trackdir);
   532 		RailType dst_type = GetTileRailType(dst_tile, src_trackdir);
   533 		RailType dst_type = GetTileRailType(dst_tile, TrackdirToExitdir(src_trackdir));
   533 		if (!IsCompatibleRail(aystar->user_data[NPF_RAILTYPE], dst_type))
   534 		if (src_type != dst_type) {
       
   535 			return;
   534 			return;
   536 		}
       
   537 	}
   535 	}
   538 
   536 
   539 	/* Check the owner of the tile */
   537 	/* Check the owner of the tile */
   540 	if (!VehicleMayEnterTile(aystar->user_data[NPF_OWNER], dst_tile, TrackdirToExitdir(src_trackdir))) {
   538 	if (!VehicleMayEnterTile(aystar->user_data[NPF_OWNER], dst_tile, TrackdirToExitdir(src_trackdir))) {
   541 		return;
   539 		return;
   602  * When we are looking for one specific target (optionally multiple tiles), we
   600  * When we are looking for one specific target (optionally multiple tiles), we
   603  * should use a good heuristic to perform aystar search. When we search for
   601  * should use a good heuristic to perform aystar search. When we search for
   604  * multiple targets that are spread around, we should perform a breadth first
   602  * multiple targets that are spread around, we should perform a breadth first
   605  * search by specifiying CalcZero as our heuristic.
   603  * search by specifiying CalcZero as our heuristic.
   606  */
   604  */
   607 static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, uint reverse_penalty)
   605 static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailType railtype, uint reverse_penalty)
   608 {
   606 {
   609 	int r;
   607 	int r;
   610 	NPFFoundTargetData result;
   608 	NPFFoundTargetData result;
   611 
   609 
   612 	/* Initialize procs */
   610 	/* Initialize procs */
   644 	_npf_aystar.user_target = target;
   642 	_npf_aystar.user_target = target;
   645 
   643 
   646 	/* Initialize user_data */
   644 	/* Initialize user_data */
   647 	_npf_aystar.user_data[NPF_TYPE] = type;
   645 	_npf_aystar.user_data[NPF_TYPE] = type;
   648 	_npf_aystar.user_data[NPF_OWNER] = owner;
   646 	_npf_aystar.user_data[NPF_OWNER] = owner;
       
   647 	_npf_aystar.user_data[NPF_RAILTYPE] = railtype;
   649 
   648 
   650 	/* GO! */
   649 	/* GO! */
   651 	r = AyStarMain_Main(&_npf_aystar);
   650 	r = AyStarMain_Main(&_npf_aystar);
   652 	assert(r != AYSTAR_STILL_BUSY);
   651 	assert(r != AYSTAR_STILL_BUSY);
   653 
   652 
   661 
   660 
   662 	}
   661 	}
   663 	return result;
   662 	return result;
   664 }
   663 }
   665 
   664 
   666 NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner)
   665 NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype)
   667 {
   666 {
   668 	AyStarNode start1;
   667 	AyStarNode start1;
   669 	AyStarNode start2;
   668 	AyStarNode start2;
   670 
   669 
   671 	start1.tile = tile1;
   670 	start1.tile = tile1;
   675 	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   674 	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   676 	start1.direction = trackdir1;
   675 	start1.direction = trackdir1;
   677 	start2.direction = trackdir2;
   676 	start2.direction = trackdir2;
   678 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   677 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   679 
   678 
   680 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, 0);
   679 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtype, 0);
   681 }
   680 }
   682 
   681 
   683 NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner)
   682 NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype)
   684 {
   683 {
   685 	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner);
   684 	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtype);
   686 }
   685 }
   687 
   686 
   688 NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, uint reverse_penalty)
   687 NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty)
   689 {
   688 {
   690 	AyStarNode start1;
   689 	AyStarNode start1;
   691 	AyStarNode start2;
   690 	AyStarNode start2;
   692 
   691 
   693 	start1.tile = tile1;
   692 	start1.tile = tile1;
   699 	start2.direction = trackdir2;
   698 	start2.direction = trackdir2;
   700 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   699 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   701 
   700 
   702 	/* perform a breadth first search. Target is NULL,
   701 	/* perform a breadth first search. Target is NULL,
   703 	 * since we are just looking for any depot...*/
   702 	 * since we are just looking for any depot...*/
   704 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, reverse_penalty);
   703 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtype, reverse_penalty);
   705 }
   704 }
   706 
   705 
   707 NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner)
   706 NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype)
   708 {
   707 {
   709 	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, 0);
   708 	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtype, 0);
   710 }
   709 }
   711 
   710 
   712 NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner)
   711 NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype)
   713 {
   712 {
   714 	/* Okay, what we're gonna do. First, we look at all depots, calculate
   713 	/* Okay, what we're gonna do. First, we look at all depots, calculate
   715 	 * the manhatten distance to get to each depot. We then sort them by
   714 	 * the manhatten distance to get to each depot. We then sort them by
   716 	 * distance. We start by trying to plan a route to the closest, then
   715 	 * distance. We start by trying to plan a route to the closest, then
   717 	 * the next closest, etc. We stop when the best route we have found so
   716 	 * the next closest, etc. We stop when the best route we have found so