/** ** 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; }
/** ** 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; }
/** ** 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; }
/** ** 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; } }
//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; }
/** ** 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; }