示例#1
0
static Subsidy *FindSubsidyPassengerRoute()
{
	assert(Subsidy::CanAllocateItem());

	const Town *src = Town::GetRandom();
	if (src->population < SUBSIDY_PAX_MIN_POPULATION ||
			src->pct_pass_transported > SUBSIDY_MAX_PCT_TRANSPORTED) {
		return NULL;
	}

	const Town *dst = Town::GetRandom();
	if (dst->population < SUBSIDY_PAX_MIN_POPULATION || src == dst) {
		return NULL;
	}

	if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return NULL;
	if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return NULL;

	Subsidy *s = new Subsidy();
	s->cargo_type = CT_PASSENGERS;
	s->src_type = s->dst_type = ST_TOWN;
	s->src = src->index;
	s->dst = dst->index;

	return s;
}
示例#2
0
文件: npf.cpp 项目: andrew889/OpenTTD
/* Calcs the heuristic to the target station or tile. For train stations, it
 * takes into account the direction of approach.
 */
static int32 NPFCalcStationOrTileHeuristic(AyStar *as, AyStarNode *current, OpenListNode *parent)
{
	NPFFindStationOrTileData *fstd = (NPFFindStationOrTileData*)as->user_target;
	NPFFoundTargetData *ftd = (NPFFoundTargetData*)as->user_path;
	TileIndex from = current->tile;
	TileIndex to = fstd->dest_coords;
	uint dist;

	/* for train-stations, we are going to aim for the closest station tile */
	if (as->user_data[NPF_TYPE] != TRANSPORT_WATER && fstd->station_index != INVALID_STATION)
		to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type);

	if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) {
		/* Since roads only have diagonal pieces, we use manhattan distance here */
		dist = DistanceManhattan(from, to) * NPF_TILE_LENGTH;
	} else {
		/* Ships and trains can also go diagonal, so the minimum distance is shorter */
		dist = NPFDistanceTrack(from, to);
	}

	DEBUG(npf, 4, "Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist);

	if (dist < ftd->best_bird_dist) {
		ftd->best_bird_dist = dist;
		ftd->best_trackdir = (Trackdir)current->user_data[NPF_TRACKDIR_CHOICE];
	}
	return dist;
}
示例#3
0
/**
 * Add a node to the component and create empty edges associated with it. Set
 * the station's last_component to this component. Calculate the distances to all
 * other nodes. The distances to _all_ nodes are important as the demand
 * calculator relies on their availability.
 * @param st New node's station.
 * @return New node's ID.
 */
NodeID LinkGraph::AddNode(const Station *st)
{
	const GoodsEntry &good = st->goods[this->cargo];

	NodeID new_node = this->Size();
	this->nodes.Append();
	/* Avoid reducing the height of the matrix as that is expensive and we
	 * most likely will increase it again later which is again expensive. */
	this->edges.Resize(new_node + 1U,
			max(new_node + 1U, this->edges.Height()));

	this->nodes[new_node].Init(st->index,
			HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));

	BaseEdge *new_edges = this->edges[new_node];

	/* Reset the first edge starting at the new node */
	new_edges[new_node].next_edge = INVALID_NODE;

	for (NodeID i = 0; i <= new_node; ++i) {
		uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
		new_edges[i].Init(distance);
		this->edges[i][new_node].Init(distance);
	}
	return new_node;
}
示例#4
0
/**
 * Checks if the source and destination of a subsidy are inside the distance limit.
 * @param src_type Type of \a src.
 * @param src      Index of source.
 * @param dst_type Type of \a dst.
 * @param dst      Index of destination.
 * @return True if they are inside the distance limit.
 */
static bool CheckSubsidyDistance(SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
{
	TileIndex tile_src = (src_type == ST_TOWN) ? Town::Get(src)->xy : Industry::Get(src)->location.tile;
	TileIndex tile_dst = (dst_type == ST_TOWN) ? Town::Get(dst)->xy : Industry::Get(dst)->location.tile;

	return (DistanceManhattan(tile_src, tile_dst) <= SUBSIDY_MAX_DISTANCE);
}
示例#5
0
static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
{
	/* Find the closest depot */
	const Depot *depot;
	const Depot *best_depot = NULL;
	/* If we don't have a maximum distance, i.e. distance = 0,
	 * we want to find any depot so the best distance of no
	 * depot must be more than any correct distance. On the
	 * other hand if we have set a maximum distance, any depot
	 * further away than max_distance can safely be ignored. */
	uint best_dist = max_distance == 0 ? UINT_MAX : max_distance + 1;

	FOR_ALL_DEPOTS(depot) {
		TileIndex tile = depot->xy;
		if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
			uint dist = DistanceManhattan(tile, v->tile);
			if (dist < best_dist) {
				best_dist = dist;
				best_depot = depot;
			}
		}
	}

	return best_depot;
}
示例#6
0
/**
 * Tries to create a passenger subsidy between two towns.
 * @return True iff the subsidy was created.
 */
bool FindSubsidyPassengerRoute()
{
	if (!Subsidy::CanAllocateItem()) return false;

	Town *src = Town::GetRandom();
	if (src->cache.population < SUBSIDY_PAX_MIN_POPULATION ||
			src->GetPercentTransported(CT_PASSENGERS) > SUBSIDY_MAX_PCT_TRANSPORTED) {
		return false;
	}

	const Town *dst = NULL;
	if (CargoHasDestinations(CT_PASSENGERS)) {
		/* Try to get a town from the demand destinations. */
		CargoLink *link = src->GetRandomLink(CT_PASSENGERS, false);
		if (link == src->cargo_links[CT_PASSENGERS].End()) return NULL;
		if (link->dest != NULL && link->dest->GetType() != ST_TOWN) return NULL;
		dst = static_cast<const Town *>(link->dest);
	}
	if (dst == NULL) dst = Town::GetRandom();

	if (dst->cache.population < SUBSIDY_PAX_MIN_POPULATION || src == dst) {
		return false;
	}

	if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return false;
	if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return false;

	CreateSubsidy(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index);

	return true;
}
示例#7
0
/**
 * Recomputes Station::industries_near, list of industries possibly
 * accepting cargo in station's catchment radius
 */
void Station::RecomputeIndustriesNear()
{
	this->industries_near.Clear();
	if (this->rect.IsEmpty()) return;

	RectAndIndustryVector riv = {
		this->GetCatchmentRect(),
		&this->industries_near
	};

	/* Compute maximum extent of acceptance rectangle wrt. station sign */
	TileIndex start_tile = this->xy;
	uint max_radius = max(
		max(DistanceManhattan(start_tile, TileXY(riv.rect.left,  riv.rect.top)), DistanceManhattan(start_tile, TileXY(riv.rect.left,  riv.rect.bottom))),
		max(DistanceManhattan(start_tile, TileXY(riv.rect.right, riv.rect.top)), DistanceManhattan(start_tile, TileXY(riv.rect.right, riv.rect.bottom)))
	);

	CircularTileSearch(&start_tile, 2 * max_radius + 1, &FindIndustryToDeliver, &riv);
}
示例#8
0
/*
This example shows how three different distance metrics calculate the same three points.

Euclidean Distance
pos1->pos2: 5.20
pos2->pos3: 5.20
pos3->pos1: 10.39

Manhattan Distance
pos1->pos2: 9.00
pos2->pos3: 9.00
pos3->pos1: 18.00

Chebyshev Distance
pos1->pos2: 3.00
pos2->pos3: 3.00
pos3->pos1: 6.00
*/
void ExampleDistance(int argIndex, int argc, char **argv) {
	double pos1[3] = { 1.0, 2.0, 3.0 };
	double pos2[3] = { 4.0, 5.0, 6.0 };
	double pos3[3] = { 7.0, 8.0, 9.0 };

	printf("Euclidean Distance\n");
	printf("pos1->pos2: %.2f\n", DistanceEuclidean(pos1,0,pos2,0,3));
	printf("pos2->pos3: %.2f\n", DistanceEuclidean(pos2,0,pos3,0,3));
	printf("pos3->pos1: %.2f\n", DistanceEuclidean(pos3,0,pos1,0,3));
	printf("\nManhattan Distance\n");
	printf("pos1->pos2: %.2f\n", DistanceManhattan(pos1,0,pos2,0,3));
	printf("pos2->pos3: %.2f\n", DistanceManhattan(pos2,0,pos3,0,3));
	printf("pos3->pos1: %.2f\n", DistanceManhattan(pos3,0,pos1,0,3));
	printf("\nChebyshev Distance\n");
	printf("pos1->pos2: %.2f\n", DistanceChebyshev(pos1,0,pos2,0,3));
	printf("pos2->pos3: %.2f\n", DistanceChebyshev(pos2,0,pos3,0,3));
	printf("pos3->pos1: %.2f\n", DistanceChebyshev(pos3,0,pos1,0,3));

}
示例#9
0
/**
 * Find a deleted waypoint close to a tile.
 * @param tile to search from
 * @param str  the string to get the 'type' of
 * @param cid previous owner of the waypoint
 * @return the deleted nearby waypoint
 */
static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile, StringID str, CompanyID cid)
{
	Waypoint *wp, *best = NULL;
	uint thres = 8;

	FOR_ALL_WAYPOINTS(wp) {
		if (!wp->IsInUse() && wp->string_id == str && wp->owner == cid) {
			uint cur_dist = DistanceManhattan(tile, wp->xy);

			if (cur_dist < thres) {
				thres = cur_dist;
				best = wp;
			}
		}
	}

	return best;
}
示例#10
0
/**
 * Tries to create a passenger subsidy between two towns.
 * @return True iff the subsidy was created.
 */
bool FindSubsidyPassengerRoute()
{
	if (!Subsidy::CanAllocateItem()) return false;

	const Town *src = Town::GetRandom();
	if (src->cache.population < SUBSIDY_PAX_MIN_POPULATION ||
			src->GetPercentTransported(CT_PASSENGERS) > SUBSIDY_MAX_PCT_TRANSPORTED) {
		return false;
	}

	const Town *dst = Town::GetRandom();
	if (dst->cache.population < SUBSIDY_PAX_MIN_POPULATION || src == dst) {
		return false;
	}

	if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return false;
	if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return false;

	CreateSubsidy(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index);

	return true;
}
/**
 * This function will activate a search around a central tile, looking for some houses
 * that fit the requested characteristics
 * @param parameter that is given by the callback.
 *                  bits 0..6 radius of the search
 *                  bits 7..8 search type i.e.: 0 = houseID/ 1 = classID/ 2 = grfID
 * @param tile TileIndex from which to start the search
 * @param house the HouseID that is associated to the house, the callback is called for
 * @return the Manhattan distance from the center tile, if any, and 0 if failure
 */
static uint32 GetDistanceFromNearbyHouse(uint8 parameter, TileIndex tile, HouseID house)
{
	static TestTileOnSearchProc * const search_procs[3] = {
		SearchNearbyHouseID,
		SearchNearbyHouseClass,
		SearchNearbyHouseGRFID,
	};
	TileIndex found_tile = tile;
	uint8 searchtype = GB(parameter, 6, 2);
	uint8 searchradius = GB(parameter, 0, 6);
	if (searchtype >= lengthof(search_procs)) return 0;  // do not run on ill-defined code
	if (searchradius < 1) return 0; // do not use a too low radius

	SearchNearbyHouseData nbhd;
	nbhd.hs = HouseSpec::Get(house);
	nbhd.north_tile = tile + GetHouseNorthPart(house); // modifies 'house'!

	/* Use a pointer for the tile to start the search. Will be required for calculating the distance*/
	if (CircularTileSearch(&found_tile, 2 * searchradius + 1, search_procs[searchtype], &nbhd)) {
		return DistanceManhattan(found_tile, tile);
	}
	return 0;
}
示例#12
0
static Subsidy *FindSubsidyCargoRoute()
{
	assert(Subsidy::CanAllocateItem());

	const Industry *i = Industry::GetRandom();
	if (i == NULL) return NULL;

	CargoID cargo;
	int trans, total;

	/* Randomize cargo type */
	if (i->produced_cargo[1] != CT_INVALID && HasBit(Random(), 0)) {
		cargo = i->produced_cargo[1];
		trans = i->last_month_pct_transported[1];
		total = i->last_month_production[1];
	} else {
		cargo = i->produced_cargo[0];
		trans = i->last_month_pct_transported[0];
		total = i->last_month_production[0];
	}

	/* Quit if no production in this industry
	 * or if the pct transported is already large enough */
	if (total == 0 || trans > SUBSIDY_MAX_PCT_TRANSPORTED || cargo == CT_INVALID) return NULL;

	/* Don't allow passengers subsidies from industry */
	const CargoSpec *cs = CargoSpec::Get(cargo);
	if (cs->town_effect == TE_PASSENGERS) return NULL;

	SourceType dst_type;
	SourceID dst;

	if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
		/*  The destination is a town */
		dst_type = ST_TOWN;
		const Town *t = Town::GetRandom();

		/* Only want big towns */
		if (t->population < SUBSIDY_CARGO_MIN_POPULATION) return NULL;

		if (DistanceManhattan(i->location.tile, t->xy) > SUBSIDY_MAX_DISTANCE) return NULL;

		dst = t->index;
	} else {
		/* The destination is an industry */
		dst_type = ST_INDUSTRY;
		const Industry *i2 = Industry::GetRandom();

		/* The industry must accept the cargo */
		if (i2 == NULL || i == i2 ||
				(cargo != i2->accepts_cargo[0] &&
				 cargo != i2->accepts_cargo[1] &&
				 cargo != i2->accepts_cargo[2])) {
			return NULL;
		}

		if (DistanceManhattan(i->location.tile, i2->location.tile) > SUBSIDY_MAX_DISTANCE) return NULL;

		dst = i2->index;
	}

	if (CheckSubsidyDuplicate(cargo, ST_INDUSTRY, i->index, dst_type, dst)) return NULL;

	Subsidy *s = new Subsidy();
	s->cargo_type = cargo;
	s->src_type = ST_INDUSTRY;
	s->src = i->index;
	s->dst_type = dst_type;
	s->dst = dst;

	return s;
}
示例#13
0
static void ShipController(Ship *v)
{
	uint32 r;
	const byte *b;
	Direction dir;
	Track track;
	TrackBits tracks;

	v->tick_counter++;
	v->current_order_time++;

	if (v->HandleBreakdown()) return;

	if (v->vehstatus & VS_STOPPED) return;

	ProcessOrders(v);
	v->HandleLoading();

	if (v->current_order.IsType(OT_LOADING)) return;

	if (CheckShipLeaveDepot(v)) return;

	v->ShowVisualEffect();

	if (!ShipAccelerate(v)) return;

	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
	if (v->state != TRACK_BIT_WORMHOLE) {
		/* Not on a bridge */
		if (gp.old_tile == gp.new_tile) {
			/* Staying in tile */
			if (v->IsInDepot()) {
				gp.x = v->x_pos;
				gp.y = v->y_pos;
			} else {
				/* Not inside depot */
				r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
				if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;

				/* A leave station order only needs one tick to get processed, so we can
				 * always skip ahead. */
				if (v->current_order.IsType(OT_LEAVESTATION)) {
					v->current_order.Free();
					SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
					/* Test if continuing forward would lead to a dead-end, moving into the dock. */
					DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
					TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
					if (TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) goto reverse_direction;
				} else if (v->dest_tile != 0) {
					/* We have a target, let's see if we reached it... */
					if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
							DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
						/* We got within 3 tiles of our target buoy, so let's skip to our
						 * next order */
						UpdateVehicleTimetable(v, true);
						v->IncrementRealOrderIndex();
						v->current_order.MakeDummy();
					} else {
						/* Non-buoy orders really need to reach the tile */
						if (v->dest_tile == gp.new_tile) {
							if (v->current_order.IsType(OT_GOTO_DEPOT)) {
								if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
									VehicleEnterDepot(v);
									return;
								}
							} else if (v->current_order.IsType(OT_GOTO_STATION)) {
								v->last_station_visited = v->current_order.GetDestination();

								/* Process station in the orderlist. */
								Station *st = Station::Get(v->current_order.GetDestination());
								if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
									ShipArrivesAt(v, st);
									v->BeginLoading();
								} else { // leave stations without docks right aways
									v->current_order.MakeLeaveStation();
									v->IncrementRealOrderIndex();
								}
							}
						}
					}
				}
			}
		} else {
			/* New tile */
			if (!IsValidTile(gp.new_tile)) goto reverse_direction;

			DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
			assert(diagdir != INVALID_DIAGDIR);
			tracks = GetAvailShipTracks(gp.new_tile, diagdir);
			if (tracks == TRACK_BIT_NONE) goto reverse_direction;

			/* Choose a direction, and continue if we find one */
			track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
			if (track == INVALID_TRACK) goto reverse_direction;

			b = _ship_subcoord[diagdir][track];

			gp.x = (gp.x & ~0xF) | b[0];
			gp.y = (gp.y & ~0xF) | b[1];

			/* Call the landscape function and tell it that the vehicle entered the tile */
			r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
			if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;

			if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
				v->tile = gp.new_tile;
				v->state = TrackToTrackBits(track);

				/* Update ship cache when the water class changes. Aqueducts are always canals. */
				WaterClass old_wc = GetEffectiveWaterClass(gp.old_tile);
				WaterClass new_wc = GetEffectiveWaterClass(gp.new_tile);
				if (old_wc != new_wc) v->UpdateCache();
			}

			v->direction = (Direction)b[2];
		}
	} else {
		/* On a bridge */
		if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
			v->x_pos = gp.x;
			v->y_pos = gp.y;
			v->UpdatePosition();
			if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
			return;
		}
	}

	/* update image of ship, as well as delta XY */
	v->x_pos = gp.x;
	v->y_pos = gp.y;
	v->z_pos = GetSlopePixelZ(gp.x, gp.y);

getout:
	v->UpdatePosition();
	v->UpdateViewport(true, true);
	return;

reverse_direction:
	dir = ReverseDir(v->direction);
	v->direction = dir;
	goto getout;
}
示例#14
0
static void ShipController(Ship *v)
{
	uint32 r;
	const byte *b;
	Direction dir;
	Track track;
	TrackBits tracks;

	v->tick_counter++;
	v->current_order_time++;

	if (v->breakdown_ctr != 0) {
		if (v->breakdown_ctr <= 2) {
			HandleBrokenShip(v);
			return;
		}
		if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
	}

	if (v->vehstatus & VS_STOPPED) return;

	ProcessOrders(v);
	v->HandleLoading();

	if (v->current_order.IsType(OT_LOADING)) return;

	CheckShipLeaveDepot(v);

	if (!ShipAccelerate(v)) return;

	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
	if (v->state != TRACK_BIT_WORMHOLE) {
		/* Not on a bridge */
		if (gp.old_tile == gp.new_tile) {
			/* Staying in tile */
			if (v->IsInDepot()) {
				gp.x = v->x_pos;
				gp.y = v->y_pos;
			} else {
				/* Not inside depot */
				r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
				if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;

				/* A leave station order only needs one tick to get processed, so we can
				 * always skip ahead. */
				if (v->current_order.IsType(OT_LEAVESTATION)) {
					v->current_order.Free();
					SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
				} else if (v->dest_tile != 0) {
					/* We have a target, let's see if we reached it... */
					if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
							DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
						/* We got within 3 tiles of our target buoy, so let's skip to our
						 * next order */
						UpdateVehicleTimetable(v, true);
						v->IncrementOrderIndex();
						v->current_order.MakeDummy();
					} else {
						/* Non-buoy orders really need to reach the tile */
						if (v->dest_tile == gp.new_tile) {
							if (v->current_order.IsType(OT_GOTO_DEPOT)) {
								if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
									VehicleEnterDepot(v);
									return;
								}
							} else if (v->current_order.IsType(OT_GOTO_STATION)) {
								v->last_station_visited = v->current_order.GetDestination();

								/* Process station in the orderlist. */
								Station *st = Station::Get(v->current_order.GetDestination());
								if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
									ShipArrivesAt(v, st);
									v->BeginLoading();
								} else { // leave stations without docks right aways
									v->current_order.MakeLeaveStation();
									v->IncrementOrderIndex();
								}
							}
						}
					}
				}
			}
		} else {
			DiagDirection diagdir;
			/* New tile */
			if (TileX(gp.new_tile) >= MapMaxX() || TileY(gp.new_tile) >= MapMaxY()) {
				goto reverse_direction;
			}

			dir = ShipGetNewDirectionFromTiles(gp.new_tile, gp.old_tile);
			assert(dir == DIR_NE || dir == DIR_SE || dir == DIR_SW || dir == DIR_NW);
			diagdir = DirToDiagDir(dir);
			tracks = GetAvailShipTracks(gp.new_tile, diagdir);
			if (tracks == TRACK_BIT_NONE) goto reverse_direction;

			/* Choose a direction, and continue if we find one */
			track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
			if (track == INVALID_TRACK) goto reverse_direction;

			b = _ship_subcoord[diagdir][track];

			gp.x = (gp.x & ~0xF) | b[0];
			gp.y = (gp.y & ~0xF) | b[1];

			/* Call the landscape function and tell it that the vehicle entered the tile */
			r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
			if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;

			if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
				v->tile = gp.new_tile;
				v->state = TrackToTrackBits(track);
			}

			v->direction = (Direction)b[2];
		}
	} else {
		/* On a bridge */
		if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
			v->x_pos = gp.x;
			v->y_pos = gp.y;
			VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
			return;
		}
	}

	/* update image of ship, as well as delta XY */
	dir = ShipGetNewDirection(v, gp.x, gp.y);
	v->x_pos = gp.x;
	v->y_pos = gp.y;
	v->z_pos = GetSlopeZ(gp.x, gp.y);

getout:
	v->UpdateViewport(true, true);
	return;

reverse_direction:
	dir = ReverseDir(v->direction);
	v->direction = dir;
	goto getout;
}
示例#15
0
bool Tools::Astar(Node start, Node destination, bool **pathingMap, std::vector<Node>& path)
{
    //initialisation des structure necessaire
    bool solution = false;
    std::vector<Node> openNodes;
    std::vector<Node> closedNodes;
    std::map<Node,Node> parents;
    //initialisation du cout du premier node a 0
    start.SetG(0);
    start.SetH(0);
    //ajout au vecteur ouvert
    openNodes.push_back(start);
    Node current;
    int currentIndex;

    while (solution == false) {

        //Si le vecteur ouvert est vide il n'y a pas de solution
        if(openNodes.empty()) {
            return false;
        }
        //index pour faciliter le retrer de current au vecteur ouvert
        int index = 0;

        //choisi le meilleur noeud dans le vecteur ouvert
        current = BestNodeInVector(openNodes, index);

        //ajout dans le vecteur fermer
        closedNodes.push_back(current);
        currentIndex = closedNodes.size() - 1;
        //on suprime le node choisi du vecteur ouvert
        openNodes.erase(openNodes.begin()+index);

        //verification si on est a destination alors on quitte la boucle
        if (current.GetX() == destination.GetX() && current.GetY() == destination.GetY()) {
            solution = true;
            break;
        }

        //Verification de la case en bas a gauche
        if(CheckInBound(current.GetBottomLeftNode()) && Passable(current.GetBottomLeftNode(),pathingMap) && !VectorContainsNode(current.GetBottomLeftNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetBottomLeftNode(),openNodes)) {
                Node nodeToAdd = current.GetBottomLeftNode();
                nodeToAdd.SetG(current.GetG()+14);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetBottomLeftNode(),openNodes, 14,parents);
            }
        }

        //Verification de la case en bas
        if(CheckInBound(current.GetBottomNode()) && Passable(current.GetBottomNode(),pathingMap) && !VectorContainsNode(current.GetBottomNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetBottomNode(),openNodes)) {
                Node nodeToAdd = current.GetBottomNode();
                nodeToAdd.SetG(current.GetG()+10);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetBottomNode(),openNodes, 10,parents);
            }
        }
        //Verification de la case a gauche
        if(CheckInBound(current.GetLeftNode()) && Passable(current.GetLeftNode(),pathingMap) && !VectorContainsNode(current.GetLeftNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetLeftNode(),openNodes)) {
                Node nodeToAdd = current.GetLeftNode();
                nodeToAdd.SetG(current.GetG()+10);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetLeftNode(),openNodes, 10,parents);
            }
        }
        // Verification de la case en haut a gauche
        if(CheckInBound(current.GetTopLeftNode()) && Passable(current.GetTopLeftNode(),pathingMap) && !VectorContainsNode(current.GetTopLeftNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetTopLeftNode(),openNodes)) {
                Node nodeToAdd = current.GetTopLeftNode();
                nodeToAdd.SetG(current.GetG()+14);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetTopLeftNode(),openNodes, 14,parents);
            }
        }
        //Verification de la case en haut
        if(CheckInBound(current.GetTopNode()) && Passable(current.GetTopNode(),pathingMap) && !VectorContainsNode(current.GetTopNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetTopNode(),openNodes)) {
                Node nodeToAdd = current.GetTopNode();
                nodeToAdd.SetG(current.GetG()+10);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetTopNode(),openNodes, 10,parents);
            }
        }
        // Verification de la case en haut a droite
        if(CheckInBound(current.GetTopRightNode()) && Passable(current.GetTopRightNode(),pathingMap) && !VectorContainsNode(current.GetTopRightNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetTopRightNode(),openNodes)) {
                Node nodeToAdd = current.GetTopRightNode();
                nodeToAdd.SetG(current.GetG()+14);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetTopRightNode(),openNodes, 14,parents);
            }
        }
        //Verification de la case a droite
        if(CheckInBound(current.GetRightNode()) && Passable(current.GetRightNode(),pathingMap) && !VectorContainsNode(current.GetRightNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetRightNode(),openNodes)) {
                Node nodeToAdd = current.GetRightNode();
                nodeToAdd.SetG(current.GetG()+10);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetRightNode(),openNodes, 10,parents);
            }
        }
        // Verification de la case en bas a droite
        if(CheckInBound(current.GetBottomRightNode()) && Passable(current.GetBottomRightNode(),pathingMap) && !VectorContainsNode(current.GetBottomRightNode(),closedNodes))
        {
            if(!VectorContainsNode(current.GetBottomRightNode(),openNodes)) {
                Node nodeToAdd = current.GetBottomRightNode();
                nodeToAdd.SetG(current.GetG()+14);
                nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10);
                nodeToAdd.SetParent(&closedNodes[currentIndex]);
                parents[nodeToAdd] = closedNodes[currentIndex];
                openNodes.push_back(nodeToAdd);
            }
            else
            {
                UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetBottomRightNode(),openNodes, 14,parents);
            }
        }
    }

    //Si on trouve une solution alors on Backtrack jusqu'au noeux d'origine
    if(solution == true) {

//      Implementation avec les pointeur parent directement dans les Node
//        Node *currentBactrack = &closedNodes[currentIndex];
//        path.push_back(*currentBactrack);
//        while (currentBactrack->HasParent()){
//            std::cout << "solution x : " << currentBactrack->GetX()<<" solution y : " << currentBactrack->GetY() << "\n";
//            std::cout << "trackback : "<< path.size() << "\n";
//            currentBactrack = currentBactrack->GetParent();
//            std::cout << "test";
//            path.push_back(*currentBactrack);
//            std::cout << " solution x : " << currentBactrack->GetX()<<" solution y : " << currentBactrack->GetY() << "\n";
//
//        }

        //Implementation en utilisant une map entre les Nodes et leur parents
        Node currentBactrack = closedNodes[currentIndex];
        path.push_back(currentBactrack);
        std::map<Node,Node>::iterator it = parents.find(currentBactrack);
        while(it != parents.end()) {
            currentBactrack = it->second;
            //std::cout << "solution x : " << currentBactrack.GetX()<<" solution y : " << currentBactrack.GetY() << "\n";
            //std::cout << "trackback : "<< path.size() << "\n";
            path.push_back(currentBactrack);
            it = parents.find(currentBactrack);

        }
    }
    return true;
}