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))
|
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||||
{
|
{
|
||||||
BattleHexArray neighbours;
|
const BattleHexArray & neighbours = BattleHexArray::neighbouringTilesCache[hex.hex];
|
||||||
neighbours.generateNeighbouringTiles(hex);
|
|
||||||
for(BattleHex neighbour : neighbours)
|
for(BattleHex neighbour : neighbours)
|
||||||
{
|
{
|
||||||
reachable = unitReachability.distances.at(neighbour) <= radius;
|
reachable = unitReachability.distances.at(neighbour) <= radius;
|
||||||
@ -1022,7 +1021,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
|
|||||||
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||||
{
|
{
|
||||||
enemyUnit = true;
|
enemyUnit = true;
|
||||||
for(BattleHex neighbour : BattleHexArray::generateNeighbouringTiles(hex))
|
for(BattleHex neighbour : BattleHexArray::neighbouringTilesCache[hex.hex])
|
||||||
{
|
{
|
||||||
reachable = unitReachability.distances.at(neighbour) <= unitSpeed;
|
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(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(const auto * s = cb->getBattle(battleID)->battleGetUnitByPos(neighbour))
|
||||||
if(s->isShooter())
|
if(s->isShooter())
|
||||||
shooters[i]++;
|
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);
|
BattleHex initialHex = BattleHex(initialPos);
|
||||||
auto compareDistance = [initialHex](const BattleHex left, const BattleHex right) -> bool
|
auto compareDistance = [initialHex](const BattleHex left, const BattleHex right) -> bool
|
||||||
@ -56,6 +56,74 @@ BattleHex BattleHexArray::getClosestTile(BattleSide side, BattleHex initialPos)
|
|||||||
return sortedTiles.front();
|
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
|
void BattleHexArray::merge(const BattleHexArray & other) noexcept
|
||||||
{
|
{
|
||||||
for(auto hex : other)
|
for(auto hex : other)
|
||||||
@ -82,22 +150,9 @@ void BattleHexArray::clear() noexcept
|
|||||||
internalStorage.clear();
|
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::NeighbouringTilesCache BattleHexArray::neighbouringTilesCache = calculateNeighbouringTiles();
|
||||||
|
|
||||||
|
const BattleHexArray BattleHexArray::closestTilesCacheForAttacker = generateAttackerClosestTilesCache();
|
||||||
|
const BattleHexArray BattleHexArray::closestTilesCacheForDefender = generateDefenderClosestTilesCache();
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
@ -33,10 +33,11 @@ public:
|
|||||||
using reverse_iterator = typename StorageType::reverse_iterator;
|
using reverse_iterator = typename StorageType::reverse_iterator;
|
||||||
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
||||||
|
|
||||||
using NeighbouringTiles = std::array<BattleHex, 6>;
|
using NeighbouringTilesCache = std::array<BattleHexArray, GameConstants::BFIELD_SIZE>;
|
||||||
using NeighbouringTilesCache = std::array<NeighbouringTiles, GameConstants::BFIELD_SIZE>;
|
|
||||||
|
|
||||||
static const NeighbouringTilesCache neighbouringTilesCache;
|
static const NeighbouringTilesCache neighbouringTilesCache;
|
||||||
|
static const BattleHexArray closestTilesCacheForAttacker;
|
||||||
|
static const BattleHexArray closestTilesCacheForDefender;
|
||||||
|
|
||||||
BattleHexArray() noexcept
|
BattleHexArray() noexcept
|
||||||
{
|
{
|
||||||
@ -62,16 +63,6 @@ public:
|
|||||||
|
|
||||||
BattleHexArray(std::initializer_list<BattleHex> initList) noexcept;
|
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
|
/// returns all tiles, unavailable tiles will be set as invalid
|
||||||
/// order of returned tiles matches EDir enum
|
/// order of returned tiles matches EDir enum
|
||||||
static BattleHexArray generateAllNeighbouringTiles(BattleHex hex)
|
static BattleHexArray generateAllNeighbouringTiles(BattleHex hex)
|
||||||
@ -86,8 +77,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHex getClosestTile(BattleSide side, BattleHex initialPos);
|
|
||||||
|
|
||||||
void checkAndPush(BattleHex tile)
|
void checkAndPush(BattleHex tile)
|
||||||
{
|
{
|
||||||
if(tile.isAvailable() && !contains(tile))
|
if(tile.isAvailable() && !contains(tile))
|
||||||
@ -114,6 +103,14 @@ public:
|
|||||||
/*if(isNotValidForInsertion(hex))
|
/*if(isNotValidForInsertion(hex))
|
||||||
return;*/
|
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))
|
if(contains(hex))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -133,6 +130,10 @@ public:
|
|||||||
return internalStorage.insert(pos, hex);
|
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 merge(const BattleHexArray & other) noexcept;
|
||||||
|
|
||||||
void clear() 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;
|
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
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -204,7 +204,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
|
|||||||
|
|
||||||
while (next != dest)
|
while (next != dest)
|
||||||
{
|
{
|
||||||
next = BattleHexArray::generateNeighbouringTiles(next).getClosestTile(direction, dest);
|
next = BattleHexArray::neighbouringTilesCache[next].getClosestTile(direction, dest);
|
||||||
ret.insert(next);
|
ret.insert(next);
|
||||||
}
|
}
|
||||||
assert(!ret.empty());
|
assert(!ret.empty());
|
||||||
@ -1360,7 +1360,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
|
|||||||
}
|
}
|
||||||
if(attacker->hasBonusOfType(BonusType::WIDE_BREATH))
|
if(attacker->hasBonusOfType(BonusType::WIDE_BREATH))
|
||||||
{
|
{
|
||||||
BattleHexArray hexes = BattleHexArray::generateNeighbouringTiles(destinationTile);
|
BattleHexArray hexes = BattleHexArray::neighbouringTilesCache[destinationTile];
|
||||||
for(int i = 0; i < hexes.size(); i++)
|
for(int i = 0; i < hexes.size(); i++)
|
||||||
{
|
{
|
||||||
if(hexes.at(i) == attackOriginHex)
|
if(hexes.at(i) == attackOriginHex)
|
||||||
@ -1433,9 +1433,9 @@ AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::
|
|||||||
AttackableTiles at;
|
AttackableTiles at;
|
||||||
RETURN_IF_NOT_BATTLE(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);
|
targetHexes.insert(destinationTile);
|
||||||
boost::copy(targetHexes, vstd::set_inserter(at.hostileCreaturePositions));
|
boost::copy(targetHexes, vstd::set_inserter(at.hostileCreaturePositions));
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
|
|||||||
|
|
||||||
for(auto targetHex : targetHexes)
|
for(auto targetHex : targetHexes)
|
||||||
{
|
{
|
||||||
for(auto & n : BattleHexArray::generateNeighbouringTiles(targetHex))
|
for(auto & n : BattleHexArray::neighbouringTilesCache[targetHex])
|
||||||
{
|
{
|
||||||
if(distances[n] < ret)
|
if(distances[n] < ret)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ BattleHexArray Unit::getSurroundingHexes(BattleHex position, bool twoHex, Battle
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return BattleHexArray::generateNeighbouringTiles(position);
|
return BattleHexArray::neighbouringTilesCache[position];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
|||||||
hexes.pop_back();
|
hexes.pop_back();
|
||||||
|
|
||||||
for(auto hex : hexes)
|
for(auto hex : hexes)
|
||||||
targetableHexes.merge(BattleHexArray::generateNeighbouringTiles(hex));
|
targetableHexes.merge(BattleHexArray::neighbouringTilesCache[hex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return targetableHexes;
|
return targetableHexes;
|
||||||
|
@ -610,7 +610,7 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
|
|||||||
{
|
{
|
||||||
hexesToCheck.insert(stack->getPosition());
|
hexesToCheck.insert(stack->getPosition());
|
||||||
|
|
||||||
for(auto adjacent : BattleHexArray::generateNeighbouringTiles(stack->getPosition()))
|
for(auto adjacent : BattleHexArray::neighbouringTilesCache[stack->getPosition().hex])
|
||||||
hexesToCheck.insert(adjacent);
|
hexesToCheck.insert(adjacent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user