Esempio n. 1
0
/**
**  Can the unit 'src' reach the place x,y.
**
**  @param src       Unit for the path.
**  @param x         Map X tile position.
**  @param y         Map Y tile position.
**  @param w         Width of Goal
**  @param h         Height of Goal
**  @param minrange  min range to the tile
**  @param range     Range to the tile.
**
**  @pre             The unit's field flags must have been marked
**                   on the map; see MarkUnitFieldFlags.
**
**  @return          Distance to place.
*/
int PlaceReachable(const CUnit *src, int x, int y, int w, int h, int minrange, int range)
{
	// Please do not use UnmarkUnitFieldFlags and MarkUnitFieldFlags
	// around PlaceReachable calls.
	Assert((Map.Field(src->X, src->Y)->Flags & src->Type->FieldFlags) != 0);

	UnmarkUnitFieldFlags(src);
	int i = AStarFindPath(src->X, src->Y, x, y, w, h,
		src->Type->TileWidth, src->Type->TileHeight, minrange, range, NULL, 0, (void *)src);
	MarkUnitFieldFlags(src);

	switch (i) {
		case PF_FAILED:
		case PF_UNREACHABLE:
		case PF_REACHED:
			i = 0;
			break;
		case PF_WAIT:
			Assert(0);
			i = 0;
			break;
		case PF_MOVE:
			break;
		default:
			break;
	}

	return i;
}
Esempio n. 2
0
/**
**  Find new path.
**
**  The destination could be a unit or a field.
**  Range gives how far we must reach the goal.
**
**  @note  The destination could become negative coordinates!
**
**  @param unit  Path for this unit.
**
**  @return      >0 remaining path length, 0 wait for path, -1
**               reached goal, -2 can't reach the goal.
*/
static int NewPath(PathFinderInput &input, PathFinderOutput &output)
{
	char *path = output.Path;
	int i = AStarFindPath(input.GetUnitPos(),
						  input.GetGoalPos(),
						  input.GetGoalSize().x, input.GetGoalSize().y,
						  input.GetUnitSize().x, input.GetUnitSize().y,
						  input.GetMinRange(), input.GetMaxRange(),
						  path, PathFinderOutput::MAX_PATH_LENGTH,
						  *input.GetUnit());
	input.PathRacalculated();
	if (i == PF_FAILED) {
		i = PF_UNREACHABLE;
	}

	// Update path if it was requested. Otherwise we may only want
	// to know if there exists a path.
	if (path != NULL) {
		output.Length = std::min<int>(i, PathFinderOutput::MAX_PATH_LENGTH);
		if (output.Length == 0) {
			++output.Length;
		}
	}
	return i;
}
Esempio n. 3
0
/**
**  Can the unit 'src' reach the place goalPos.
**
**  @param src       Unit for the path.
**  @param goalPos   Map tile position.
**  @param w         Width of Goal
**  @param h         Height of Goal
**  @param minrange  min range to the tile
**  @param range     Range to the tile.
**
**  @return          Distance to place.
*/
int PlaceReachable(const CUnit &src, const Vec2i &goalPos, int w, int h, int minrange, int range)
{
	int i = AStarFindPath(src.tilePos, goalPos, w, h,
						  src.Type->TileWidth, src.Type->TileHeight,
						  minrange, range, NULL, 0, src);

	switch (i) {
		case PF_FAILED:
		case PF_UNREACHABLE:
			i = 0;
			break;
		case PF_REACHED:
			/* since most of this function usage check return value as bool
			 * then reached state should be track as true value */
			i = 1;
			break;
		case PF_WAIT:
			Assert(0);
			i = 0;
			break;
		case PF_MOVE:
			break;
		default:
			break;
	}
	return i;
}
Esempio n. 4
0
/**
**	Returns the next element of a path with astar algo.
**
**	@param unit	Unit that wants the path element. 
**	@param pxd	Pointer for the x direction.
**	@param pyd	Pointer for the y direction.
**
**	@returns	>0 remaining path length, 0 wait for path, -1
**			reached goal, -2 can't reach the goal.
*/
global int AStarNextPathElement(Unit* unit,int* pxd,int *pyd)
{
    // FIXME: Cache for often used pathes, like peons to goldmine.
    AStarFindPath(unit,pxd,pyd);

    switch( NewPath(unit,pxd,pyd) ) {
	case 0:
	    return 999;
	case 1:
	    return -1;
	default:
	    return -2;
    }
}
Esempio n. 5
0
//Wyrmgus start
//int PlaceReachable(const CUnit &src, const Vec2i &goalPos, int w, int h, int minrange, int range)
int PlaceReachable(const CUnit &src, const Vec2i &goalPos, int w, int h, int minrange, int range, int max_length, int z)
//Wyrmgus end
{
	//Wyrmgus start
	if (src.MapLayer != z) {
		return 0;
	}
	//Wyrmgus end
	
	int i = AStarFindPath(src.tilePos, goalPos, w, h,
						  src.Type->TileWidth, src.Type->TileHeight,
						  //Wyrmgus start
//						  minrange, range, NULL, 0, src);
						  minrange, range, NULL, 0, src, max_length, z);
						  //Wyrmgus end

	switch (i) {
		case PF_FAILED:
		case PF_UNREACHABLE:
			i = 0;
			break;
		case PF_REACHED:
			/* since most of this function usage check return value as bool
			 * then reached state should be track as true value */
			i = 1;
			break;
		case PF_WAIT:
			Assert(0);
			i = 0;
			break;
		case PF_MOVE:
			break;
		default:
			break;
	}
	return i;
}
Esempio n. 6
0
/**
**  Find new path.
**
**  The destination could be a unit or a field.
**  Range gives how far we must reach the goal.
**
**  @note  The destination could become negative coordinates!
**
**  @param unit  Path for this unit.
**
**  @pre         The unit's field flags must have been unmarked
**               on the map; see UnmarkUnitFieldFlags.
**
**  @return      >0 remaining path length, 0 wait for path, -1
**               reached goal, -2 can't reach the goal.
*/
int NewPath(CUnit *unit)
{
	int i;
	int gw;
	int gh;
	int gx;
	int gy;
	int minrange;
	int maxrange;
	char *path;

	// Please use UnmarkUnitFieldFlags and MarkUnitFieldFlags
	// around NewPath calls.
	Assert((Map.Field(unit->X, unit->Y)->Flags & unit->Type->FieldFlags) == 0);

	if (unit->Orders[0]->Goal) {
		gw = unit->Orders[0]->Goal->Type->TileWidth;
		gh = unit->Orders[0]->Goal->Type->TileHeight;
		gx = unit->Orders[0]->Goal->X;
		gy = unit->Orders[0]->Goal->Y;
		maxrange = unit->Orders[0]->Range;
		minrange = unit->Orders[0]->MinRange;
	} else {
		// Take care of non square goals :)
		// If goal is non square, range states a non-existant goal rather
		// than a tile.
		gw = unit->Orders[0]->Width;
		gh = unit->Orders[0]->Height;
		maxrange = unit->Orders[0]->Range;
		minrange = unit->Orders[0]->MinRange;
		// Large units may have a goal that goes outside the map, fix it here
		if (unit->Orders[0]->X + unit->Type->TileWidth - 1 >= Map.Info.MapWidth) {
			unit->Orders[0]->X = Map.Info.MapWidth - unit->Type->TileWidth;
		}
		if (unit->Orders[0]->Y + unit->Type->TileHeight - 1 >= Map.Info.MapHeight) {
			unit->Orders[0]->Y = Map.Info.MapHeight - unit->Type->TileHeight;
		}
		gx = unit->Orders[0]->X;
		gy = unit->Orders[0]->Y;
	}
	path = unit->Data.Move.Path;
	i = AStarFindPath(unit->X, unit->Y, gx, gy, gw, gh,
		unit->Type->TileWidth, unit->Type->TileHeight, minrange, maxrange, path, MAX_PATH_LENGTH, unit);
	if (i == PF_FAILED) {
		i = PF_UNREACHABLE;
	}

	// Update path if it was requested. Otherwise we may only want
	// to know if there exists a path.

	if (path != NULL) {
		if (i >= MAX_PATH_LENGTH) {
			unit->Data.Move.Length = MAX_PATH_LENGTH;
		} else {
			unit->Data.Move.Length = i;
		}
		if (unit->Data.Move.Length == 0) {
			++unit->Data.Move.Length;
		}
	}
	return i;
}