1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-19 21:10:12 +02:00

Merge pull request #5266 from MichalZr6/battlefield

Minor fixes to BattleHexArray. BattleHex'es as const reference where possible.
This commit is contained in:
Ivan Savenko 2025-01-25 17:44:14 +02:00 committed by GitHub
commit f858a6e04b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
63 changed files with 347 additions and 359 deletions

View File

@ -72,7 +72,7 @@ void DamageCache::buildObstacleDamageCache(std::shared_ptr<HypotheticBattle> hb,
auto damageDealt = stack->getAvailableHealth() - updated->getAvailableHealth(); auto damageDealt = stack->getAvailableHealth() - updated->getAvailableHealth();
for(auto hex : affectedHexes) for(const auto & hex : affectedHexes)
{ {
obstacleDamage[hex][stack->unitId()] = damageDealt; obstacleDamage[hex][stack->unitId()] = damageDealt;
} }
@ -129,7 +129,7 @@ int64_t DamageCache::getDamage(const battle::Unit * attacker, const battle::Unit
return damageCache[attacker->unitId()][defender->unitId()] * attacker->getCount(); return damageCache[attacker->unitId()][defender->unitId()] * attacker->getCount();
} }
int64_t DamageCache::getObstacleDamage(BattleHex hex, const battle::Unit * defender) int64_t DamageCache::getObstacleDamage(const BattleHex & hex, const battle::Unit * defender)
{ {
if(parent) if(parent)
return parent->getObstacleDamage(hex, defender); return parent->getObstacleDamage(hex, defender);
@ -166,7 +166,7 @@ int64_t DamageCache::getOriginalDamage(const battle::Unit * attacker, const batt
return getDamage(attacker, defender, hb); return getDamage(attacker, defender, hb);
} }
AttackPossibility::AttackPossibility(BattleHex from, BattleHex dest, const BattleAttackInfo & attack) AttackPossibility::AttackPossibility(const BattleHex & from, const BattleHex & dest, const BattleAttackInfo & attack)
: from(from), dest(dest), attack(attack) : from(from), dest(dest), attack(attack)
{ {
this->attack.attackerPos = from; this->attack.attackerPos = from;
@ -281,7 +281,7 @@ int64_t AttackPossibility::evaluateBlockedShootersDmg(
auto attacker = attackInfo.attacker; auto attacker = attackInfo.attacker;
const auto & hexes = attacker->getSurroundingHexes(hex); const auto & hexes = attacker->getSurroundingHexes(hex);
for(BattleHex tile : hexes) for(const BattleHex & tile : hexes)
{ {
auto st = state->battleGetUnitByPos(tile, true); auto st = state->battleGetUnitByPos(tile, true);
if(!st || !state->battleMatchOwner(st, attacker)) if(!st || !state->battleMatchOwner(st, attacker))
@ -332,7 +332,7 @@ AttackPossibility AttackPossibility::evaluate(
else else
defenderHex = CStack::meleeAttackHexes(attacker, defender, hex); defenderHex = CStack::meleeAttackHexes(attacker, defender, hex);
for(BattleHex defHex : defenderHex) for(const BattleHex & defHex : defenderHex)
{ {
if(defHex == hex) // should be impossible but check anyway if(defHex == hex) // should be impossible but check anyway
continue; continue;
@ -489,7 +489,7 @@ AttackPossibility AttackPossibility::evaluate(
logAi->trace("BattleAI AP: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld", logAi->trace("BattleAI AP: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld",
attackInfo.attacker->unitType()->getJsonKey(), attackInfo.attacker->unitType()->getJsonKey(),
attackInfo.defender->unitType()->getJsonKey(), attackInfo.defender->unitType()->getJsonKey(),
(int)ap.dest, (int)ap.from, (int)ap.affectedUnits.size(), ap.dest.toInt(), ap.from.toInt(), (int)ap.affectedUnits.size(),
ap.defenderDamageReduce, ap.attackerDamageReduce, ap.collateralDamageReduce, ap.shootersBlockedDmg); ap.defenderDamageReduce, ap.attackerDamageReduce, ap.collateralDamageReduce, ap.shootersBlockedDmg);
#endif #endif
@ -504,7 +504,7 @@ AttackPossibility AttackPossibility::evaluate(
logAi->trace("BattleAI best AP: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld", logAi->trace("BattleAI best AP: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld",
attackInfo.attacker->unitType()->getJsonKey(), attackInfo.attacker->unitType()->getJsonKey(),
attackInfo.defender->unitType()->getJsonKey(), attackInfo.defender->unitType()->getJsonKey(),
(int)bestAp.dest, (int)bestAp.from, (int)bestAp.affectedUnits.size(), bestAp.dest.toInt(), bestAp.from.toInt(), (int)bestAp.affectedUnits.size(),
bestAp.defenderDamageReduce, bestAp.attackerDamageReduce, bestAp.collateralDamageReduce, bestAp.shootersBlockedDmg); bestAp.defenderDamageReduce, bestAp.attackerDamageReduce, bestAp.collateralDamageReduce, bestAp.shootersBlockedDmg);
#endif #endif

View File

@ -29,7 +29,7 @@ public:
void cacheDamage(const battle::Unit * attacker, const battle::Unit * defender, std::shared_ptr<CBattleInfoCallback> hb); void cacheDamage(const battle::Unit * attacker, const battle::Unit * defender, std::shared_ptr<CBattleInfoCallback> hb);
int64_t getDamage(const battle::Unit * attacker, const battle::Unit * defender, std::shared_ptr<CBattleInfoCallback> hb); int64_t getDamage(const battle::Unit * attacker, const battle::Unit * defender, std::shared_ptr<CBattleInfoCallback> hb);
int64_t getObstacleDamage(BattleHex hex, const battle::Unit * defender); int64_t getObstacleDamage(const BattleHex & hex, const battle::Unit * defender);
int64_t getOriginalDamage(const battle::Unit * attacker, const battle::Unit * defender, std::shared_ptr<CBattleInfoCallback> hb); int64_t getOriginalDamage(const battle::Unit * attacker, const battle::Unit * defender, std::shared_ptr<CBattleInfoCallback> hb);
void buildDamageCache(std::shared_ptr<HypotheticBattle> hb, BattleSide side); void buildDamageCache(std::shared_ptr<HypotheticBattle> hb, BattleSide side);
}; };
@ -55,7 +55,7 @@ public:
int64_t shootersBlockedDmg = 0; int64_t shootersBlockedDmg = 0;
bool defenderDead = false; bool defenderDead = false;
AttackPossibility(BattleHex from, BattleHex dest, const BattleAttackInfo & attack_); AttackPossibility(const BattleHex & from, const BattleHex & dest, const BattleAttackInfo & attack_);
float damageDiff() const; float damageDiff() const;
float attackValue() const; float attackValue() const;

View File

@ -54,8 +54,8 @@ void logHexNumbers()
#if BATTLE_TRACE_LEVEL >= 1 #if BATTLE_TRACE_LEVEL >= 1
logVisual->updateWithLock("hexes", [](IVisualLogBuilder & b) logVisual->updateWithLock("hexes", [](IVisualLogBuilder & b)
{ {
for(BattleHex hex = BattleHex(0); hex < GameConstants::BFIELD_SIZE; hex = BattleHex(hex + 1)) for(BattleHex hex = BattleHex(0); hex < GameConstants::BFIELD_SIZE; ++hex)
b.addText(hex, std::to_string(hex.hex)); b.addText(hex, std::to_string(hex.toInt()));
}); });
#endif #endif
} }

View File

@ -327,7 +327,7 @@ uint64_t timeElapsed(std::chrono::time_point<std::chrono::steady_clock> start)
return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
} }
BattleAction BattleEvaluator::moveOrAttack(const CStack * stack, BattleHex hex, const PotentialTargets & targets) BattleAction BattleEvaluator::moveOrAttack(const CStack * stack, const BattleHex & hex, const PotentialTargets & targets)
{ {
auto additionalScore = 0; auto additionalScore = 0;
std::optional<AttackPossibility> attackOnTheWay; std::optional<AttackPossibility> attackOnTheWay;
@ -376,16 +376,14 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const Battl
}); });
} }
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked if(avHexes.empty() || hexes.empty()) //we are blocked or dest is blocked
{ {
return BattleAction::makeDefend(stack); return BattleAction::makeDefend(stack);
} }
BattleHexArray targetHexes = hexes; BattleHexArray targetHexes = hexes;
vstd::erase_if(targetHexes, [](const BattleHex & hex) { return !hex.isValid(); }); std::sort(targetHexes.begin(), targetHexes.end(), [&](const BattleHex & h1, const BattleHex & h2) -> bool
std::sort(targetHexes.begin(), targetHexes.end(), [&](BattleHex h1, BattleHex h2) -> bool
{ {
return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()]; return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()];
}); });
@ -399,9 +397,9 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const Battl
} }
// this turn // this turn
for(auto hex : targetHexes) for(const auto & hex : targetHexes)
{ {
if(vstd::contains(avHexes, hex)) if(avHexes.contains(hex))
{ {
return moveOrAttack(stack, hex, targets); return moveOrAttack(stack, hex, targets);
} }
@ -436,14 +434,14 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const Battl
} }
// Flying stack doesn't go hex by hex, so we can't backtrack using predecessors. // Flying stack doesn't go hex by hex, so we can't backtrack using predecessors.
// We just check all available hexes and pick the one closest to the target. // We just check all available hexes and pick the one closest to the target.
auto nearestAvailableHex = vstd::minElementByFun(avHexes, [&](BattleHex hex) -> int auto nearestAvailableHex = vstd::minElementByFun(avHexes, [&](const BattleHex & hex) -> int
{ {
const int NEGATIVE_OBSTACLE_PENALTY = 100; // avoid landing on negative obstacle (moat, fire wall, etc) const int NEGATIVE_OBSTACLE_PENALTY = 100; // avoid landing on negative obstacle (moat, fire wall, etc)
const int BLOCKED_STACK_PENALTY = 100; // avoid landing on moat const int BLOCKED_STACK_PENALTY = 100; // avoid landing on moat
auto distance = BattleHex::getDistance(bestNeighbour, hex); auto distance = BattleHex::getDistance(bestNeighbour, hex);
if(vstd::contains(obstacleHexes, hex)) if(obstacleHexes.contains(hex))
distance += NEGATIVE_OBSTACLE_PENALTY; distance += NEGATIVE_OBSTACLE_PENALTY;
return scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, hex) ? BLOCKED_STACK_PENALTY + distance : distance; return scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, hex) ? BLOCKED_STACK_PENALTY + distance : distance;
@ -462,7 +460,7 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const Battl
return BattleAction::makeDefend(stack); return BattleAction::makeDefend(stack);
} }
if(vstd::contains(avHexes, currentDest) if(avHexes.contains(currentDest)
&& !scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, currentDest)) && !scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, currentDest))
{ {
return moveOrAttack(stack, currentDest, targets); return moveOrAttack(stack, currentDest, targets);
@ -687,7 +685,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
else else
{ {
auto psFirst = ps.dest.front(); auto psFirst = ps.dest.front();
auto strWhere = psFirst.unitValue ? psFirst.unitValue->getDescription() : std::to_string(psFirst.hexValue.hex); auto strWhere = psFirst.unitValue ? psFirst.unitValue->getDescription() : std::to_string(psFirst.hexValue.toInt());
logAi->trace("Evaluating %s at %s", ps.spell->getNameTranslated(), strWhere); logAi->trace("Evaluating %s at %s", ps.spell->getNameTranslated(), strWhere);
} }
@ -805,7 +803,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
logAi->trace( logAi->trace(
"Spell %s to %d affects %s (%d), dps: %2f oldHealth: %d newHealth: %d", "Spell %s to %d affects %s (%d), dps: %2f oldHealth: %d newHealth: %d",
ps.spell->getNameTranslated(), ps.spell->getNameTranslated(),
ps.dest.at(0).hexValue.hex, // Safe to access .at(0) now ps.dest.at(0).hexValue.toInt(), // Safe to access .at(0) now
unit->creatureId().toCreature()->getNameSingularTranslated(), unit->creatureId().toCreature()->getNameSingularTranslated(),
unit->getCount(), unit->getCount(),
dpsReduce, dpsReduce,

View File

@ -56,7 +56,7 @@ public:
bool hasWorkingTowers() const; bool hasWorkingTowers() const;
void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only
void print(const std::string & text) const; void print(const std::string & text) const;
BattleAction moveOrAttack(const CStack * stack, BattleHex hex, const PotentialTargets & targets); BattleAction moveOrAttack(const CStack * stack, const BattleHex & hex, const PotentialTargets & targets);
BattleEvaluator( BattleEvaluator(
std::shared_ptr<Environment> env, std::shared_ptr<Environment> env,

View File

@ -349,7 +349,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
logAi->trace( logAi->trace(
"Checking movement towards %d of %s", "Checking movement towards %d of %s",
enemy->getCount(), enemy->getCount(),
enemy->creatureId().toCreature()->getNameSingularTranslated()); VLC->creatures()->getById(enemy->creatureId())->getJsonKey());
auto distance = dists.distToNearestNeighbour(activeStack, enemy); auto distance = dists.distToNearestNeighbour(activeStack, enemy);
@ -427,7 +427,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
if(defenderToBypass) if(defenderToBypass)
{ {
#if BATTLE_TRACE_LEVEL >= 1 #if BATTLE_TRACE_LEVEL >= 1
logAi->trace("Found target to bypass at %d", enemyHex.hex); logAi->trace("Found target to bypass at %d", enemyHex.toInt());
#endif #endif
auto attackHex = dists.predecessors[enemyHex.toInt()]; auto attackHex = dists.predecessors[enemyHex.toInt()];
@ -486,7 +486,7 @@ battle::Units BattleExchangeEvaluator::getAdjacentUnits(const battle::Unit * blo
checkedStacks.push_back(stack); checkedStacks.push_back(stack);
auto const & hexes = stack->getSurroundingHexes(); auto const & hexes = stack->getSurroundingHexes();
for(auto hex : hexes) for(const auto & hex : hexes)
{ {
auto neighbour = cb->battleGetUnitByPos(hex); auto neighbour = cb->battleGetUnitByPos(hex);
@ -517,14 +517,14 @@ ReachabilityData BattleExchangeEvaluator::getExchangeUnits(
battle::Units allReachableUnits = additionalUnits; battle::Units allReachableUnits = additionalUnits;
for(auto hex : hexes) for(const auto & hex : hexes)
{ {
vstd::concatenate(allReachableUnits, getOneTurnReachableUnits(turn, hex)); vstd::concatenate(allReachableUnits, getOneTurnReachableUnits(turn, hex));
} }
if(!ap.attack.attacker->isTurret()) if(!ap.attack.attacker->isTurret())
{ {
for(auto hex : ap.attack.attacker->getHexes()) for(const auto & hex : ap.attack.attacker->getHexes())
{ {
auto unitsReachingAttacker = getOneTurnReachableUnits(turn, hex); auto unitsReachingAttacker = getOneTurnReachableUnits(turn, hex);
for(auto unit : unitsReachingAttacker) for(auto unit : unitsReachingAttacker)
@ -577,7 +577,7 @@ ReachabilityData BattleExchangeEvaluator::getExchangeUnits(
if(!accessible) if(!accessible)
{ {
for(auto hex : unit->getSurroundingHexes()) for(const auto & hex : unit->getSurroundingHexes())
{ {
if(ap.attack.defender->coversPos(hex)) if(ap.attack.defender->coversPos(hex))
{ {
@ -639,7 +639,7 @@ BattleScore BattleExchangeEvaluator::calculateExchange(
battle::Units additionalUnits) const battle::Units additionalUnits) const
{ {
#if BATTLE_TRACE_LEVEL>=1 #if BATTLE_TRACE_LEVEL>=1
logAi->trace("Battle exchange at %d", ap.attack.shooting ? ap.dest.hex : ap.from.hex); logAi->trace("Battle exchange at %d", ap.attack.shooting ? ap.dest.toInt() : ap.from.toInt());
#endif #endif
if(cb->battleGetMySide() == BattleSide::LEFT_SIDE if(cb->battleGetMySide() == BattleSide::LEFT_SIDE
@ -927,7 +927,7 @@ void BattleExchangeEvaluator::updateReachabilityMap(std::shared_ptr<HypotheticBa
reachabilityMap.update(turnOrder, hb); reachabilityMap.update(turnOrder, hb);
} }
const battle::Units & ReachabilityMapCache::getOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, BattleHex hex) const battle::Units & ReachabilityMapCache::getOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, const BattleHex & hex)
{ {
auto & turnData = hexReachabilityPerTurn[turn]; auto & turnData = hexReachabilityPerTurn[turn];
@ -940,7 +940,7 @@ const battle::Units & ReachabilityMapCache::getOneTurnReachableUnits(std::shared
return turnData.hexes[hex.toInt()]; return turnData.hexes[hex.toInt()];
} }
battle::Units ReachabilityMapCache::computeOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, BattleHex hex) battle::Units ReachabilityMapCache::computeOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, const BattleHex & hex)
{ {
battle::Units result; battle::Units result;
@ -977,7 +977,7 @@ battle::Units ReachabilityMapCache::computeOneTurnReachableUnits(std::shared_ptr
if(hexStack && cb->battleMatchOwner(unit, hexStack, false)) if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
{ {
for(BattleHex neighbour : hex.getNeighbouringTiles()) for(const BattleHex & neighbour : hex.getNeighbouringTiles())
{ {
reachable = unitReachability.distances.at(neighbour.toInt()) <= radius; reachable = unitReachability.distances.at(neighbour.toInt()) <= radius;
@ -996,13 +996,13 @@ battle::Units ReachabilityMapCache::computeOneTurnReachableUnits(std::shared_ptr
return result; return result;
} }
const battle::Units & BattleExchangeEvaluator::getOneTurnReachableUnits(uint8_t turn, BattleHex hex) const const battle::Units & BattleExchangeEvaluator::getOneTurnReachableUnits(uint8_t turn, const BattleHex & hex) const
{ {
return reachabilityMap.getOneTurnReachableUnits(cb, env, turnOrder, turn, hex); return reachabilityMap.getOneTurnReachableUnits(cb, env, turnOrder, turn, hex);
} }
// avoid blocking path for stronger stack by weaker stack // avoid blocking path for stronger stack by weaker stack
bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb, const battle::Unit * activeUnit, BattleHex position) bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb, const battle::Unit * activeUnit, const BattleHex & position)
{ {
const int BLOCKING_THRESHOLD = 70; const int BLOCKING_THRESHOLD = 70;
const int BLOCKING_OWN_ATTACK_PENALTY = 100; const int BLOCKING_OWN_ATTACK_PENALTY = 100;
@ -1031,7 +1031,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
auto unitReachability = turnBattle.getReachability(unit); auto unitReachability = turnBattle.getReachability(unit);
auto unitSpeed = unit->getMovementRange(turn); // Cached value, to avoid performance hit auto unitSpeed = unit->getMovementRange(turn); // Cached value, to avoid performance hit
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex++) for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); ++hex)
{ {
bool enemyUnit = false; bool enemyUnit = false;
bool reachable = unitReachability.distances.at(hex.toInt()) <= unitSpeed; bool reachable = unitReachability.distances.at(hex.toInt()) <= unitSpeed;
@ -1043,7 +1043,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 : hex.getNeighbouringTiles()) for(const BattleHex & neighbour : hex.getNeighbouringTiles())
{ {
reachable = unitReachability.distances.at(neighbour.toInt()) <= unitSpeed; reachable = unitReachability.distances.at(neighbour.toInt()) <= unitSpeed;
@ -1063,7 +1063,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
} }
#if BATTLE_TRACE_LEVEL>=1 #if BATTLE_TRACE_LEVEL>=1
logAi->trace("Position %d, blocking score %f", position.hex, blockingScore); logAi->trace("Position %d, blocking score %f", position.toInt(), blockingScore);
#endif #endif
return blockingScore > BLOCKING_THRESHOLD; return blockingScore > BLOCKING_THRESHOLD;

View File

@ -134,9 +134,9 @@ class ReachabilityMapCache
std::map<uint32_t, PerTurnData> hexReachabilityPerTurn; std::map<uint32_t, PerTurnData> hexReachabilityPerTurn;
//const ReachabilityInfo & update(); //const ReachabilityInfo & update();
battle::Units computeOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, BattleHex hex); battle::Units computeOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, const BattleHex & hex);
public: public:
const battle::Units & getOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, BattleHex hex); const battle::Units & getOneTurnReachableUnits(std::shared_ptr<CBattleInfoCallback> cb, std::shared_ptr<Environment> env, const std::vector<battle::Units> & turnOrder, uint8_t turn, const BattleHex & hex);
void update(const std::vector<battle::Units> & turnOrder, std::shared_ptr<HypotheticBattle> hb); void update(const std::vector<battle::Units> & turnOrder, std::shared_ptr<HypotheticBattle> hb);
}; };
@ -185,7 +185,7 @@ public:
DamageCache & damageCache, DamageCache & damageCache,
std::shared_ptr<HypotheticBattle> hb) const; std::shared_ptr<HypotheticBattle> hb) const;
const battle::Units & getOneTurnReachableUnits(uint8_t turn, BattleHex hex) const; const battle::Units & getOneTurnReachableUnits(uint8_t turn, const BattleHex & hex) const;
void updateReachabilityMap(std::shared_ptr<HypotheticBattle> hb); void updateReachabilityMap(std::shared_ptr<HypotheticBattle> hb);
ReachabilityData getExchangeUnits( ReachabilityData getExchangeUnits(
@ -195,7 +195,7 @@ public:
std::shared_ptr<HypotheticBattle> hb, std::shared_ptr<HypotheticBattle> hb,
battle::Units additionalUnits = {}) const; battle::Units additionalUnits = {}) const;
bool checkPositionBlocksOurStacks(HypotheticBattle & hb, const battle::Unit * unit, BattleHex position); bool checkPositionBlocksOurStacks(HypotheticBattle & hb, const battle::Unit * unit, const BattleHex & position);
MoveTarget findMoveTowardsUnreachable( MoveTarget findMoveTowardsUnreachable(
const battle::Unit * activeStack, const battle::Unit * activeStack,

View File

@ -48,7 +48,7 @@ PotentialTargets::PotentialTargets(
if(!forceTarget && !state->battleMatchOwner(attackerInfo, defender)) if(!forceTarget && !state->battleMatchOwner(attackerInfo, defender))
continue; continue;
auto GenerateAttackInfo = [&](bool shooting, BattleHex hex) -> AttackPossibility auto GenerateAttackInfo = [&](bool shooting, const BattleHex & hex) -> AttackPossibility
{ {
int distance = hex.isValid() ? reachability.distances[hex.toInt()] : 0; int distance = hex.isValid() ? reachability.distances[hex.toInt()] : 0;
auto bai = BattleAttackInfo(attackerInfo, defender, distance, shooting); auto bai = BattleAttackInfo(attackerInfo, defender, distance, shooting);
@ -69,7 +69,7 @@ PotentialTargets::PotentialTargets(
} }
else else
{ {
for(BattleHex hex : avHexes) for(const BattleHex & hex : avHexes)
{ {
if(!CStack::isMeleeAttackPossible(attackerInfo, defender, hex)) if(!CStack::isMeleeAttackPossible(attackerInfo, defender, hex))
continue; continue;

View File

@ -360,7 +360,7 @@ void HypotheticBattle::addUnit(uint32_t id, const JsonNode & data)
stackStates[newUnit->unitId()] = newUnit; stackStates[newUnit->unitId()] = newUnit;
} }
void HypotheticBattle::moveUnit(uint32_t id, BattleHex destination) void HypotheticBattle::moveUnit(uint32_t id, const BattleHex & destination)
{ {
std::shared_ptr<StackWithBonuses> changed = getForUpdate(id); std::shared_ptr<StackWithBonuses> changed = getForUpdate(id);
changed->position = destination; changed->position = destination;

View File

@ -141,7 +141,7 @@ public:
void addUnit(uint32_t id, const JsonNode & data) override; void addUnit(uint32_t id, const JsonNode & data) override;
void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) override; void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) override;
void moveUnit(uint32_t id, BattleHex destination) override; void moveUnit(uint32_t id, const BattleHex & destination) override;
void removeUnit(uint32_t id) override; void removeUnit(uint32_t id) override;
void updateUnit(uint32_t id, const JsonNode & data) override; void updateUnit(uint32_t id, const JsonNode & data) override;

View File

@ -160,7 +160,7 @@ void CStupidAI::activeStack(const BattleID & battleID, const CStack * stack)
{ {
BattleHexArray avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(stack, false); BattleHexArray avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(stack, false);
for (BattleHex hex : avHexes) for (const BattleHex & hex : avHexes)
{ {
if(CStack::isMeleeAttackPossible(stack, s, hex)) if(CStack::isMeleeAttackPossible(stack, s, hex))
{ {
@ -289,12 +289,12 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
return BattleAction::makeDefend(stack); return BattleAction::makeDefend(stack);
} }
std::sort(hexes.begin(), hexes.end(), [&](BattleHex h1, BattleHex h2) -> bool std::sort(hexes.begin(), hexes.end(), [&](const BattleHex & h1, const BattleHex & h2) -> bool
{ {
return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()]; return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()];
}); });
for(auto hex : hexes) for(const auto & hex : hexes)
{ {
if(avHexes.contains(hex)) if(avHexes.contains(hex))
{ {
@ -322,7 +322,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
{ {
// Flying stack doesn't go hex by hex, so we can't backtrack using predecessors. // Flying stack doesn't go hex by hex, so we can't backtrack using predecessors.
// We just check all available hexes and pick the one closest to the target. // We just check all available hexes and pick the one closest to the target.
auto nearestAvailableHex = vstd::minElementByFun(avHexes, [&](BattleHex hex) -> int auto nearestAvailableHex = vstd::minElementByFun(avHexes, [&](const BattleHex & hex) -> int
{ {
return BattleHex::getDistance(bestneighbour, hex); return BattleHex::getDistance(bestneighbour, hex);
}); });

View File

@ -358,7 +358,7 @@ const CSpell * BattleActionsController::getHeroSpellToCast( ) const
return nullptr; return nullptr;
} }
const CSpell * BattleActionsController::getStackSpellToCast(BattleHex hoveredHex) const CSpell * BattleActionsController::getStackSpellToCast(const BattleHex & hoveredHex)
{ {
if (heroSpellToCast) if (heroSpellToCast)
return nullptr; return nullptr;
@ -383,14 +383,14 @@ const CSpell * BattleActionsController::getStackSpellToCast(BattleHex hoveredHex
return action.spell().toSpell(); return action.spell().toSpell();
} }
const CSpell * BattleActionsController::getCurrentSpell(BattleHex hoveredHex) const CSpell * BattleActionsController::getCurrentSpell(const BattleHex & hoveredHex)
{ {
if (getHeroSpellToCast()) if (getHeroSpellToCast())
return getHeroSpellToCast(); return getHeroSpellToCast();
return getStackSpellToCast(hoveredHex); return getStackSpellToCast(hoveredHex);
} }
const CStack * BattleActionsController::getStackForHex(BattleHex hoveredHex) const CStack * BattleActionsController::getStackForHex(const BattleHex & hoveredHex)
{ {
const CStack * shere = owner.getBattle()->battleGetStackByPos(hoveredHex, true); const CStack * shere = owner.getBattle()->battleGetStackByPos(hoveredHex, true);
if(shere) if(shere)
@ -398,7 +398,7 @@ const CStack * BattleActionsController::getStackForHex(BattleHex hoveredHex)
return owner.getBattle()->battleGetStackByPos(hoveredHex, false); return owner.getBattle()->battleGetStackByPos(hoveredHex, false);
} }
void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action, BattleHex targetHex) void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action, const BattleHex & targetHex)
{ {
switch (action.get()) switch (action.get())
{ {
@ -479,7 +479,7 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
assert(0); assert(0);
} }
void BattleActionsController::actionSetCursorBlocked(PossiblePlayerBattleAction action, BattleHex targetHex) void BattleActionsController::actionSetCursorBlocked(PossiblePlayerBattleAction action, const BattleHex & targetHex)
{ {
switch (action.get()) switch (action.get())
{ {
@ -500,7 +500,7 @@ void BattleActionsController::actionSetCursorBlocked(PossiblePlayerBattleAction
assert(0); assert(0);
} }
std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattleAction action, BattleHex targetHex) std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattleAction action, const BattleHex & targetHex)
{ {
const CStack * targetStack = getStackForHex(targetHex); const CStack * targetStack = getStackForHex(targetHex);
@ -589,7 +589,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
return ""; return "";
} }
std::string BattleActionsController::actionGetStatusMessageBlocked(PossiblePlayerBattleAction action, BattleHex targetHex) std::string BattleActionsController::actionGetStatusMessageBlocked(PossiblePlayerBattleAction action, const BattleHex & targetHex)
{ {
switch (action.get()) switch (action.get())
{ {
@ -611,7 +611,7 @@ std::string BattleActionsController::actionGetStatusMessageBlocked(PossiblePlaye
} }
} }
bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, BattleHex targetHex) bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, const BattleHex & targetHex)
{ {
const CStack * targetStack = getStackForHex(targetHex); const CStack * targetStack = getStackForHex(targetHex);
bool targetStackOwned = targetStack && targetStack->unitOwner() == owner.curInt->playerID; bool targetStackOwned = targetStack && targetStack->unitOwner() == owner.curInt->playerID;
@ -706,7 +706,7 @@ bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, B
return false; return false;
} }
void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, BattleHex targetHex) void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, const BattleHex & targetHex)
{ {
const CStack * targetStack = getStackForHex(targetHex); const CStack * targetStack = getStackForHex(targetHex);
@ -846,7 +846,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
return; return;
} }
PossiblePlayerBattleAction BattleActionsController::selectAction(BattleHex targetHex) PossiblePlayerBattleAction BattleActionsController::selectAction(const BattleHex & targetHex)
{ {
assert(owner.stacksController->getActiveStack() != nullptr); assert(owner.stacksController->getActiveStack() != nullptr);
assert(!possibleActions.empty()); assert(!possibleActions.empty());
@ -870,7 +870,7 @@ PossiblePlayerBattleAction BattleActionsController::selectAction(BattleHex targe
return possibleActions.front(); return possibleActions.front();
} }
void BattleActionsController::onHexHovered(BattleHex hoveredHex) void BattleActionsController::onHexHovered(const BattleHex & hoveredHex)
{ {
if (owner.openingPlaying()) if (owner.openingPlaying())
{ {
@ -926,7 +926,7 @@ void BattleActionsController::onHoverEnded()
currentConsoleMsg.clear(); currentConsoleMsg.clear();
} }
void BattleActionsController::onHexLeftClicked(BattleHex clickedHex) void BattleActionsController::onHexLeftClicked(const BattleHex & clickedHex)
{ {
if (owner.stacksController->getActiveStack() == nullptr) if (owner.stacksController->getActiveStack() == nullptr)
return; return;
@ -983,7 +983,7 @@ spells::Mode BattleActionsController::getCurrentCastMode() const
} }
bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell, const CStack *targetStack, BattleHex targetHex) bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell, const CStack *targetStack, const BattleHex & targetHex)
{ {
assert(currentSpell); assert(currentSpell);
if (!currentSpell) if (!currentSpell)
@ -1006,7 +1006,7 @@ bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell,
return m->canBeCastAt(target, problem); return m->canBeCastAt(target, problem);
} }
bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, const BattleHex & myNumber) const
{ {
BattleHexArray acc = owner.getBattle()->battleGetAvailableHexes(stackToMove, false); BattleHexArray acc = owner.getBattle()->battleGetAvailableHexes(stackToMove, false);
BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false); BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false);
@ -1057,7 +1057,7 @@ void BattleActionsController::activateStack()
} }
} }
void BattleActionsController::onHexRightClicked(BattleHex clickedHex) void BattleActionsController::onHexRightClicked(const BattleHex & clickedHex)
{ {
bool isCurrentStackInSpellcastMode = creatureSpellcastingModeActive(); bool isCurrentStackInSpellcastMode = creatureSpellcastingModeActive();
@ -1095,7 +1095,7 @@ bool BattleActionsController::creatureSpellcastingModeActive() const
return !possibleActions.empty() && std::all_of(possibleActions.begin(), possibleActions.end(), spellcastModePredicate); return !possibleActions.empty() && std::all_of(possibleActions.begin(), possibleActions.end(), spellcastModePredicate);
} }
bool BattleActionsController::currentActionSpellcasting(BattleHex hoveredHex) bool BattleActionsController::currentActionSpellcasting(const BattleHex & hoveredHex)
{ {
if (heroSpellToCast) if (heroSpellToCast)
return true; return true;

View File

@ -44,24 +44,24 @@ class BattleActionsController
/// stack that has been selected as first target for multi-target spells (Teleport & Sacrifice) /// stack that has been selected as first target for multi-target spells (Teleport & Sacrifice)
const CStack * selectedStack; const CStack * selectedStack;
bool isCastingPossibleHere (const CSpell * spell, const CStack *shere, BattleHex myNumber); bool isCastingPossibleHere (const CSpell * spell, const CStack *shere, const BattleHex & myNumber);
bool canStackMoveHere (const CStack *sactive, BattleHex MyNumber) const; //TODO: move to BattleState / callback bool canStackMoveHere (const CStack *sactive, const BattleHex & MyNumber) const; //TODO: move to BattleState / callback
std::vector<PossiblePlayerBattleAction> getPossibleActionsForStack (const CStack *stack) const; //called when stack gets its turn std::vector<PossiblePlayerBattleAction> getPossibleActionsForStack (const CStack *stack) const; //called when stack gets its turn
void reorderPossibleActionsPriority(const CStack * stack, const CStack * targetStack); void reorderPossibleActionsPriority(const CStack * stack, const CStack * targetStack);
bool actionIsLegal(PossiblePlayerBattleAction action, BattleHex hoveredHex); bool actionIsLegal(PossiblePlayerBattleAction action, const BattleHex & hoveredHex);
void actionSetCursor(PossiblePlayerBattleAction action, BattleHex hoveredHex); void actionSetCursor(PossiblePlayerBattleAction action, const BattleHex & hoveredHex);
void actionSetCursorBlocked(PossiblePlayerBattleAction action, BattleHex hoveredHex); void actionSetCursorBlocked(PossiblePlayerBattleAction action, const BattleHex & hoveredHex);
std::string actionGetStatusMessage(PossiblePlayerBattleAction action, BattleHex hoveredHex); std::string actionGetStatusMessage(PossiblePlayerBattleAction action, const BattleHex & hoveredHex);
std::string actionGetStatusMessageBlocked(PossiblePlayerBattleAction action, BattleHex hoveredHex); std::string actionGetStatusMessageBlocked(PossiblePlayerBattleAction action, const BattleHex & hoveredHex);
void actionRealize(PossiblePlayerBattleAction action, BattleHex hoveredHex); void actionRealize(PossiblePlayerBattleAction action, const BattleHex & hoveredHex);
PossiblePlayerBattleAction selectAction(BattleHex myNumber); PossiblePlayerBattleAction selectAction(const BattleHex & myNumber);
const CStack * getStackForHex(BattleHex myNumber) ; const CStack * getStackForHex(const BattleHex & myNumber) ;
/// attempts to initialize spellcasting action for stack /// attempts to initialize spellcasting action for stack
/// will silently return if stack is not a spellcaster /// will silently return if stack is not a spellcaster
@ -71,7 +71,7 @@ class BattleActionsController
const CSpell * getHeroSpellToCast() const; const CSpell * getHeroSpellToCast() const;
/// if current stack is spellcaster, returns spell being cast, or null othervice /// if current stack is spellcaster, returns spell being cast, or null othervice
const CSpell * getStackSpellToCast(BattleHex hoveredHex); const CSpell * getStackSpellToCast(const BattleHex & hoveredHex);
/// returns true if current stack is a spellcaster /// returns true if current stack is a spellcaster
bool isActiveStackSpellcaster() const; bool isActiveStackSpellcaster() const;
@ -91,7 +91,7 @@ public:
/// - we are casting spell by hero /// - we are casting spell by hero
/// - we are casting spell by creature in targeted mode (F hotkey) /// - we are casting spell by creature in targeted mode (F hotkey)
/// - current creature is spellcaster and preferred action for current hex is spellcast /// - current creature is spellcaster and preferred action for current hex is spellcast
bool currentActionSpellcasting(BattleHex hoveredHex); bool currentActionSpellcasting(const BattleHex & hoveredHex);
/// enter targeted spellcasting mode for creature, e.g. via "F" hotkey /// enter targeted spellcasting mode for creature, e.g. via "F" hotkey
void enterCreatureCastingMode(); void enterCreatureCastingMode();
@ -103,19 +103,19 @@ public:
void endCastingSpell(); void endCastingSpell();
/// update cursor and status bar according to new active hex /// update cursor and status bar according to new active hex
void onHexHovered(BattleHex hoveredHex); void onHexHovered(const BattleHex & hoveredHex);
/// called when cursor is no longer over battlefield and cursor/battle log should be reset /// called when cursor is no longer over battlefield and cursor/battle log should be reset
void onHoverEnded(); void onHoverEnded();
/// performs action according to selected hex /// performs action according to selected hex
void onHexLeftClicked(BattleHex clickedHex); void onHexLeftClicked(const BattleHex & clickedHex);
/// performs action according to selected hex /// performs action according to selected hex
void onHexRightClicked(BattleHex clickedHex); void onHexRightClicked(const BattleHex & clickedHex);
const spells::Caster * getCurrentSpellcaster() const; const spells::Caster * getCurrentSpellcaster() const;
const CSpell * getCurrentSpell(BattleHex hoveredHex); const CSpell * getCurrentSpell(const BattleHex & hoveredHex);
spells::Mode getCurrentCastMode() const; spells::Mode getCurrentCastMode() const;
/// methods to work with array of possible actions, needed to control special creatures abilities /// methods to work with array of possible actions, needed to control special creatures abilities

View File

@ -281,7 +281,7 @@ void BattleFieldController::redrawBackgroundWithHexes()
{ {
BattleHexArray hexesToShade = occupiableHexes; BattleHexArray hexesToShade = occupiableHexes;
hexesToShade.insert(attackableHexes); hexesToShade.insert(attackableHexes);
for(BattleHex hex : hexesToShade) for(const BattleHex & hex : hexesToShade)
{ {
showHighlightedHex(*backgroundWithHexes, cellShade, hex, false); showHighlightedHex(*backgroundWithHexes, cellShade, hex, false);
} }
@ -302,7 +302,7 @@ void BattleFieldController::redrawBackgroundWithHexes()
} }
} }
void BattleFieldController::showHighlightedHex(Canvas & canvas, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder) void BattleFieldController::showHighlightedHex(Canvas & canvas, std::shared_ptr<IImage> highlight, const BattleHex & hex, bool darkBorder)
{ {
Point hexPos = hexPositionLocal(hex).topLeft(); Point hexPos = hexPositionLocal(hex).topLeft();
@ -313,41 +313,30 @@ void BattleFieldController::showHighlightedHex(Canvas & canvas, std::shared_ptr<
BattleHexArray BattleFieldController::getHighlightedHexesForActiveStack() BattleHexArray BattleFieldController::getHighlightedHexesForActiveStack()
{ {
BattleHexArray result;
if(!owner.stacksController->getActiveStack()) if(!owner.stacksController->getActiveStack())
return result; return BattleHexArray();
if(!settings["battle"]["stackRange"].Bool()) if(!settings["battle"]["stackRange"].Bool())
return result; return BattleHexArray();
auto hoveredHex = getHoveredHex(); auto hoveredHex = getHoveredHex();
BattleHexArray set = owner.getBattle()->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex); return owner.getBattle()->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex);
for(BattleHex hex : set)
result.insert(hex);
return result;
} }
BattleHexArray BattleFieldController::getMovementRangeForHoveredStack() BattleHexArray BattleFieldController::getMovementRangeForHoveredStack()
{ {
BattleHexArray result;
if (!owner.stacksController->getActiveStack()) if (!owner.stacksController->getActiveStack())
return result; return BattleHexArray();
if (!settings["battle"]["movementHighlightOnHover"].Bool() && !GH.isKeyboardShiftDown()) if (!settings["battle"]["movementHighlightOnHover"].Bool() && !GH.isKeyboardShiftDown())
return result; return BattleHexArray();
auto hoveredStack = getHoveredStack(); auto hoveredStack = getHoveredStack();
if(hoveredStack) if(hoveredStack)
{ return owner.getBattle()->battleGetAvailableHexes(hoveredStack, true, true, nullptr);
BattleHexArray v = owner.getBattle()->battleGetAvailableHexes(hoveredStack, true, true, nullptr); else
for(BattleHex hex : v) return BattleHexArray();
result.insert(hex);
}
return result;
} }
BattleHexArray BattleFieldController::getHighlightedHexesForSpellRange() BattleHexArray BattleFieldController::getHighlightedHexesForSpellRange()
@ -368,7 +357,7 @@ BattleHexArray BattleFieldController::getHighlightedHexesForSpellRange()
spells::BattleCast event(owner.getBattle().get(), caster, mode, spell); spells::BattleCast event(owner.getBattle().get(), caster, mode, spell);
auto shadedHexes = spell->battleMechanics(&event)->rangeInHexes(hoveredHex); auto shadedHexes = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
for(BattleHex shadedHex : shadedHexes) for(const BattleHex & shadedHex : shadedHexes)
{ {
if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1)) if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1))
result.insert(shadedHex); result.insert(shadedHex);
@ -411,7 +400,7 @@ BattleHexArray BattleFieldController::getHighlightedHexesForMovementTarget()
if(stack->doubleWide()) if(stack->doubleWide())
{ {
for(auto hex : availableHexes) for(const auto & hex : availableHexes)
{ {
if(stack->occupiedHex(hex) == hoveredHex) if(stack->occupiedHex(hex) == hoveredHex)
return {hoveredHex, hex}; return {hoveredHex, hex};
@ -423,7 +412,7 @@ BattleHexArray BattleFieldController::getHighlightedHexesForMovementTarget()
// Range limit highlight helpers // Range limit highlight helpers
BattleHexArray BattleFieldController::getRangeHexes(BattleHex sourceHex, uint8_t distance) BattleHexArray BattleFieldController::getRangeHexes(const BattleHex & sourceHex, uint8_t distance)
{ {
BattleHexArray rangeHexes; BattleHexArray rangeHexes;
@ -441,7 +430,7 @@ BattleHexArray BattleFieldController::getRangeHexes(BattleHex sourceHex, uint8_t
return rangeHexes; return rangeHexes;
} }
BattleHexArray BattleFieldController::getRangeLimitHexes(BattleHex hoveredHex, const BattleHexArray & rangeHexes, uint8_t distanceToLimit) BattleHexArray BattleFieldController::getRangeLimitHexes(const BattleHex & hoveredHex, const BattleHexArray & rangeHexes, uint8_t distanceToLimit)
{ {
BattleHexArray rangeLimitHexes; BattleHexArray rangeLimitHexes;
@ -455,7 +444,7 @@ BattleHexArray BattleFieldController::getRangeLimitHexes(BattleHex hoveredHex, c
return rangeLimitHexes; return rangeLimitHexes;
} }
bool BattleFieldController::IsHexInRangeLimit(BattleHex hex, const BattleHexArray & rangeLimitHexes, int * hexIndexInRangeLimit) bool BattleFieldController::IsHexInRangeLimit(const BattleHex & hex, const BattleHexArray & rangeLimitHexes, int * hexIndexInRangeLimit)
{ {
bool hexInRangeLimit = false; bool hexInRangeLimit = false;
@ -477,7 +466,7 @@ std::vector<std::vector<BattleHex::EDir>> BattleFieldController::getOutsideNeigh
if(wholeRangeHexes.empty()) if(wholeRangeHexes.empty())
return output; return output;
for(auto hex : rangeLimitHexes) for(const auto & hex : rangeLimitHexes)
{ {
// get all neighbours and their directions // get all neighbours and their directions
@ -606,7 +595,7 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
} }
} }
Rect BattleFieldController::hexPositionLocal(BattleHex hex) const Rect BattleFieldController::hexPositionLocal(const BattleHex & hex) const
{ {
int x = 14 + ((hex.getY())%2==0 ? 22 : 0) + 44*hex.getX(); int x = 14 + ((hex.getY())%2==0 ? 22 : 0) + 44*hex.getX();
int y = 86 + 42 *hex.getY(); int y = 86 + 42 *hex.getY();
@ -615,7 +604,7 @@ Rect BattleFieldController::hexPositionLocal(BattleHex hex) const
return Rect(x, y, w, h); return Rect(x, y, w, h);
} }
Rect BattleFieldController::hexPositionAbsolute(BattleHex hex) const Rect BattleFieldController::hexPositionAbsolute(const BattleHex & hex) const
{ {
return hexPositionLocal(hex) + pos.topLeft(); return hexPositionLocal(hex) + pos.topLeft();
} }
@ -674,7 +663,7 @@ BattleHex BattleFieldController::getHexAtPosition(Point hoverPos)
return BattleHex::INVALID; return BattleHex::INVALID;
} }
BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber) BattleHex::EDir BattleFieldController::selectAttackDirection(const BattleHex & myNumber)
{ {
const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide(); const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
const BattleHexArray & neighbours = myNumber.getAllNeighbouringTiles(); const BattleHexArray & neighbours = myNumber.getAllNeighbouringTiles();
@ -748,7 +737,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber)
return BattleHex::EDir(nearest); return BattleHex::EDir(nearest);
} }
BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget) BattleHex BattleFieldController::fromWhichHexAttack(const BattleHex & attackTarget)
{ {
BattleHex::EDir direction = selectAttackDirection(getHoveredHex()); BattleHex::EDir direction = selectAttackDirection(getHoveredHex());

View File

@ -55,7 +55,7 @@ class BattleFieldController : public CIntObject
/// hexes that when in front of a unit cause it's amount box to move back /// hexes that when in front of a unit cause it's amount box to move back
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes; std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
void showHighlightedHex(Canvas & to, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder); void showHighlightedHex(Canvas & to, std::shared_ptr<IImage> highlight, const BattleHex & hex, bool darkBorder);
BattleHexArray getHighlightedHexesForActiveStack(); BattleHexArray getHighlightedHexesForActiveStack();
BattleHexArray getMovementRangeForHoveredStack(); BattleHexArray getMovementRangeForHoveredStack();
@ -65,13 +65,13 @@ class BattleFieldController : public CIntObject
// Range limit highlight helpers // Range limit highlight helpers
/// get all hexes within a certain distance of given hex /// get all hexes within a certain distance of given hex
BattleHexArray getRangeHexes(BattleHex sourceHex, uint8_t distance); BattleHexArray getRangeHexes(const BattleHex & sourceHex, uint8_t distance);
/// get only hexes at the limit of a range /// get only hexes at the limit of a range
BattleHexArray getRangeLimitHexes(BattleHex hoveredHex, const BattleHexArray & hexRange, uint8_t distanceToLimit); BattleHexArray getRangeLimitHexes(const BattleHex & hoveredHex, const BattleHexArray & hexRange, uint8_t distanceToLimit);
/// calculate if a hex is in range limit and return its index in range /// calculate if a hex is in range limit and return its index in range
bool IsHexInRangeLimit(BattleHex hex, const BattleHexArray & rangeLimitHexes, int * hexIndexInRangeLimit); bool IsHexInRangeLimit(const BattleHex & hex, const BattleHexArray & rangeLimitHexes, int * hexIndexInRangeLimit);
/// get an array that has for each hex in range, an array with all directions where an outside neighbour hex exists /// get an array that has for each hex in range, an array with all directions where an outside neighbour hex exists
std::vector<std::vector<BattleHex::EDir>> getOutsideNeighbourDirectionsForLimitHexes(const BattleHexArray & rangeHexes, const BattleHexArray & rangeLimitHexes); std::vector<std::vector<BattleHex::EDir>> getOutsideNeighbourDirectionsForLimitHexes(const BattleHexArray & rangeHexes, const BattleHexArray & rangeLimitHexes);
@ -94,7 +94,7 @@ class BattleFieldController : public CIntObject
/// Checks whether selected pixel is transparent, uses local coordinates of a hex /// Checks whether selected pixel is transparent, uses local coordinates of a hex
bool isPixelInHex(Point const & position); bool isPixelInHex(Point const & position);
size_t selectBattleCursor(BattleHex myNumber); size_t selectBattleCursor(const BattleHex & myNumber);
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
@ -118,10 +118,10 @@ public:
void renderBattlefield(Canvas & canvas); void renderBattlefield(Canvas & canvas);
/// Returns position of hex relative to owner (BattleInterface) /// Returns position of hex relative to owner (BattleInterface)
Rect hexPositionLocal(BattleHex hex) const; Rect hexPositionLocal(const BattleHex & hex) const;
/// Returns position of hex relative to game window /// Returns position of hex relative to game window
Rect hexPositionAbsolute(BattleHex hex) const; Rect hexPositionAbsolute(const BattleHex & hex) const;
/// Returns ID of currently hovered hex or BattleHex::INVALID if none /// Returns ID of currently hovered hex or BattleHex::INVALID if none
BattleHex getHoveredHex(); BattleHex getHoveredHex();
@ -135,7 +135,7 @@ public:
/// returns true if stack should render its stack count image in default position - outside own hex /// returns true if stack should render its stack count image in default position - outside own hex
bool stackCountOutsideHex(const BattleHex & number) const; bool stackCountOutsideHex(const BattleHex & number) const;
BattleHex::EDir selectAttackDirection(BattleHex myNumber); BattleHex::EDir selectAttackDirection(const BattleHex & myNumber);
BattleHex fromWhichHexAttack(BattleHex myNumber); BattleHex fromWhichHexAttack(const BattleHex & myNumber);
}; };

View File

@ -261,7 +261,7 @@ void BattleInterface::newRound()
round++; round++;
} }
void BattleInterface::giveCommand(EActionType action, BattleHex tile, SpellID spell) void BattleInterface::giveCommand(EActionType action, const BattleHex & tile, SpellID spell)
{ {
const CStack * actor = nullptr; const CStack * actor = nullptr;
if(action != EActionType::HERO_SPELL && action != EActionType::RETREAT && action != EActionType::SURRENDER) if(action != EActionType::HERO_SPELL && action != EActionType::RETREAT && action != EActionType::SURRENDER)
@ -506,7 +506,7 @@ void BattleInterface::displayBattleLog(const std::vector<MetaString> & battleLog
} }
} }
void BattleInterface::displaySpellAnimationQueue(const CSpell * spell, const CSpell::TAnimationQueue & q, BattleHex destinationTile, bool isHit) void BattleInterface::displaySpellAnimationQueue(const CSpell * spell, const CSpell::TAnimationQueue & q, const BattleHex & destinationTile, bool isHit)
{ {
for(const CSpell::TAnimation & animation : q) for(const CSpell::TAnimation & animation : q)
{ {
@ -542,19 +542,19 @@ void BattleInterface::displaySpellAnimationQueue(const CSpell * spell, const CSp
} }
} }
void BattleInterface::displaySpellCast(const CSpell * spell, BattleHex destinationTile) void BattleInterface::displaySpellCast(const CSpell * spell, const BattleHex & destinationTile)
{ {
if(spell) if(spell)
displaySpellAnimationQueue(spell, spell->animationInfo.cast, destinationTile, false); displaySpellAnimationQueue(spell, spell->animationInfo.cast, destinationTile, false);
} }
void BattleInterface::displaySpellEffect(const CSpell * spell, BattleHex destinationTile) void BattleInterface::displaySpellEffect(const CSpell * spell, const BattleHex & destinationTile)
{ {
if(spell) if(spell)
displaySpellAnimationQueue(spell, spell->animationInfo.affect, destinationTile, false); displaySpellAnimationQueue(spell, spell->animationInfo.affect, destinationTile, false);
} }
void BattleInterface::displaySpellHit(const CSpell * spell, BattleHex destinationTile) void BattleInterface::displaySpellHit(const CSpell * spell, const BattleHex & destinationTile)
{ {
if(spell) if(spell)
displaySpellAnimationQueue(spell, spell->animationInfo.hit, destinationTile, true); displaySpellAnimationQueue(spell, spell->animationInfo.hit, destinationTile, true);

View File

@ -163,7 +163,7 @@ public:
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
void requestAutofightingAIToTakeAction(); void requestAutofightingAIToTakeAction();
void giveCommand(EActionType action, BattleHex tile = BattleHex(), SpellID spell = SpellID::NONE); void giveCommand(EActionType action, const BattleHex & tile = BattleHex(), SpellID spell = SpellID::NONE);
void sendCommand(BattleAction command, const CStack * actor = nullptr); void sendCommand(BattleAction command, const CStack * actor = nullptr);
const CGHeroInstance *getActiveHero(); //returns hero that can currently cast a spell const CGHeroInstance *getActiveHero(); //returns hero that can currently cast a spell
@ -215,10 +215,10 @@ public:
void displayBattleLog(const std::vector<MetaString> & battleLog); void displayBattleLog(const std::vector<MetaString> & battleLog);
void displaySpellAnimationQueue(const CSpell * spell, const CSpell::TAnimationQueue & q, BattleHex destinationTile, bool isHit); void displaySpellAnimationQueue(const CSpell * spell, const CSpell::TAnimationQueue & q, const BattleHex & destinationTile, bool isHit);
void displaySpellCast(const CSpell * spell, BattleHex destinationTile); //displays spell`s cast animation void displaySpellCast(const CSpell * spell, const BattleHex & destinationTile); //displays spell`s cast animation
void displaySpellEffect(const CSpell * spell, BattleHex destinationTile); //displays spell`s affected animation void displaySpellEffect(const CSpell * spell, const BattleHex & destinationTile); //displays spell`s affected animation
void displaySpellHit(const CSpell * spell, BattleHex destinationTile); //displays spell`s affected animation void displaySpellHit(const CSpell * spell, const BattleHex & destinationTile); //displays spell`s affected animation
void endAction(const BattleAction & action); void endAction(const BattleAction & action);

View File

@ -29,7 +29,7 @@ BattleOverlayLogVisualizer::BattleOverlayLogVisualizer(
{ {
} }
void BattleOverlayLogVisualizer::drawText(BattleHex hex, int lineNumber, const std::string & text) void BattleOverlayLogVisualizer::drawText(const BattleHex & hex, int lineNumber, const std::string & text)
{ {
Point offset = owner.fieldController->hexPositionLocal(hex).topLeft() + Point(20, 20); Point offset = owner.fieldController->hexPositionLocal(hex).topLeft() + Point(20, 20);
const auto & font = GH.renderHandler().loadFont(FONT_TINY); const auto & font = GH.renderHandler().loadFont(FONT_TINY);

View File

@ -24,5 +24,5 @@ private:
public: public:
BattleOverlayLogVisualizer(BattleRenderer::RendererRef & target, BattleInterface & owner); BattleOverlayLogVisualizer(BattleRenderer::RendererRef & target, BattleInterface & owner);
void drawText(BattleHex hex, int lineNumber, const std::string & text) override; void drawText(const BattleHex & hex, int lineNumber, const std::string & text) override;
}; };

View File

@ -64,7 +64,7 @@ BattleRenderer::BattleRenderer(BattleInterface & owner):
{ {
} }
void BattleRenderer::insert(EBattleFieldLayer layer, BattleHex tile, BattleRenderer::RenderFunctor functor) void BattleRenderer::insert(EBattleFieldLayer layer, const BattleHex & tile, BattleRenderer::RenderFunctor functor)
{ {
objects.push_back({functor, layer, tile}); objects.push_back({functor, layer, tile});
} }

View File

@ -48,6 +48,6 @@ private:
public: public:
BattleRenderer(BattleInterface & owner); BattleRenderer(BattleInterface & owner);
void insert(EBattleFieldLayer layer, BattleHex tile, RenderFunctor functor); void insert(EBattleFieldLayer layer, const BattleHex & tile, RenderFunctor functor);
void execute(RendererRef targetCanvas); void execute(RendererRef targetCanvas);
}; };

View File

@ -183,7 +183,7 @@ BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTo
} }
} }
const CCreature *BattleSiegeController::getTurretCreature(BattleHex position) const const CCreature *BattleSiegeController::getTurretCreature(const BattleHex & position) const
{ {
switch (position.toInt()) switch (position.toInt())
{ {
@ -322,7 +322,7 @@ void BattleSiegeController::collectRenderableObjects(BattleRenderer & renderer)
} }
} }
bool BattleSiegeController::isAttackableByCatapult(BattleHex hex) const bool BattleSiegeController::isAttackableByCatapult(const BattleHex & hex) const
{ {
if (owner.tacticsMode) if (owner.tacticsMode)
return false; return false;

View File

@ -102,9 +102,9 @@ public:
void collectRenderableObjects(BattleRenderer & renderer); void collectRenderableObjects(BattleRenderer & renderer);
/// queries from other battle controllers /// queries from other battle controllers
bool isAttackableByCatapult(BattleHex hex) const; bool isAttackableByCatapult(const BattleHex & hex) const;
ImagePath getBattleBackgroundName() const; ImagePath getBattleBackgroundName() const;
const CCreature *getTurretCreature(BattleHex turretPosition) const; const CCreature *getTurretCreature(const BattleHex & turretPosition) const;
Point getTurretCreaturePosition( BattleHex position ) const; Point getTurretCreaturePosition( BattleHex position ) const;
const CGTownInstance *getSiegedTown() const; const CGTownInstance *getSiegedTown() const;

View File

@ -733,7 +733,7 @@ bool BattleStacksController::facingRight(const CStack * stack) const
return stackFacingRight.at(stack->unitId()); return stackFacingRight.at(stack->unitId());
} }
Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CStack * stack) const Point BattleStacksController::getStackPositionAtHex(const BattleHex & hexNum, const CStack * stack) const
{ {
Point ret(-500, -500); //returned value Point ret(-500, -500); //returned value
if(stack && stack->initialPosition < 0) //creatures in turrets if(stack && stack->initialPosition < 0) //creatures in turrets

View File

@ -143,7 +143,7 @@ public:
void tick(uint32_t msPassed); void tick(uint32_t msPassed);
/// returns position of animation needed to place stack in specific hex /// returns position of animation needed to place stack in specific hex
Point getStackPositionAtHex(BattleHex hexNum, const CStack * creature) const; Point getStackPositionAtHex(const BattleHex & hexNum, const CStack * creature) const;
friend class BattleAnimation; // for exposing pendingAnims/creAnims/creDir to animations friend class BattleAnimation; // for exposing pendingAnims/creAnims/creDir to animations
}; };

View File

@ -167,7 +167,7 @@ std::string CStack::nodeName() const
oss << owner.toString(); oss << owner.toString();
oss << " battle stack [" << ID << "]: " << getCount() << " of "; oss << " battle stack [" << ID << "]: " << getCount() << " of ";
if(typeID.hasValue()) if(typeID.hasValue())
oss << typeID.toEntity(VLC)->getNamePluralTextID(); oss << typeID.toEntity(VLC)->getJsonKey();
else else
oss << "[UNDEFINED TYPE]"; oss << "[UNDEFINED TYPE]";

View File

@ -55,7 +55,7 @@ Obstacle ObstacleInfo::getId() const
return obstacle; return obstacle;
} }
BattleHexArray ObstacleInfo::getBlocked(BattleHex hex) const BattleHexArray ObstacleInfo::getBlocked(const BattleHex & hex) const
{ {
if(isAbsoluteObstacle) if(isAbsoluteObstacle)
{ {

View File

@ -54,7 +54,7 @@ public:
void registerIcons(const IconRegistar & cb) const override; void registerIcons(const IconRegistar & cb) const override;
Obstacle getId() const override; Obstacle getId() const override;
BattleHexArray getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex' BattleHexArray getBlocked(const BattleHex & hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex'
bool isAppropriate(const TerrainId terrainType, const BattleField & specialBattlefield) const; bool isAppropriate(const TerrainId terrainType, const BattleField & specialBattlefield) const;
}; };

View File

@ -15,7 +15,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
bool AccessibilityInfo::tileAccessibleWithGate(BattleHex tile, BattleSide side) const bool AccessibilityInfo::tileAccessibleWithGate(const BattleHex & tile, BattleSide side) const
{ {
//at(otherHex) != EAccessibility::ACCESSIBLE && (at(otherHex) != EAccessibility::GATE || side != BattleSide::DEFENDER) //at(otherHex) != EAccessibility::ACCESSIBLE && (at(otherHex) != EAccessibility::GATE || side != BattleSide::DEFENDER)
const auto & accessibility = at(tile.toInt()); const auto & accessibility = at(tile.toInt());
@ -35,12 +35,12 @@ bool AccessibilityInfo::tileAccessibleWithGate(BattleHex tile, BattleSide side)
return true; return true;
} }
bool AccessibilityInfo::accessible(BattleHex tile, const battle::Unit * stack) const bool AccessibilityInfo::accessible(const BattleHex & tile, const battle::Unit * stack) const
{ {
return accessible(tile, stack->doubleWide(), stack->unitSide()); return accessible(tile, stack->doubleWide(), stack->unitSide());
} }
bool AccessibilityInfo::accessible(BattleHex tile, bool doubleWide, BattleSide side) const bool AccessibilityInfo::accessible(const BattleHex & tile, bool doubleWide, BattleSide side) const
{ {
// All hexes that stack would cover if standing on tile have to be accessible. // All hexes that stack would cover if standing on tile have to be accessible.
//do not use getHexes for speed reasons //do not use getHexes for speed reasons

View File

@ -39,10 +39,10 @@ struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
std::shared_ptr<const TBattlefieldTurnsArray> destructibleEnemyTurns; //used only as a view for destructibleEnemyTurns from ReachabilityInfo::Parameters std::shared_ptr<const TBattlefieldTurnsArray> destructibleEnemyTurns; //used only as a view for destructibleEnemyTurns from ReachabilityInfo::Parameters
public: public:
bool accessible(BattleHex tile, const battle::Unit * stack) const; //checks for both tiles if stack is double wide bool accessible(const BattleHex & tile, const battle::Unit * stack) const; //checks for both tiles if stack is double wide
bool accessible(BattleHex tile, bool doubleWide, BattleSide side) const; //checks for both tiles if stack is double wide bool accessible(const BattleHex & tile, bool doubleWide, BattleSide side) const; //checks for both tiles if stack is double wide
private: private:
bool tileAccessibleWithGate(BattleHex tile, BattleSide side) const; bool tileAccessibleWithGate(const BattleHex & tile, BattleSide side) const;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -43,7 +43,7 @@ BattleAction BattleAction::makeDefend(const battle::Unit * stack)
return ba; return ba;
} }
BattleAction BattleAction::makeMeleeAttack(const battle::Unit * stack, BattleHex destination, BattleHex attackFrom, bool returnAfterAttack) BattleAction BattleAction::makeMeleeAttack(const battle::Unit * stack, const BattleHex & destination, const BattleHex & attackFrom, bool returnAfterAttack)
{ {
BattleAction ba; BattleAction ba;
ba.side = stack->unitSide(); //FIXME: will it fail if stack mind controlled? ba.side = stack->unitSide(); //FIXME: will it fail if stack mind controlled?
@ -86,7 +86,7 @@ BattleAction BattleAction::makeCreatureSpellcast(const battle::Unit * stack, con
return ba; return ba;
} }
BattleAction BattleAction::makeMove(const battle::Unit * stack, BattleHex dest) BattleAction BattleAction::makeMove(const battle::Unit * stack, const BattleHex & dest)
{ {
BattleAction ba; BattleAction ba;
ba.side = stack->unitSide(); ba.side = stack->unitSide();

View File

@ -35,10 +35,10 @@ public:
static BattleAction makeHeal(const battle::Unit * healer, const battle::Unit * healed); static BattleAction makeHeal(const battle::Unit * healer, const battle::Unit * healed);
static BattleAction makeDefend(const battle::Unit * stack); static BattleAction makeDefend(const battle::Unit * stack);
static BattleAction makeWait(const battle::Unit * stack); static BattleAction makeWait(const battle::Unit * stack);
static BattleAction makeMeleeAttack(const battle::Unit * stack, BattleHex destination, BattleHex attackFrom, bool returnAfterAttack = true); static BattleAction makeMeleeAttack(const battle::Unit * stack, const BattleHex & destination, const BattleHex & attackFrom, bool returnAfterAttack = true);
static BattleAction makeShotAttack(const battle::Unit * shooter, const battle::Unit * target); static BattleAction makeShotAttack(const battle::Unit * shooter, const battle::Unit * target);
static BattleAction makeCreatureSpellcast(const battle::Unit * stack, const battle::Target & target, const SpellID & spellID); static BattleAction makeCreatureSpellcast(const battle::Unit * stack, const battle::Target & target, const SpellID & spellID);
static BattleAction makeMove(const battle::Unit * stack, BattleHex dest); static BattleAction makeMove(const battle::Unit * stack, const BattleHex & dest);
static BattleAction makeEndOFTacticPhase(BattleSide side); static BattleAction makeEndOFTacticPhase(BattleSide side);
static BattleAction makeRetreat(BattleSide side); static BattleAction makeRetreat(BattleSide side);
static BattleAction makeSurrender(BattleSide side); static BattleAction makeSurrender(BattleSide side);

View File

@ -13,7 +13,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
BattleHex BattleHex::getClosestTile(BattleSide side, BattleHex initialPos, const BattleHexArray & hexes) BattleHex BattleHex::getClosestTile(BattleSide side, const BattleHex & initialPos, const BattleHexArray & hexes)
{ {
if(hexes.empty()) if(hexes.empty())
return BattleHex(); return BattleHex();
@ -22,7 +22,7 @@ BattleHex BattleHex::getClosestTile(BattleSide side, BattleHex initialPos, const
int closestDistance = std::numeric_limits<int>::max(); int closestDistance = std::numeric_limits<int>::max();
BattleHexArray closestTiles; BattleHexArray closestTiles;
for(auto hex : hexes) for(const auto & hex : hexes)
{ {
int distance = initialHex.getDistance(initialHex, hex); int distance = initialHex.getDistance(initialHex, hex);
if(distance < closestDistance) if(distance < closestDistance)
@ -65,7 +65,7 @@ const BattleHexArray & BattleHex::getNeighbouringTilesDoubleWide(BattleSide side
std::ostream & operator<<(std::ostream & os, const BattleHex & hex) std::ostream & operator<<(std::ostream & os, const BattleHex & hex)
{ {
return os << boost::str(boost::format("{BattleHex: x '%d', y '%d', hex '%d'}") % hex.getX() % hex.getY() % hex.toInt()); return os << hex.toInt();
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -24,8 +24,12 @@ namespace GameConstants
class BattleHexArray; class BattleHexArray;
// for battle stacks' positions; valid hexes are from 0 to 186; available are only those not in first and last column /**
// castle towers are -2, -3 and -4 * @brief Represents a battlefield hexagonal tile.
*
* Valid hexes are within the range 0 to 186, excluding some invalid values, ex. castle towers (-2, -3, -4).
* Available hexes are those valid ones but NOT in the first or last column.
*/
class DLL_LINKAGE BattleHex class DLL_LINKAGE BattleHex
{ {
public: public:
@ -94,6 +98,11 @@ public:
return isValid() && getX() > 0 && getX() < GameConstants::BFIELD_WIDTH - 1; return isValid() && getX() > 0 && getX() < GameConstants::BFIELD_WIDTH - 1;
} }
[[nodiscard]] inline bool isTower() const noexcept
{
return hex == BattleHex::CASTLE_CENTRAL_TOWER || hex == BattleHex::CASTLE_UPPER_TOWER || hex == BattleHex::CASTLE_BOTTOM_TOWER;
}
void setX(si16 x) void setX(si16 x)
{ {
setXY(x, getY()); setXY(x, getY());
@ -175,7 +184,7 @@ public:
return result; return result;
} }
[[nodiscard]] static uint8_t getDistance(BattleHex hex1, BattleHex hex2) noexcept [[nodiscard]] static uint8_t getDistance(const BattleHex & hex1, const BattleHex & hex2) noexcept
{ {
int y1 = hex1.getY(); int y1 = hex1.getY();
int y2 = hex2.getY(); int y2 = hex2.getY();
@ -192,7 +201,7 @@ public:
return std::abs(xDst) + std::abs(yDst); return std::abs(xDst) + std::abs(yDst);
} }
[[nodiscard]] static BattleHex getClosestTile(BattleSide side, BattleHex initialPos, const BattleHexArray & hexes); [[nodiscard]] static BattleHex getClosestTile(BattleSide side, const BattleHex & initialPos, const BattleHexArray & hexes);
//Constexpr defined array with all directions used in battle //Constexpr defined array with all directions used in battle
[[nodiscard]] static constexpr auto hexagonalDirections() noexcept [[nodiscard]] static constexpr auto hexagonalDirections() noexcept
@ -200,7 +209,7 @@ public:
return std::array<EDir,6>{TOP_LEFT, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT}; return std::array<EDir,6>{TOP_LEFT, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT};
} }
[[nodiscard]] static EDir mutualPosition(BattleHex hex1, BattleHex hex2) [[nodiscard]] static EDir mutualPosition(const BattleHex & hex1, const BattleHex & hex2)
{ {
for(auto dir : hexagonalDirections()) for(auto dir : hexagonalDirections())
if(hex2 == hex1.cloneInDirection(dir, false)) if(hex2 == hex1.cloneInDirection(dir, false))
@ -240,25 +249,20 @@ public:
return *this; return *this;
} }
// Postfix increment // Postfix increment is deleted; use prefix increment as it has better performance
BattleHex operator++(int) noexcept BattleHex operator++(int) = delete;
{
BattleHex temp = *this;
++hex;
return temp;
}
[[nodiscard]] bool operator ==(BattleHex other) const noexcept [[nodiscard]] bool operator ==(const BattleHex & other) const noexcept
{ {
return hex == other.hex; return hex == other.hex;
} }
[[nodiscard]] bool operator !=(BattleHex other) const noexcept [[nodiscard]] bool operator !=(const BattleHex & other) const noexcept
{ {
return hex != other.hex; return hex != other.hex;
} }
[[nodiscard]] bool operator <(BattleHex other) const noexcept [[nodiscard]] bool operator <(const BattleHex & other) const noexcept
{ {
return hex < other.hex; return hex < other.hex;
} }

View File

@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
BattleHexArray::BattleHexArray(std::initializer_list<BattleHex> initList) noexcept BattleHexArray::BattleHexArray(std::initializer_list<BattleHex> initList) noexcept
: BattleHexArray() : BattleHexArray()
{ {
for(auto hex : initList) for(const auto & hex : initList)
{ {
insert(hex); insert(hex);
} }
@ -24,7 +24,7 @@ BattleHexArray::BattleHexArray(std::initializer_list<BattleHex> initList) noexce
void BattleHexArray::insert(const BattleHexArray & other) noexcept void BattleHexArray::insert(const BattleHexArray & other) noexcept
{ {
for(auto hex : other) for(const auto & hex : other)
{ {
insert(hex); insert(hex);
} }
@ -34,7 +34,7 @@ void BattleHexArray::erase(iterator first, iterator last) noexcept
{ {
for(auto it = first; it != last && it != internalStorage.end(); ++it) for(auto it = first; it != last && it != internalStorage.end(); ++it)
{ {
presenceFlags[it->toInt()] = 0; presenceFlags[it->toInt()] = false;
} }
internalStorage.erase(first, last); internalStorage.erase(first, last);
@ -42,8 +42,8 @@ void BattleHexArray::erase(iterator first, iterator last) noexcept
void BattleHexArray::clear() noexcept void BattleHexArray::clear() noexcept
{ {
for(auto hex : internalStorage) for(const auto & hex : internalStorage)
presenceFlags[hex.toInt()] = 0; presenceFlags[hex.toInt()] = false;
internalStorage.clear(); internalStorage.clear();
} }

View File

@ -15,7 +15,18 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
/// Class representing an array of unique BattleHex objects /**
* @brief Class representing a collection of unique, valid BattleHex objects.
* The BattleHexArray is a specialized container designed for storing instances
* of BattleHex. Key notes:
* - Each BattleHex in the array is unique.
* - Invalid BattleHex objects (e.g., those with an out-of-bounds or special
* value) cannot be inserted into the array.
* - Maintains an efficient storage mechanism for fast access and presence tracking system using bitset for quick existence checks.
* - Attempting to insert invalid BattleHex objects will have no effect.
*
*/
class DLL_LINKAGE BattleHexArray class DLL_LINKAGE BattleHexArray
{ {
public: public:
@ -56,7 +67,7 @@ public:
BattleHexArray(std::initializer_list<BattleHex> initList) noexcept; BattleHexArray(std::initializer_list<BattleHex> initList) noexcept;
void checkAndPush(BattleHex tile) void checkAndPush(const BattleHex & tile)
{ {
if(tile.isAvailable() && !contains(tile)) if(tile.isAvailable() && !contains(tile))
{ {
@ -65,7 +76,7 @@ public:
} }
} }
void insert(BattleHex hex) noexcept void insert(const BattleHex & hex) noexcept
{ {
if(contains(hex)) if(contains(hex))
return; return;
@ -74,7 +85,7 @@ public:
internalStorage.emplace_back(hex); internalStorage.emplace_back(hex);
} }
void set(size_type index, BattleHex hex) void set(size_type index, const BattleHex & hex)
{ {
if(index >= internalStorage.size()) if(index >= internalStorage.size())
{ {
@ -91,7 +102,7 @@ public:
internalStorage[index] = hex; internalStorage[index] = hex;
} }
iterator insert(iterator pos, BattleHex hex) noexcept iterator insert(iterator pos, const BattleHex & hex) noexcept
{ {
if(contains(hex)) if(contains(hex))
return pos; return pos;
@ -113,11 +124,11 @@ public:
} }
void clear() noexcept; void clear() noexcept;
inline void erase(BattleHex target) noexcept inline void erase(const BattleHex & target) noexcept
{ {
assert(contains(target)); assert(contains(target));
vstd::erase(internalStorage, target); vstd::erase(internalStorage, target);
presenceFlags[target.toInt()] = 0; presenceFlags[target.toInt()] = false;
} }
void erase(iterator first, iterator last) noexcept; void erase(iterator first, iterator last) noexcept;
inline void pop_back() noexcept inline void pop_back() noexcept
@ -131,6 +142,20 @@ public:
return std::vector<BattleHex>(internalStorage.begin(), internalStorage.end()); return std::vector<BattleHex>(internalStorage.begin(), internalStorage.end());
} }
[[nodiscard]] std::string toString(std::string delimiter = ", ") const noexcept
{
std::string result = "[";
for(auto it = internalStorage.begin(); it != internalStorage.end(); ++it)
{
if(it != internalStorage.begin())
result += delimiter;
result += std::to_string(it->toInt());
}
result += "]";
return result;
}
template <typename Predicate> template <typename Predicate>
iterator findIf(Predicate predicate) noexcept iterator findIf(Predicate predicate) noexcept
{ {
@ -147,7 +172,7 @@ public:
BattleHexArray filterBy(Predicate predicate) const noexcept BattleHexArray filterBy(Predicate predicate) const noexcept
{ {
BattleHexArray filtered; BattleHexArray filtered;
for(auto hex : internalStorage) for(const auto & hex : internalStorage)
{ {
if(predicate(hex)) if(predicate(hex))
{ {
@ -158,7 +183,7 @@ public:
} }
/// get (precomputed) all possible surrounding tiles /// get (precomputed) all possible surrounding tiles
static const BattleHexArray & getAllNeighbouringTiles(BattleHex hex) noexcept static const BattleHexArray & getAllNeighbouringTiles(const BattleHex & hex) noexcept
{ {
static const BattleHexArray invalid; static const BattleHexArray invalid;
@ -169,7 +194,7 @@ public:
} }
/// get (precomputed) only valid and available surrounding tiles /// get (precomputed) only valid and available surrounding tiles
static const BattleHexArray & getNeighbouringTiles(BattleHex hex) noexcept static const BattleHexArray & getNeighbouringTiles(const BattleHex & hex) noexcept
{ {
static const BattleHexArray invalid; static const BattleHexArray invalid;
@ -180,23 +205,19 @@ public:
} }
/// get (precomputed) only valid and available surrounding tiles for double wide creatures /// get (precomputed) only valid and available surrounding tiles for double wide creatures
static const BattleHexArray & getNeighbouringTilesDoubleWide(BattleHex hex, BattleSide side) noexcept static const BattleHexArray & getNeighbouringTilesDoubleWide(const BattleHex & hex, BattleSide side) noexcept
{ {
assert(hex.isValid() && (side == BattleSide::ATTACKER || side == BattleSide::DEFENDER)); assert(hex.isValid() && (side == BattleSide::ATTACKER || side == BattleSide::DEFENDER));
return neighbouringTilesDoubleWide.at(side)[hex.toInt()]; return neighbouringTilesDoubleWide.at(side)[hex.toInt()];
} }
[[nodiscard]] inline bool contains(BattleHex hex) const noexcept /// note: returns true when param is ivalid BattleHex
[[nodiscard]] inline bool contains(const BattleHex & hex) const noexcept
{ {
if(hex.isValid()) if(hex.isValid())
return presenceFlags[hex.toInt()]; return presenceFlags[hex.toInt()];
/*
if(!isTower(hex))
logGlobal->warn("BattleHexArray::contains( %d ) - invalid BattleHex!", hex);
*/
// returns true also for invalid hexes
return true; return true;
} }
@ -206,7 +227,7 @@ public:
s & internalStorage; s & internalStorage;
if(!s.saving) if(!s.saving)
{ {
for(auto hex : internalStorage) for(const auto & hex : internalStorage)
presenceFlags[hex.toInt()] = true; presenceFlags[hex.toInt()] = true;
} }
} }
@ -293,24 +314,6 @@ private:
StorageType internalStorage; StorageType internalStorage;
std::bitset<totalSize> presenceFlags; std::bitset<totalSize> presenceFlags;
[[nodiscard]] inline bool isNotValidForInsertion(BattleHex hex) const
{
if(isTower(hex))
return true;
if(!hex.isValid())
{
//logGlobal->warn("BattleHexArray::insert( %d ) - invalid BattleHex!", hex);
return true;
}
return contains(hex) || internalStorage.size() >= totalSize;
}
[[nodiscard]] inline bool isTower(BattleHex hex) const
{
return hex == BattleHex::CASTLE_CENTRAL_TOWER || hex == BattleHex::CASTLE_UPPER_TOWER || hex == BattleHex::CASTLE_BOTTOM_TOWER;
}
static const ArrayOfBattleHexArrays neighbouringTiles; static const ArrayOfBattleHexArrays neighbouringTiles;
static const ArrayOfBattleHexArrays allNeighbouringTiles; static const ArrayOfBattleHexArrays allNeighbouringTiles;
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDoubleWide; static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDoubleWide;

View File

@ -40,7 +40,7 @@ SideInBattle & BattleInfo::getSide(BattleSide side)
} }
///BattleInfo ///BattleInfo
CStack * BattleInfo::generateNewStack(uint32_t id, const CStackInstance & base, BattleSide side, const SlotID & slot, BattleHex position) CStack * BattleInfo::generateNewStack(uint32_t id, const CStackInstance & base, BattleSide side, const SlotID & slot, const BattleHex & position)
{ {
PlayerColor owner = getSide(side).color; PlayerColor owner = getSide(side).color;
assert(!owner.isValidPlayer() || (base.armyObj && base.armyObj->tempOwner == owner)); assert(!owner.isValidPlayer() || (base.armyObj && base.armyObj->tempOwner == owner));
@ -51,7 +51,7 @@ CStack * BattleInfo::generateNewStack(uint32_t id, const CStackInstance & base,
return ret; return ret;
} }
CStack * BattleInfo::generateNewStack(uint32_t id, const CStackBasicDescriptor & base, BattleSide side, const SlotID & slot, BattleHex position) CStack * BattleInfo::generateNewStack(uint32_t id, const CStackBasicDescriptor & base, BattleSide side, const SlotID & slot, const BattleHex & position)
{ {
PlayerColor owner = getSide(side).color; PlayerColor owner = getSide(side).color;
auto * ret = new CStack(&base, owner, id, side, slot); auto * ret = new CStack(&base, owner, id, side, slot);
@ -231,7 +231,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
obstPtr->uniqueID = static_cast<si32>(currentBattle->obstacles.size()); obstPtr->uniqueID = static_cast<si32>(currentBattle->obstacles.size());
currentBattle->obstacles.push_back(obstPtr); currentBattle->obstacles.push_back(obstPtr);
for(BattleHex blocked : obstPtr->getBlockedTiles()) for(const BattleHex & blocked : obstPtr->getBlockedTiles())
blockedTiles.insert(blocked); blockedTiles.insert(blocked);
tilesToBlock -= Obstacle(obstPtr->ID).getInfo()->blockedTiles.size() / 2; tilesToBlock -= Obstacle(obstPtr->ID).getInfo()->blockedTiles.size() / 2;
} }
@ -251,7 +251,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
const int obid = obidgen.getSuchNumber(appropriateUsualObstacle); const int obid = obidgen.getSuchNumber(appropriateUsualObstacle);
const ObstacleInfo &obi = *Obstacle(obid).getInfo(); const ObstacleInfo &obi = *Obstacle(obid).getInfo();
auto validPosition = [&](BattleHex pos) -> bool auto validPosition = [&](const BattleHex & pos) -> bool
{ {
if(obi.height >= pos.getY()) if(obi.height >= pos.getY())
return false; return false;
@ -262,7 +262,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
if(blockedTiles.contains(pos)) if(blockedTiles.contains(pos))
return false; return false;
for(BattleHex blocked : obi.getBlocked(pos)) for(const BattleHex & blocked : obi.getBlocked(pos))
{ {
if(tileAccessibility[blocked.toInt()] == EAccessibility::UNAVAILABLE) //for ship-to-ship battlefield - exclude hardcoded unavailable tiles if(tileAccessibility[blocked.toInt()] == EAccessibility::UNAVAILABLE) //for ship-to-ship battlefield - exclude hardcoded unavailable tiles
return false; return false;
@ -284,7 +284,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
obstPtr->uniqueID = static_cast<si32>(currentBattle->obstacles.size()); obstPtr->uniqueID = static_cast<si32>(currentBattle->obstacles.size());
currentBattle->obstacles.push_back(obstPtr); currentBattle->obstacles.push_back(obstPtr);
for(BattleHex blocked : obstPtr->getBlockedTiles()) for(const BattleHex & blocked : obstPtr->getBlockedTiles())
blockedTiles.insert(blocked); blockedTiles.insert(blocked);
tilesToBlock -= static_cast<int>(obi.blockedTiles.size()); tilesToBlock -= static_cast<int>(obi.blockedTiles.size());
} }
@ -297,7 +297,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
//adding war machines //adding war machines
//Checks if hero has artifact and create appropriate stack //Checks if hero has artifact and create appropriate stack
auto handleWarMachine = [&](BattleSide side, const ArtifactPosition & artslot, BattleHex hex) auto handleWarMachine = [&](BattleSide side, const ArtifactPosition & artslot, const BattleHex & hex)
{ {
const CArtifactInstance * warMachineArt = heroes[side]->getArt(artslot); const CArtifactInstance * warMachineArt = heroes[side]->getArt(artslot);
@ -682,7 +682,7 @@ void BattleInfo::addUnit(uint32_t id, const JsonNode & data)
ret->summoned = info.summoned; ret->summoned = info.summoned;
} }
void BattleInfo::moveUnit(uint32_t id, BattleHex destination) void BattleInfo::moveUnit(uint32_t id, const BattleHex & destination)
{ {
auto * sta = getStack(id); auto * sta = getStack(id);
if(!sta) if(!sta)

View File

@ -121,7 +121,7 @@ public:
void nextTurn(uint32_t unitId) override; void nextTurn(uint32_t unitId) override;
void addUnit(uint32_t id, const JsonNode & data) override; void addUnit(uint32_t id, const JsonNode & data) override;
void moveUnit(uint32_t id, BattleHex destination) override; void moveUnit(uint32_t id, const BattleHex & destination) override;
void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) override; void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) override;
void removeUnit(uint32_t id) override; void removeUnit(uint32_t id) override;
void updateUnit(uint32_t id, const JsonNode & data) override; void updateUnit(uint32_t id, const JsonNode & data) override;
@ -145,8 +145,8 @@ public:
using CBattleInfoEssentials::battleGetFightingHero; using CBattleInfoEssentials::battleGetFightingHero;
CGHeroInstance * battleGetFightingHero(BattleSide side) const; CGHeroInstance * battleGetFightingHero(BattleSide side) const;
CStack * generateNewStack(uint32_t id, const CStackInstance & base, BattleSide side, const SlotID & slot, BattleHex position); CStack * generateNewStack(uint32_t id, const CStackInstance & base, BattleSide side, const SlotID & slot, const BattleHex & position);
CStack * generateNewStack(uint32_t id, const CStackBasicDescriptor & base, BattleSide side, const SlotID & slot, BattleHex position); CStack * generateNewStack(uint32_t id, const CStackBasicDescriptor & base, BattleSide side, const SlotID & slot, const BattleHex & position);
const SideInBattle & getSide(BattleSide side) const; const SideInBattle & getSide(BattleSide side) const;
SideInBattle & getSide(BattleSide side); SideInBattle & getSide(BattleSide side);

View File

@ -41,7 +41,7 @@ static BattleHex lineToWallHex(int line) //returns hex with wall in given line (
return lineToHex[line]; return lineToHex[line];
} }
static bool sameSideOfWall(BattleHex pos1, BattleHex pos2) static bool sameSideOfWall(const BattleHex & pos1, const BattleHex & pos2)
{ {
const bool stackLeft = pos1 < lineToWallHex(pos1.getY()); const bool stackLeft = pos1 < lineToWallHex(pos1.getY());
const bool destLeft = pos2 < lineToWallHex(pos2.getY()); const bool destLeft = pos2 < lineToWallHex(pos2.getY());
@ -49,7 +49,7 @@ static bool sameSideOfWall(BattleHex pos1, BattleHex pos2)
return stackLeft == destLeft; return stackLeft == destLeft;
} }
static bool isInsideWalls(BattleHex pos) static bool isInsideWalls(const BattleHex & pos)
{ {
return lineToWallHex(pos.getY()) < pos; return lineToWallHex(pos.getY()) < pos;
} }
@ -73,7 +73,7 @@ static const std::pair<int, EWallPart> wallParts[] =
std::make_pair(165, EWallPart::INDESTRUCTIBLE_PART) std::make_pair(165, EWallPart::INDESTRUCTIBLE_PART)
}; };
static EWallPart hexToWallPart(BattleHex hex) static EWallPart hexToWallPart(const BattleHex & hex)
{ {
si16 hexValue = hex.toInt(); si16 hexValue = hex.toInt();
for(const auto & elem : wallParts) for(const auto & elem : wallParts)
@ -144,7 +144,7 @@ ESpellCastProblem CBattleInfoCallback::battleCanCastSpell(const spells::Caster *
return ESpellCastProblem::OK; return ESpellCastProblem::OK;
} }
std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(BattleHex start, BattleHex dest, const battle::Unit * stack) const std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(const BattleHex & start, const BattleHex & dest, const battle::Unit * stack) const
{ {
auto reachability = getReachability(stack); auto reachability = getReachability(stack);
@ -165,17 +165,17 @@ std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(BattleHex start, B
return std::make_pair(path, reachability.distances[dest.toInt()]); return std::make_pair(path, reachability.distances[dest.toInt()]);
} }
bool CBattleInfoCallback::battleIsInsideWalls(BattleHex from) const bool CBattleInfoCallback::battleIsInsideWalls(const BattleHex & from) const
{ {
return isInsideWalls(from); return isInsideWalls(from);
} }
bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest, bool checkWall, bool checkMoat) const bool CBattleInfoCallback::battleHasPenaltyOnLine(const BattleHex & from, const BattleHex & dest, bool checkWall, bool checkMoat) const
{ {
if (!from.isAvailable() || !dest.isAvailable()) if (!from.isAvailable() || !dest.isAvailable())
throw std::runtime_error("Invalid hex (" + std::to_string(from.toInt()) + " and " + std::to_string(dest.toInt()) + ") received in battleHasPenaltyOnLine!" ); throw std::runtime_error("Invalid hex (" + std::to_string(from.toInt()) + " and " + std::to_string(dest.toInt()) + ") received in battleHasPenaltyOnLine!" );
auto isTileBlocked = [&](BattleHex tile) auto isTileBlocked = [&](const BattleHex & tile)
{ {
EWallPart wallPart = battleHexToWallPart(tile); EWallPart wallPart = battleHexToWallPart(tile);
if (wallPart == EWallPart::INVALID) if (wallPart == EWallPart::INVALID)
@ -188,7 +188,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
return isWallPartAttackable(wallPart); return isWallPartAttackable(wallPart);
}; };
// Count wall penalty requirement by shortest path, not by arbitrary line, to avoid various OH3 bugs // Count wall penalty requirement by shortest path, not by arbitrary line, to avoid various OH3 bugs
auto getShortestPath = [](BattleHex from, BattleHex dest) -> BattleHexArray auto getShortestPath = [](const BattleHex & from, const BattleHex & dest) -> BattleHexArray
{ {
//Out early //Out early
if(from == dest) if(from == dest)
@ -231,7 +231,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
return checkNeeded && ( (checkWall && pathHasWall) || (checkMoat && pathHasMoat) ); return checkNeeded && ( (checkWall && pathHasWall) || (checkMoat && pathHasMoat) );
} }
bool CBattleInfoCallback::battleHasWallPenalty(const IBonusBearer * shooter, BattleHex shooterPosition, BattleHex destHex) const bool CBattleInfoCallback::battleHasWallPenalty(const IBonusBearer * shooter, const BattleHex & shooterPosition, const BattleHex & destHex) const
{ {
RETURN_IF_NOT_BATTLE(false); RETURN_IF_NOT_BATTLE(false);
if(battleGetFortifications().wallsHealth == 0) if(battleGetFortifications().wallsHealth == 0)
@ -313,14 +313,14 @@ PossiblePlayerBattleAction CBattleInfoCallback::getCasterAction(const CSpell * s
return PossiblePlayerBattleAction(spellSelMode, spell->id); return PossiblePlayerBattleAction(spellSelMode, spell->id);
} }
BattleHexArray CBattleInfoCallback::battleGetAttackedHexes(const battle::Unit * attacker, BattleHex destinationTile, BattleHex attackerPos) const BattleHexArray CBattleInfoCallback::battleGetAttackedHexes(const battle::Unit * attacker, const BattleHex & destinationTile, const BattleHex & attackerPos) const
{ {
BattleHexArray attackedHexes; BattleHexArray attackedHexes;
RETURN_IF_NOT_BATTLE(attackedHexes); RETURN_IF_NOT_BATTLE(attackedHexes);
AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos); AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos);
for (BattleHex tile : at.hostileCreaturePositions) for (const BattleHex & tile : at.hostileCreaturePositions)
{ {
const auto * st = battleGetUnitByPos(tile, true); const auto * st = battleGetUnitByPos(tile, true);
if(st && st->unitOwner() != attacker->unitOwner()) //only hostile stacks - does it work well with Berserk? if(st && st->unitOwner() != attacker->unitOwner()) //only hostile stacks - does it work well with Berserk?
@ -328,7 +328,7 @@ BattleHexArray CBattleInfoCallback::battleGetAttackedHexes(const battle::Unit *
attackedHexes.insert(tile); attackedHexes.insert(tile);
} }
} }
for (BattleHex tile : at.friendlyCreaturePositions) for (const BattleHex & tile : at.friendlyCreaturePositions)
{ {
if(battleGetUnitByPos(tile, true)) //friendly stacks can also be damaged by Dragon Breath if(battleGetUnitByPos(tile, true)) //friendly stacks can also be damaged by Dragon Breath
{ {
@ -338,7 +338,7 @@ BattleHexArray CBattleInfoCallback::battleGetAttackedHexes(const battle::Unit *
return attackedHexes; return attackedHexes;
} }
const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyAlive) const const CStack* CBattleInfoCallback::battleGetStackByPos(const BattleHex & pos, bool onlyAlive) const
{ {
RETURN_IF_NOT_BATTLE(nullptr); RETURN_IF_NOT_BATTLE(nullptr);
for(const auto * s : battleGetAllStacks(true)) for(const auto * s : battleGetAllStacks(true))
@ -348,7 +348,7 @@ const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyA
return nullptr; return nullptr;
} }
const battle::Unit * CBattleInfoCallback::battleGetUnitByPos(BattleHex pos, bool onlyAlive) const const battle::Unit * CBattleInfoCallback::battleGetUnitByPos(const BattleHex & pos, bool onlyAlive) const
{ {
RETURN_IF_NOT_BATTLE(nullptr); RETURN_IF_NOT_BATTLE(nullptr);
@ -622,7 +622,7 @@ BattleHexArray CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit *
{ {
BattleHexArray occupiable; BattleHexArray occupiable;
for(auto hex : ret) for(const auto & hex : ret)
occupiable.insert(unit->occupiedHex(hex)); occupiable.insert(unit->occupiedHex(hex));
ret.insert(occupiable); ret.insert(occupiable);
@ -631,11 +631,11 @@ BattleHexArray CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit *
if(attackable) if(attackable)
{ {
auto meleeAttackable = [&](BattleHex hex) -> bool auto meleeAttackable = [&](const BattleHex & hex) -> bool
{ {
// Return true if given hex has at least one available neighbour. // Return true if given hex has at least one available neighbour.
// Available hexes are already present in ret vector. // Available hexes are already present in ret vector.
auto availableNeighbour = boost::find_if(ret, [=] (BattleHex availableHex) auto availableNeighbour = boost::find_if(ret, [=] (const BattleHex & availableHex)
{ {
return BattleHex::mutualPosition(hex, availableHex) >= 0; return BattleHex::mutualPosition(hex, availableHex) >= 0;
}); });
@ -654,7 +654,7 @@ BattleHexArray CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit *
continue; continue;
} }
for(BattleHex he : occupied) for(const BattleHex & he : occupied)
{ {
if(meleeAttackable(he)) if(meleeAttackable(he))
attackable->insert(he); attackable->insert(he);
@ -665,7 +665,7 @@ BattleHexArray CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit *
return ret; return ret;
} }
bool CBattleInfoCallback::battleCanAttack(const battle::Unit * stack, const battle::Unit * target, BattleHex dest) const bool CBattleInfoCallback::battleCanAttack(const battle::Unit * stack, const battle::Unit * target, const BattleHex & dest) const
{ {
RETURN_IF_NOT_BATTLE(false); RETURN_IF_NOT_BATTLE(false);
@ -729,7 +729,7 @@ bool CBattleInfoCallback::battleCanTargetEmptyHex(const battle::Unit * attacker)
return false; return false;
} }
bool CBattleInfoCallback::battleCanShoot(const battle::Unit * attacker, BattleHex dest) const bool CBattleInfoCallback::battleCanShoot(const battle::Unit * attacker, const BattleHex & dest) const
{ {
RETURN_IF_NOT_BATTLE(false); RETURN_IF_NOT_BATTLE(false);
@ -777,7 +777,7 @@ DamageEstimation CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo &
return calculator.calculateDmgRange(); return calculator.calculateDmgRange();
} }
DamageEstimation CBattleInfoCallback::battleEstimateDamage(const battle::Unit * attacker, const battle::Unit * defender, BattleHex attackerPosition, DamageEstimation * retaliationDmg) const DamageEstimation CBattleInfoCallback::battleEstimateDamage(const battle::Unit * attacker, const battle::Unit * defender, const BattleHex & attackerPosition, DamageEstimation * retaliationDmg) const
{ {
RETURN_IF_NOT_BATTLE({}); RETURN_IF_NOT_BATTLE({});
auto reachability = battleGetDistances(attacker, attacker->getPosition()); auto reachability = battleGetDistances(attacker, attacker->getPosition());
@ -840,7 +840,7 @@ DamageEstimation CBattleInfoCallback::battleEstimateDamage(const BattleAttackInf
return ret; return ret;
} }
std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking) const std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::battleGetAllObstaclesOnPos(const BattleHex & tile, bool onlyBlocking) const
{ {
auto obstacles = std::vector<std::shared_ptr<const CObstacleInstance>>(); auto obstacles = std::vector<std::shared_ptr<const CObstacleInstance>>();
RETURN_IF_NOT_BATTLE(obstacles); RETURN_IF_NOT_BATTLE(obstacles);
@ -871,7 +871,7 @@ std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::getAl
if(!vstd::contains(affectedObstacles, i)) if(!vstd::contains(affectedObstacles, i))
affectedObstacles.push_back(i); affectedObstacles.push_back(i);
} }
for(auto hex : unit->getHexes()) for(const auto & hex : unit->getHexes())
if(hex == BattleHex::GATE_BRIDGE && battleIsGatePassable()) if(hex == BattleHex::GATE_BRIDGE && battleIsGatePassable())
for(int i=0; i<affectedObstacles.size(); i++) for(int i=0; i<affectedObstacles.size(); i++)
if(affectedObstacles.at(i)->obstacleType == CObstacleInstance::MOAT) if(affectedObstacles.at(i)->obstacleType == CObstacleInstance::MOAT)
@ -959,7 +959,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
if(bFieldType != BattleField::NONE) if(bFieldType != BattleField::NONE)
{ {
for(auto hex : bFieldType.getInfo()->impassableHexes) for(const auto & hex : bFieldType.getInfo()->impassableHexes)
ret[hex.toInt()] = EAccessibility::UNAVAILABLE; ret[hex.toInt()] = EAccessibility::UNAVAILABLE;
} }
@ -983,7 +983,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
//tiles occupied by standing stacks //tiles occupied by standing stacks
for(const auto * unit : battleAliveUnits()) for(const auto * unit : battleAliveUnits())
{ {
for(auto hex : unit->getHexes()) for(const auto & hex : unit->getHexes())
if(hex.isAvailable()) //towers can have <0 pos; we don't also want to overwrite side columns if(hex.isAvailable()) //towers can have <0 pos; we don't also want to overwrite side columns
ret[hex.toInt()] = EAccessibility::ALIVE_STACK; ret[hex.toInt()] = EAccessibility::ALIVE_STACK;
} }
@ -991,7 +991,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
//obstacles //obstacles
for(const auto &obst : battleGetAllObstacles()) for(const auto &obst : battleGetAllObstacles())
{ {
for(auto hex : obst->getBlockedTiles()) for(const auto & hex : obst->getBlockedTiles())
ret[hex.toInt()] = EAccessibility::OBSTACLE; ret[hex.toInt()] = EAccessibility::OBSTACLE;
} }
@ -999,7 +999,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
if(battleGetFortifications().wallsHealth > 0) if(battleGetFortifications().wallsHealth > 0)
{ {
static const int permanentlyLocked[] = {12, 45, 62, 112, 147, 165}; static const int permanentlyLocked[] = {12, 45, 62, 112, 147, 165};
for(auto hex : permanentlyLocked) for(const auto & hex : permanentlyLocked)
ret[hex] = EAccessibility::UNAVAILABLE; ret[hex] = EAccessibility::UNAVAILABLE;
//TODO likely duplicated logic //TODO likely duplicated logic
@ -1024,13 +1024,13 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
AccessibilityInfo CBattleInfoCallback::getAccessibility(const battle::Unit * stack) const AccessibilityInfo CBattleInfoCallback::getAccessibility(const battle::Unit * stack) const
{ {
return getAccessibility(battle::Unit::getHexes(stack->getPosition(), stack->doubleWide(), stack->unitSide())); return getAccessibility(stack->getHexes());
} }
AccessibilityInfo CBattleInfoCallback::getAccessibility(const BattleHexArray & accessibleHexes) const AccessibilityInfo CBattleInfoCallback::getAccessibility(const BattleHexArray & accessibleHexes) const
{ {
auto ret = getAccessibility(); auto ret = getAccessibility();
for(auto hex : accessibleHexes) for(const auto & hex : accessibleHexes)
if(hex.isValid()) if(hex.isValid())
ret[hex.toInt()] = EAccessibility::ACCESSIBLE; ret[hex.toInt()] = EAccessibility::ACCESSIBLE;
@ -1074,7 +1074,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
const int costToNeighbour = ret.distances.at(curHex.toInt()) + 1; const int costToNeighbour = ret.distances.at(curHex.toInt()) + 1;
for(BattleHex neighbour : curHex.getNeighbouringTiles()) for(const BattleHex & neighbour : curHex.getNeighbouringTiles())
{ {
auto additionalCost = 0; auto additionalCost = 0;
@ -1103,12 +1103,12 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
} }
bool CBattleInfoCallback::isInObstacle( bool CBattleInfoCallback::isInObstacle(
BattleHex hex, const BattleHex & hex,
const BattleHexArray & obstacleHexes, const BattleHexArray & obstacleHexes,
const ReachabilityInfo::Parameters & params) const const ReachabilityInfo::Parameters & params) const
{ {
for(auto occupiedHex : battle::Unit::getHexes(hex, params.doubleWide, params.side)) for(const auto & occupiedHex : battle::Unit::getHexes(hex, params.doubleWide, params.side))
{ {
if(params.ignoreKnownAccessible && params.knownAccessible->contains(occupiedHex)) if(params.ignoreKnownAccessible && params.knownAccessible->contains(occupiedHex))
continue; continue;
@ -1138,7 +1138,7 @@ BattleHexArray CBattleInfoCallback::getStoppers(BattleSide whichSidePerspective)
if(!battleIsObstacleVisibleForSide(*oi, whichSidePerspective)) if(!battleIsObstacleVisibleForSide(*oi, whichSidePerspective))
continue; continue;
for(auto hex : oi->getStoppingTile()) for(const auto & hex : oi->getStoppingTile())
{ {
if(hex == BattleHex::GATE_BRIDGE && oi->obstacleType == CObstacleInstance::MOAT) if(hex == BattleHex::GATE_BRIDGE && oi->obstacleType == CObstacleInstance::MOAT)
{ {
@ -1173,7 +1173,7 @@ std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(
for(const battle::Unit * st : possible) for(const battle::Unit * st : possible)
{ {
for(BattleHex hex : avHexes) for(const BattleHex & hex : avHexes)
if(CStack::isMeleeAttackPossible(closest, st, hex)) if(CStack::isMeleeAttackPossible(closest, st, hex))
{ {
DistStack hlp = {reachability.distances[hex.toInt()], hex, st}; DistStack hlp = {reachability.distances[hex.toInt()], hex, st};
@ -1232,7 +1232,7 @@ si8 CBattleInfoCallback::battleGetTacticDist() const
return 0; return 0;
} }
bool CBattleInfoCallback::isInTacticRange(BattleHex dest) const bool CBattleInfoCallback::isInTacticRange(const BattleHex & dest) const
{ {
RETURN_IF_NOT_BATTLE(false); RETURN_IF_NOT_BATTLE(false);
auto side = battleGetTacticsSide(); auto side = battleGetTacticsSide();
@ -1340,7 +1340,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
if(attacker->hasBonusOfType(BonusType::THREE_HEADED_ATTACK)) if(attacker->hasBonusOfType(BonusType::THREE_HEADED_ATTACK))
{ {
const BattleHexArray & hexes = attacker->getSurroundingHexes(attackerPos); const BattleHexArray & hexes = attacker->getSurroundingHexes(attackerPos);
for(BattleHex tile : hexes) for(const BattleHex & tile : hexes)
{ {
if((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, attackOriginHex) > -1)) //adjacent both to attacker's head and attacked tile if((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, attackOriginHex) > -1)) //adjacent both to attacker's head and attacked tile
{ {
@ -1356,7 +1356,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
if (hexes.contains(attackOriginHex)) if (hexes.contains(attackOriginHex))
hexes.erase(attackOriginHex); hexes.erase(attackOriginHex);
for(BattleHex tile : hexes) for(const BattleHex & tile : hexes)
{ {
//friendly stacks can also be damaged by Dragon Breath //friendly stacks can also be damaged by Dragon Breath
const auto * st = battleGetUnitByPos(tile, true); const auto * st = battleGetUnitByPos(tile, true);
@ -1414,7 +1414,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
return at; return at;
} }
AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::Unit * attacker, BattleHex destinationTile, BattleHex attackerPos) const AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::Unit * attacker, const BattleHex & destinationTile, const BattleHex & attackerPos) const
{ {
//does not return hex attacked directly //does not return hex attacked directly
AttackableTiles at; AttackableTiles at;
@ -1458,7 +1458,7 @@ battle::Units CBattleInfoCallback::getAttackedBattleUnits(
if (unit->isGhost() || !unit->alive()) if (unit->isGhost() || !unit->alive())
return false; return false;
for (BattleHex hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide())) for (const BattleHex & hex : unit->getHexes())
{ {
if (at.hostileCreaturePositions.contains(hex)) if (at.hostileCreaturePositions.contains(hex))
return true; return true;
@ -1471,7 +1471,7 @@ battle::Units CBattleInfoCallback::getAttackedBattleUnits(
return units; return units;
} }
std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, bool rangedAttack, BattleHex attackerPos) const std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack* attacker, const BattleHex & destinationTile, bool rangedAttack, BattleHex attackerPos) const
{ {
std::set<const CStack*> attackedCres; std::set<const CStack*> attackedCres;
RETURN_IF_NOT_BATTLE(attackedCres); RETURN_IF_NOT_BATTLE(attackedCres);
@ -1483,7 +1483,7 @@ std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack*
else else
at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos); at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos);
for (BattleHex tile : at.hostileCreaturePositions) //all around & three-headed attack for (const BattleHex & tile : at.hostileCreaturePositions) //all around & three-headed attack
{ {
const CStack * st = battleGetStackByPos(tile, true); const CStack * st = battleGetStackByPos(tile, true);
if(st && st->unitOwner() != attacker->unitOwner()) //only hostile stacks - does it work well with Berserk? if(st && st->unitOwner() != attacker->unitOwner()) //only hostile stacks - does it work well with Berserk?
@ -1491,7 +1491,7 @@ std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack*
attackedCres.insert(st); attackedCres.insert(st);
} }
} }
for (BattleHex tile : at.friendlyCreaturePositions) for (const BattleHex & tile : at.friendlyCreaturePositions)
{ {
const CStack * st = battleGetStackByPos(tile, true); const CStack * st = battleGetStackByPos(tile, true);
if(st) //friendly stacks can also be damaged by Dragon Breath if(st) //friendly stacks can also be damaged by Dragon Breath
@ -1502,7 +1502,7 @@ std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack*
return attackedCres; return attackedCres;
} }
static bool isHexInFront(BattleHex hex, BattleHex testHex, BattleSide side ) static bool isHexInFront(const BattleHex & hex, const BattleHex & testHex, BattleSide side )
{ {
static const std::set<BattleHex::EDir> rightDirs { BattleHex::BOTTOM_RIGHT, BattleHex::TOP_RIGHT, BattleHex::RIGHT }; static const std::set<BattleHex::EDir> rightDirs { BattleHex::BOTTOM_RIGHT, BattleHex::TOP_RIGHT, BattleHex::RIGHT };
static const std::set<BattleHex::EDir> leftDirs { BattleHex::BOTTOM_LEFT, BattleHex::TOP_LEFT, BattleHex::LEFT }; static const std::set<BattleHex::EDir> leftDirs { BattleHex::BOTTOM_LEFT, BattleHex::TOP_LEFT, BattleHex::LEFT };
@ -1559,7 +1559,7 @@ bool CBattleInfoCallback::isToReverse(const battle::Unit * attacker, const battl
return true; return true;
} }
ReachabilityInfo::TDistances CBattleInfoCallback::battleGetDistances(const battle::Unit * unit, BattleHex assumedPosition) const ReachabilityInfo::TDistances CBattleInfoCallback::battleGetDistances(const battle::Unit * unit, const BattleHex & assumedPosition) const
{ {
ReachabilityInfo::TDistances ret; ReachabilityInfo::TDistances ret;
ret.fill(-1); ret.fill(-1);
@ -1572,7 +1572,7 @@ ReachabilityInfo::TDistances CBattleInfoCallback::battleGetDistances(const battl
return ret; return ret;
} }
bool CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer * shooter, BattleHex shooterPosition, BattleHex destHex) const bool CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer * shooter, const BattleHex & shooterPosition, const BattleHex & destHex) const
{ {
RETURN_IF_NOT_BATTLE(false); RETURN_IF_NOT_BATTLE(false);
@ -1603,16 +1603,16 @@ bool CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer * shooter,
return true; return true;
} }
bool CBattleInfoCallback::isEnemyUnitWithinSpecifiedRange(BattleHex attackerPosition, const battle::Unit * defenderUnit, unsigned int range) const bool CBattleInfoCallback::isEnemyUnitWithinSpecifiedRange(const BattleHex & attackerPosition, const battle::Unit * defenderUnit, unsigned int range) const
{ {
for(auto hex : defenderUnit->getHexes()) for(const auto & hex : defenderUnit->getHexes())
if(BattleHex::getDistance(attackerPosition, hex) <= range) if(BattleHex::getDistance(attackerPosition, hex) <= range)
return true; return true;
return false; return false;
} }
bool CBattleInfoCallback::isHexWithinSpecifiedRange(BattleHex attackerPosition, BattleHex targetPosition, unsigned int range) const bool CBattleInfoCallback::isHexWithinSpecifiedRange(const BattleHex & attackerPosition, const BattleHex & targetPosition, unsigned int range) const
{ {
if(BattleHex::getDistance(attackerPosition, targetPosition) <= range) if(BattleHex::getDistance(attackerPosition, targetPosition) <= range)
return true; return true;
@ -1626,7 +1626,7 @@ BattleHex CBattleInfoCallback::wallPartToBattleHex(EWallPart part) const
return WallPartToHex(part); return WallPartToHex(part);
} }
EWallPart CBattleInfoCallback::battleHexToWallPart(BattleHex hex) const EWallPart CBattleInfoCallback::battleHexToWallPart(const BattleHex & hex) const
{ {
RETURN_IF_NOT_BATTLE(EWallPart::INVALID); RETURN_IF_NOT_BATTLE(EWallPart::INVALID);
return hexToWallPart(hex); return hexToWallPart(hex);
@ -1692,7 +1692,7 @@ int32_t CBattleInfoCallback::battleGetSpellCost(const spells::Spell * sp, const
return std::max(0, ret - manaReduction + manaIncrease); return std::max(0, ret - manaReduction + manaIncrease);
} }
bool CBattleInfoCallback::battleHasShootingPenalty(const battle::Unit * shooter, BattleHex destHex) const bool CBattleInfoCallback::battleHasShootingPenalty(const battle::Unit * shooter, const BattleHex & destHex) const
{ {
return battleHasDistancePenalty(shooter, shooter->getPosition(), destHex) || battleHasWallPenalty(shooter, shooter->getPosition(), destHex); return battleHasDistancePenalty(shooter, shooter->getPosition(), destHex) || battleHasWallPenalty(shooter, shooter->getPosition(), destHex);
} }

View File

@ -58,14 +58,14 @@ class DLL_LINKAGE CBattleInfoCallback : public virtual CBattleInfoEssentials
public: public:
std::optional<BattleSide> battleIsFinished() const override; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw std::optional<BattleSide> battleIsFinished() const override; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const override; std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(const BattleHex & tile, bool onlyBlocking = true) const override;
std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit, const BattleHexArray & passed) const override; std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit, const BattleHexArray & passed) const override;
//Handle obstacle damage here, requires SpellCastEnvironment //Handle obstacle damage here, requires SpellCastEnvironment
bool handleObstacleTriggersForUnit(SpellCastEnvironment & spellEnv, const battle::Unit & unit, const BattleHexArray & passed = {}) const; bool handleObstacleTriggersForUnit(SpellCastEnvironment & spellEnv, const battle::Unit & unit, const BattleHexArray & passed = {}) const;
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const; const CStack * battleGetStackByPos(const BattleHex & pos, bool onlyAlive = true) const;
const battle::Unit * battleGetUnitByPos(BattleHex pos, bool onlyAlive = true) const override; const battle::Unit * battleGetUnitByPos(const BattleHex & pos, bool onlyAlive = true) const override;
///returns all alive units excluding turrets ///returns all alive units excluding turrets
battle::Units battleAliveUnits() const; battle::Units battleAliveUnits() const;
@ -83,16 +83,16 @@ public:
BattleHexArray battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit, bool obtainMovementRange) const; BattleHexArray battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit, bool obtainMovementRange) const;
int battleGetSurrenderCost(const PlayerColor & Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible int battleGetSurrenderCost(const PlayerColor & Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
ReachabilityInfo::TDistances battleGetDistances(const battle::Unit * unit, BattleHex assumedPosition) const; ReachabilityInfo::TDistances battleGetDistances(const battle::Unit * unit, const BattleHex & assumedPosition) const;
BattleHexArray battleGetAttackedHexes(const battle::Unit * attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; BattleHexArray battleGetAttackedHexes(const battle::Unit * attacker, const BattleHex & destinationTile, const BattleHex & attackerPos = BattleHex::INVALID) const;
bool isEnemyUnitWithinSpecifiedRange(BattleHex attackerPosition, const battle::Unit * defenderUnit, unsigned int range) const; bool isEnemyUnitWithinSpecifiedRange(const BattleHex & attackerPosition, const battle::Unit * defenderUnit, unsigned int range) const;
bool isHexWithinSpecifiedRange(BattleHex attackerPosition, BattleHex targetPosition, unsigned int range) const; bool isHexWithinSpecifiedRange(const BattleHex & attackerPosition, const BattleHex & targetPosition, unsigned int range) const;
std::pair< BattleHexArray, int > getPath(BattleHex start, BattleHex dest, const battle::Unit * stack) const; std::pair< BattleHexArray, int > getPath(const BattleHex & start, const BattleHex & dest, const battle::Unit * stack) const;
bool battleCanTargetEmptyHex(const battle::Unit * attacker) const; //determines of stack with given ID can target empty hex to attack - currently used only for SPELL_LIKE_ATTACK shooting bool battleCanTargetEmptyHex(const battle::Unit * attacker) const; //determines of stack with given ID can target empty hex to attack - currently used only for SPELL_LIKE_ATTACK shooting
bool battleCanAttack(const battle::Unit * stack, const battle::Unit * target, BattleHex dest) const; //determines if stack with given ID can attack target at the selected destination bool battleCanAttack(const battle::Unit * stack, const battle::Unit * target, const BattleHex & dest) const; //determines if stack with given ID can attack target at the selected destination
bool battleCanShoot(const battle::Unit * attacker, BattleHex dest) const; //determines if stack with given ID shoot at the selected destination bool battleCanShoot(const battle::Unit * attacker, const BattleHex & dest) const; //determines if stack with given ID shoot at the selected destination
bool battleCanShoot(const battle::Unit * attacker) const; //determines if stack with given ID shoot in principle bool battleCanShoot(const battle::Unit * attacker) const; //determines if stack with given ID shoot in principle
bool battleIsUnitBlocked(const battle::Unit * unit) const; //returns true if there is neighboring enemy stack bool battleIsUnitBlocked(const battle::Unit * unit) const; //returns true if there is neighboring enemy stack
battle::Units battleAdjacentUnits(const battle::Unit * unit) const; battle::Units battleAdjacentUnits(const battle::Unit * unit) const;
@ -103,17 +103,17 @@ public:
/// only non-random bonuses are considered in estimation /// only non-random bonuses are considered in estimation
/// returns pair <min dmg, max dmg> /// returns pair <min dmg, max dmg>
DamageEstimation battleEstimateDamage(const BattleAttackInfo & bai, DamageEstimation * retaliationDmg = nullptr) const; DamageEstimation battleEstimateDamage(const BattleAttackInfo & bai, DamageEstimation * retaliationDmg = nullptr) const;
DamageEstimation battleEstimateDamage(const battle::Unit * attacker, const battle::Unit * defender, BattleHex attackerPosition, DamageEstimation * retaliationDmg = nullptr) const; DamageEstimation battleEstimateDamage(const battle::Unit * attacker, const battle::Unit * defender, const BattleHex & attackerPosition, DamageEstimation * retaliationDmg = nullptr) const;
DamageEstimation battleEstimateDamage(const battle::Unit * attacker, const battle::Unit * defender, int getMovementRange, DamageEstimation * retaliationDmg = nullptr) const; DamageEstimation battleEstimateDamage(const battle::Unit * attacker, const battle::Unit * defender, int getMovementRange, DamageEstimation * retaliationDmg = nullptr) const;
bool battleIsInsideWalls(BattleHex from) const; bool battleIsInsideWalls(const BattleHex & from) const;
bool battleHasPenaltyOnLine(BattleHex from, BattleHex dest, bool checkWall, bool checkMoat) const; bool battleHasPenaltyOnLine(const BattleHex & from, const BattleHex & dest, bool checkWall, bool checkMoat) const;
bool battleHasDistancePenalty(const IBonusBearer * shooter, BattleHex shooterPosition, BattleHex destHex) const; bool battleHasDistancePenalty(const IBonusBearer * shooter, const BattleHex & shooterPosition, const BattleHex & destHex) const;
bool battleHasWallPenalty(const IBonusBearer * shooter, BattleHex shooterPosition, BattleHex destHex) const; bool battleHasWallPenalty(const IBonusBearer * shooter, const BattleHex & shooterPosition, const BattleHex & destHex) const;
bool battleHasShootingPenalty(const battle::Unit * shooter, BattleHex destHex) const; bool battleHasShootingPenalty(const battle::Unit * shooter, const BattleHex & destHex) const;
BattleHex wallPartToBattleHex(EWallPart part) const; BattleHex wallPartToBattleHex(EWallPart part) const;
EWallPart battleHexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found EWallPart battleHexToWallPart(const BattleHex & hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
bool isWallPartPotentiallyAttackable(EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not bool isWallPartPotentiallyAttackable(EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not
bool isWallPartAttackable(EWallPart wallPart) const; // returns true if the wall part is actually attackable, false if not bool isWallPartAttackable(EWallPart wallPart) const; // returns true if the wall part is actually attackable, false if not
BattleHexArray getAttackableBattleHexes() const; BattleHexArray getAttackableBattleHexes() const;
@ -130,7 +130,7 @@ public:
PossiblePlayerBattleAction getCasterAction(const CSpell * spell, const spells::Caster * caster, spells::Mode mode) const; PossiblePlayerBattleAction getCasterAction(const CSpell * spell, const spells::Caster * caster, spells::Mode mode) const;
//convenience methods using the ones above //convenience methods using the ones above
bool isInTacticRange(BattleHex dest) const; bool isInTacticRange(const BattleHex & dest) const;
si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side) si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
AttackableTiles getPotentiallyAttackableHexes( AttackableTiles getPotentiallyAttackableHexes(
@ -145,7 +145,7 @@ public:
BattleHex destinationTile, BattleHex destinationTile,
BattleHex attackerPos) const; BattleHex attackerPos) const;
AttackableTiles getPotentiallyShootableHexes(const battle::Unit* attacker, BattleHex destinationTile, BattleHex attackerPos) const; AttackableTiles getPotentiallyShootableHexes(const battle::Unit* attacker, const BattleHex & destinationTile, const BattleHex & attackerPos) const;
battle::Units getAttackedBattleUnits( battle::Units getAttackedBattleUnits(
const battle::Unit* attacker, const battle::Unit* attacker,
@ -155,7 +155,7 @@ public:
BattleHex attackerPos = BattleHex::INVALID, BattleHex attackerPos = BattleHex::INVALID,
BattleHex defenderPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks BattleHex defenderPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, bool rangedAttack, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks std::set<const CStack*> getAttackedCreatures(const CStack* attacker, const BattleHex & destinationTile, bool rangedAttack, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
bool isToReverse(const battle::Unit * attacker, const battle::Unit * defender, BattleHex attackerHex = BattleHex::INVALID, BattleHex defenderHex = BattleHex::INVALID) const; //determines if attacker standing at attackerHex should reverse in order to attack defender bool isToReverse(const battle::Unit * attacker, const battle::Unit * defender, BattleHex attackerHex = BattleHex::INVALID, BattleHex defenderHex = BattleHex::INVALID) const; //determines if attacker standing at attackerHex should reverse in order to attack defender
ReachabilityInfo getReachability(const battle::Unit * unit) const; ReachabilityInfo getReachability(const battle::Unit * unit) const;
@ -169,7 +169,7 @@ public:
protected: protected:
ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters & params) const; ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters & params) const;
ReachabilityInfo makeBFS(const AccessibilityInfo & accessibility, const ReachabilityInfo::Parameters & params) const; ReachabilityInfo makeBFS(const AccessibilityInfo & accessibility, const ReachabilityInfo::Parameters & params) const;
bool isInObstacle(BattleHex hex, const BattleHexArray & obstacles, const ReachabilityInfo::Parameters & params) const; bool isInObstacle(const BattleHex & hex, const BattleHexArray & obstacles, const ReachabilityInfo::Parameters & params) const;
BattleHexArray getStoppers(BattleSide whichSidePerspective) const; //get hexes with stopping obstacles (quicksands) BattleHexArray getStoppers(BattleSide whichSidePerspective) const; //get hexes with stopping obstacles (quicksands)
}; };

View File

@ -577,7 +577,7 @@ BattleHex CUnitState::getPosition() const
return position; return position;
} }
void CUnitState::setPosition(BattleHex hex) void CUnitState::setPosition(const BattleHex & hex)
{ {
position = hex; position = hex;
} }

View File

@ -212,7 +212,7 @@ public:
uint32_t getMaxHealth() const override; uint32_t getMaxHealth() const override;
BattleHex getPosition() const override; BattleHex getPosition() const override;
void setPosition(BattleHex hex) override; void setPosition(const BattleHex & hex) override;
int32_t getInitiative(int turn = 0) const override; int32_t getInitiative(int turn = 0) const override;
uint8_t getRangedFullDamageDistance() const; uint8_t getRangedFullDamageDistance() const;
uint8_t getShootingRangeDistance() const; uint8_t getShootingRangeDistance() const;

View File

@ -75,12 +75,12 @@ public:
virtual battle::Units battleGetUnitsIf(const battle::UnitFilter & predicate) const = 0; virtual battle::Units battleGetUnitsIf(const battle::UnitFilter & predicate) const = 0;
virtual const battle::Unit * battleGetUnitByID(uint32_t ID) const = 0; virtual const battle::Unit * battleGetUnitByID(uint32_t ID) const = 0;
virtual const battle::Unit * battleGetUnitByPos(BattleHex pos, bool onlyAlive = true) const = 0; virtual const battle::Unit * battleGetUnitByPos(const BattleHex & pos, bool onlyAlive = true) const = 0;
virtual const battle::Unit * battleActiveUnit() const = 0; virtual const battle::Unit * battleActiveUnit() const = 0;
//blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands) //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
virtual std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const = 0; virtual std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(const BattleHex & tile, bool onlyBlocking = true) const = 0;
virtual std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit, const BattleHexArray & passed) const = 0; virtual std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit, const BattleHexArray & passed) const = 0;
}; };

View File

@ -84,7 +84,7 @@ public:
virtual void addUnit(uint32_t id, const JsonNode & data) = 0; virtual void addUnit(uint32_t id, const JsonNode & data) = 0;
virtual void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) = 0; virtual void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) = 0;
virtual void moveUnit(uint32_t id, BattleHex destination) = 0; virtual void moveUnit(uint32_t id, const BattleHex & destination) = 0;
virtual void removeUnit(uint32_t id) = 0; virtual void removeUnit(uint32_t id) = 0;
virtual void updateUnit(uint32_t id, const JsonNode & data) = 0; virtual void updateUnit(uint32_t id, const JsonNode & data) = 0;

View File

@ -14,7 +14,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
ReachabilityInfo::Parameters::Parameters(const battle::Unit * Stack, BattleHex StartPosition): ReachabilityInfo::Parameters::Parameters(const battle::Unit * Stack, const BattleHex & StartPosition):
perspective(static_cast<BattleSide>(Stack->unitSide())), perspective(static_cast<BattleSide>(Stack->unitSide())),
startPosition(StartPosition), startPosition(StartPosition),
doubleWide(Stack->doubleWide()), doubleWide(Stack->doubleWide()),
@ -31,7 +31,7 @@ ReachabilityInfo::ReachabilityInfo()
predecessors.fill(BattleHex::INVALID); predecessors.fill(BattleHex::INVALID);
} }
bool ReachabilityInfo::isReachable(BattleHex hex) const bool ReachabilityInfo::isReachable(const BattleHex & hex) const
{ {
return distances[hex.toInt()] < INFINITE_DIST; return distances[hex.toInt()] < INFINITE_DIST;
} }
@ -42,7 +42,7 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
{ {
uint32_t ret = 1000000; uint32_t ret = 1000000;
for(auto targetHex : targetHexes) for(const auto & targetHex : targetHexes)
{ {
for(auto & n : targetHex.getNeighbouringTiles()) for(auto & n : targetHex.getNeighbouringTiles())
{ {
@ -79,7 +79,7 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
} }
} }
vstd::erase_if(attackableHexes, [defender](BattleHex h) -> bool vstd::erase_if(attackableHexes, [defender](const BattleHex & h) -> bool
{ {
return h.getY() != defender->getPosition().getY() || !h.isAvailable(); return h.getY() != defender->getPosition().getY() || !h.isAvailable();
}); });

View File

@ -42,7 +42,7 @@ struct DLL_LINKAGE ReachabilityInfo
{ {
destructibleEnemyTurns.fill(-1); destructibleEnemyTurns.fill(-1);
} }
Parameters(const battle::Unit * Stack, BattleHex StartPosition); Parameters(const battle::Unit * Stack, const BattleHex & StartPosition);
}; };
Parameters params; Parameters params;
@ -52,7 +52,7 @@ struct DLL_LINKAGE ReachabilityInfo
ReachabilityInfo(); ReachabilityInfo();
bool isReachable(BattleHex hex) const; bool isReachable(const BattleHex & hex) const;
uint32_t distToNearestNeighbour( uint32_t distToNearestNeighbour(
const BattleHexArray & targetHexes, const BattleHexArray & targetHexes,

View File

@ -51,14 +51,14 @@ const IBonusBearer* Unit::getBonusBearer() const
return this; return this;
} }
const BattleHexArray & Unit::getSurroundingHexes(BattleHex assumedPosition) const const BattleHexArray & Unit::getSurroundingHexes(const BattleHex & assumedPosition) const
{ {
BattleHex hex = (assumedPosition.toInt() != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position BattleHex hex = (assumedPosition.toInt() != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
return getSurroundingHexes(hex, doubleWide(), unitSide()); return getSurroundingHexes(hex, doubleWide(), unitSide());
} }
const BattleHexArray & Unit::getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side) const BattleHexArray & Unit::getSurroundingHexes(const BattleHex & position, bool twoHex, BattleSide side)
{ {
if(!twoHex) if(!twoHex)
return position.getNeighbouringTiles(); return position.getNeighbouringTiles();
@ -68,31 +68,25 @@ const BattleHexArray & Unit::getSurroundingHexes(BattleHex position, bool twoHex
BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
{ {
const BattleHexArray & defenderHexes = battle::Unit::getHexes( const BattleHexArray & defenderHexes = getHexes();
getPosition(),
doubleWide(),
unitSide());
BattleHexArray targetableHexes; BattleHexArray targetableHexes;
for(auto defenderHex : defenderHexes) for(const auto & defenderHex : defenderHexes)
{ {
auto hexes = battle::Unit::getHexes( auto hexes = battle::Unit::getHexes(defenderHex);
defenderHex,
attacker->doubleWide(),
unitSide());
if(hexes.size() == 2 && BattleHex::getDistance(hexes.front(), hexes.back()) != 1) if(hexes.size() == 2 && BattleHex::getDistance(hexes.front(), hexes.back()) != 1)
hexes.pop_back(); hexes.pop_back();
for(auto hex : hexes) for(const auto & hex : hexes)
targetableHexes.insert(hex.getNeighbouringTiles()); targetableHexes.insert(hex.getNeighbouringTiles());
} }
return targetableHexes; return targetableHexes;
} }
bool Unit::coversPos(BattleHex pos) const bool Unit::coversPos(const BattleHex & pos) const
{ {
return getPosition() == pos || (doubleWide() && (occupiedHex() == pos)); return getPosition() == pos || (doubleWide() && (occupiedHex() == pos));
} }
@ -102,7 +96,7 @@ const BattleHexArray & Unit::getHexes() const
return getHexes(getPosition(), doubleWide(), unitSide()); return getHexes(getPosition(), doubleWide(), unitSide());
} }
const BattleHexArray & Unit::getHexes(BattleHex assumedPos) const const BattleHexArray & Unit::getHexes(const BattleHex & assumedPos) const
{ {
return getHexes(assumedPos, doubleWide(), unitSide()); return getHexes(assumedPos, doubleWide(), unitSide());
} }
@ -125,7 +119,7 @@ BattleHexArray::ArrayOfBattleHexArrays Unit::precomputeUnitHexes(BattleSide side
return result; return result;
} }
const BattleHexArray & Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleSide side) const BattleHexArray & Unit::getHexes(const BattleHex & assumedPos, bool twoHex, BattleSide side)
{ {
static const std::array<BattleHexArray::ArrayOfBattleHexArrays, 4> precomputed = { static const std::array<BattleHexArray::ArrayOfBattleHexArrays, 4> precomputed = {
precomputeUnitHexes(BattleSide::ATTACKER, false), precomputeUnitHexes(BattleSide::ATTACKER, false),
@ -159,12 +153,12 @@ BattleHex Unit::occupiedHex() const
return occupiedHex(getPosition(), doubleWide(), unitSide()); return occupiedHex(getPosition(), doubleWide(), unitSide());
} }
BattleHex Unit::occupiedHex(BattleHex assumedPos) const BattleHex Unit::occupiedHex(const BattleHex & assumedPos) const
{ {
return occupiedHex(assumedPos, doubleWide(), unitSide()); return occupiedHex(assumedPos, doubleWide(), unitSide());
} }
BattleHex Unit::occupiedHex(BattleHex assumedPos, bool twoHex, BattleSide side) BattleHex Unit::occupiedHex(const BattleHex & assumedPos, bool twoHex, BattleSide side)
{ {
if(twoHex) if(twoHex)
{ {

View File

@ -116,7 +116,7 @@ public:
virtual int getTotalAttacks(bool ranged) const = 0; virtual int getTotalAttacks(bool ranged) const = 0;
virtual BattleHex getPosition() const = 0; virtual BattleHex getPosition() const = 0;
virtual void setPosition(BattleHex hex) = 0; virtual void setPosition(const BattleHex & hex) = 0;
virtual bool canMove(int turn = 0) const = 0; //if stack can move virtual bool canMove(int turn = 0) const = 0; //if stack can move
virtual bool defended(int turn = 0) const = 0; virtual bool defended(int turn = 0) const = 0;
@ -131,19 +131,19 @@ public:
virtual std::string getDescription() const; virtual std::string getDescription() const;
const BattleHexArray & getSurroundingHexes(BattleHex assumedPosition = BattleHex::INVALID) const; // get six or 8 surrounding hexes depending on creature size const BattleHexArray & getSurroundingHexes(const BattleHex & assumedPosition = BattleHex::INVALID) const; // get six or 8 surrounding hexes depending on creature size
BattleHexArray getAttackableHexes(const Unit * attacker) const; BattleHexArray getAttackableHexes(const Unit * attacker) const;
static const BattleHexArray & getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side); static const BattleHexArray & getSurroundingHexes(const BattleHex & position, bool twoHex, BattleSide side);
bool coversPos(BattleHex position) const; //checks also if unit is double-wide bool coversPos(const BattleHex & position) const; //checks also if unit is double-wide
const BattleHexArray & getHexes() const; //up to two occupied hexes, starting from front const BattleHexArray & getHexes() const; //up to two occupied hexes, starting from front
const BattleHexArray & getHexes(BattleHex assumedPos) const; //up to two occupied hexes, starting from front const BattleHexArray & getHexes(const BattleHex & assumedPos) const; //up to two occupied hexes, starting from front
static const BattleHexArray & getHexes(BattleHex assumedPos, bool twoHex, BattleSide side); static const BattleHexArray & getHexes(const BattleHex & assumedPos, bool twoHex, BattleSide side);
BattleHex occupiedHex() const; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1 BattleHex occupiedHex() const; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1
BattleHex occupiedHex(BattleHex assumedPos) const; //returns number of occupied hex (not the position) if stack is double wide and would stand on assumedPos; otherwise -1 BattleHex occupiedHex(const BattleHex & assumedPos) const; //returns number of occupied hex (not the position) if stack is double wide and would stand on assumedPos; otherwise -1
static BattleHex occupiedHex(BattleHex assumedPos, bool twoHex, BattleSide side); static BattleHex occupiedHex(const BattleHex & assumedPos, bool twoHex, BattleSide side);
///MetaStrings ///MetaStrings
void addText(MetaString & text, EMetaText type, int32_t serial, const boost::logic::tribool & plural = boost::logic::indeterminate) const; void addText(MetaString & text, EMetaText type, int32_t serial, const boost::logic::tribool & plural = boost::logic::indeterminate) const;

View File

@ -221,7 +221,7 @@ ILimiter::EDecision UnitOnHexLimiter::limit(const BonusLimitationContext &contex
auto accept = false; auto accept = false;
for (auto hex : stack->getHexes()) for (const auto & hex : stack->getHexes())
accept |= applicableHexes.contains(hex); accept |= applicableHexes.contains(hex);
return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
@ -237,7 +237,7 @@ JsonNode UnitOnHexLimiter::toJsonNode() const
JsonNode root; JsonNode root;
root["type"].String() = "UNIT_ON_HEXES"; root["type"].String() = "UNIT_ON_HEXES";
for(auto hex : applicableHexes) for(const auto & hex : applicableHexes)
root["parameters"].Vector().emplace_back(hex.toInt()); root["parameters"].Vector().emplace_back(hex.toInt());
return root; return root;

View File

@ -26,7 +26,7 @@ public:
class IBattleOverlayLogVisualizer class IBattleOverlayLogVisualizer
{ {
public: public:
virtual void drawText(BattleHex tile, int lineNumber, const std::string & text) = 0; virtual void drawText(const BattleHex & tile, int lineNumber, const std::string & text) = 0;
}; };
class DLL_LINKAGE IVisualLogBuilder class DLL_LINKAGE IVisualLogBuilder
@ -34,7 +34,7 @@ class DLL_LINKAGE IVisualLogBuilder
public: public:
virtual void addLine(int3 start, int3 end) = 0; virtual void addLine(int3 start, int3 end) = 0;
virtual void addText(int3 tile, const std::string & text, const std::optional<ColorRGBA> & color = {}) = 0; virtual void addText(int3 tile, const std::string & text, const std::optional<ColorRGBA> & color = {}) = 0;
virtual void addText(BattleHex tile, const std::string & text) = 0; virtual void addText(const BattleHex & tile, const std::string & text) = 0;
void addText(int3 tile, const std::string & text, PlayerColor background); void addText(int3 tile, const std::string & text, PlayerColor background);
}; };
@ -89,7 +89,7 @@ private:
mapLines.emplace_back(start, end); mapLines.emplace_back(start, end);
} }
void addText(BattleHex tile, const std::string & text) override void addText(const BattleHex & tile, const std::string & text) override
{ {
battleTexts.emplace_back(tile, text, std::optional<ColorRGBA>()); battleTexts.emplace_back(tile, text, std::optional<ColorRGBA>());
} }

View File

@ -508,7 +508,7 @@ bool BattleSpellMechanics::counteringSelector(const Bonus * bonus) const
return false; return false;
} }
BattleHexArray BattleSpellMechanics::spellRangeInHexes(BattleHex centralHex) const BattleHexArray BattleSpellMechanics::spellRangeInHexes(const BattleHex & centralHex) const
{ {
using namespace SRSLPraserHelpers; using namespace SRSLPraserHelpers;
@ -612,7 +612,7 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
hexesToCheck.insert(stack->getPosition().getNeighbouringTiles()); hexesToCheck.insert(stack->getPosition().getNeighbouringTiles());
} }
for(auto hex : hexesToCheck) for(const auto & hex : hexesToCheck)
{ {
if(hex.isAvailable()) if(hex.isAvailable())
{ {
@ -659,7 +659,7 @@ bool BattleSpellMechanics::isReceptive(const battle::Unit * target) const
return targetCondition->isReceptive(this, target); return targetCondition->isReceptive(this, target);
} }
BattleHexArray BattleSpellMechanics::rangeInHexes(BattleHex centralHex) const BattleHexArray BattleSpellMechanics::rangeInHexes(const BattleHex & centralHex) const
{ {
if(isMassive() || !centralHex.isValid()) if(isMassive() || !centralHex.isValid())
return BattleHexArray(); return BattleHexArray();

View File

@ -61,7 +61,7 @@ public:
bool isReceptive(const battle::Unit * target) const override; bool isReceptive(const battle::Unit * target) const override;
/// Returns list of hexes that are affected by spell assuming cast at centralHex /// Returns list of hexes that are affected by spell assuming cast at centralHex
BattleHexArray rangeInHexes(BattleHex centralHex) const override; BattleHexArray rangeInHexes(const BattleHex & centralHex) const override;
const Spell * getSpell() const override; const Spell * getSpell() const override;
@ -80,7 +80,7 @@ private:
void doRemoveEffects(ServerCallback * server, const battle::Units & targets, const CSelector & selector); void doRemoveEffects(ServerCallback * server, const battle::Units & targets, const CSelector & selector);
BattleHexArray spellRangeInHexes(BattleHex centralHex) const; BattleHexArray spellRangeInHexes(const BattleHex & centralHex) const;
Target transformSpellTarget(const Target & aimPoint) const; Target transformSpellTarget(const Target & aimPoint) const;
}; };

View File

@ -758,7 +758,7 @@ std::vector<int> CSpellHandler::spellRangeInHexes(std::string input) const
result.reserve(ret.size()); result.reserve(ret.size());
std::transform(ret.begin(), ret.end(), std::back_inserter(result), std::transform(ret.begin(), ret.end(), std::back_inserter(result),
[](BattleHex hex) { return hex.toInt(); } [](const BattleHex & hex) { return hex.toInt(); }
); );
return result; return result;

View File

@ -185,7 +185,7 @@ public:
virtual bool adaptProblem(ESpellCastProblem source, Problem & target) const = 0; virtual bool adaptProblem(ESpellCastProblem source, Problem & target) const = 0;
virtual bool adaptGenericProblem(Problem & target) const = 0; virtual bool adaptGenericProblem(Problem & target) const = 0;
virtual BattleHexArray rangeInHexes(BattleHex centralHex) const = 0; virtual BattleHexArray rangeInHexes(const BattleHex & centralHex) const = 0;
virtual std::vector<const CStack *> getAffectedStacks(const Target & target) const = 0; virtual std::vector<const CStack *> getAffectedStacks(const Target & target) const = 0;
virtual bool canBeCast(Problem & problem) const = 0; virtual bool canBeCast(Problem & problem) const = 0;

View File

@ -107,7 +107,7 @@ bool DemonSummon::isValidTarget(const Mechanics * m, const battle::Unit * unit)
return false; return false;
//check if alive unit blocks rising //check if alive unit blocks rising
for(const BattleHex & hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide())) for(const BattleHex & hex : unit->getHexes())
{ {
auto blocking = m->battle()->battleGetUnitsIf([hex, unit](const battle::Unit * other) auto blocking = m->battle()->battleGetUnitsIf([hex, unit](const battle::Unit * other)
{ {

View File

@ -70,7 +70,7 @@ bool Heal::isValidTarget(const Mechanics * m, const battle::Unit * unit) const
if(unit->isDead()) if(unit->isDead())
{ {
//check if alive unit blocks resurrection //check if alive unit blocks resurrection
for(const BattleHex & hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide())) for(const BattleHex & hex : unit->getHexes())
{ {
auto blocking = m->battle()->battleGetUnitsIf([hex, unit](const battle::Unit * other) auto blocking = m->battle()->battleGetUnitsIf([hex, unit](const battle::Unit * other)
{ {

View File

@ -202,7 +202,7 @@ EffectTarget UnitEffect::transformTargetByChain(const Mechanics * m, const Targe
for(const auto *unit : possibleTargets) for(const auto *unit : possibleTargets)
{ {
for(auto hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide())) for(const auto & hex : unit->getHexes())
possibleHexes.insert(hex); possibleHexes.insert(hex);
} }
@ -222,7 +222,7 @@ EffectTarget UnitEffect::transformTargetByChain(const Mechanics * m, const Targe
else else
effectTarget.emplace_back(); effectTarget.emplace_back();
for(auto hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide())) for(const auto & hex : unit->getHexes())
if (possibleHexes.contains(hex)) if (possibleHexes.contains(hex))
possibleHexes.erase(hex); possibleHexes.erase(hex);

View File

@ -679,7 +679,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
return obst->obstacleType == CObstacleInstance::MOAT; return obst->obstacleType == CObstacleInstance::MOAT;
}); });
auto isGateDrawbridgeHex = [&](BattleHex hex) -> bool auto isGateDrawbridgeHex = [&](const BattleHex & hex) -> bool
{ {
if (hasWideMoat && hex == BattleHex::GATE_BRIDGE) if (hasWideMoat && hex == BattleHex::GATE_BRIDGE)
return true; return true;
@ -691,7 +691,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
return false; return false;
}; };
auto occupyGateDrawbridgeHex = [&](BattleHex hex) -> bool auto occupyGateDrawbridgeHex = [&](const BattleHex & hex) -> bool
{ {
if (isGateDrawbridgeHex(hex)) if (isGateDrawbridgeHex(hex))
return true; return true;
@ -744,7 +744,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
{ {
for (int i = (int)path.first.size()-1; i >= 0; i--) for (int i = (int)path.first.size()-1; i >= 0; i--)
{ {
auto needOpenGates = [&](BattleHex hex) -> bool auto needOpenGates = [&](const BattleHex & hex) -> bool
{ {
if (hasWideMoat && hex == BattleHex::GATE_BRIDGE) if (hasWideMoat && hex == BattleHex::GATE_BRIDGE)
return true; return true;
@ -911,7 +911,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
return ret; return ret;
} }
void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const CStack * attacker, const CStack * defender, int distance, BattleHex targetHex, bool first, bool ranged, bool counter) void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const CStack * attacker, const CStack * defender, int distance, const BattleHex & targetHex, bool first, bool ranged, bool counter)
{ {
if(defender && first && !counter) if(defender && first && !counter)
handleAttackBeforeCasting(battle, ranged, attacker, defender); handleAttackBeforeCasting(battle, ranged, attacker, defender);

View File

@ -42,7 +42,7 @@ class BattleActionProcessor : boost::noncopyable
CGameHandler * gameHandler; CGameHandler * gameHandler;
int moveStack(const CBattleInfoCallback & battle, int stack, BattleHex dest); //returned value - travelled distance int moveStack(const CBattleInfoCallback & battle, int stack, BattleHex dest); //returned value - travelled distance
void makeAttack(const CBattleInfoCallback & battle, const CStack * attacker, const CStack * defender, int distance, BattleHex targetHex, bool first, bool ranged, bool counter); void makeAttack(const CBattleInfoCallback & battle, const CStack * attacker, const CStack * defender, int distance, const BattleHex & targetHex, bool first, bool ranged, bool counter);
void handleAttackBeforeCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender); void handleAttackBeforeCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender);

View File

@ -163,7 +163,7 @@ void BattleFlowProcessor::trySummonGuardians(const CBattleInfoCallback & battle,
else else
summonGuardiansHelper(battle, targetHexes, stack->getPosition(), stack->unitSide(), targetIsBig); summonGuardiansHelper(battle, targetHexes, stack->getPosition(), stack->unitSide(), targetIsBig);
for(auto hex : targetHexes) for(const auto & hex : targetHexes)
{ {
if(accessibility.accessible(hex, guardianIsBig, stack->unitSide())) //without this multiple creatures can occupy one hex if(accessibility.accessible(hex, guardianIsBig, stack->unitSide())) //without this multiple creatures can occupy one hex
{ {

View File

@ -45,7 +45,7 @@ public:
MOCK_METHOD1(nextTurn, void(uint32_t)); MOCK_METHOD1(nextTurn, void(uint32_t));
MOCK_METHOD2(addUnit, void(uint32_t, const JsonNode &)); MOCK_METHOD2(addUnit, void(uint32_t, const JsonNode &));
MOCK_METHOD3(setUnitState, void(uint32_t, const JsonNode &, int64_t)); MOCK_METHOD3(setUnitState, void(uint32_t, const JsonNode &, int64_t));
MOCK_METHOD2(moveUnit, void(uint32_t, BattleHex)); MOCK_METHOD2(moveUnit, void(uint32_t, const BattleHex &));
MOCK_METHOD1(removeUnit, void(uint32_t)); MOCK_METHOD1(removeUnit, void(uint32_t));
MOCK_METHOD2(updateUnit, void(uint32_t, const JsonNode &)); MOCK_METHOD2(updateUnit, void(uint32_t, const JsonNode &));
MOCK_METHOD2(addUnitBonus, void(uint32_t, const std::vector<Bonus> &)); MOCK_METHOD2(addUnitBonus, void(uint32_t, const std::vector<Bonus> &));

View File

@ -76,7 +76,7 @@ public:
MOCK_CONST_METHOD1(getTotalAttacks, int(bool)); MOCK_CONST_METHOD1(getTotalAttacks, int(bool));
MOCK_CONST_METHOD0(getPosition, BattleHex()); MOCK_CONST_METHOD0(getPosition, BattleHex());
MOCK_METHOD1(setPosition, void(BattleHex)); MOCK_METHOD1(setPosition, void(const BattleHex&));
MOCK_CONST_METHOD1(getInitiative, int32_t(int)); MOCK_CONST_METHOD1(getInitiative, int32_t(int));
MOCK_CONST_METHOD1(canMove, bool(int)); MOCK_CONST_METHOD1(canMove, bool(int));

View File

@ -23,7 +23,7 @@ public:
MOCK_CONST_METHOD2(adaptProblem, bool(ESpellCastProblem, Problem &)); MOCK_CONST_METHOD2(adaptProblem, bool(ESpellCastProblem, Problem &));
MOCK_CONST_METHOD1(adaptGenericProblem, bool(Problem &)); MOCK_CONST_METHOD1(adaptGenericProblem, bool(Problem &));
MOCK_CONST_METHOD1(rangeInHexes, BattleHexArray(BattleHex)); MOCK_CONST_METHOD1(rangeInHexes, BattleHexArray(const BattleHex&));
MOCK_CONST_METHOD1(getAffectedStacks, std::vector<const CStack *>(const Target &)); MOCK_CONST_METHOD1(getAffectedStacks, std::vector<const CStack *>(const Target &));
MOCK_CONST_METHOD1(canBeCast, bool(Problem &)); MOCK_CONST_METHOD1(canBeCast, bool(Problem &));