diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp index b688dc06cb..dcb538009a 100644 --- a/src/action/action_attack.cpp +++ b/src/action/action_attack.cpp @@ -229,18 +229,14 @@ bool COrder_Attack::IsValid() const /* override */ PixelPos COrder_Attack::Show(const CViewport &vp, const PixelPos &lastScreenPos) const /* override */ { - PixelPos targetPos; - PixelPos orderedPos; - bool isAttackMove = IsAutoTargeting(); + const bool isAttackMove = IsAutoTargeting(); + const PixelPos targetPos = this->HasGoal() + ? vp.MapToScreenPixelPos(this->GetGoal()->GetMapPixelPosCenter()) + : IsMovingToAttackPos() ? vp.TilePosToScreen_Center(this->attackMovePos) + : vp.TilePosToScreen_Center(this->goalPos); + const PixelPos orderedPos = isAttackMove ? vp.TilePosToScreen_Center(this->attackMovePos) : targetPos; + const Uint32 color = isAttackMove ? ColorOrange : ColorRed; - targetPos = this->HasGoal() ? vp.MapToScreenPixelPos(this->GetGoal()->GetMapPixelPosCenter()) - : IsMovingToAttackPos() ? vp.TilePosToScreen_Center(this->attackMovePos) - : vp.TilePosToScreen_Center(this->goalPos); - - orderedPos = isAttackMove ? vp.TilePosToScreen_Center(this->attackMovePos) - : targetPos; - - Uint32 color = isAttackMove ? ColorOrange : ColorRed; Video.FillCircleClip(color, lastScreenPos, 2); Video.DrawLineClip(ColorRed, lastScreenPos, orderedPos); Video.FillCircleClip(color, orderedPos, 3); @@ -317,10 +313,6 @@ bool COrder_Attack::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/) /* return false; } -bool COrder_Attack::IsWeakTargetSelected() const -{ - return (this->State & AUTO_TARGETING) != 0; -} bool COrder_Attack::IsAutoTargeting() const { return (this->State & AUTO_TARGETING) != 0; @@ -335,14 +327,14 @@ bool COrder_Attack::IsAttackGroundOrWall() const return this->Action == UnitAction::AttackGround || Map.WallOnMap(this->goalPos); } -CUnit *COrder_Attack::BestTarget(const CUnit &unit, CUnit *const target1, CUnit *const target2) const +CUnit &COrder_Attack::BestTarget(const CUnit &unit, CUnit &target1, CUnit &target2) const { - Assert(target1 != nullptr); - Assert(target2 != nullptr); - return (GameSettings.SimplifiedAutoTargeting - ? ((TargetPriorityCalculate(&unit, target1) > TargetPriorityCalculate(&unit, target2)) ? target1 : target2) - : ((ThreatCalculate(unit, *target1) < ThreatCalculate(unit, *target2)) ? target1 : target2)); + ? ((TargetPriorityCalculate(unit, target1) > TargetPriorityCalculate(unit, target2)) + ? target1 + : target2) + : ((ThreatCalculate(unit, target1) < ThreatCalculate(unit, target2)) ? target1 + : target2)); } /** @@ -352,23 +344,22 @@ CUnit *COrder_Attack::BestTarget(const CUnit &unit, CUnit *const target1, CUnit ** @param target Target that offered as the new current goal ** */ -void COrder_Attack::OfferNewTarget(const CUnit &unit, CUnit *const target) +void COrder_Attack::OfferNewTarget(const CUnit &unit, CUnit &target) { - Assert(target != nullptr); Assert(this->IsAutoTargeting() || unit.Player->AiEnabled); /// if attacker cant't move (stand_ground, building, in a bunker or transport) const bool immobile = this->Action == UnitAction::StandGround || unit.Removed || !unit.CanMove(); - if (immobile && !InAttackRange(unit, *target)) { + if (immobile && !InAttackRange(unit, target)) { return; } - CUnit *best = (this->offeredTarget != nullptr && this->offeredTarget->IsVisibleAsGoal(*unit.Player)) - ? BestTarget(unit, this->offeredTarget, target) + CUnit &best = (this->offeredTarget != nullptr && this->offeredTarget->IsVisibleAsGoal(*unit.Player)) + ? BestTarget(unit, *this->offeredTarget, target) : target; if (this->offeredTarget != nullptr) { this->offeredTarget.Reset(); } - this->offeredTarget = best; + this->offeredTarget = &best; } /** @@ -387,7 +378,7 @@ bool COrder_Attack::CheckIfGoalValid(CUnit &unit) CUnit *goal = this->GetGoal(); // Wall was destroyed - if (!goal && this->State & ATTACK_TARGET && this->Action != UnitAction::AttackGround && !Map.WallOnMap(this->goalPos)) { + if (!goal && (this->State & ATTACK_TARGET) && this->Action != UnitAction::AttackGround && !Map.WallOnMap(this->goalPos)) { return false; } // Position or valid target, it is ok. @@ -417,7 +408,7 @@ void COrder_Attack::TurnToTarget(CUnit &unit, const CUnit *target) return; } const Vec2i dir = target ? (target->tilePos + target->Type->GetHalfTileSize() - unit.tilePos) - : (this->goalPos - unit.tilePos); + : (this->goalPos - unit.tilePos); const unsigned char oldDir = unit.Direction; UnitHeadingFromDeltaXY(unit, dir); @@ -447,9 +438,9 @@ void COrder_Attack::SetAutoTarget(CUnit &unit, CUnit *target) this->ClearGoal(); } this->SetGoal(target); - this->goalPos = target->tilePos; - this->Range = unit.Stats->Variables[ATTACKRANGE_INDEX].Max; - this->MinRange = unit.Type->MinAttackRange; + this->goalPos = target->tilePos; + this->Range = unit.Stats->Variables[ATTACKRANGE_INDEX].Max; + this->MinRange = unit.Type->MinAttackRange; if (unit.Type->BoolFlag[SKIRMISHER_INDEX].value) { this->SkirmishRange = this->Range; } @@ -476,8 +467,9 @@ bool COrder_Attack::AutoSelectTarget(CUnit &unit) // if unit can't attack, or if unit is not bunkered and removed - exit, no targets if (unit.Type->CanAttack == false - || (unit.Removed - && (unit.Container == nullptr || unit.Container->Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value == false))) { + || (unit.Removed + && (unit.Container == nullptr + || unit.Container->Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value == false))) { this->offeredTarget.Reset(); return false; } @@ -498,9 +490,9 @@ bool COrder_Attack::AutoSelectTarget(CUnit &unit) /// If we have target offered from outside - try it if (this->offeredTarget != nullptr) { if (this->offeredTarget->IsVisibleAsGoal(*unit.Player) - && (!immobile || InAttackRange(unit, *this->offeredTarget))) { - - newTarget = newTarget ? BestTarget(unit, this->offeredTarget, newTarget) : &(*this->offeredTarget); + && (!immobile || InAttackRange(unit, *this->offeredTarget))) { + newTarget = newTarget ? &BestTarget(unit, *this->offeredTarget, *newTarget) + : static_cast(this->offeredTarget); } this->offeredTarget.Reset(); } @@ -518,8 +510,8 @@ bool COrder_Attack::AutoSelectTarget(CUnit &unit) return true; } if (GameSettings.SimplifiedAutoTargeting) { - const int goal_priority = TargetPriorityCalculate(&unit, goal); - const int newTarget_priority = TargetPriorityCalculate(&unit, newTarget); + const int goal_priority = TargetPriorityCalculate(unit, *goal); + const int newTarget_priority = TargetPriorityCalculate(unit, *newTarget); if ((newTarget_priority & AT_PRIORITY_MASK_HI) > (goal_priority & AT_PRIORITY_MASK_HI)) { if (goal_priority & AT_ATTACKED_BY_FACTOR) { /// if unit under attack by current goal @@ -556,19 +548,19 @@ bool COrder_Attack::AutoSelectTarget(CUnit &unit) ** Restore action/order when current action is finished ** ** @param unit -** @param canBeFinished False if ony restore order/action needed +** @param canBeFinished False if only restore order/action needed ** -** @return false if order/action restored, true else (if order finished). +** @return false if order/action restored, true else (if order finished). */ bool COrder_Attack::EndActionAttack(CUnit &unit, const bool canBeFinished = true) { /// Restore saved order only when UnderAttack counter is expired if ((unit.UnderAttack && IsAutoTargeting()) || !unit.RestoreOrder()) { if (IsAutoTargeting() && this->goalPos != this->attackMovePos) { - this->goalPos = this->attackMovePos; - this->Range = 0; - this->MinRange = 0; - this->State = AUTO_TARGETING; + this->goalPos = this->attackMovePos; + this->Range = 0; + this->MinRange = 0; + this->State = AUTO_TARGETING; return false; } this->Finished = canBeFinished; @@ -584,7 +576,7 @@ bool COrder_Attack::EndActionAttack(CUnit &unit, const bool canBeFinished = true */ void COrder_Attack::MoveToBetterPos(CUnit &unit) { - CUnit *goal = this->GetGoal(); + CUnit *goal = this->GetGoal(); /// Save current goalPos if target is ground or wall if (!goal && IsAttackGroundOrWall()) { @@ -594,13 +586,15 @@ void COrder_Attack::MoveToBetterPos(CUnit &unit) this->attackMovePos = this->goalPos; } } - this->goalPos = goal ? GetRndPosInDirection(unit.tilePos, *goal, true, unit.Type->MinAttackRange, 3) - : GetRndPosInDirection(unit.tilePos, this->goalPos, true, unit.Type->MinAttackRange, 3); - this->Range = 0; - this->MinRange = 0; - unit.Frame = 0; - this->State &= AUTO_TARGETING; - this->State |= MOVE_TO_ATTACKPOS; + this->goalPos = + goal + ? GetRndPosInDirection(unit.tilePos, *goal, true, unit.Type->MinAttackRange, 3) + : GetRndPosInDirection(unit.tilePos, this->goalPos, true, unit.Type->MinAttackRange, 3); + this->Range = 0; + this->MinRange = 0; + unit.Frame = 0; + this->State &= AUTO_TARGETING; + this->State |= MOVE_TO_ATTACKPOS; } /** @@ -645,9 +639,9 @@ bool COrder_Attack::IsTargetTooClose(const CUnit &unit) const if (!this->HasGoal() && !IsAttackGroundOrWall()) { return false; } - const int distance = this->HasGoal() ? unit.MapDistanceTo(*this->GetGoal()) - : IsMovingToAttackPos() ? unit.MapDistanceTo(this->attackMovePos) - : unit.MapDistanceTo(this->goalPos); + const int distance = this->HasGoal() ? unit.MapDistanceTo(*this->GetGoal()) + : IsMovingToAttackPos() ? unit.MapDistanceTo(this->attackMovePos) + : unit.MapDistanceTo(this->goalPos); const bool tooClose = distance < unit.Type->MinAttackRange; return tooClose; } @@ -759,8 +753,8 @@ void COrder_Attack::MoveToTarget(CUnit &unit) } // Attacking wall or ground. if (((goal && goal->Type && goal->Type->BoolFlag[WALL_INDEX].value) - || (!goal && IsAttackGroundOrWall())) - && InAttackRange(unit, this->goalPos)) { + || (!goal && IsAttackGroundOrWall())) + && InAttackRange(unit, this->goalPos)) { // Reached wall or ground, now attacking it TurnToTarget(unit, nullptr); @@ -781,7 +775,6 @@ void COrder_Attack::MoveToTarget(CUnit &unit) this->ClearGoal(); } EndActionAttack(unit); - return; } /** @@ -868,7 +861,7 @@ void COrder_Attack::Execute(CUnit &unit) /* override */ this->State |= MOVE_TO_TARGET; // FIXME: should use a reachable place to reduce pathfinder time. - // FALL THROUGH + [[fallthrough]]; case MOVE_TO_TARGET: case MOVE_TO_TARGET + AUTO_TARGETING: case MOVE_TO_ATTACKPOS: diff --git a/src/action/action_resource.cpp b/src/action/action_resource.cpp index cd5f30343e..c7efb8d2f4 100644 --- a/src/action/action_resource.cpp +++ b/src/action/action_resource.cpp @@ -989,9 +989,9 @@ int COrder_Resource::StopGathering(CUnit &unit) int COrder_Resource::MoveToDepot(CUnit &unit) { const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource]; + Assert(this->GetGoal()); CUnit &goal = *this->GetGoal(); CPlayer &player = *unit.Player; - Assert(&goal); switch (DoActionMove(unit)) { // reached end-point? case PF_UNREACHABLE: diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index be23e84a90..ae63bcc745 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -161,7 +161,7 @@ int AiSleepCycles; /// Ai sleeps # cycles -std::vector AiTypes; /// List of all AI types. +std::vector> AiTypes; /// List of all AI types. AiHelper AiHelpers; /// AI helper variables PlayerAi *AiPlayer; /// Current AI player @@ -439,22 +439,17 @@ void AiInit(CPlayer &player) LogPrint("AI: Look at the DefineAi() documentation.\n"); Exit(0); } - size_t i; - CAiType *ait = nullptr; - for (i = 0; i < AiTypes.size(); ++i) { - ait = AiTypes[i]; - if (!ait->Race.empty() && ait->Race != PlayerRaces.Name[player.Race]) { - continue; - } - if (!player.AiName.empty() && ait->Name != player.AiName) { - continue; - } - break; - } - if (i == AiTypes.size()) { + auto it = ranges::find_if(AiTypes, [&](const auto& ait){ + return (ait->Race.empty() || ait->Race == PlayerRaces.Name[player.Race]) + && (player.AiName.empty() || ait->Name == player.AiName); + }); + CAiType *ait = nullptr; + if (it == AiTypes.end()) { LogPrint("AI: Found no matching ai scripts at all, defaulting to the first AI!\n"); - ait = AiTypes[0]; + ait = AiTypes[0].get(); + } else { + ait = it->get(); } if (player.AiName.empty()) { LogPrint("AI: not found!!!!!!!!!!\n"); @@ -505,9 +500,6 @@ void FreeAi() CleanAi(); // Free AiTypes. - for (CAiType *aitype : AiTypes) { - delete aitype; - } AiTypes.clear(); // Free AiHelpers. diff --git a/src/ai/ai_local.h b/src/ai/ai_local.h index 3ba9b56f04..9d7728b018 100644 --- a/src/ai/ai_local.h +++ b/src/ai/ai_local.h @@ -37,6 +37,7 @@ ----------------------------------------------------------------------------*/ #include +#include #include #include @@ -378,7 +379,7 @@ class AiHelper -- Variables ----------------------------------------------------------------------------*/ -extern std::vector AiTypes; /// List of all AI types +extern std::vector> AiTypes; /// List of all AI types extern AiHelper AiHelpers; /// AI helper variables extern int UnitTypeEquivs[UnitTypeMax + 1]; /// equivalence between unittypes diff --git a/src/ai/ai_plan.cpp b/src/ai/ai_plan.cpp index babeec8e6a..80c778ce2d 100644 --- a/src/ai/ai_plan.cpp +++ b/src/ai/ai_plan.cpp @@ -430,31 +430,31 @@ bool AiForce::PlanAttack() return false; } -static bool ChooseRandomUnexploredPositionNear(const Vec2i ¢er, Vec2i *pos) +static std::optional ChooseRandomUnexploredPositionNear(const Vec2i ¢er) { - Assert(pos != nullptr); - int ray = 3; const int maxTryCount = 8; for (int i = 0; i != maxTryCount; ++i) { - pos->x = center.x + SyncRand() % (2 * ray + 1) - ray; - pos->y = center.y + SyncRand() % (2 * ray + 1) - ray; + Vec2i pos; + pos.x = center.x + SyncRand() % (2 * ray + 1) - ray; + pos.y = center.y + SyncRand() % (2 * ray + 1) - ray; - if (Map.Info.IsPointOnMap(*pos) - && Map.Field(*pos)->playerInfo.IsExplored(*AiPlayer->Player) == false) { - return true; + if (Map.Info.IsPointOnMap(pos) + && Map.Field(pos)->playerInfo.IsExplored(*AiPlayer->Player) == false) { + return pos; } ray = 3 * ray / 2; } - return false; + return std::nullopt; } -static CUnit *GetBestExplorer(const AiExplorationRequest &request, Vec2i *pos) +static std::pair GetBestExplorer(const AiExplorationRequest &request) { // Choose a target, "near" const Vec2i ¢er = request.pos; - if (ChooseRandomUnexploredPositionNear(center, pos) == false) { - return nullptr; + auto pos = ChooseRandomUnexploredPositionNear(center); + if (!pos) { + return {nullptr, {-1, -1}}; } // We have an unexplored tile in sight (pos) @@ -495,7 +495,7 @@ static CUnit *GetBestExplorer(const AiExplorationRequest &request, Vec2i *pos) bestunit = unit; } } - return bestunit; + return {bestunit, *pos}; } @@ -517,8 +517,7 @@ void AiSendExplorers() const int requestid = SyncRand() % requestcount; const AiExplorationRequest &request = AiPlayer->FirstExplorationRequest[requestid]; - Vec2i pos; - CUnit *bestunit = GetBestExplorer(request, &pos); + const auto& [bestunit, pos] = GetBestExplorer(request); if (bestunit != nullptr) { CommandMove(*bestunit, pos, FlushCommands); AiPlayer->LastExplorationGameCycle = GameCycle; diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp index af620b804e..acebe65ebf 100644 --- a/src/ai/ai_resource.cpp +++ b/src/ai/ai_resource.cpp @@ -997,8 +997,8 @@ static bool AiAssignHarvester(CUnit &unit, int resource) return false; } + Assert(unit.Type->ResInfo[resource]); const ResourceInfo &resinfo = *unit.Type->ResInfo[resource]; - Assert(&resinfo); if (resinfo.TerrainHarvester) { return AiAssignHarvesterFromTerrain(unit, resource); diff --git a/src/ai/script_ai.cpp b/src/ai/script_ai.cpp index a9484dc89e..3bb94b025d 100644 --- a/src/ai/script_ai.cpp +++ b/src/ai/script_ai.cpp @@ -337,9 +337,9 @@ static int CclDefineAiHelper(lua_State *l) static CAiType *GetAiTypesByName(const std::string_view name) { - for (CAiType *ait : AiTypes) { + for (auto &ait : AiTypes) { if (ait->Name == name) { - return ait; + return ait.get(); } } return nullptr; @@ -394,18 +394,17 @@ static int CclDefineAi(lua_State *l) LuaError(l, "incorrect argument"); } - CAiType *aitype = new CAiType; - // AI Name const std::string_view aiName = LuaToString(l, 1); - aitype->Name = aiName; #ifdef DEBUG if (GetAiTypesByName(aiName)) { DebugPrint("Warning two or more AI's with the same name '%s'\n", aiName.data()); } #endif - AiTypes.insert(AiTypes.begin(), aitype); + AiTypes.insert(AiTypes.begin(), std::make_unique()); + CAiType *aitype = AiTypes.front().get(); + aitype->Name = aiName; // AI Race const std::string_view value = LuaToString(l, 2); diff --git a/src/include/action/action_attack.h b/src/include/action/action_attack.h index 8f81651869..8aa72849ec 100644 --- a/src/include/action/action_attack.h +++ b/src/include/action/action_attack.h @@ -56,17 +56,16 @@ class COrder_Attack : public COrder PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const override; void UpdatePathFinderData(PathFinderInput &input) override; bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/) override; - const Vec2i GetGoalPos() const override { return goalPos; } - bool IsWeakTargetSelected() const; + bool IsAutoTargeting() const; + void OfferNewTarget(const CUnit &unit, CUnit &target); + +private: bool IsMovingToAttackPos() const; bool IsAttackGroundOrWall() const; bool IsTargetTooClose(const CUnit &unit) const; - CUnit *BestTarget(const CUnit &unit, CUnit *const target1, CUnit *const target2) const; - void OfferNewTarget(const CUnit &unit, CUnit *const target); - -private: + CUnit &BestTarget(const CUnit &unit, CUnit &target1, CUnit &target2) const; bool CheckIfGoalValid(CUnit &unit); void TurnToTarget(CUnit &unit, const CUnit *target); void SetAutoTarget(CUnit &unit, CUnit *target); diff --git a/src/include/fow.h b/src/include/fow.h index 920eab96cb..f3af8caa3c 100644 --- a/src/include/fow.h +++ b/src/include/fow.h @@ -30,8 +30,6 @@ #ifndef __FOW_H__ #define __FOW_H__ -#include -#include #include "filesystem.h" #include "fow_utils.h" #include "map.h" @@ -39,6 +37,10 @@ #include "settings.h" #include "video.h" +#include +#include +#include + //@{ @@ -203,7 +205,7 @@ class CFogOfWar const uint32_t (*CurrUpscaleTableExplored)[4] = UpscaleTableVisible; }; -extern CFogOfWar *FogOfWar; +extern std::unique_ptr FogOfWar; /** diff --git a/src/include/unit.h b/src/include/unit.h index dcbe811a6b..835ab9d1d8 100644 --- a/src/include/unit.h +++ b/src/include/unit.h @@ -606,7 +606,7 @@ extern void LetUnitDie(CUnit &unit, bool suicide = false); extern void DestroyAllInside(CUnit &source); /// Calculate some value to measure the unit's priority for AI extern int ThreatCalculate(const CUnit &unit, const CUnit &dest); -extern int TargetPriorityCalculate(const CUnit *const attacker, const CUnit *const dest); +extern int TargetPriorityCalculate(const CUnit &attacker, const CUnit &dest); /// Is target within reaction range of this unit? extern bool InReactRange(const CUnit &unit, const CUnit &target); diff --git a/src/include/unit_manager.h b/src/include/unit_manager.h index b874f6290e..6893363ace 100644 --- a/src/include/unit_manager.h +++ b/src/include/unit_manager.h @@ -54,7 +54,7 @@ class CUnitManager void Init(); CUnit *AllocUnit(); - void ReleaseUnit(CUnit *unit); + void ReleaseUnit(CUnit &unit); void Save(CFile &file) const; void Load(lua_State *Lua); diff --git a/src/map/fow.cpp b/src/map/fow.cpp index 82c1dfef50..6cf03171ec 100644 --- a/src/map/fow.cpp +++ b/src/map/fow.cpp @@ -55,7 +55,7 @@ -- Variables ----------------------------------------------------------------------------*/ /// FIXME: Maybe move it into CMap -CFogOfWar *FogOfWar; /// Fog of war itself +std::unique_ptr FogOfWar; /// Fog of war itself CGraphic *CFogOfWar::TiledFogSrc {nullptr}; // Graphic tiles set for tiled fog /*---------------------------------------------------------------------------- diff --git a/src/network/commands.cpp b/src/network/commands.cpp index 33c3f60bd6..a62eeda197 100644 --- a/src/network/commands.cpp +++ b/src/network/commands.cpp @@ -617,7 +617,7 @@ void ExecCommand(unsigned char msgnr, UnitRef unum, CUnit *dest = nullptr; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager->GetSlotUnit(dstnr); - Assert(dest && dest->Type); + Assert(dest->Type); } CommandLog("repair", &unit, status, pos.x, pos.y, dest, nullptr, -1); CommandRepair(unit, pos, dest, status); @@ -631,7 +631,7 @@ void ExecCommand(unsigned char msgnr, UnitRef unum, CUnit *dest = nullptr; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager->GetSlotUnit(dstnr); - Assert(dest && dest->Type); + Assert(dest->Type); } CommandLog("attack", &unit, status, pos.x, pos.y, dest, nullptr, -1); CommandAttack(unit, pos, dest, status); @@ -658,7 +658,7 @@ void ExecCommand(unsigned char msgnr, UnitRef unum, CUnit *dest = nullptr; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager->GetSlotUnit(dstnr); - Assert(dest && dest->Type); + Assert(dest->Type); } CommandLog("unload", &unit, status, pos.x, pos.y, dest, nullptr, -1); CommandUnload(unit, pos, dest, status); @@ -734,7 +734,7 @@ void ExecCommand(unsigned char msgnr, UnitRef unum, CUnit *dest = nullptr; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager->GetSlotUnit(dstnr); - Assert(dest && dest->Type); + Assert(dest->Type); } CommandLog("spell-cast", &unit, status, pos.x, pos.y, dest, nullptr, id); CommandSpellCast(unit, pos, dest, *SpellTypeTable[id], status); diff --git a/src/stratagus/construct.cpp b/src/stratagus/construct.cpp index 37e87e150b..9ceac2b266 100644 --- a/src/stratagus/construct.cpp +++ b/src/stratagus/construct.cpp @@ -51,7 +51,7 @@ /** ** Constructions. */ -static std::vector Constructions; +static std::vector> Constructions; /*---------------------------------------------------------------------------- -- Functions @@ -133,7 +133,7 @@ void InitConstructions() */ void LoadConstructions() { - for (CConstruction *c :Constructions) { + for (auto &c : Constructions) { c->Load(); } } @@ -144,9 +144,6 @@ void LoadConstructions() void CleanConstructions() { // Free the construction table. - for (CConstruction *c : Constructions) { - delete c; - } Constructions.clear(); } @@ -187,10 +184,10 @@ static int CclDefineConstruction(lua_State *l) CConstruction *construction = nullptr; if (it == Constructions.end()) { - construction = new CConstruction; - Constructions.push_back(construction); + Constructions.push_back(std::make_unique()); + construction = Constructions.back().get(); } else { // redefine completely. - construction = *it; + construction = it->get(); construction->Clean(); } construction->Ident = str; diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp index c963c3b79a..e2217200a1 100644 --- a/src/stratagus/stratagus.cpp +++ b/src/stratagus/stratagus.cpp @@ -421,9 +421,6 @@ void Exit(int err) if (UnitManager) { delete UnitManager; } - if (FogOfWar) { - delete FogOfWar; - } fprintf(stdout, "%s", _("Thanks for playing Stratagus.\n")); exit(err); @@ -759,7 +756,7 @@ int stratagusMain(int argc, char **argv) // init globals Map.AllocateTileset(); UnitManager = new CUnitManager(); - FogOfWar = new CFogOfWar(); + FogOfWar = std::make_unique(); LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments); diff --git a/src/ui/botpanel.cpp b/src/ui/botpanel.cpp index c9152eca51..39148322fc 100644 --- a/src/ui/botpanel.cpp +++ b/src/ui/botpanel.cpp @@ -110,7 +110,6 @@ void AddButton(int pos, int level, const std::string &icon_ident, { char buf[2048]; ButtonAction *ba = new ButtonAction; - Assert(ba); ba->Pos = pos; ba->Level = level; diff --git a/src/ui/mainscr.cpp b/src/ui/mainscr.cpp index 46c80f601e..ae0cbf0255 100644 --- a/src/ui/mainscr.cpp +++ b/src/ui/mainscr.cpp @@ -544,8 +544,8 @@ static void DrawUnitInfo(CUnit &unit) } } + Assert(unit.Type); const CUnitType &type = *unit.Type; - Assert(&type); // Draw IconUnit DrawUnitInfo_portrait(unit); diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp index d18069aadb..a42be0452a 100644 --- a/src/unit/unit.cpp +++ b/src/unit/unit.cpp @@ -549,7 +549,7 @@ void CUnit::Release(bool final) CriticalOrder = nullptr; // Remove the unit from the global units table. - UnitManager->ReleaseUnit(this); + UnitManager->ReleaseUnit(*this); } UnitAction CUnit::CurrentAction() const @@ -786,9 +786,8 @@ CUnit *MakeUnit(const CUnitType &type, CPlayer *player) ** @param f2 Function to (un)mark for cloaking vision. */ static void MapMarkUnitSightRec(const CUnit &unit, const Vec2i &pos, int width, int height, - MapMarkerFunc *f, MapMarkerFunc *f2) + MapMarkerFunc &f, MapMarkerFunc *f2) { - Assert(f); MapSight(*unit.Player, unit, pos, width, height, unit.Container ? unit.Container->CurrentSightRange : unit.CurrentSightRange, f); @@ -1329,10 +1328,9 @@ void CUnit::Remove(CUnit *host) */ void UnitLost(CUnit &unit) { + Assert(unit.Player); // Next code didn't support no player! CPlayer &player = *unit.Player; - Assert(&player); // Next code didn't support no player! - // Call back to AI, for killed or lost units. if (Editor.Running == EditorNotRunning) { if (player.AiEnabled) { @@ -2548,7 +2546,7 @@ int ThreatCalculate(const CUnit &unit, const CUnit &dest) if (GameSettings.SimplifiedAutoTargeting) { // Original algorithm return smaler values for better targets - return -TargetPriorityCalculate(&unit, &dest); + return -TargetPriorityCalculate(unit, dest); } const CUnitType &type = *unit.Type; @@ -2599,36 +2597,32 @@ int ThreatCalculate(const CUnit &unit, const CUnit &dest) return cost; } -int TargetPriorityCalculate(const CUnit *const attacker, const CUnit *const dest) +int TargetPriorityCalculate(const CUnit &attacker, const CUnit &dest) { - Assert(attacker != nullptr); - Assert(dest != nullptr); - - const CPlayer &player = *attacker->Player; - const CUnitType &type = *attacker->Type; - const CUnitType &dtype = *dest->Type; + const CPlayer &player = *attacker.Player; + const CUnitType &type = *attacker.Type; + const CUnitType &dtype = *dest.Type; - if (!player.IsEnemy(*dest) // a friend or neutral - || !dest->IsVisibleAsGoal(player) + if (!player.IsEnemy(dest) // a friend or neutral + || !dest.IsVisibleAsGoal(player) || !CanTarget(type, dtype)) { return INT_MIN; } // Don't attack invulnerable units - if (dtype.BoolFlag[INDESTRUCTIBLE_INDEX].value || dest->Variable[UNHOLYARMOR_INDEX].Value) { + if (dtype.BoolFlag[INDESTRUCTIBLE_INDEX].value || dest.Variable[UNHOLYARMOR_INDEX].Value) { return INT_MIN; } - const int attackRange = attacker->Stats->Variables[ATTACKRANGE_INDEX].Max; - const int minAttackRange = attacker->Type->MinAttackRange; - const int pathLength = CalcPathLengthToUnit(*attacker, *dest, minAttackRange, attackRange); - int distance = attacker->MapDistanceTo(*dest); + const int attackRange = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max; + const int minAttackRange = attacker.Type->MinAttackRange; + const int pathLength = CalcPathLengthToUnit(attacker, dest, minAttackRange, attackRange); + int distance = attacker.MapDistanceTo(dest); const int reactionRange = (player.Type == PlayerTypes::PlayerPerson) ? type.ReactRangePerson : type.ReactRangeComputer; - if (!InAttackRange(*attacker, *dest) - && ((distance > minAttackRange && pathLength < 0) - || attacker->CanMove() == false)) { + if (!InAttackRange(attacker, dest) + && ((distance > minAttackRange && pathLength < 0) || attacker.CanMove() == false)) { return INT_MIN; } @@ -2644,8 +2638,8 @@ int TargetPriorityCalculate(const CUnit *const attacker, const CUnit *const dest // is Threat? /// Check if target attacks us (or has us as goal for any action) - if (dest->CurrentOrder()->HasGoal() && dest->CurrentOrder()->GetGoal() == attacker - && InAttackRange(*dest, *attacker)) { + if (dest.CurrentOrder()->HasGoal() && dest.CurrentOrder()->GetGoal() == &attacker + && InAttackRange(dest, attacker)) { priority |= AT_ATTACKED_BY_FACTOR; } /// Unit can attack back. @@ -2683,7 +2677,7 @@ int TargetPriorityCalculate(const CUnit *const attacker, const CUnit *const dest priority |= (255 - (pathLength > 255 || pathLength < 0 ? 255 : pathLength)) << AT_DISTANCE_OFFSET; // Remaining HP (Health) (0..100)% - priority |= 100 - dest->Variable[HP_INDEX].Value * 100 / dest->Variable[HP_INDEX].Max; + priority |= 100 - dest.Variable[HP_INDEX].Value * 100 / dest.Variable[HP_INDEX].Max; return priority; } @@ -2699,7 +2693,6 @@ int TargetPriorityCalculate(const CUnit *const attacker, const CUnit *const dest */ bool InReactRange(const CUnit &unit, const CUnit &target) { - Assert(&target != nullptr); const int distance = unit.MapDistanceTo(target); const int range = (unit.Player->Type == PlayerTypes::PlayerPerson) ? unit.Type->ReactRangePerson @@ -2717,7 +2710,6 @@ bool InReactRange(const CUnit &unit, const CUnit &target) */ bool InAttackRange(const CUnit &unit, const CUnit &target) { - Assert(&target != nullptr); const int range = unit.Stats->Variables[ATTACKRANGE_INDEX].Max; const int minRange = unit.Type->MinAttackRange; const int distance = unit.Container ? unit.Container->MapDistanceTo(target) @@ -2764,7 +2756,6 @@ bool InAttackRange(const CUnit &unit, const Vec2i &tilePos) */ Vec2i GetRndPosInDirection(const Vec2i &srcPos, const CUnit &dirUnit, const bool dirFrom, const int minRange, const int devRadius, const int rangeDev) { - Assert(&dirUnit != nullptr); const Vec2i dirPos = dirUnit.tilePos + dirUnit.Type->GetHalfTileSize(); return GetRndPosInDirection(srcPos, dirPos, dirFrom, minRange, devRadius, rangeDev); } @@ -2982,7 +2973,7 @@ static void HitUnit_AttackBack(CUnit &attacker, CUnit &target) if (attacker.IsVisibleAsGoal(*target.Player)) { if (UnitReachable(target, attacker, target.Stats->Variables[ATTACKRANGE_INDEX].Max, false)) { target.UnderAttack = underAttack; /// allow target to ignore non aggressive targets while searching attacker - order.OfferNewTarget(target, &attacker); + order.OfferNewTarget(target, attacker); } return; } diff --git a/src/unit/unit_find.cpp b/src/unit/unit_find.cpp index fb88298dbf..daa0fe0cff 100644 --- a/src/unit/unit_find.cpp +++ b/src/unit/unit_find.cpp @@ -59,7 +59,7 @@ std::vector Select(const Vec2i <Pos, const Vec2i &rbPos) return Select(ltPos, rbPos, NoFilter()); } -std::vector SelectFixed(const Vec2i <Pos, const Vec2i &rbPos) +std::vector SelectFixed(const Vec2i <Pos, const Vec2i &rbPos) { return Select(ltPos, rbPos, NoFilter()); } @@ -667,7 +667,7 @@ class BestTargetFinder int best_cost = GameSettings.SimplifiedAutoTargeting ? INT_MIN : INT_MAX; for (Iterator it = begin; it != end; ++it) { - int cost = GameSettings.SimplifiedAutoTargeting ? TargetPriorityCalculate(attacker, *it) : ComputeCost(*it); + int cost = GameSettings.SimplifiedAutoTargeting ? TargetPriorityCalculate(*attacker, **it) : ComputeCost(*it); if (GameSettings.SimplifiedAutoTargeting ? (cost > best_cost) : (cost < best_cost)) { enemy = *it; @@ -767,17 +767,13 @@ class BestRangeTargetFinder ** @param range Distance range to look. ** */ - BestRangeTargetFinder(const CUnit &a, const int r) : attacker(&a), range(r), - best_unit(0), best_cost(INT_MIN), size((a.Type->Missile.Missile->Range + r) * 2) + BestRangeTargetFinder(const CUnit &a, const int r) : + attacker(&a), + range(r), + size((a.Type->Missile.Missile->Range + r) * 2), + good(size * size, 0), + bad(size * size, 0) { - good = new std::vector(size * size, 0); - bad = new std::vector(size * size, 0); - } - - ~BestRangeTargetFinder() - { - delete good; - delete bad; } class FillBadGood @@ -789,35 +785,35 @@ class BestRangeTargetFinder { } - template - int Fill(Iterator begin, Iterator end) + template + int Fill(Container &&container) { - for (Iterator it = begin; it != end; ++it) { - Compute(*it); + for (auto *elem : container) { + Compute(*elem); } return enemy_count; } private: - void Compute(CUnit *const dest) + void Compute(CUnit &dest) { const CPlayer &player = *attacker->Player; - if (!dest->IsVisibleAsGoal(player)) { - dest->CacheLock = 1; + if (!dest.IsVisibleAsGoal(player)) { + dest.CacheLock = 1; return; } - const CUnitType &type = *attacker->Type; - const CUnitType &dtype = *dest->Type; + const CUnitType &type = *attacker->Type; + const CUnitType &dtype = *dest.Type; // won't be a target... if (!CanTarget(type, dtype)) { // can't be attacked. - dest->CacheLock = 1; + dest.CacheLock = 1; return; } // Don't attack invulnerable units - if (dtype.BoolFlag[INDESTRUCTIBLE_INDEX].value || dest->Variable[UNHOLYARMOR_INDEX].Value) { - dest->CacheLock = 1; + if (dtype.BoolFlag[INDESTRUCTIBLE_INDEX].value || dest.Variable[UNHOLYARMOR_INDEX].Value) { + dest.CacheLock = 1; return; } @@ -827,13 +823,13 @@ class BestRangeTargetFinder int cost = 0; int hp_damage_evaluate; if (Damage) { - hp_damage_evaluate = CalculateDamage(*attacker, *dest, Damage.get()); + hp_damage_evaluate = CalculateDamage(*attacker, dest, Damage.get()); } else { hp_damage_evaluate = attacker->Stats->Variables[BASICDAMAGE_INDEX].Value + attacker->Stats->Variables[PIERCINGDAMAGE_INDEX].Value; } - if (!player.IsEnemy(*dest)) { // a friend or neutral - dest->CacheLock = 1; + if (!player.IsEnemy(dest)) { // a friend or neutral + dest.CacheLock = 1; // Calc a negative cost // The gost is more important when the unit would be killed @@ -841,9 +837,8 @@ class BestRangeTargetFinder // It costs (is positive) if hp_damage_evaluate>dest->HP ...) // FIXME : assume that PRIORITY_FACTOR>HEALTH_FACTOR - cost = HEALTH_FACTOR * (2 * hp_damage_evaluate - - dest->Variable[HP_INDEX].Value) / - (dtype.TileWidth * dtype.TileWidth); + cost = HEALTH_FACTOR * (2 * hp_damage_evaluate - dest.Variable[HP_INDEX].Value) + / (dtype.TileWidth * dtype.TileWidth); cost = std::max(cost, 1); cost = -cost; } else { @@ -866,7 +861,7 @@ class BestRangeTargetFinder // Give a boost to unit we can kill in one shoot only // calculate HP which will remain in the enemy unit, after hit - int effective_hp = (dest->Variable[HP_INDEX].Value - 2 * hp_damage_evaluate); + int effective_hp = (dest.Variable[HP_INDEX].Value - 2 * hp_damage_evaluate); // Unit we won't kill are evaluated the same // Unit we are sure to kill are all evaluated the same (except PRIORITY) @@ -888,27 +883,27 @@ class BestRangeTargetFinder // Removed Unit's are in bunkers int d; if (attacker->Removed) { - d = attacker->Container->MapDistanceTo(*dest); + d = attacker->Container->MapDistanceTo(dest); } else { - d = attacker->MapDistanceTo(*dest); + d = attacker->MapDistanceTo(dest); } int attackrange = attacker->Stats->Variables[ATTACKRANGE_INDEX].Max; if (d <= attackrange || - (d <= range && UnitReachable(*attacker, *dest, attackrange, false))) { + (d <= range && UnitReachable(*attacker, dest, attackrange, false))) { ++enemy_count; } else { - dest->CacheLock = 1; + dest.CacheLock = 1; } // Attack walls only if we are stuck in them if (dtype.BoolFlag[WALL_INDEX].value && d > 1) { - dest->CacheLock = 1; + dest.CacheLock = 1; } } // cost map is relative to attacker position - const int x = dest->tilePos.x - attacker->tilePos.x + (size / 2); - const int y = dest->tilePos.y - attacker->tilePos.y + (size / 2); + const int x = dest.tilePos.x - attacker->tilePos.x + (size / 2); + const int y = dest.tilePos.y - attacker->tilePos.y + (size / 2); // Mark the good/bad array... for (int yy = 0; yy < dtype.TileHeight; ++yy) { @@ -934,7 +929,6 @@ class BestRangeTargetFinder } } - private: const CUnit *attacker; const int range; @@ -947,54 +941,48 @@ class BestRangeTargetFinder CUnit *Find(std::vector &table) { if (!GameSettings.SimplifiedAutoTargeting) { - FillBadGood(*attacker, range, good, bad, size).Fill(table.begin(), table.end()); + FillBadGood(*attacker, range, &good, &bad, size).Fill(table); } - return Find(table.begin(), table.end()); - - } - -private: - template - CUnit *Find(Iterator begin, Iterator end) - { - for (Iterator it = begin; it != end; ++it) { - Compute(*it); + for (auto* unit : table) { + Compute(*unit); } return best_unit; } - void Compute(CUnit *const dest) +private: + + void Compute(CUnit &dest) { - if (dest->CacheLock) { - dest->CacheLock = 0; + if (dest.CacheLock) { + dest.CacheLock = 0; return; } if (GameSettings.SimplifiedAutoTargeting) { - const int cost = TargetPriorityCalculate(attacker, dest); + const int cost = TargetPriorityCalculate(*attacker, dest); if (cost > best_cost) { - best_unit = dest; + best_unit = &dest; best_cost = cost; } return; } const CUnitType &type = *attacker->Type; - const CUnitType &dtype = *dest->Type; + const CUnitType &dtype = *dest.Type; int x = attacker->tilePos.x; int y = attacker->tilePos.y; // put in x-y the real point which will be hit... // (only meaningful when dtype->TileWidth > 1) - clamp(&x, dest->tilePos.x, dest->tilePos.x + dtype.TileWidth - 1); - clamp(&y, dest->tilePos.y, dest->tilePos.y + dtype.TileHeight - 1); + clamp(&x, dest.tilePos.x, dest.tilePos.x + dtype.TileWidth - 1); + clamp(&y, dest.tilePos.y, dest.tilePos.y + dtype.TileHeight - 1); int sbad = 0; int sgood = 0; // cost map is relative to attacker position - x = dest->tilePos.x - attacker->tilePos.x + (size / 2); - y = dest->tilePos.y - attacker->tilePos.y + (size / 2); + x = dest.tilePos.x - attacker->tilePos.x + (size / 2); + y = dest.tilePos.y - attacker->tilePos.y + (size / 2); // calculate the costs: // costs are the full costs at the target and the splash-factor @@ -1004,7 +992,7 @@ class BestRangeTargetFinder for (int xx = -1; xx <= 1; ++xx) { int pos = (y + yy) * (size / 2) + (x + xx); int localFactor = (!xx && !yy) ? 1 : splashFactor; - if (pos < 0 || static_cast(pos) >= good->size()) { + if (pos < 0 || static_cast(pos) >= good.size()) { DebugPrint("BUG: RangeTargetFinder.Compute out of range. " "size: %d, pos: %d, x: %d, xx: %d, y: %d, yy: %d \n", size, @@ -1015,8 +1003,8 @@ class BestRangeTargetFinder yy); break; } - sbad += bad->at(pos) / localFactor; - sgood += good->at(pos) / localFactor; + sbad += bad.at(pos) / localFactor; + sgood += good.at(pos) / localFactor; } } @@ -1029,18 +1017,18 @@ class BestRangeTargetFinder int cost = sbad / sgood; if (cost > best_cost) { best_cost = cost; - best_unit = dest; + best_unit = &dest; } } private: const CUnit *attacker; const int range; - CUnit *best_unit; - int best_cost; - std::vector *good; - std::vector *bad; + CUnit *best_unit = nullptr; + int best_cost = INT_MIN; const int size; + std::vector good; + std::vector bad; }; struct CompareUnitDistance { @@ -1144,9 +1132,8 @@ CUnit *AttackUnitsInDistance(const CUnit &unit, int range, CUnitFilter pred) range, MakeAndPredicate(HasNotSamePlayerAs(Players[PlayerNumNeutral]), pred)); - const int n = static_cast(table.size()); if (range > 25 && table.size() > 9) { - std::sort(table.begin(), table.begin() + n, CompareUnitDistance(unit)); + ranges::sort(table, CompareUnitDistance(unit)); } // Find the best unit to attack diff --git a/src/unit/unit_manager.cpp b/src/unit/unit_manager.cpp index 158e804516..3806209964 100644 --- a/src/unit/unit_manager.cpp +++ b/src/unit/unit_manager.cpp @@ -100,25 +100,23 @@ CUnit *CUnitManager::AllocUnit() ** ** @param unit Unit to release */ -void CUnitManager::ReleaseUnit(CUnit *unit) +void CUnitManager::ReleaseUnit(CUnit &unit) { - Assert(unit); - - if (lastCreated == unit) { + if (lastCreated == &unit) { lastCreated = nullptr; } - if (unit->UnitManagerData.unitSlot != -1) { // == -1 when loading. - Assert(units[unit->UnitManagerData.unitSlot] == unit); + if (unit.UnitManagerData.unitSlot != -1) { // == -1 when loading. + Assert(units[unit.UnitManagerData.unitSlot] == &unit); CUnit *temp = units.back(); - temp->UnitManagerData.unitSlot = unit->UnitManagerData.unitSlot; - units[unit->UnitManagerData.unitSlot] = temp; - unit->UnitManagerData.unitSlot = -1; + temp->UnitManagerData.unitSlot = unit.UnitManagerData.unitSlot; + units[unit.UnitManagerData.unitSlot] = temp; + unit.UnitManagerData.unitSlot = -1; units.pop_back(); } - Assert(unit->PlayerSlot == -1); - releasedUnits.push_back(unit); - unit->ReleaseCycle = GameCycle + 500; // can be reused after this time + Assert(unit.PlayerSlot == -1); + releasedUnits.push_back(&unit); + unit.ReleaseCycle = GameCycle + 500; // can be reused after this time //Refs = GameCycle + (NetworkMaxLag << 1); // could be reuse after this time } @@ -201,7 +199,7 @@ void CUnitManager::Load(lua_State *l) } } Assert(unit_index != -1 && cycle != static_cast(-1)); - ReleaseUnit(unitSlots[unit_index]); + ReleaseUnit(*unitSlots[unit_index]); unitSlots[unit_index]->ReleaseCycle = cycle; lua_pop(l, 1); } diff --git a/src/unit/unit_save.cpp b/src/unit/unit_save.cpp index f672422f7f..e28054e58c 100644 --- a/src/unit/unit_save.cpp +++ b/src/unit/unit_save.cpp @@ -72,11 +72,7 @@ std::string UnitReference(const CUnit &unit) std::string UnitReference(const CUnitPtr &unit) { Assert(unit != nullptr); - - std::ostringstream ss; - ss << "U" << std::setfill('0') << std::setw(4) << std::uppercase - << std::hex << UnitNumber(*unit); - return ss.str(); + return UnitReference(*unit); } void PathFinderInput::Save(CFile &file) const