improve performance of AiEnemyUnitsInDistance
This commit is contained in:
parent
300db83ef4
commit
f7c12a74f0
3 changed files with 34 additions and 22 deletions
|
@ -459,8 +459,8 @@ extern int AiFindWall(AiForce *force);
|
|||
/// Plan the an attack
|
||||
/// Send explorers around the map
|
||||
extern void AiSendExplorers();
|
||||
/// Enemy units in distance
|
||||
extern int AiEnemyUnitsInDistance(const CPlayer &player, const CUnitType *type,
|
||||
/// Check if there are enemy units in a given range (optionally of type)
|
||||
extern bool AiEnemyUnitsInDistance(const CPlayer &player, const CUnitType *type,
|
||||
const Vec2i &pos, unsigned range);
|
||||
|
||||
//
|
||||
|
|
|
@ -169,18 +169,20 @@ static int AiCheckUnitTypeCosts(const CUnitType &type)
|
|||
return AiCheckCosts(type.Stats[AiPlayer->Player->Index].Costs);
|
||||
}
|
||||
|
||||
template <bool ignoreVisibility = false>
|
||||
class IsAEnemyUnitOf
|
||||
{
|
||||
public:
|
||||
explicit IsAEnemyUnitOf(const CPlayer &_player) : player(&_player) {}
|
||||
bool operator()(const CUnit *unit) const
|
||||
{
|
||||
return unit->IsVisibleAsGoal(*player) && unit->IsEnemy(*player);
|
||||
return (ignoreVisibility || unit->IsVisibleAsGoal(*player)) && unit->IsEnemy(*player);
|
||||
}
|
||||
private:
|
||||
const CPlayer *player;
|
||||
};
|
||||
|
||||
template <bool ignoreVisibility = false>
|
||||
class IsAEnemyUnitWhichCanCounterAttackOf
|
||||
{
|
||||
public:
|
||||
|
@ -189,7 +191,7 @@ public:
|
|||
{}
|
||||
bool operator()(const CUnit *unit) const
|
||||
{
|
||||
return unit->IsVisibleAsGoal(*player)
|
||||
return (ignoreVisibility || unit->IsVisibleAsGoal(*player))
|
||||
&& unit->IsEnemy(*player)
|
||||
&& CanTarget(*unit->Type, *type);
|
||||
}
|
||||
|
@ -199,42 +201,42 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
** Enemy units in distance.
|
||||
** Check if there are enemy units in a given range.
|
||||
**
|
||||
** @param player Find enemies of this player
|
||||
** @param type Optional unit type to check if enemy can target this
|
||||
** @param pos location
|
||||
** @param range Distance range to look.
|
||||
**
|
||||
** @return Number of enemy units.
|
||||
** @return If there are any enemy units in the range
|
||||
*/
|
||||
int AiEnemyUnitsInDistance(const CPlayer &player,
|
||||
const CUnitType *type, const Vec2i &pos, unsigned range)
|
||||
bool AiEnemyUnitsInDistance(const CPlayer &player,
|
||||
const CUnitType *type, const Vec2i &pos, unsigned range)
|
||||
{
|
||||
const Vec2i offset(range, range);
|
||||
std::vector<CUnit *> units;
|
||||
|
||||
if (type == NULL) {
|
||||
Select(pos - offset, pos + offset, units, IsAEnemyUnitOf(player));
|
||||
Select<1>(pos - offset, pos + offset, units, IsAEnemyUnitOf<true>(player));
|
||||
return static_cast<int>(units.size());
|
||||
} else {
|
||||
const Vec2i typeSize(type->TileWidth - 1, type->TileHeight - 1);
|
||||
const IsAEnemyUnitWhichCanCounterAttackOf pred(player, *type);
|
||||
const IsAEnemyUnitWhichCanCounterAttackOf<true> pred(player, *type);
|
||||
|
||||
Select(pos - offset, pos + typeSize + offset, units, pred);
|
||||
Select<1>(pos - offset, pos + typeSize + offset, units, pred);
|
||||
return static_cast<int>(units.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Enemy units in distance.
|
||||
** Check if there are enemy units in a given range.
|
||||
**
|
||||
** @param unit Find in distance for this unit.
|
||||
** @param range Distance range to look.
|
||||
**
|
||||
** @return Number of enemy units.
|
||||
** @return If there are any enemy units in the range
|
||||
*/
|
||||
int AiEnemyUnitsInDistance(const CUnit &unit, unsigned range)
|
||||
bool AiEnemyUnitsInDistance(const CUnit &unit, unsigned range)
|
||||
{
|
||||
return AiEnemyUnitsInDistance(*unit.Player, unit.Type, unit.tilePos, range);
|
||||
}
|
||||
|
|
|
@ -221,12 +221,14 @@ void Select(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units)
|
|||
void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units);
|
||||
void SelectAroundUnit(const CUnit &unit, int range, std::vector<CUnit *> &around);
|
||||
|
||||
template <typename Pred>
|
||||
template <int selectMax = 0, typename Pred>
|
||||
void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units, Pred pred)
|
||||
{
|
||||
Assert(Map.Info.IsPointOnMap(ltPos));
|
||||
Assert(Map.Info.IsPointOnMap(rbPos));
|
||||
Assert(units.empty());
|
||||
units.reserve(selectMax << 1);
|
||||
int max = selectMax || INT_MAX;
|
||||
|
||||
for (Vec2i posIt = ltPos; posIt.y != rbPos.y + 1; ++posIt.y) {
|
||||
for (posIt.x = ltPos.x; posIt.x != rbPos.x + 1; ++posIt.x) {
|
||||
|
@ -236,9 +238,17 @@ void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &u
|
|||
for (size_t i = 0; i != cache.size(); ++i) {
|
||||
CUnit &unit = *cache[i];
|
||||
|
||||
if (unit.CacheLock == 0 && pred(&unit)) {
|
||||
unit.CacheLock = 1;
|
||||
units.push_back(&unit);
|
||||
if ((selectMax == 1 || unit.CacheLock == 0) && pred(&unit)) {
|
||||
if (selectMax == 1) {
|
||||
units.push_back(&unit);
|
||||
return;
|
||||
} else {
|
||||
unit.CacheLock = 1;
|
||||
units.push_back(&unit);
|
||||
if (--max == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,25 +258,25 @@ void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &u
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
template <int selectMax = 0, typename Pred>
|
||||
void SelectAroundUnit(const CUnit &unit, int range, std::vector<CUnit *> &around, Pred pred)
|
||||
{
|
||||
const Vec2i offset(range, range);
|
||||
const Vec2i typeSize(unit.Type->TileWidth - 1, unit.Type->TileHeight - 1);
|
||||
|
||||
Select(unit.tilePos - offset,
|
||||
Select<selectMax>(unit.tilePos - offset,
|
||||
unit.tilePos + typeSize + offset, around,
|
||||
MakeAndPredicate(IsNotTheSameUnitAs(unit), pred));
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
template <int selectMax = 0, typename Pred>
|
||||
void Select(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units, Pred pred)
|
||||
{
|
||||
Vec2i minPos = ltPos;
|
||||
Vec2i maxPos = rbPos;
|
||||
|
||||
Map.FixSelectionArea(minPos, maxPos);
|
||||
SelectFixed(minPos, maxPos, units, pred);
|
||||
SelectFixed<selectMax>(minPos, maxPos, units, pred);
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
|
|
Loading…
Reference in a new issue