Find a more logical position to harvest giving a pos inside wood (but still ignore peon pos in computation).
This commit is contained in:
parent
28f4a213c3
commit
37b23caeb1
4 changed files with 74 additions and 78 deletions
src
|
@ -71,22 +71,73 @@
|
|||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
class NearReachableTerrainFinder
|
||||
{
|
||||
public:
|
||||
NearReachableTerrainFinder(const CPlayer &player, int maxDist, int movemask, int resmask, Vec2i* resPos) :
|
||||
player(player), maxDist(maxDist), movemask(movemask), resmask(resmask), resPos(resPos) {}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
const CPlayer &player;
|
||||
int maxDist;
|
||||
int movemask;
|
||||
int resmask;
|
||||
Vec2i* resPos;
|
||||
};
|
||||
|
||||
VisitResult NearReachableTerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
{
|
||||
if (!player.AiEnabled && !Map.IsFieldExplored(player, pos)) {
|
||||
terrainTraversal.Get(pos) = -1;
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
// Look if found what was required.
|
||||
if (CanMoveToMask(pos, movemask)) {
|
||||
if (resPos) {
|
||||
*resPos = from;
|
||||
}
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
if (Map.CheckMask(pos, resmask)) { // reachable
|
||||
terrainTraversal.Get(pos) = terrainTraversal.Get(from) + 1;
|
||||
if (terrainTraversal.Get(pos) <= maxDist) {
|
||||
return VisitResult_Ok;
|
||||
} else {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
} else { // unreachable
|
||||
terrainTraversal.Get(pos) = -1;
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
static bool FindNearestReachableTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *terrainPos)
|
||||
{
|
||||
TerrainTraversal terrainTraversal;
|
||||
|
||||
terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight);
|
||||
terrainTraversal.Init(-1);
|
||||
|
||||
Assert(Map.CheckMask(startPos, resmask));
|
||||
terrainTraversal.PushPos(startPos);
|
||||
|
||||
NearReachableTerrainFinder nearReachableTerrainFinder(player, range, movemask, resmask, terrainPos);
|
||||
|
||||
return terrainTraversal.Run(nearReachableTerrainFinder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* static */ COrder *COrder::NewActionResource(CUnit &harvester, const Vec2i &pos)
|
||||
{
|
||||
COrder_Resource *order = new COrder_Resource(harvester);
|
||||
Vec2i ressourceLoc;
|
||||
|
||||
// Find the closest piece of wood next to a tile where the unit can move
|
||||
if (!FindTerrainType(0, (harvester.Type->MovementMask), 1, 20, *harvester.Player, pos, &ressourceLoc)) {
|
||||
if (!FindNearestReachableTerrainType(harvester.Type->MovementMask, MapFieldForest, 20, *harvester.Player, pos, &ressourceLoc)) {
|
||||
DebugPrint("FIXME: Give up???\n");
|
||||
}
|
||||
// Max Value > 1
|
||||
if ((MyAbs(ressourceLoc.x - pos.x) | MyAbs(ressourceLoc.y - pos.y)) > 1) {
|
||||
if (!FindTerrainType(0, MapFieldForest, 0, 20, *harvester.Player, ressourceLoc, &ressourceLoc)) {
|
||||
DebugPrint("FIXME: Give up???\n");
|
||||
}
|
||||
} else {
|
||||
// The destination is next to a reachable tile.
|
||||
ressourceLoc = pos;
|
||||
}
|
||||
order->goalPos = ressourceLoc;
|
||||
|
@ -320,8 +371,7 @@ int COrder_Resource::MoveToResource_Terrain(CUnit &unit)
|
|||
|
||||
// Wood gone, look somewhere else.
|
||||
if ((Map.Info.IsPointOnMap(pos) == false || Map.ForestOnMap(pos) == false) && (!unit.IX) && (!unit.IY)) {
|
||||
if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 16,
|
||||
*unit.Player, this->goalPos, &pos)) {
|
||||
if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 16, *unit.Player, this->goalPos, &pos)) {
|
||||
// no wood in range
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -331,8 +381,7 @@ int COrder_Resource::MoveToResource_Terrain(CUnit &unit)
|
|||
switch (DoActionMove(unit)) {
|
||||
case PF_UNREACHABLE:
|
||||
unit.Wait = 10;
|
||||
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 9999,
|
||||
*unit.Player, unit.tilePos, &pos)) {
|
||||
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 9999, *unit.Player, unit.tilePos, &pos)) {
|
||||
this->goalPos = pos;
|
||||
DebugPrint("Found a better place to harvest %d,%d\n" _C_ pos.x _C_ pos.y);
|
||||
// FIXME: can't this overflow? It really shouldn't, since
|
||||
|
@ -959,7 +1008,7 @@ bool COrder_Resource::WaitInDepot(CUnit &unit)
|
|||
if (resinfo.TerrainHarvester) {
|
||||
Vec2i pos = this->Resource.Pos;
|
||||
|
||||
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 10, *unit.Player, pos, &pos)) {
|
||||
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 10, *unit.Player, pos, &pos)) {
|
||||
if (depot) {
|
||||
DropOutNearest(unit, pos, depot);
|
||||
}
|
||||
|
|
|
@ -835,7 +835,7 @@ static int AiAssignHarvesterFromTerrain(CUnit &unit, int resource)
|
|||
Vec2i forestPos;
|
||||
|
||||
// Code for terrain harvesters. Search for piece of terrain to mine.
|
||||
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 1000, *unit.Player, unit.tilePos, &forestPos)) {
|
||||
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 1000, *unit.Player, unit.tilePos, &forestPos)) {
|
||||
CommandResourceLoc(unit, forestPos, FlushCommands);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -947,7 +947,7 @@ extern CUnit *FindDeposit(const CUnit &unit, int range, int resource);
|
|||
extern CUnit *FindIdleWorker(const CPlayer &player, const CUnit *last);
|
||||
|
||||
/// Find the neareast piece of terrain with specific flags.
|
||||
extern bool FindTerrainType(int movemask, int resmask, int rvresult, int range,
|
||||
extern bool FindTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *pos);
|
||||
|
||||
/// @todo more docu
|
||||
|
|
|
@ -2008,8 +2008,8 @@ void DropOutAll(const CUnit &source)
|
|||
class TerrainFinder
|
||||
{
|
||||
public:
|
||||
TerrainFinder(const CPlayer &player, int maxDist, int movemask, int resmask, Vec2i* resPos, Vec2i* lastPos) :
|
||||
player(player), maxDist(maxDist), movemask(movemask), resmask(resmask), resPos(resPos), lastPos(lastPos) {}
|
||||
TerrainFinder(const CPlayer &player, int maxDist, int movemask, int resmask, Vec2i* resPos) :
|
||||
player(player), maxDist(maxDist), movemask(movemask), resmask(resmask), resPos(resPos) {}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
const CPlayer &player;
|
||||
|
@ -2017,22 +2017,6 @@ private:
|
|||
int movemask;
|
||||
int resmask;
|
||||
Vec2i* resPos;
|
||||
Vec2i* lastPos;
|
||||
};
|
||||
|
||||
class TerrainFinder_Inv
|
||||
{
|
||||
public:
|
||||
TerrainFinder_Inv(const CPlayer &player, int maxDist, int movemask, int resmask, Vec2i* resPos, Vec2i* lastPos) :
|
||||
player(player), maxDist(maxDist), movemask(movemask), resmask(resmask), resPos(resPos), lastPos(lastPos) {}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
const CPlayer &player;
|
||||
int maxDist;
|
||||
int movemask;
|
||||
int resmask;
|
||||
Vec2i* resPos;
|
||||
Vec2i* lastPos;
|
||||
};
|
||||
|
||||
VisitResult TerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
|
@ -2042,11 +2026,9 @@ VisitResult TerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i
|
|||
return VisitResult_DeadEnd;
|
||||
}
|
||||
// Look if found what was required.
|
||||
bool can_move_to = CanMoveToMask(pos, resmask);
|
||||
if (!can_move_to) {
|
||||
*resPos = pos;
|
||||
if (lastPos) {
|
||||
*lastPos = from;
|
||||
if (Map.CheckMask(pos, resmask)) {
|
||||
if (resPos) {
|
||||
*resPos = pos;
|
||||
}
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
|
@ -2063,53 +2045,24 @@ VisitResult TerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i
|
|||
}
|
||||
}
|
||||
|
||||
VisitResult TerrainFinder_Inv::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
{
|
||||
if (!player.AiEnabled && !Map.IsFieldExplored(player, pos)) {
|
||||
terrainTraversal.Get(pos) = -1;
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
// Look if found what was required.
|
||||
bool can_move_to = CanMoveToMask(pos, resmask);
|
||||
if (can_move_to) {
|
||||
*resPos = pos;
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
if (CanMoveToMask(pos, movemask)) { // reachable
|
||||
terrainTraversal.Get(pos) = terrainTraversal.Get(from) + 1;
|
||||
if (terrainTraversal.Get(pos) <= maxDist) {
|
||||
return VisitResult_Ok;
|
||||
} else {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
} else { // unreachable
|
||||
terrainTraversal.Get(pos) = -1;
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Find the closest piece of terrain with the given flags.
|
||||
**
|
||||
** @param movemask The movement mask to reach that location.
|
||||
** @param resmask Result tile mask.
|
||||
** @param rvresult Return a tile that doesn't match.
|
||||
** @param range Maximum distance for the search.
|
||||
** @param player Only search fields explored by player
|
||||
** @param startPos Map start position for the search.
|
||||
**
|
||||
** @param pos OUT: Map position of tile.
|
||||
** @param terrainPos OUT: Map position of tile.
|
||||
**
|
||||
** @note Movement mask can be 0xFFFFFFFF to have no effect
|
||||
** Range is not circular, but square.
|
||||
** Player is ignored if nil(search the entire map)
|
||||
** Use rvresult if you search for a tile that doesn't
|
||||
** match resmask. Like for a tile where an unit can go
|
||||
** with it's movement mask.
|
||||
**
|
||||
** @return True if wood was found.
|
||||
*/
|
||||
bool FindTerrainType(int movemask, int resmask, int rvresult, int range,
|
||||
bool FindTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *terrainPos)
|
||||
{
|
||||
TerrainTraversal terrainTraversal;
|
||||
|
@ -2119,15 +2072,9 @@ bool FindTerrainType(int movemask, int resmask, int rvresult, int range,
|
|||
|
||||
terrainTraversal.PushPos(startPos);
|
||||
|
||||
if (rvresult) {
|
||||
TerrainFinder_Inv terrainFinder(player, range, movemask, resmask, terrainPos, NULL);
|
||||
TerrainFinder terrainFinder(player, range, movemask, resmask, terrainPos);
|
||||
|
||||
return terrainTraversal.Run(terrainFinder);
|
||||
} else {
|
||||
TerrainFinder terrainFinder(player, range, movemask, resmask, terrainPos, NULL);
|
||||
|
||||
return terrainTraversal.Run(terrainFinder);
|
||||
}
|
||||
return terrainTraversal.Run(terrainFinder);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue