mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-17 20:58:07 +02:00
Use cached neighbouring tiles where possible
This commit is contained in:
parent
a99274d72e
commit
5f799d41b3
@ -959,8 +959,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getOneTurnReachableUn
|
||||
|
||||
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||
{
|
||||
BattleHexArray neighbours;
|
||||
neighbours.generateNeighbouringTiles(hex);
|
||||
const BattleHexArray & neighbours = BattleHexArray::neighbouringTilesCache[hex.hex];
|
||||
for(BattleHex neighbour : neighbours)
|
||||
{
|
||||
reachable = unitReachability.distances.at(neighbour) <= radius;
|
||||
@ -1022,7 +1021,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
|
||||
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||
{
|
||||
enemyUnit = true;
|
||||
for(BattleHex neighbour : BattleHexArray::generateNeighbouringTiles(hex))
|
||||
for(BattleHex neighbour : BattleHexArray::neighbouringTilesCache[hex.hex])
|
||||
{
|
||||
reachable = unitReachability.distances.at(neighbour) <= unitSpeed;
|
||||
|
||||
|
@ -107,7 +107,7 @@ static bool willSecondHexBlockMoreEnemyShooters(std::shared_ptr<CBattleCallback>
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
for (auto neighbour : BattleHexArray::generateNeighbouringTiles(i ? h2 : h1))
|
||||
for (auto neighbour : BattleHexArray::neighbouringTilesCache[i ? h2.hex : h1.hex])
|
||||
if(const auto * s = cb->getBattle(battleID)->battleGetUnitByPos(neighbour))
|
||||
if(s->isShooter())
|
||||
shooters[i]++;
|
||||
|
@ -22,7 +22,7 @@ BattleHexArray::BattleHexArray(std::initializer_list<BattleHex> initList) noexce
|
||||
}
|
||||
}
|
||||
|
||||
BattleHex BattleHexArray::getClosestTile(BattleSide side, BattleHex initialPos)
|
||||
BattleHex BattleHexArray::getClosestTile(BattleSide side, BattleHex initialPos) const
|
||||
{
|
||||
BattleHex initialHex = BattleHex(initialPos);
|
||||
auto compareDistance = [initialHex](const BattleHex left, const BattleHex right) -> bool
|
||||
@ -54,8 +54,76 @@ BattleHex BattleHexArray::getClosestTile(BattleSide side, BattleHex initialPos)
|
||||
};
|
||||
boost::sort(sortedTiles, compareHorizontal);
|
||||
return sortedTiles.front();
|
||||
}
|
||||
|
||||
BattleHexArray::NeighbouringTilesCache BattleHexArray::calculateNeighbouringTiles()
|
||||
{
|
||||
BattleHexArray::NeighbouringTilesCache ret;
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
BattleHexArray hexes = BattleHexArray::generateNeighbouringTiles(hex);
|
||||
|
||||
size_t index = 0;
|
||||
ret[hex].resize(hexes.size());
|
||||
for(auto neighbour : hexes)
|
||||
ret[hex].set(index++, neighbour);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray BattleHexArray::generateNeighbouringTiles(BattleHex hex)
|
||||
{
|
||||
BattleHexArray ret;
|
||||
for(auto dir : BattleHex::hexagonalDirections())
|
||||
ret.checkAndPush(hex.cloneInDirection(dir, false));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray BattleHexArray::generateAttackerClosestTilesCache()
|
||||
{
|
||||
assert(!neighbouringTilesCache.empty());
|
||||
|
||||
BattleHexArray ret;
|
||||
|
||||
ret.resize(GameConstants::BFIELD_SIZE);
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
ret.set(hex, neighbouringTilesCache[hex].getClosestTile(BattleSide::ATTACKER, hex));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray BattleHexArray::generateDefenderClosestTilesCache()
|
||||
{
|
||||
assert(!neighbouringTilesCache.empty());
|
||||
|
||||
BattleHexArray ret;
|
||||
|
||||
ret.resize(GameConstants::BFIELD_SIZE);
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
ret.set(hex, neighbouringTilesCache[hex].getClosestTile(BattleSide::DEFENDER, hex));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHex BattleHexArray::getClosestTileFromAllPossibleNeighbours(BattleSide side, BattleHex pos)
|
||||
{
|
||||
if(side == BattleSide::ATTACKER)
|
||||
return closestTilesCacheForAttacker[pos.hex];
|
||||
else if(side == BattleSide::DEFENDER)
|
||||
return closestTilesCacheForDefender[pos.hex];
|
||||
else
|
||||
assert(false); // we should never be here
|
||||
}
|
||||
|
||||
void BattleHexArray::merge(const BattleHexArray & other) noexcept
|
||||
{
|
||||
for(auto hex : other)
|
||||
@ -82,22 +150,9 @@ void BattleHexArray::clear() noexcept
|
||||
internalStorage.clear();
|
||||
}
|
||||
|
||||
static BattleHexArray::NeighbouringTilesCache calculateNeighbouringTiles()
|
||||
{
|
||||
BattleHexArray::NeighbouringTilesCache ret;
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
auto hexes = BattleHexArray::generateNeighbouringTiles(hex);
|
||||
|
||||
size_t index = 0;
|
||||
for(auto neighbour : hexes)
|
||||
ret[hex].at(index++) = neighbour;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const BattleHexArray::NeighbouringTilesCache BattleHexArray::neighbouringTilesCache = calculateNeighbouringTiles();
|
||||
|
||||
const BattleHexArray BattleHexArray::closestTilesCacheForAttacker = generateAttackerClosestTilesCache();
|
||||
const BattleHexArray BattleHexArray::closestTilesCacheForDefender = generateDefenderClosestTilesCache();
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -33,10 +33,11 @@ public:
|
||||
using reverse_iterator = typename StorageType::reverse_iterator;
|
||||
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
||||
|
||||
using NeighbouringTiles = std::array<BattleHex, 6>;
|
||||
using NeighbouringTilesCache = std::array<NeighbouringTiles, GameConstants::BFIELD_SIZE>;
|
||||
using NeighbouringTilesCache = std::array<BattleHexArray, GameConstants::BFIELD_SIZE>;
|
||||
|
||||
static const NeighbouringTilesCache neighbouringTilesCache;
|
||||
static const BattleHexArray closestTilesCacheForAttacker;
|
||||
static const BattleHexArray closestTilesCacheForDefender;
|
||||
|
||||
BattleHexArray() noexcept
|
||||
{
|
||||
@ -62,16 +63,6 @@ public:
|
||||
|
||||
BattleHexArray(std::initializer_list<BattleHex> initList) noexcept;
|
||||
|
||||
/// returns all valid neighbouring tiles
|
||||
static BattleHexArray generateNeighbouringTiles(BattleHex hex)
|
||||
{
|
||||
BattleHexArray ret;
|
||||
for(auto dir : BattleHex::hexagonalDirections())
|
||||
ret.checkAndPush(hex.cloneInDirection(dir, false));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// returns all tiles, unavailable tiles will be set as invalid
|
||||
/// order of returned tiles matches EDir enum
|
||||
static BattleHexArray generateAllNeighbouringTiles(BattleHex hex)
|
||||
@ -86,8 +77,6 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHex getClosestTile(BattleSide side, BattleHex initialPos);
|
||||
|
||||
void checkAndPush(BattleHex tile)
|
||||
{
|
||||
if(tile.isAvailable() && !contains(tile))
|
||||
@ -114,6 +103,14 @@ public:
|
||||
/*if(isNotValidForInsertion(hex))
|
||||
return;*/
|
||||
|
||||
if(index >= internalStorage.size())
|
||||
{
|
||||
logGlobal->error("Invalid BattleHexArray::set index parameter. It is " + std::to_string(index)
|
||||
+ " and current size is " + std::to_string(internalStorage.size()));
|
||||
throw std::out_of_range("Invalid BattleHexArray::set index parameter. It is " + std::to_string(index)
|
||||
+ " and current size is " + std::to_string(internalStorage.size()));
|
||||
}
|
||||
|
||||
if(contains(hex))
|
||||
return;
|
||||
|
||||
@ -133,6 +130,10 @@ public:
|
||||
return internalStorage.insert(pos, hex);
|
||||
}
|
||||
|
||||
static BattleHex getClosestTileFromAllPossibleNeighbours(BattleSide side, BattleHex pos);
|
||||
|
||||
BattleHex getClosestTile(BattleSide side, BattleHex initialPos) const;
|
||||
|
||||
void merge(const BattleHexArray & other) noexcept;
|
||||
|
||||
void clear() noexcept;
|
||||
@ -295,6 +296,12 @@ private:
|
||||
{
|
||||
return hex == BattleHex::CASTLE_CENTRAL_TOWER || hex == BattleHex::CASTLE_UPPER_TOWER || hex == BattleHex::CASTLE_BOTTOM_TOWER;
|
||||
}
|
||||
|
||||
/// returns all valid neighbouring tiles
|
||||
static BattleHexArray::NeighbouringTilesCache calculateNeighbouringTiles();
|
||||
static BattleHexArray generateNeighbouringTiles(BattleHex hex);
|
||||
static BattleHexArray generateAttackerClosestTilesCache();
|
||||
static BattleHexArray generateDefenderClosestTilesCache();
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -204,7 +204,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
|
||||
|
||||
while (next != dest)
|
||||
{
|
||||
next = BattleHexArray::generateNeighbouringTiles(next).getClosestTile(direction, dest);
|
||||
next = BattleHexArray::neighbouringTilesCache[next].getClosestTile(direction, dest);
|
||||
ret.insert(next);
|
||||
}
|
||||
assert(!ret.empty());
|
||||
@ -1360,7 +1360,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
|
||||
}
|
||||
if(attacker->hasBonusOfType(BonusType::WIDE_BREATH))
|
||||
{
|
||||
BattleHexArray hexes = BattleHexArray::generateNeighbouringTiles(destinationTile);
|
||||
BattleHexArray hexes = BattleHexArray::neighbouringTilesCache[destinationTile];
|
||||
for(int i = 0; i < hexes.size(); i++)
|
||||
{
|
||||
if(hexes.at(i) == attackOriginHex)
|
||||
@ -1433,9 +1433,9 @@ AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::
|
||||
AttackableTiles at;
|
||||
RETURN_IF_NOT_BATTLE(at);
|
||||
|
||||
if(attacker->hasBonusOfType(BonusType::SHOOTS_ALL_ADJACENT) && !BattleHexArray::generateNeighbouringTiles(attackerPos).contains(destinationTile))
|
||||
if(attacker->hasBonusOfType(BonusType::SHOOTS_ALL_ADJACENT) && !BattleHexArray::neighbouringTilesCache[attackerPos].contains(destinationTile))
|
||||
{
|
||||
auto targetHexes = BattleHexArray::generateNeighbouringTiles(destinationTile);
|
||||
auto targetHexes = BattleHexArray::neighbouringTilesCache[destinationTile];
|
||||
targetHexes.insert(destinationTile);
|
||||
boost::copy(targetHexes, vstd::set_inserter(at.hostileCreaturePositions));
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
|
||||
|
||||
for(auto targetHex : targetHexes)
|
||||
{
|
||||
for(auto & n : BattleHexArray::generateNeighbouringTiles(targetHex))
|
||||
for(auto & n : BattleHexArray::neighbouringTilesCache[targetHex])
|
||||
{
|
||||
if(distances[n] < ret)
|
||||
{
|
||||
|
@ -88,7 +88,7 @@ BattleHexArray Unit::getSurroundingHexes(BattleHex position, bool twoHex, Battle
|
||||
}
|
||||
else
|
||||
{
|
||||
return BattleHexArray::generateNeighbouringTiles(position);
|
||||
return BattleHexArray::neighbouringTilesCache[position];
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
||||
hexes.pop_back();
|
||||
|
||||
for(auto hex : hexes)
|
||||
targetableHexes.merge(BattleHexArray::generateNeighbouringTiles(hex));
|
||||
targetableHexes.merge(BattleHexArray::neighbouringTilesCache[hex]);
|
||||
}
|
||||
|
||||
return targetableHexes;
|
||||
|
@ -610,7 +610,7 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
|
||||
{
|
||||
hexesToCheck.insert(stack->getPosition());
|
||||
|
||||
for(auto adjacent : BattleHexArray::generateNeighbouringTiles(stack->getPosition()))
|
||||
for(auto adjacent : BattleHexArray::neighbouringTilesCache[stack->getPosition().hex])
|
||||
hexesToCheck.insert(adjacent);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user