src/npf.cpp
branchnoai
changeset 9732 f8eb3e208514
parent 9724 b39bc69bb2f2
child 9837 c9ec4f82e0d0
equal deleted inserted replaced
9731:9b1552d0fd9b 9732:f8eb3e208514
   455 
   455 
   456 /**
   456 /**
   457  * Finds out if a given player's vehicles are allowed to enter a given tile.
   457  * Finds out if a given player's vehicles are allowed to enter a given tile.
   458  * @param owner    The owner of the vehicle.
   458  * @param owner    The owner of the vehicle.
   459  * @param tile     The tile that is about to be entered.
   459  * @param tile     The tile that is about to be entered.
   460  * @param enterdir The direction from which the vehicle wants to enter the tile.
   460  * @param enterdir The direction in which the vehicle wants to enter the tile.
   461  * @return         true if the vehicle can enter the tile.
   461  * @return         true if the vehicle can enter the tile.
   462  * @todo           This function should be used in other places than just NPF,
   462  * @todo           This function should be used in other places than just NPF,
   463  *                 maybe moved to another file too.
   463  *                 maybe moved to another file too.
   464  */
   464  */
   465 static bool VehicleMayEnterTile(Owner owner, TileIndex tile, DiagDirection enterdir)
   465 static bool CanEnterTileOwnerCheck(Owner owner, TileIndex tile, DiagDirection enterdir)
   466 {
   466 {
   467 	if (IsTileType(tile, MP_RAILWAY) ||           /* Rail tile (also rail depot) */
   467 	if (IsTileType(tile, MP_RAILWAY) ||           /* Rail tile (also rail depot) */
   468 			IsRailwayStationTile(tile) ||               /* Rail station tile */
   468 			IsRailwayStationTile(tile) ||               /* Rail station tile */
   469 			IsTileDepotType(tile, TRANSPORT_ROAD) ||  /* Road depot tile */
   469 			IsTileDepotType(tile, TRANSPORT_ROAD) ||  /* Road depot tile */
   470 			IsStandardRoadStopTile(tile) || /* Road station tile (but not drive-through stops) */
   470 			IsStandardRoadStopTile(tile)) { /* Road station tile (but not drive-through stops) */
   471 			IsTileDepotType(tile, TRANSPORT_WATER)) { /* Water depot tile */
       
   472 		return IsTileOwner(tile, owner); /* You need to own these tiles entirely to use them */
   471 		return IsTileOwner(tile, owner); /* You need to own these tiles entirely to use them */
   473 	}
   472 	}
   474 
   473 
   475 	switch (GetTileType(tile)) {
   474 	switch (GetTileType(tile)) {
   476 		case MP_ROAD:
   475 		case MP_ROAD:
   508 		case TRANSPORT_WATER: return GetShipDepotDirection(tile);
   507 		case TRANSPORT_WATER: return GetShipDepotDirection(tile);
   509 		default: return INVALID_DIAGDIR; /* Not reached */
   508 		default: return INVALID_DIAGDIR; /* Not reached */
   510 	}
   509 	}
   511 }
   510 }
   512 
   511 
       
   512 /** Tests if a tile is a road tile with a single tramtrack (tram can reverse) */
       
   513 static DiagDirection GetSingleTramBit(TileIndex tile)
       
   514 {
       
   515 	if (IsNormalRoadTile(tile)) {
       
   516 		RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
       
   517 		switch (rb) {
       
   518 			case ROAD_NW: return DIAGDIR_NW;
       
   519 			case ROAD_SW: return DIAGDIR_SW;
       
   520 			case ROAD_SE: return DIAGDIR_SE;
       
   521 			case ROAD_NE: return DIAGDIR_NE;
       
   522 			default: break;
       
   523 		}
       
   524 	}
       
   525 	return INVALID_DIAGDIR;
       
   526 }
       
   527 
       
   528 /**
       
   529  * Tests if a tile can be entered or left only from one side.
       
   530  *
       
   531  * Depots, non-drive-through roadstops, and tiles with single trambits are tested.
       
   532  *
       
   533  * @param tile The tile of interest.
       
   534  * @param type The transporttype of the vehicle.
       
   535  * @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
       
   536  * @return The single entry/exit-direction of the tile, or INVALID_DIAGDIR if there are more or less directions
       
   537  */
       
   538 static DiagDirection GetTileSingleEntry(TileIndex tile, TransportType type, uint subtype)
       
   539 {
       
   540 	if (type != TRANSPORT_WATER && IsTileDepotType(tile, type)) return GetDepotDirection(tile, type);
       
   541 
       
   542 	if (type == TRANSPORT_ROAD) {
       
   543 		if (IsStandardRoadStopTile(tile)) return GetRoadStopDir(tile);
       
   544 		if (HasBit(subtype, ROADTYPE_TRAM)) return GetSingleTramBit(tile);
       
   545 	}
       
   546 
       
   547 	return INVALID_DIAGDIR;
       
   548 }
       
   549 
       
   550 /**
       
   551  * Tests if a vehicle must reverse on a tile.
       
   552  *
       
   553  * @param tile The tile of interest.
       
   554  * @param dir The direction in which the vehicle drives on a tile.
       
   555  * @param type The transporttype of the vehicle.
       
   556  * @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
       
   557  * @return true iff the vehicle must reverse on the tile.
       
   558  */
       
   559 static inline bool ForceReverse(TileIndex tile, DiagDirection dir, TransportType type, uint subtype)
       
   560 {
       
   561 	DiagDirection single_entry = GetTileSingleEntry(tile, type, subtype);
       
   562 	return single_entry != INVALID_DIAGDIR && single_entry != dir;
       
   563 }
       
   564 
       
   565 /**
       
   566  * Tests if a vehicle can enter a tile.
       
   567  *
       
   568  * @param tile The tile of interest.
       
   569  * @param dir The direction in which the vehicle drives onto a tile.
       
   570  * @param type The transporttype of the vehicle.
       
   571  * @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
       
   572  * @param railtypes For TRANSPORT_RAIL the compatible RailTypes of the vehicle.
       
   573  * @param owner The owner of the vehicle.
       
   574  * @return true iff the vehicle can enter the tile.
       
   575  */
       
   576 static bool CanEnterTile(TileIndex tile, DiagDirection dir, TransportType type, uint subtype, RailTypes railtypes, Owner owner)
       
   577 {
       
   578 	/* Check tunnel entries and bridge ramps */
       
   579 	if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(tile) != dir) return false;
       
   580 
       
   581 	/* Test ownership */
       
   582 	if (!CanEnterTileOwnerCheck(owner, tile, dir)) return false;
       
   583 
       
   584 	/* check correct rail type (mono, maglev, etc) */
       
   585 	if (type == TRANSPORT_RAIL) {
       
   586 		RailType rail_type = GetTileRailType(tile);
       
   587 		if (!HasBit(railtypes, rail_type)) return false;
       
   588 	}
       
   589 
       
   590 	/* Depots, standard roadstops and single tram bits can only be entered from one direction */
       
   591 	DiagDirection single_entry = GetTileSingleEntry(tile, type, subtype);
       
   592 	if (single_entry != INVALID_DIAGDIR && single_entry != ReverseDiagDir(dir)) return false;
       
   593 
       
   594 	return true;
       
   595 }
       
   596 
       
   597 /**
       
   598  * Returns the driveable Trackdirs on a tile.
       
   599  *
       
   600  * One-way-roads are taken into account. Signals are not tested.
       
   601  *
       
   602  * @param dst_tile The tile of interest.
       
   603  * @param src_trackdir The direction the vehicle is currently moving.
       
   604  * @param type The transporttype of the vehicle.
       
   605  * @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
       
   606  * @return The Trackdirs the vehicle can continue moving on.
       
   607  */
       
   608 static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_trackdir, TransportType type, uint subtype)
       
   609 {
       
   610 	TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype));
       
   611 
       
   612 	if (trackdirbits == 0 && type == TRANSPORT_ROAD && HasBit(subtype, ROADTYPE_TRAM)) {
       
   613 		/* GetTileTrackStatus() returns 0 for single tram bits.
       
   614 		 * As we cannot change it there (easily) without breaking something, change it here */
       
   615 		switch (GetSingleTramBit(dst_tile)) {
       
   616 			case DIAGDIR_NE:
       
   617 			case DIAGDIR_SW:
       
   618 				trackdirbits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW;
       
   619 				break;
       
   620 
       
   621 			case DIAGDIR_NW:
       
   622 			case DIAGDIR_SE:
       
   623 				trackdirbits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE;
       
   624 				break;
       
   625 
       
   626 			default: break;
       
   627 		}
       
   628 	}
       
   629 
       
   630 	DEBUG(npf, 4, "Next node: (%d, %d) [%d], possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirbits);
       
   631 
       
   632 	/* Select only trackdirs we can reach from our current trackdir */
       
   633 	trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
       
   634 
       
   635 	/* Filter out trackdirs that would make 90 deg turns for trains */
       
   636 	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
       
   637 
       
   638 	DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);
       
   639 
       
   640 	return trackdirbits;
       
   641 }
       
   642 
   513 
   643 
   514 /* Will just follow the results of GetTileTrackStatus concerning where we can
   644 /* Will just follow the results of GetTileTrackStatus concerning where we can
   515  * go and where not. Uses AyStar.user_data[NPF_TYPE] as the transport type and
   645  * go and where not. Uses AyStar.user_data[NPF_TYPE] as the transport type and
   516  * an argument to GetTileTrackStatus. Will skip tunnels, meaning that the
   646  * an argument to GetTileTrackStatus. Will skip tunnels, meaning that the
   517  * entry and exit are neighbours. Will fill
   647  * entry and exit are neighbours. Will fill
   518  * AyStarNode.user_data[NPF_TRACKDIR_CHOICE] with an appropriate value, and
   648  * AyStarNode.user_data[NPF_TRACKDIR_CHOICE] with an appropriate value, and
   519  * copy AyStarNode.user_data[NPF_NODE_FLAGS] from the parent */
   649  * copy AyStarNode.user_data[NPF_NODE_FLAGS] from the parent */
   520 static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
   650 static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
   521 {
   651 {
       
   652 	/* We leave src_tile on track src_trackdir in direction src_exitdir */
   522 	Trackdir src_trackdir = (Trackdir)current->path.node.direction;
   653 	Trackdir src_trackdir = (Trackdir)current->path.node.direction;
   523 	TileIndex src_tile = current->path.node.tile;
   654 	TileIndex src_tile = current->path.node.tile;
   524 	DiagDirection src_exitdir = TrackdirToExitdir(src_trackdir);
   655 	DiagDirection src_exitdir = TrackdirToExitdir(src_trackdir);
   525 	TileIndex dst_tile = INVALID_TILE;
   656 
   526 	int i;
   657 	/* Is src_tile valid, and can be used?
   527 	uint32 ts;
   658 	 * When choosing track on a junction src_tile is the tile neighboured to the junction wrt. exitdir.
   528 	TrackdirBits trackdirbits;
   659 	 * But we must not check the validity of this move, as src_tile is totally unrelated to the move, if a roadvehicle reversed on a junction. */
       
   660 	bool ignore_src_tile = (current->path.parent == NULL && NPFGetFlag(&current->path.node, NPF_FLAG_IGNORE_START_TILE));
       
   661 
       
   662 	/* Information about the vehicle: TransportType (road/rail/water) and SubType (compatible rail/road types) */
   529 	TransportType type = (TransportType)aystar->user_data[NPF_TYPE];
   663 	TransportType type = (TransportType)aystar->user_data[NPF_TYPE];
   530 	uint subtype = aystar->user_data[NPF_SUB_TYPE];
   664 	uint subtype = aystar->user_data[NPF_SUB_TYPE];
   531 	bool override_dst_check = false;
   665 
   532 	/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
   666 	/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
   533 	aystar->num_neighbours = 0;
   667 	aystar->num_neighbours = 0;
   534 	DEBUG(npf, 4, "Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile);
   668 	DEBUG(npf, 4, "Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile);
   535 
   669 
       
   670 	/* We want to determine the tile we arrive, and which choices we have there */
       
   671 	TileIndex dst_tile;
       
   672 	TrackdirBits trackdirbits;
       
   673 
   536 	/* Find dest tile */
   674 	/* Find dest tile */
   537 	if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(src_tile) == src_exitdir) {
   675 	if (ignore_src_tile) {
   538 		/* This is a tunnel/bridge. We know this tunnel/bridge is our type,
   676 		/* Do not perform any checks that involve src_tile */
   539 		 * otherwise we wouldn't have got here. It is also facing us,
   677 		dst_tile = src_tile + TileOffsByDiagDir(src_exitdir);
   540 		 * so we should skip it's body */
   678 		trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype);
       
   679 	} else if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(src_tile) == src_exitdir) {
       
   680 		/* We drive through the wormhole and arrive on the other side */
   541 		dst_tile = GetOtherTunnelBridgeEnd(src_tile);
   681 		dst_tile = GetOtherTunnelBridgeEnd(src_tile);
   542 		override_dst_check = true;
   682 		trackdirbits = TrackdirToTrackdirBits(src_trackdir);
   543 	} else if (type != TRANSPORT_WATER && (IsStandardRoadStopTile(src_tile) || IsTileDepotType(src_tile, type))) {
   683 	} else if (ForceReverse(src_tile, src_exitdir, type, subtype)) {
   544 		/* This is a road station (non drive-through) or a train or road depot. We can enter and exit
   684 		/* We can only reverse on this tile */
   545 		 * those from one side only. Trackdirs don't support that (yet), so we'll
   685 		dst_tile = src_tile;
   546 		 * do this here. */
   686 		src_trackdir = ReverseTrackdir(src_trackdir);
   547 
   687 		trackdirbits = TrackdirToTrackdirBits(src_trackdir);
   548 		DiagDirection exitdir;
   688 	} else {
   549 		/* Find out the exit direction first */
   689 		/* We leave src_tile in src_exitdir and reach dst_tile */
   550 		if (IsRoadStopTile(src_tile)) {
   690 		dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(src_exitdir));
   551 			exitdir = GetRoadStopDir(src_tile);
   691 
   552 		} else { // Train or road depot
   692 		if (dst_tile != INVALID_TILE && !CanEnterTile(dst_tile, src_exitdir, type, subtype, (RailTypes)aystar->user_data[NPF_RAILTYPES], (Owner)aystar->user_data[NPF_OWNER])) dst_tile = INVALID_TILE;
   553 			exitdir = GetDepotDirection(src_tile, type);
   693 
       
   694 		if (dst_tile == INVALID_TILE) {
       
   695 			/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
       
   696 			if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return;
       
   697 
       
   698 			dst_tile = src_tile;
       
   699 			src_trackdir = ReverseTrackdir(src_trackdir);
   554 		}
   700 		}
   555 
   701 
   556 		/* Let's see if were headed the right way into the depot */
   702 		trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype);
   557 		if (src_trackdir == DiagdirToDiagTrackdir(ReverseDiagDir(exitdir))) {
   703 
   558 			/* We are headed inwards. We cannot go through the back of the depot.
   704 		if (trackdirbits == 0) {
   559 			 * For rail, we can now reverse. Reversing for road vehicles is never
   705 			/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
   560 			 * useful, since you cannot take paths you couldn't take before
   706 			if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return;
   561 			 * reversing (as with rail). */
   707 
   562 			if (type == TRANSPORT_RAIL) {
   708 			dst_tile = src_tile;
   563 				/* We can only reverse here, so we'll not consider this direction, but
   709 			src_trackdir = ReverseTrackdir(src_trackdir);
   564 				 * jump ahead to the reverse direction.  It would be nicer to return
   710 
   565 				 * one neighbour here (the reverse trackdir of the one we are
   711 			trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype);
   566 				 * considering now) and then considering that one to return the tracks
       
   567 				 * outside of the depot. But, because the code layout is cleaner this
       
   568 				 * way, we will just pretend we are reversed already */
       
   569 				src_trackdir = ReverseTrackdir(src_trackdir);
       
   570 				dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(exitdir));
       
   571 			} else {
       
   572 				dst_tile = INVALID_TILE; /* Road vehicle heading inwards: dead end */
       
   573 			}
       
   574 		} else {
       
   575 			dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(exitdir));
       
   576 		}
   712 		}
   577 	} else {
   713 	}
   578 		/* This a normal tile, a bridge, a tunnel exit, etc. */
   714 
   579 		dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(TrackdirToExitdir(src_trackdir)));
       
   580 	}
       
   581 	if (dst_tile == INVALID_TILE) {
       
   582 		/* We reached the border of the map */
       
   583 		/* TODO Nicer control flow for this */
       
   584 		return;
       
   585 	}
       
   586 
       
   587 	/* I can't enter a tunnel entry/exit tile from a tile above the tunnel. Note
       
   588 	 * that I can enter the tunnel from a tile below the tunnel entrance. This
       
   589 	 * solves the problem of vehicles wanting to drive off a tunnel entrance */
       
   590 	if (!override_dst_check && IsTileType(dst_tile, MP_TUNNELBRIDGE) &&
       
   591 			GetTunnelBridgeDirection(dst_tile) != src_exitdir) {
       
   592 		return;
       
   593 	}
       
   594 
       
   595 	/* check correct rail type (mono, maglev, etc) */
       
   596 	if (type == TRANSPORT_RAIL) {
       
   597 		RailType dst_type = GetTileRailType(dst_tile);
       
   598 		if (!HasBit(aystar->user_data[NPF_RAILTYPES], dst_type))
       
   599 			return;
       
   600 	}
       
   601 
       
   602 	/* Check the owner of the tile */
       
   603 	if (!VehicleMayEnterTile((Owner)aystar->user_data[NPF_OWNER], dst_tile, TrackdirToExitdir(src_trackdir))) {
       
   604 		return;
       
   605 	}
       
   606 
       
   607 	/* Determine available tracks */
       
   608 	if (type != TRANSPORT_WATER && (IsStandardRoadStopTile(dst_tile) || IsTileDepotType(dst_tile, type))){
       
   609 		/* Road stations and road and train depots return 0 on GTTS, so we have to do this by hand... */
       
   610 		DiagDirection exitdir;
       
   611 		if (IsRoadStopTile(dst_tile)) {
       
   612 			exitdir = GetRoadStopDir(dst_tile);
       
   613 		} else { // Road or train depot
       
   614 			exitdir = GetDepotDirection(dst_tile, type);
       
   615 		}
       
   616 		/* Find the trackdirs that are available for a depot or station with this
       
   617 		 * orientation. They are only "inwards", since we are reaching this tile
       
   618 		 * from some other tile. This prevents vehicles driving into depots from
       
   619 		 * the back */
       
   620 		ts = TrackdirToTrackdirBits(DiagdirToDiagTrackdir(ReverseDiagDir(exitdir)));
       
   621 	} else {
       
   622 		ts = GetTileTrackStatus(dst_tile, type, subtype);
       
   623 	}
       
   624 	trackdirbits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK); /* Filter out signal status and the unused bits */
       
   625 
       
   626 	DEBUG(npf, 4, "Next node: (%d, %d) [%d], possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirbits);
       
   627 	/* Select only trackdirs we can reach from our current trackdir */
       
   628 	trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
       
   629 	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) /* Filter out trackdirs that would make 90 deg turns for trains */
       
   630 		trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
       
   631 
       
   632 	DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);
       
   633 
       
   634 	i = 0;
       
   635 	/* Enumerate possible track */
   715 	/* Enumerate possible track */
       
   716 	uint i = 0;
   636 	while (trackdirbits != 0) {
   717 	while (trackdirbits != 0) {
   637 		Trackdir dst_trackdir = RemoveFirstTrackdir(&trackdirbits);
   718 		Trackdir dst_trackdir = RemoveFirstTrackdir(&trackdirbits);
   638 		DEBUG(npf, 5, "Expanded into trackdir: %d, remaining trackdirs: 0x%X", dst_trackdir, trackdirbits);
   719 		DEBUG(npf, 5, "Expanded into trackdir: %d, remaining trackdirs: 0x%X", dst_trackdir, trackdirbits);
   639 
   720 
   640 		/* Check for oneway signal against us */
   721 		/* Check for oneway signal against us */
   665  * When we are looking for one specific target (optionally multiple tiles), we
   746  * When we are looking for one specific target (optionally multiple tiles), we
   666  * should use a good heuristic to perform aystar search. When we search for
   747  * should use a good heuristic to perform aystar search. When we search for
   667  * multiple targets that are spread around, we should perform a breadth first
   748  * multiple targets that are spread around, we should perform a breadth first
   668  * search by specifiying CalcZero as our heuristic.
   749  * search by specifiying CalcZero as our heuristic.
   669  */
   750  */
   670 static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, uint sub_type, Owner owner, RailTypes railtypes, uint reverse_penalty)
   751 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)
   671 {
   752 {
   672 	int r;
   753 	int r;
   673 	NPFFoundTargetData result;
   754 	NPFFoundTargetData result;
   674 
   755 
   675 	/* Initialize procs */
   756 	/* Initialize procs */
   685 	}
   766 	}
   686 
   767 
   687 	/* Initialize Start Node(s) */
   768 	/* Initialize Start Node(s) */
   688 	start1->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   769 	start1->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   689 	start1->user_data[NPF_NODE_FLAGS] = 0;
   770 	start1->user_data[NPF_NODE_FLAGS] = 0;
       
   771 	NPFSetFlag(start1, NPF_FLAG_IGNORE_START_TILE, ignore_start_tile1);
   690 	_npf_aystar.addstart(&_npf_aystar, start1, 0);
   772 	_npf_aystar.addstart(&_npf_aystar, start1, 0);
   691 	if (start2) {
   773 	if (start2) {
   692 		start2->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   774 		start2->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   693 		start2->user_data[NPF_NODE_FLAGS] = 0;
   775 		start2->user_data[NPF_NODE_FLAGS] = 0;
       
   776 		NPFSetFlag(start2, NPF_FLAG_IGNORE_START_TILE, ignore_start_tile2);
   694 		NPFSetFlag(start2, NPF_FLAG_REVERSE, true);
   777 		NPFSetFlag(start2, NPF_FLAG_REVERSE, true);
   695 		_npf_aystar.addstart(&_npf_aystar, start2, reverse_penalty);
   778 		_npf_aystar.addstart(&_npf_aystar, start2, reverse_penalty);
   696 	}
   779 	}
   697 
   780 
   698 	/* Initialize result */
   781 	/* Initialize result */
   724 
   807 
   725 	}
   808 	}
   726 	return result;
   809 	return result;
   727 }
   810 }
   728 
   811 
   729 NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   812 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)
   730 {
   813 {
   731 	AyStarNode start1;
   814 	AyStarNode start1;
   732 	AyStarNode start2;
   815 	AyStarNode start2;
   733 
   816 
   734 	start1.tile = tile1;
   817 	start1.tile = tile1;
   738 	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   821 	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   739 	start1.direction = trackdir1;
   822 	start1.direction = trackdir1;
   740 	start2.direction = trackdir2;
   823 	start2.direction = trackdir2;
   741 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   824 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   742 
   825 
   743 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, sub_type, owner, railtypes, 0);
   826 	return NPFRouteInternal(&start1, ignore_start_tile1, (IsValidTile(tile2) ? &start2 : NULL), ignore_start_tile2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, sub_type, owner, railtypes, 0);
   744 }
   827 }
   745 
   828 
   746 NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   829 NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   747 {
   830 {
   748 	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, target, type, sub_type, owner, railtypes);
   831 	return NPFRouteToStationOrTileTwoWay(tile, trackdir, ignore_start_tile, INVALID_TILE, INVALID_TRACKDIR, false, target, type, sub_type, owner, railtypes);
   749 }
   832 }
   750 
   833 
   751 NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypes railtypes, uint reverse_penalty)
   834 NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, bool ignore_start_tile1, TileIndex tile2, Trackdir trackdir2, bool ignore_start_tile2, TransportType type, uint sub_type, Owner owner, RailTypes railtypes, uint reverse_penalty)
   752 {
   835 {
   753 	AyStarNode start1;
   836 	AyStarNode start1;
   754 	AyStarNode start2;
   837 	AyStarNode start2;
   755 
   838 
   756 	start1.tile = tile1;
   839 	start1.tile = tile1;
   762 	start2.direction = trackdir2;
   845 	start2.direction = trackdir2;
   763 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   846 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   764 
   847 
   765 	/* perform a breadth first search. Target is NULL,
   848 	/* perform a breadth first search. Target is NULL,
   766 	 * since we are just looking for any depot...*/
   849 	 * since we are just looking for any depot...*/
   767 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, sub_type, owner, railtypes, reverse_penalty);
   850 	return NPFRouteInternal(&start1, ignore_start_tile1, (IsValidTile(tile2) ? &start2 : NULL), ignore_start_tile2, NULL, NPFFindDepot, NPFCalcZero, type, sub_type, owner, railtypes, reverse_penalty);
   768 }
   851 }
   769 
   852 
   770 NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   853 NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   771 {
   854 {
   772 	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, type, sub_type, owner, railtypes, 0);
   855 	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, ignore_start_tile, INVALID_TILE, INVALID_TRACKDIR, false, type, sub_type, owner, railtypes, 0);
   773 }
   856 }
   774 
   857 
   775 NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   858 NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
   776 {
   859 {
   777 	/* Okay, what we're gonna do. First, we look at all depots, calculate
   860 	/* Okay, what we're gonna do. First, we look at all depots, calculate
   778 	 * the manhatten distance to get to each depot. We then sort them by
   861 	 * the manhatten distance to get to each depot. We then sort them by
   779 	 * distance. We start by trying to plan a route to the closest, then
   862 	 * distance. We start by trying to plan a route to the closest, then
   780 	 * the next closest, etc. We stop when the best route we have found so
   863 	 * the next closest, etc. We stop when the best route we have found so
   845 		/* Initialize Start Node */
   928 		/* Initialize Start Node */
   846 		/* We set this in case the target is also the start tile, we will just
   929 		/* We set this in case the target is also the start tile, we will just
   847 		 * return a not found then */
   930 		 * return a not found then */
   848 		start.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   931 		start.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
   849 		start.user_data[NPF_NODE_FLAGS] = 0;
   932 		start.user_data[NPF_NODE_FLAGS] = 0;
       
   933 		NPFSetFlag(&start, NPF_FLAG_IGNORE_START_TILE, ignore_start_tile);
   850 		_npf_aystar.addstart(&_npf_aystar, &start, 0);
   934 		_npf_aystar.addstart(&_npf_aystar, &start, 0);
   851 
   935 
   852 		/* Initialize result */
   936 		/* Initialize result */
   853 		result.best_bird_dist = (uint)-1;
   937 		result.best_bird_dist = (uint)-1;
   854 		result.best_path_dist = (uint)-1;
   938 		result.best_path_dist = (uint)-1;