Changeset - r1777:6d7bf202b4ef
[Not reviewed]
master
0 8 0
matthijs - 20 years ago 2005-05-07 22:00:36
matthijs@openttd.org
(svn r2281) - Fix: [ 1115204 ] [NPF] When pressing the goto depot button, trains will now also look behind it if there is no depot in front. If so, the train reverses immediately. This also work anywhere, not just at stations.
- Add: [NPF] Reversing inside of depots now has a penalty. It also applies to trains only, other vehicles shouldn't bother reversing.
- Fix: [NPF] When checking whether to reverse a train, the trackdir of the first loc was used instead of the last vehicle as a starting node for pathfindig.
This might have caused some trains not reversing when they should have (or vice versa). Typo introduced when converting to GetVehicleTrackdir() in r2256.
- CodeChange: [NPF] Removed duplicate code by letting NPFRouteTjoStationOrTile() call NPFRouteToStationOrTileTwoWay().
- Add: [NPF] NPFRouteToDepotBreadthFirstTwoWay() to find a depot while also looking backwards.
- Add: It is now possibly to specify a path cost for aystar starting nodes.
8 files changed with 96 insertions and 38 deletions:
0 comments (0 inline, 0 general)
ai_pathfinder.c
Show inline comments
 
@@ -113,13 +113,13 @@ AyStar *new_AyStar_AiPathFinder(int max_
 
	start_node.node.user_data[0] = 0;
 

	
 
	// Now we add all the starting tiles
 
	for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
 
		for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
 
			start_node.node.tile = TILE_XY(x, y);
 
			result->addstart(result, &start_node.node);
 
			result->addstart(result, &start_node.node, 0);
 
		}
 
	}
 

	
 
	return result;
 
}
 

	
 
@@ -144,13 +144,13 @@ void clean_AyStar_AiPathFinder(AyStar *a
 
	// Now we add all the starting tiles
 
	for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
 
		for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
 
			if (!(IsTileType(TILE_XY(x, y), MP_CLEAR) || IsTileType(TILE_XY(x, y), MP_TREES))) continue;
 
			if (!TestCanBuildStationHere(TILE_XY(x, y), TEST_STATION_NO_DIR)) continue;
 
			start_node.node.tile = TILE_XY(x, y);
 
			aystar->addstart(aystar, &start_node.node);
 
			aystar->addstart(aystar, &start_node.node, 0);
 
		}
 
	}
 
}
 

	
 
// The h-value, simple calculation
 
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
aystar.c
Show inline comments
 
@@ -53,13 +53,13 @@ static OpenListNode *AyStarMain_OpenList
 

	
 
	return res;
 
}
 

	
 
// Adds a node to the OpenList
 
//  It makes a copy of node, and puts the pointer of parent in the struct
 
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g, int userdata)
 
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g)
 
{
 
	// Add a new Node to the OpenList
 
	OpenListNode* new_node = malloc(sizeof(OpenListNode));
 
	new_node->g = g;
 
	new_node->path.parent = parent;
 
	new_node->path.node = *node;
 
@@ -117,13 +117,13 @@ int AyStarMain_CheckTile(AyStar *aystar,
 
		for (i=0;i<lengthof(current->user_data);i++)
 
			check->path.node.user_data[i] = current->user_data[i];
 
		// Readd him in the OpenListQueue
 
		aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
 
	} else {
 
		// A new node, add him to the OpenList
 
		AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g, 0);
 
		AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g);
 
	}
 

	
 
	return AYSTAR_DONE;
 
}
 

	
 
/*
 
@@ -245,19 +245,20 @@ int AyStarMain_Main(AyStar *aystar) {
 

	
 
/*
 
 * Adds a node from where to start an algorithm. Multiple nodes can be added
 
 * if wanted. You should make sure that clear() is called before adding nodes
 
 * if the AyStar has been used before (though the normal main loop calls
 
 * clear() automatically when the algorithm finishes
 
 * g is the cost for starting with this node.
 
 */
 
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node) {
 
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g) {
 
#ifdef AYSTAR_DEBUG
 
	printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n",
 
		TileX(start_node->tile), TileY(start_node->tile), start_node->direction);
 
#endif
 
	AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, 0, 0);
 
	AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, g);
 
}
 

	
 
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {
 
	// Allocated the Hash for the OpenList and ClosedList
 
	init_Hash(&aystar->OpenListHash, hash, num_buckets);
 
	init_Hash(&aystar->ClosedListHash, hash, num_buckets);
aystar.h
Show inline comments
 
@@ -94,13 +94,13 @@ typedef void AyStar_GetNeighbours(AyStar
 
 * If the End Node is found, this function is called.
 
 *  It can do, for example, calculate the route and put that in an array
 
 */
 
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
 

	
 
// For internal use, see aystar.c
 
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node);
 
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node, uint g);
 
typedef int AyStar_Main(AyStar *aystar);
 
typedef int AyStar_Loop(AyStar *aystar);
 
typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
 
typedef void AyStar_Free(AyStar *aystar);
 
typedef void AyStar_Clear(AyStar *aystar);
 

	
 
@@ -158,13 +158,13 @@ struct AyStar {
 
	/* An extra hash to speed up the process of looking up an element in
 
	 * the open list */
 
	Hash OpenListHash;
 
};
 

	
 

	
 
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node);
 
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
 
int AyStarMain_Main(AyStar *aystar);
 
int AyStarMain_Loop(AyStar *aystar);
 
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
 
void AyStarMain_Free(AyStar *aystar);
 
void AyStarMain_Clear(AyStar *aystar);
 

	
npf.c
Show inline comments
 
@@ -297,12 +297,13 @@ int32 NPFWaterPathCost(AyStar* as, AySta
 
}
 

	
 
/* Determine the cost of this node, for road tracks */
 
int32 NPFRoadPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) {
 
	TileIndex tile = current->tile;
 
	int32 cost = 0;
 

	
 
	/* Determine base length */
 
	switch (GetTileType(tile)) {
 
		case MP_TUNNELBRIDGE:
 
			if ((_map5[tile] & 0xF0)==0) {
 
				cost = NPFTunnelCost(current);
 
				break;
 
@@ -332,12 +333,13 @@ int32 NPFRoadPathCost(AyStar* as, AyStar
 

	
 
/* Determine the cost of this node, for railway tracks */
 
int32 NPFRailPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) {
 
	TileIndex tile = current->tile;
 
	byte trackdir = current->direction;
 
	int32 cost = 0;
 
	/* HACK: We create a OpenListNode manualy, so we can call EndNodeCheck */
 
	OpenListNode new_node;
 

	
 
	/* Determine base length */
 
	switch (GetTileType(tile)) {
 
		case MP_TUNNELBRIDGE:
 
			if ((_map5[tile] & 0xF0)==0) {
 
@@ -405,23 +407,33 @@ int32 NPFRailPathCost(AyStar* as, AyStar
 
	/* Check for turns */
 
	if (current->direction != _next_trackdir[parent->path.node.direction])
 
		cost += _patches.npf_rail_curve_penalty;
 
	//TODO, with realistic acceleration, also the amount of straight track between
 
	//      curves should be taken into account, as this affects the speed limit.
 

	
 
	/* Check for reverse in depot */
 
	if (IsTileDepotType(tile, TRANSPORT_RAIL) && !as->EndNodeCheck(as, &new_node)==AYSTAR_FOUND_END_NODE)
 
		/* Penalise any depot tile that is not the last tile in the path. This
 
		 * _should_ penalise every occurence of reversing in a depot (and only
 
		 * that) */
 
		cost += _patches.npf_rail_depot_reverse_penalty;
 

	
 
	/* Check for occupied track */
 
	//TODO
 

	
 
	NPFMarkTile(tile);
 
	DEBUG(npf, 4)("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost);
 
	return cost;
 
}
 

	
 
/* Will find any depot */
 
int32 NPFFindDepot(AyStar* as, OpenListNode *current) {
 
	TileIndex tile = current->path.node.tile;
 

	
 
	/* It's not worth caching the result with NPF_FLAG_IS_TARGET here as below,
 
	 * since checking the cache not that much faster than the actual check */
 
	if (IsTileDepotType(tile, as->user_data[NPF_TYPE]))
 
		return AYSTAR_FOUND_END_NODE;
 
	else
 
		return AYSTAR_DONE;
 
}
 

	
 
@@ -541,14 +553,17 @@ void NPFFollowTrack(AyStar* aystar, Open
 
			/* Find out the exit direction first */
 
			if (IsRoadStationTile(src_tile))
 
				exitdir = GetRoadStationDir(src_tile);
 
			else /* Train or road depot. Direction is stored the same for both, in map5 */
 
				exitdir = GetDepotDirection(src_tile, type);
 

	
 
			/* Let's see if were headed the right way */
 
			if (src_trackdir == _dir_to_diag_trackdir[_reverse_dir[exitdir]])
 
			/* Let's see if were headed the right way into the depot, and reverse
 
			 * otherwise (only for trains, since only with trains you can
 
			 * (sometimes) reach tiles after reversing that you couldn't reach
 
			 * without reversing. */
 
			if (src_trackdir == _dir_to_diag_trackdir[_reverse_dir[exitdir]] && type == TRANSPORT_RAIL)
 
				/* We are headed inwards. We can only reverse here, so we'll not
 
				 * consider this direction, but jump ahead to the reverse direction.
 
				 * It would be nicer to return one neighbour here (the reverse
 
				 * trackdir of the one we are considering now) and then considering
 
				 * that one to return the tracks outside of the depot. But, because
 
				 * the code layout is cleaner this way, we will just pretend we are
 
@@ -644,19 +659,20 @@ void NPFFollowTrack(AyStar* aystar, Open
 
	aystar->num_neighbours = i;
 
}
 

	
 
/*
 
 * Plan a route to the specified target (which is checked by target_proc),
 
 * from start1 and if not NULL, from start2 as well. The type of transport we
 
 * are checking is in type.
 
 * are checking is in type. reverse_penalty is applied to all routes that
 
 * originate from the second start node.
 
 * When we are looking for one specific target (optionally multiple tiles), we
 
 * should use a good heuristic to perform aystar search. When we search for
 
 * multiple targets that are spread around, we should perform a breadth first
 
 * search by specifiying CalcZero as our heuristic.
 
 */
 
NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner) {
 
NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, uint reverse_penalty) {
 
	int r;
 
	NPFFoundTargetData result;
 

	
 
	/* Initialize procs */
 
	_npf_aystar.CalculateH = heuristic_proc;
 
	_npf_aystar.EndNodeCheck = target_proc;
 
@@ -671,18 +687,18 @@ NPFFoundTargetData NPFRouteInternal(AySt
 
	else
 
		assert(0);
 

	
 
	/* Initialize Start Node(s) */
 
	start1->user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1->user_data[NPF_NODE_FLAGS] = 0;
 
	_npf_aystar.addstart(&_npf_aystar, start1);
 
	_npf_aystar.addstart(&_npf_aystar, start1, 0);
 
	if (start2) {
 
		start2->user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
		start2->user_data[NPF_NODE_FLAGS] = 0;
 
		NPFSetFlag(start2, NPF_FLAG_REVERSE, true);
 
		_npf_aystar.addstart(&_npf_aystar, start2);
 
		_npf_aystar.addstart(&_npf_aystar, start2, reverse_penalty);
 
	}
 

	
 
	/* Initialize result */
 
	result.best_bird_dist = (uint)-1;
 
	result.best_path_dist = (uint)-1;
 
	result.best_trackdir = 0xff;
 
@@ -714,44 +730,46 @@ NPFFoundTargetData NPFRouteInternal(AySt
 
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 
	AyStarNode start1;
 
	AyStarNode start2;
 

	
 
	start1.tile = tile1;
 
	start2.tile = tile2;
 
	/* We set this in case the target is also the start tile, we will just
 
	 * return a not found then */
 
	start1.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1.direction = trackdir1;
 
	start2.direction = trackdir2;
 
	start2.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 

	
 
	return NPFRouteInternal(&start1, &start2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner);
 
	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, 0);
 
}
 

	
 
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 
	AyStarNode start;
 
	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner);
 
}
 

	
 
	assert(tile != 0);
 
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, TransportType type, Owner owner, uint reverse_penalty) {
 
	AyStarNode start1;
 
	AyStarNode start2;
 

	
 
	start.tile = tile;
 
	start.direction = trackdir;
 
	start1.tile = tile1;
 
	start2.tile = tile2;
 
	/* We set this in case the target is also the start tile, we will just
 
	 * return a not found then */
 
	start.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1.direction = trackdir1;
 
	start2.direction = trackdir2;
 
	start2.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 

	
 
	return NPFRouteInternal(&start, NULL, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner);
 
	/* perform a breadth first search. Target is NULL,
 
	 * since we are just looking for any depot...*/
 
	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, reverse_penalty);
 
}
 

	
 
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner) {
 
	AyStarNode start;
 

	
 
	start.tile = tile;
 
	start.direction = trackdir;
 
	/* We set this in case the target is also the start tile, we will just
 
	 * return a not found then */
 
	start.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 

	
 
	/* perform a breadth first search. Target is NULL,
 
	 * since we are just looking for any depot...*/
 
	return NPFRouteInternal(&start, NULL, NULL, NPFFindDepot, NPFCalcZero, type, owner);
 
	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, 0);
 
}
 

	
 
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner) {
 
	/* Okay, what we're gonna do. First, we look at all depots, calculate
 
	 * the manhatten distance to get to each depot. We then sort them by
 
	 * distance. We start by trying to plan a route to the closest, then
 
@@ -823,13 +841,13 @@ NPFFoundTargetData NPFRouteToDepotTrialE
 

	
 
		/* Initialize Start Node */
 
		/* We set this in case the target is also the start tile, we will just
 
		 * return a not found then */
 
		start.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
		start.user_data[NPF_NODE_FLAGS] = 0;
 
		_npf_aystar.addstart(&_npf_aystar, &start);
 
		_npf_aystar.addstart(&_npf_aystar, &start, 0);
 

	
 
		/* Initialize result */
 
		result.best_bird_dist = (uint)-1;
 
		result.best_path_dist = (uint)-1;
 
		result.best_trackdir = 0xff;
 

	
npf.h
Show inline comments
 
@@ -11,12 +11,23 @@ enum {
 
	/* Do no change below values */
 
	NPF_HASH_SIZE = 1 << NPF_HASH_BITS,
 
	NPF_HASH_HALFBITS = NPF_HASH_BITS / 2,
 
	NPF_HASH_HALFMASK = (1 << NPF_HASH_HALFBITS) - 1
 
};
 

	
 
enum {
 
	/** This penalty is the equivalent of "inifite", which means that paths that
 
	 * get this penalty will be chosen, but only if there is no other route
 
	 * without it. Be careful with not applying this penalty to often, or the
 
	 * total path cost might overflow..
 
	 * For now, this is just a Very Big Penalty, we might actually implement
 
	 * this in a nicer way :-)
 
	 */
 
	NPF_INFINITE_PENALTY = 1000 * NPF_TILE_LENGTH
 
};
 

	
 
typedef struct NPFFindStationOrTileData { /* Meant to be stored in AyStar.targetdata */
 
	TileIndex dest_coords; /* An indication of where the station is, for heuristic purposes, or the target tile */
 
	int station_index; /* station index we're heading for, or -1 when we're heading for a tile */
 
} NPFFindStationOrTileData;
 

	
 
enum { /* Indices into AyStar.userdata[] */
 
@@ -59,14 +70,21 @@ NPFFoundTargetData NPFRouteToStationOrTi
 
 * direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
 
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner);
 

	
 
/* Will search a route to the closest depot. */
 

	
 
/* Search using breadth first. Good for little track choice and inaccurate
 
 * heuristic, such as railway/road */
 
 * heuristic, such as railway/road.*/
 
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner);
 
/* Same as above but with two start nodes, the second being the reverse. Call
 
 * NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
 
 * orginated. All pathfs from the second node will have the given
 
 * reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
 
 * tile).
 
 */
 
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, TransportType type, Owner owner, uint reverse_penalty);
 
/* Search by trying each depot in order of Manhattan Distance. Good for lots
 
 * of choices and accurate heuristics, such as water. */
 
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner);
 

	
 
void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);
 

	
settings.c
Show inline comments
 
@@ -963,12 +963,16 @@ const SettingDesc patch_settings[] = {
 
	{"npf_rail_station_penalty",    SDT_UINT32, (void*)(1 * NPF_TILE_LENGTH),   &_patches.npf_rail_station_penalty,     NULL},
 
	{"npf_rail_slope_penalty",      SDT_UINT32, (void*)(1 * NPF_TILE_LENGTH),   &_patches.npf_rail_slope_penalty,       NULL},
 
	/* This penalty is applied when a train makes a turn. Its value of 1 makes
 
	 * sure that it has a minimal impact on the pathfinding, only when two
 
	 * paths have equal length it will make a difference */
 
	{"npf_rail_curve_penalty",      SDT_UINT32, (void*)(1),                     &_patches.npf_rail_curve_penalty,       NULL},
 
	/* Ths penalty is applied when a vehicle reverses inside a depot (doesn't
 
	 * apply to ships, as they can just come out the other end). XXX: Is this a
 
	 * good value? */
 
	{"npf_rail_depot_reverse_penalty", SDT_UINT32, (void*)(NPF_TILE_LENGTH * 50), &_patches.npf_rail_depot_reverse_penalty, NULL},
 
	{"npf_buoy_penalty",            SDT_UINT32, (void*)(2 * NPF_TILE_LENGTH),   &_patches.npf_buoy_penalty,             NULL},
 
	/* This penalty is applied when a ship makes a turn. It is bigger than the
 
	 * rail curve penalty, since ships (realisticly) have more trouble with
 
	 * making turns */
 
	{"npf_water_curve_penalty",     SDT_UINT32, (void*)(NPF_TILE_LENGTH / 4),   &_patches.npf_water_curve_penalty,      NULL},
 

	
train_cmd.c
Show inline comments
 
@@ -1326,12 +1326,17 @@ int32 CmdRefitRailVehicle(int x, int y, 
 
}
 

	
 
typedef struct TrainFindDepotData {
 
	uint best_length;
 
	uint tile;
 
	byte owner;
 
	/**
 
	 * true if reversing is necesarry for the train to get to this depot This
 
	 * value is unused when new depot finding and NPF are both disabled
 
	 */
 
	bool reverse;
 
} TrainFindDepotData;
 

	
 
static bool TrainFindDepotEnumProc(uint tile, TrainFindDepotData *tfdd, int track, uint length, byte *state)
 
{
 
	if (IsTileType(tile, MP_RAILWAY) && _map_owner[tile] == tfdd->owner) {
 
		if ((_map5[tile] & ~0x3) == 0xC0) {
 
@@ -1362,45 +1367,52 @@ static TrainFindDepotData FindClosestTra
 
	uint tile = v->tile;
 

	
 
	assert(!(v->vehstatus & VS_CRASHED));
 

	
 
	tfdd.owner = v->owner;
 
	tfdd.best_length = (uint)-1;
 
	tfdd.reverse = false;
 

	
 
	if (IsTileDepotType(tile, TRANSPORT_RAIL)){
 
		tfdd.tile = tile;
 
		tfdd.best_length = 0;
 
		return tfdd;
 
	}
 

	
 
	if (v->u.rail.track == 0x40) { tile = GetVehicleOutOfTunnelTile(v); }
 

	
 
	if (_patches.new_pathfinding_all) {
 
		NPFFoundTargetData ftd;
 
		Vehicle* last = GetLastVehicleInChain(v);
 
		byte trackdir = GetVehicleTrackdir(v);
 
		byte trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
 

	
 
		assert (trackdir != 0xFF);
 
		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_RAIL, v->owner);
 
		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, NPF_INFINITE_PENALTY);
 
		if (ftd.best_bird_dist == 0) {
 
			/* Found target */
 
			tfdd.tile = ftd.node.tile;
 
			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
 
			/* Our caller expects a number of tiles, so we just approximate that
 
			* number by this. It might not be completely what we want, but it will
 
			* work for now :-) We can possibly change this when the old pathfinder
 
			* is removed. */
 
			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
 
			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE))
 
				tfdd.reverse = true;
 
		}
 
	} else if (!_patches.new_depot_finding) {
 
		// search in all directions
 
		for(i=0; i!=4; i++)
 
			NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL);
 
	} else {
 
		// search in the forward direction first.
 
		i = v->direction >> 1;
 
		if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; }
 
		NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL);
 
		if (tfdd.best_length == (uint)-1){
 
			tfdd.reverse = true;
 
			// search in backwards direction
 
			i = (v->direction^4) >> 1;
 
			if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; }
 
			NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL);
 
		}
 
	}
 
@@ -1444,12 +1456,15 @@ int32 CmdTrainGotoDepot(int x, int y, ui
 
	if (flags & DC_EXEC) {
 
		v->dest_tile = tfdd.tile;
 
		v->current_order.type = OT_GOTO_DEPOT;
 
		v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD;
 
		v->current_order.station = GetDepotByTile(tfdd.tile)->index;
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
		/* If there is no depot in front, reverse automatically */
 
		if (tfdd.reverse)
 
			DoCommandByTile(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
 
	}
 

	
 
	return 0;
 
}
 

	
 
/* p1 = vehicle
 
@@ -1865,13 +1880,13 @@ static bool CheckReverseTrain(Vehicle *v
 
		byte trackdir, trackdir_rev;
 
		Vehicle* last = GetLastVehicleInChain(v);
 

	
 
		NPFFillWithOrderData(&fstd, v);
 

	
 
		trackdir = GetVehicleTrackdir(v);
 
		trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(v));
 
		trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
 
		assert(trackdir != 0xff);
 
		assert(trackdir_rev != 0xff);
 

	
 
		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner);
 
		if (ftd.best_bird_dist != 0) {
 
			/* We didn't find anything, just keep on going straight ahead */
variables.h
Show inline comments
 
@@ -209,12 +209,13 @@ typedef struct Patches {
 
	uint32 npf_rail_firstred_penalty; /* The penalty for when the first signal is red (and it is not an exit or combo signal) */
 
	uint32 npf_rail_firstred_exit_penalty; /* The penalty for when the first signal is red (and it is an exit or combo signal) */
 
	uint32 npf_rail_lastred_penalty; /* The penalty for when the last signal is red */
 
	uint32 npf_rail_station_penalty; /* The penalty for station tiles */
 
	uint32 npf_rail_slope_penalty; /* The penalty for sloping upwards */
 
	uint32 npf_rail_curve_penalty; /* The penalty for curves */
 
	uint32 npf_rail_depot_reverse_penalty; /* The penalty for reversing in depots */
 
	uint32 npf_buoy_penalty; /* The penalty for going over (through) a buoy */
 
	uint32 npf_water_curve_penalty; /* The penalty for curves */
 

	
 
	bool population_in_label; // Show the population of a town in his label?
 
} Patches;
 

	
 
@@ -449,13 +450,14 @@ VARDEF char _screenshot_name[128];
 
VARDEF char _userstring[USERSTRING_LEN];
 
VARDEF byte _vehicle_design_names;
 

	
 
/* tunnelbridge */
 
#define MAX_BRIDGES 13
 

	
 
/* For new pathfinding. Define here so it is globally available */
 
/* For new pathfinding. Define here so it is globally available without having
 
 * to include npf.h */
 
#define NPF_TILE_LENGTH 100
 

	
 
/* Autoreplace vehicle stuff*/
 
VARDEF byte _autoreplace_array[256];
 
VARDEF uint16 _player_num_engines[256];
 
VARDEF byte _railtype_selected_in_replace_gui;
0 comments (0 inline, 0 general)