From d90266e9dbcceb2a159ac60ab6bd2087bd91ab67 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Wed, 18 Oct 2023 21:29:04 +0200 Subject: [PATCH 01/17] Use `enum class` for `LocBaseType`. --- src/include/spell/spell_spawnmissile.h | 14 +++++----- src/spell/spell_spawnmissile.cpp | 37 +++++++++++++++----------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/include/spell/spell_spawnmissile.h b/src/include/spell/spell_spawnmissile.h index 32681284a6..bbc984a2d6 100644 --- a/src/include/spell/spell_spawnmissile.h +++ b/src/include/spell/spell_spawnmissile.h @@ -41,9 +41,9 @@ /** ** Different targets. */ -enum LocBaseType { - LocBaseCaster, - LocBaseTarget +enum class ELocBaseType { + Caster, + Target }; /** @@ -55,9 +55,9 @@ enum LocBaseType { class SpellActionMissileLocation { public: - explicit SpellActionMissileLocation(LocBaseType base) : Base(base) {} + explicit SpellActionMissileLocation(ELocBaseType base) : Base(base) {} - LocBaseType Base; /// The base for the location (caster/target) + ELocBaseType Base; /// The base for the location (caster/target) int AddX = 0; /// Add to the X coordinate int AddY = 0; /// Add to the X coordinate int AddRandX = 0; /// Random add to the X coordinate @@ -76,8 +76,8 @@ class Spell_SpawnMissile : public SpellActionType int TTL = -1; /// Missile TTL. int Delay = 0; /// Missile original delay. bool UseUnitVar = false; /// Use the caster's damage parameters - SpellActionMissileLocation StartPoint{LocBaseCaster}; /// Start point description. - SpellActionMissileLocation EndPoint{LocBaseTarget}; /// Start point description. + SpellActionMissileLocation StartPoint{ELocBaseType::Caster}; /// Start point description. + SpellActionMissileLocation EndPoint{ELocBaseType::Target}; /// Start point description. MissileType *Missile = nullptr; /// Missile fired on cast }; diff --git a/src/spell/spell_spawnmissile.cpp b/src/spell/spell_spawnmissile.cpp index 01f32350f1..126ec03394 100644 --- a/src/spell/spell_spawnmissile.cpp +++ b/src/spell/spell_spawnmissile.cpp @@ -57,6 +57,18 @@ struct CompareUnitDistance { } }; +ELocBaseType toELocBaseType(std::string_view s) +{ + if (s == "caster") { + return ELocBaseType::Caster; + } else if (s == "target") { + return ELocBaseType::Target; + } else { + fprintf(stderr, "Unsupported location base flag: %s", s.data()); + ExitFatal(-1); + } +} + /** ** Parse the missile location description for a spell action. ** @@ -78,14 +90,7 @@ static void CclSpellMissileLocation(lua_State *l, SpellActionMissileLocation *lo std::string_view value = LuaToString(l, -1, j + 1); ++j; if (value == "base") { - value = LuaToString(l, -1, j + 1); - if (value == "caster") { - location->Base = LocBaseCaster; - } else if (value == "target") { - location->Base = LocBaseTarget; - } else { - LuaError(l, "Unsupported missile location base flag: %s", value.data()); - } + location->Base = toELocBaseType(LuaToString(l, -1, j + 1)); } else if (value == "add-x") { location->AddX = LuaToNumber(l, -1, j + 1); } else if (value == "add-y") { @@ -151,14 +156,14 @@ static PixelPos EvaluateMissileLocation(const SpellActionMissileLocation &locati { PixelPos res; - if (location.Base == LocBaseCaster) { - res = caster.GetMapPixelPosCenter(); - } else { - if (target) { - res = target->GetMapPixelPosCenter(); - } else { - res = Map.TilePosToMapPixelPos_Center(goalPos); - } + switch (location.Base) { + case ELocBaseType::Caster: + res = caster.GetMapPixelPosCenter(); + break; + default: + case ELocBaseType::Target: + res = target ? target->GetMapPixelPosCenter() : Map.TilePosToMapPixelPos_Center(goalPos); + break; } res.x += location.AddX; if (location.AddRandX) { From f9c359e4e70cf3cd45fb32ac7af400b4910b2d2e Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Wed, 18 Oct 2023 23:16:34 +0200 Subject: [PATCH 02/17] Use `ranges::erase_if`. --- src/ai/ai_resource.cpp | 38 +-- src/include/util.h | 4 +- src/spell/spells.cpp | 83 +++---- src/stratagus/selection.cpp | 458 +++++++++++++++++------------------- 4 files changed, 264 insertions(+), 319 deletions(-) diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp index acebe65ebf..7521fea6be 100644 --- a/src/ai/ai_resource.cpp +++ b/src/ai/ai_resource.cpp @@ -266,36 +266,31 @@ static bool AiBuildBuilding(const CUnitType &type, CUnitType &building, const Ve { std::vector table = FindPlayerUnitsByType(*AiPlayer->Player, type, true); - int num = 0; - // Remove all workers on the way building something - for (size_t i = 0; i != table.size(); ++i) { - CUnit &unit = *table[i]; - - if (IsAlreadyWorking(unit) == false) { - table[num++] = &unit; - } - } - if (num == 0) { + ranges::erase_if(table, [](const CUnit *unit) { return IsAlreadyWorking(*unit); }); + if (table.empty()) { // No workers available to build return false; } - CUnit &unit = (num == 1) ? *table[0] : *table[SyncRand() % num]; + CUnit &candidate = (table.size() == 1) ? *table[0] : *table[SyncRand() % table.size()]; Vec2i pos; // Find a place to build. - if (AiFindBuildingPlace(unit, building, nearPos, &pos)) { - CommandBuildBuilding(unit, pos, building, FlushCommands); + if (AiFindBuildingPlace(candidate, building, nearPos, &pos)) { + CommandBuildBuilding(candidate, pos, building, FlushCommands); return true; } else { //when first worker can't build then rest also won't be able (save CPU) if (Map.Info.IsPointOnMap(nearPos)) { //Crush CPU !!!!! - for (int i = 0; i < num && table[i] != &unit; ++i) { + for (auto *unit : table) { + if (unit == &candidate) { // already checked. + continue; + } // Find a place to build. - if (AiFindBuildingPlace(*table[i], building, nearPos, &pos)) { - CommandBuildBuilding(*table[i], pos, building, FlushCommands); + if (AiFindBuildingPlace(*unit, building, nearPos, &pos)) { + CommandBuildBuilding(*unit, pos, building, FlushCommands); return true; } } @@ -1248,16 +1243,7 @@ static bool AiRepairBuilding(const CPlayer &player, const CUnitType &type, CUnit // AI shouldn't send workers that are far away from repair point // Selection of mining workers. std::vector table = FindPlayerUnitsByType(*AiPlayer->Player, type, true); - int num = 0; - for (size_t i = 0; i != table.size(); ++i) { - CUnit &unit = *table[i]; - - if (IsReadyToRepair(unit)) { - table[num++] = &unit; - } - } - table.resize(num); - + ranges::erase_if(table, [](const CUnit *unit) { return !IsReadyToRepair(*unit); }); if (table.empty()) { return false; } diff --git a/src/include/util.h b/src/include/util.h index 4a538d8cd6..e434b7e7c6 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -226,7 +226,9 @@ namespace ranges template auto find_if(Range &range, Predicate &&predicate) { - return std::find_if(std::begin(range), std::end(range), std::forward(predicate)); + return std::find_if(std::begin(range), std::end(range), [&](const auto &elem) { + return std::invoke(std::forward(predicate), elem); + }); } template diff --git a/src/spell/spells.cpp b/src/spell/spells.cpp index d5962f8444..96d5132e5f 100644 --- a/src/spell/spells.cpp +++ b/src/spell/spells.cpp @@ -273,33 +273,26 @@ static std::optional> SelectTargetUnitsOfAutoCast(CUnit return std::nullopt; case TargetPosition: { if (autocast->PositionAutoCast && table.empty() == false) { - size_t count = 0; - for (size_t i = 0; i != table.size(); ++i) { - // Check for corpse - if (autocast->Corpse == ECondition::ShouldBeTrue) { - if (table[i]->CurrentAction() != UnitAction::Die) { - continue; - } - } else if (autocast->Corpse == ECondition::ShouldBeFalse) { - if (table[i]->CurrentAction() == UnitAction::Die || table[i]->IsAlive() == false) { - continue; - } - } - if (PassCondition(caster, spell, table[i], pos, spell.Condition.get()) - && PassCondition(caster, spell, table[i], pos, autocast->Condition.get())) { - table[count++] = table[i]; - } - } - if (count > 0) { + ranges::erase_if(table, [&](const CUnit *unit) { + return (autocast->Corpse == ECondition::ShouldBeTrue + && unit->CurrentAction() != UnitAction::Die) + || (autocast->Corpse == ECondition::ShouldBeFalse + && (unit->CurrentAction() == UnitAction::Die + || unit->IsAlive() == false)) + || !PassCondition(caster, spell, unit, pos, spell.Condition.get()) + || !PassCondition(caster, spell, unit, pos, autocast->Condition.get()); + }); + if (!table.empty()) { if (autocast->PriorytyVar != ACP_NOVALUE) { - std::sort(table.begin(), table.begin() + count, - AutoCastPrioritySort(caster, autocast->PriorytyVar, autocast->ReverseSort)); + ranges::sort(table, + AutoCastPrioritySort( + caster, autocast->PriorytyVar, autocast->ReverseSort)); } - std::vector array(count + 1); - for (size_t i = 1; i != count + 1; ++i) { - array[i] = UnitNumber(*table[i - 1]); + std::vector array{UnitNumber(caster)}; + array.reserve(table.size() + 1); + for (const auto *unit : table) { + array.push_back(UnitNumber(*unit)); } - array[0] = UnitNumber(caster); const auto [x, y] = autocast->PositionAutoCast->call(array); Vec2i resPos(x, y); if (Map.Info.IsPointOnMap(resPos)) { @@ -313,44 +306,42 @@ static std::optional> SelectTargetUnitsOfAutoCast(CUnit // The units are already selected. // Check every unit if it is a possible target - int n = 0; - for (size_t i = 0; i != table.size(); ++i) { + ranges::erase_if(table, [&](const auto* unit) { // Check if unit in battle if (autocast->Attacker == ECondition::ShouldBeTrue) { - const int range = table[i]->Player->Type == PlayerTypes::PlayerPerson ? table[i]->Type->ReactRangePerson : table[i]->Type->ReactRangeComputer; - if ((table[i]->CurrentAction() != UnitAction::Attack - && table[i]->CurrentAction() != UnitAction::AttackGround - && table[i]->CurrentAction() != UnitAction::SpellCast) - || table[i]->CurrentOrder()->HasGoal() == false - || table[i]->MapDistanceTo(table[i]->CurrentOrder()->GetGoalPos()) > range) { - continue; + const int range = unit->Player->Type == PlayerTypes::PlayerPerson ? unit->Type->ReactRangePerson : unit->Type->ReactRangeComputer; + if ((unit->CurrentAction() != UnitAction::Attack + && unit->CurrentAction() != UnitAction::AttackGround + && unit->CurrentAction() != UnitAction::SpellCast) + || unit->CurrentOrder()->HasGoal() == false + || unit->MapDistanceTo(unit->CurrentOrder()->GetGoalPos()) > range) { + return true; } } // Check for corpse if (autocast->Corpse == ECondition::ShouldBeTrue) { - if (table[i]->CurrentAction() != UnitAction::Die) { - continue; + if (unit->CurrentAction() != UnitAction::Die) { + return true; } } else if (autocast->Corpse == ECondition::ShouldBeFalse) { - if (table[i]->CurrentAction() == UnitAction::Die) { - continue; + if (unit->CurrentAction() == UnitAction::Die) { + return true; } } - if (PassCondition(caster, spell, table[i], pos, spell.Condition.get()) - && PassCondition(caster, spell, table[i], pos, autocast->Condition.get())) { - table[n++] = table[i]; - } - } + return !PassCondition(caster, spell, unit, pos, spell.Condition.get()) + || !PassCondition(caster, spell, unit, pos, autocast->Condition.get()); + }); // Now select the best unit to target. - if (n != 0) { + if (!table.empty()) { // For the best target??? CUnit *unit; if (autocast->PriorytyVar != ACP_NOVALUE) { - std::sort(table.begin(), table.begin() + n, - AutoCastPrioritySort(caster, autocast->PriorytyVar, autocast->ReverseSort)); + ranges::sort( + table, + AutoCastPrioritySort(caster, autocast->PriorytyVar, autocast->ReverseSort)); unit = table[0]; } else { // Use the old behavior - unit = table[SyncRand() % n]; + unit = table[SyncRand() % table.size()]; } return std::pair{unit, unit->tilePos}; } diff --git a/src/stratagus/selection.cpp b/src/stratagus/selection.cpp index dc52f07987..623caf6dfc 100644 --- a/src/stratagus/selection.cpp +++ b/src/stratagus/selection.cpp @@ -592,8 +592,6 @@ int SelectGroupFromUnit(CUnit &unit) static bool SelectOrganicUnitsInTable(std::vector &table, bool added_table) //Wyrmgus end { - unsigned int n = 0; - //Wyrmgus start //check if has non-building bool hasNonBuilding = false; @@ -604,34 +602,29 @@ static bool SelectOrganicUnitsInTable(std::vector &table, bool added_ta } //Wyrmgus end - for (size_t i = 0; i != table.size(); ++i) { - CUnit &unit = *table[i]; - - if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { - continue; - } - if (unit.IsUnusable()) { // guess SelectUnits doesn't check this - continue; - } - if (unit.TeamSelected) { // Somebody else onteam has this unit - continue; - } - //Wyrmgus start - //only select buildings if another building of the same type is already selected - if (added_table == false && unit.Type->Building && ((i != 0 && unit.Type != table[0]->Type) || hasNonBuilding)) { - continue; - } - //Wyrmgus end - table[n++] = &unit; - if (n == MaxSelectable) { - break; - } - } - if (n != 0) { - table.resize(n); - return true; - } - return false; + ranges::erase_if(table, [&](CUnit *unitPtr) { + const CUnit &unit = *unitPtr; + if (!CanSelectMultipleUnits(*unit.Player) + || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { + return true; + } + if (unit.IsUnusable()) { // guess SelectUnits doesn't check this + return true; + } + if (unit.TeamSelected) { // Somebody else onteam has this unit + return true; + } + //Wyrmgus start + //only select buildings if another building of the same type is already selected + if (added_table == false && unit.Type->Building + && (unit.Type != table[0]->Type || hasNonBuilding)) { + return true; + } + //Wyrmgus end + return false; + }); + table.resize(std::min(table.size(), MaxSelectable)); + return !table.empty(); } /** @@ -643,30 +636,21 @@ static bool SelectOrganicUnitsInTable(std::vector &table, bool added_ta ** @param corner_topleft coord of upper left corner of the rectangle ** @param corner_bottomright coord of lower right corner of the rectangle ** @param table table of units -** -** @return number of units found */ static void SelectSpritesInsideRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright, std::vector &table) { - int n = 0; - - for (size_t i = 0; i != table.size(); ++i) { - CUnit &unit = *table[i]; - const CUnitType &type = *unit.Type; - PixelPos spritePos = unit.GetMapPixelPosCenter(); + ranges::erase_if(table, [&](const CUnit *unit) { + const CUnitType &type = *unit->Type; + PixelPos spritePos = unit->GetMapPixelPosCenter(); spritePos.x += type.Offset.x - (type.BoxWidth + type.BoxOffset.x) / 2; spritePos.y += type.Offset.y - (type.BoxHeight + type.BoxOffset.y) / 2; - if (spritePos.x + type.BoxWidth + type.BoxOffset.x < corner_topleft.x - || spritePos.x > corner_bottomright.x - || spritePos.y + type.BoxHeight + type.BoxOffset.y < corner_topleft.y - || spritePos.y > corner_bottomright.y) { - continue; - } - table[n++] = &unit; - } - table.resize(n); + return (spritePos.x + type.BoxWidth + type.BoxOffset.x < corner_topleft.x + || spritePos.x > corner_bottomright.x + || spritePos.y + type.BoxHeight + type.BoxOffset.y < corner_topleft.y + || spritePos.y > corner_bottomright.y); + }); } /** @@ -701,51 +685,41 @@ int SelectUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corne return size; } - // 2) If no unit found, try a player's unit not selectable by rectangle - for (CUnit *unit : table) { - if (!CanSelectMultipleUnits(*unit->Player)) { - continue; - } - // FIXME: Can we get this? - if (!unit->Removed && unit->IsAlive()) { - SelectSingleUnit(*unit); - return 1; - } - } - - // 3) If no unit found, try a resource or a neutral critter - for (CUnit *unit : table) { - // Unit visible FIXME: write function UnitSelectable - if (!unit->IsVisibleInViewport(*UI.SelectedViewport)) { - continue; - } - const CUnitType &type = *unit->Type; - // Buildings are visible but not selectable - if (type.Building && !unit->IsVisibleOnMap(*ThisPlayer)) { - continue; - } - if ((type.GivesResource && !unit->Removed)) { // no built resources. - SelectSingleUnit(*unit); - return 1; - } - } - - // 4) If no unit found, select an enemy unit (first found) - for (CUnit *unit : table) { - // Unit visible FIXME: write function UnitSelectable - if (!unit->IsVisibleInViewport(*UI.SelectedViewport)) { - continue; - } - // Buildings are visible but not selectable - if (unit->Type->Building && !unit->IsVisibleOnMap(*ThisPlayer)) { - continue; - } - if (unit->IsAliveOnMap()) { - SelectSingleUnit(*unit); - return 1; - } - } - return 0; + // 2) If no unit found, try a player's unit not selectable by rectangle + const auto selectable = [](const CUnit *unit) { + return CanSelectMultipleUnits(*unit->Player) && !unit->Removed && unit->IsAlive(); + }; + if (const auto it = ranges::find_if(table, selectable); it != table.end()) { + SelectSingleUnit(**it); + return 1; + } + ranges::erase_if(table, [](const CUnit *unit) { + // Unit visible FIXME: write function UnitSelectable + if (!unit->IsVisibleInViewport(*UI.SelectedViewport)) { + return true; + } + const CUnitType &type = *unit->Type; + // Buildings are visible but not selectable + if (type.Building && !unit->IsVisibleOnMap(*ThisPlayer)) { + return true; + } + return false; + }); + // 3) If no unit found, try a resource or a neutral critter + const auto isMine = [](const CUnit *unit) { + const CUnitType &type = *unit->Type; + return (type.GivesResource && !unit->Removed); // no built resources. + }; + if (const auto it = ranges::find_if(table, isMine); it != table.end()) { + SelectSingleUnit(**it); + return 1; + } + // 4) If no unit found, select an enemy unit (first found) + if (const auto it = ranges::find_if(table, &CUnit::IsAliveOnMap); it != table.end()) { + SelectSingleUnit(**it); + return 1; + } + return 0; } /** @@ -815,43 +789,41 @@ int AddSelectedUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos & */ int SelectGroundUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright) { - const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft); - const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright); - const Vec2i range(2, 2); - std::vector table = Select(t0 - range, t1 + range); + const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft); + const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright); + const Vec2i range(2, 2); + std::vector table = Select(t0 - range, t1 + range); - SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); + SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); - unsigned int n = 0; - for (size_t i = 0; i != table.size(); ++i) { - CUnit &unit = *table[i]; + ranges::erase_if(table, [](const CUnit *unitPtr) { + const CUnit &unit = *unitPtr; - if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { - continue; - } - if (unit.IsUnusable()) { // guess SelectUnits doesn't check this - continue; - } - if (unit.Type->UnitType == UnitTypeFly) { - continue; - } - if (unit.TeamSelected) { // Somebody else onteam has this unit - continue; - } - //Wyrmgus start - if (unit.Type->Building) { //this selection mode is not for buildings - continue; - } - //Wyrmgus end - table[n++] = &unit; - if (n == MaxSelectable) { - break; - } - } - if (n) { - ChangeSelectedUnits(&table[0], n); - } - return n; + if (!CanSelectMultipleUnits(*unit.Player) + || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { + return true; + } + if (unit.IsUnusable()) { // guess SelectUnits doesn't check this + return true; + } + if (unit.Type->UnitType == UnitTypeFly) { + return true; + } + if (unit.TeamSelected) { // Somebody else onteam has this unit + return true; + } + //Wyrmgus start + if (unit.Type->Building) { //this selection mode is not for buildings + return true; + } + //Wyrmgus end + return false; + }); + table.resize(std::min(table.size(), MaxSelectable)); + if (!table.empty()) { + ChangeSelectedUnits(&table[0], table.size()); + } + return table.size(); } /** @@ -864,41 +836,40 @@ int SelectGroundUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos */ int SelectAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright) { - const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft); - const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright); - const Vec2i range(2, 2); - std::vector table = Select(t0 - range, t1 + range); - - SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); - unsigned int n = 0; - for (size_t i = 0; i != table.size(); ++i) { - CUnit &unit = *table[i]; - if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { - continue; - } - if (unit.IsUnusable()) { // guess SelectUnits doesn't check this - continue; - } - if (unit.Type->UnitType != UnitTypeFly) { - continue; - } - if (unit.TeamSelected) { // Somebody else onteam has this unit - continue; - } - //Wyrmgus start - if (unit.Type->Building) { //this selection mode is not for buildings - continue; - } - //Wyrmgus end - table[n++] = &unit; - if (n == MaxSelectable) { - break; - } - } - if (n) { - ChangeSelectedUnits(&table[0], n); - } - return n; + const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft); + const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright); + const Vec2i range(2, 2); + std::vector table = Select(t0 - range, t1 + range); + + SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); + + ranges::erase_if(table, [](const CUnit *unitPtr) { + const CUnit &unit = *unitPtr; + if (!CanSelectMultipleUnits(*unit.Player) + || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { + return true; + } + if (unit.IsUnusable()) { // guess SelectUnits doesn't check this + return true; + } + if (unit.Type->UnitType != UnitTypeFly) { + return true; + } + if (unit.TeamSelected) { // Somebody else onteam has this unit + return true; + } + //Wyrmgus start + if (unit.Type->Building) { //this selection mode is not for buildings + return true; + } + //Wyrmgus end + return false; + }); + table.resize(std::min(table.size(), MaxSelectable)); + if (!table.empty()) { + ChangeSelectedUnits(&table[0], table.size()); + } + return table.size(); } @@ -912,63 +883,61 @@ int SelectAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &co */ int AddSelectedGroundUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright) { - // Check if the original selected unit (if it's alone) is ours, - // and can be selectable by rectangle. - // In this case, do nothing. - if (Selected.size() == 1 - && (!CanSelectMultipleUnits(*Selected[0]->Player) - || !Selected[0]->Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value)) { - return Selected.size(); - } + // Check if the original selected unit (if it's alone) is ours, + // and can be selectable by rectangle. + // In this case, do nothing. + if (Selected.size() == 1 + && (!CanSelectMultipleUnits(*Selected[0]->Player) + || !Selected[0]->Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value)) { + return Selected.size(); + } - // If there is no selected unit yet, do a simple selection. - //Wyrmgus start -// if (Selected.empty()) { - if (Selected.empty() || (Selected.size() && Selected[0]->Type->Building)) { - //Wyrmgus end - return SelectGroundUnitsInRectangle(corner_topleft, corner_bottomright); - } + // If there is no selected unit yet, do a simple selection. + //Wyrmgus start + // if (Selected.empty()) { + if (Selected.empty() || (Selected.size() && Selected[0]->Type->Building)) { + //Wyrmgus end + return SelectGroundUnitsInRectangle(corner_topleft, corner_bottomright); + } - const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft); - const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright); - const Vec2i range(2, 2); - std::vector table = Select(t0 - range, t1 + range); + const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft); + const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright); + const Vec2i range(2, 2); + std::vector table = Select(t0 - range, t1 + range); - SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); + SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); - unsigned int n = 0; - for (size_t i = 0; i < table.size(); ++i) { - CUnit &unit = *table[i]; + ranges::erase_if(table, [](const CUnit *unitPtr) { + const CUnit &unit = *unitPtr; - if (!CanSelectMultipleUnits(*unit.Player) || - !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { - continue; - } - if (unit.IsUnusable()) { // guess SelectUnits doesn't check this - continue; - } - if (unit.Type->UnitType == UnitTypeFly) { - continue; - } - if (unit.TeamSelected) { // Somebody else onteam has this unit - continue; - } - //Wyrmgus start - if (unit.Type->Building) { //this selection mode is not for buildings - continue; - } - //Wyrmgus end - table[n++] = &unit; - if (n == MaxSelectable) { - break; - } - } + if (!CanSelectMultipleUnits(*unit.Player) + || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { + return true; + } + if (unit.IsUnusable()) { // guess SelectUnits doesn't check this + return true; + } + if (unit.Type->UnitType == UnitTypeFly) { + return true; + } + if (unit.TeamSelected) { // Somebody else onteam has this unit + return true; + } + //Wyrmgus start + if (unit.Type->Building) { //this selection mode is not for buildings + return true; + } + //Wyrmgus end + return false; + }); - // Add the units to selected. - for (unsigned int i = 0; i < n && Selected.size() < MaxSelectable; ++i) { - SelectUnit(*table[i]); - } - return Selected.size(); + table.resize(std::min(table.size(), MaxSelectable)); + + // Add the units to selected. + for (unsigned int i = 0; i < table.size() && Selected.size() < MaxSelectable; ++i) { + SelectUnit(*table[i]); + } + return Selected.size(); } /** @@ -1004,38 +973,36 @@ int AddSelectedAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPo std::vector table = Select(t0 - range, t1 + range); SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table); - unsigned int n = 0; - for (size_t i = 0; i < table.size(); ++i) { - CUnit &unit = *table[i]; - if (!CanSelectMultipleUnits(*unit.Player) || - !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { - continue; - } - if (unit.IsUnusable()) { // guess SelectUnits doesn't check this - continue; - } - if (unit.Type->UnitType != UnitTypeFly) { - continue; - } - if (unit.TeamSelected) { // Somebody else onteam has this unit - continue; - } - //Wyrmgus start - if (unit.Type->Building) { //this selection mode is not for buildings - continue; - } - //Wyrmgus end - table[n++] = &unit; - if (n == MaxSelectable) { - break; - } - } - // Add the units to selected. - for (unsigned int i = 0; i < n && Selected.size() < MaxSelectable; ++i) { - SelectUnit(*table[i]); - } - return Selected.size(); + ranges::erase_if(table, [](const CUnit *unitPtr) { + const CUnit &unit = *unitPtr; + if (!CanSelectMultipleUnits(*unit.Player) + || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) { + return true; + } + if (unit.IsUnusable()) { // guess SelectUnits doesn't check this + return true; + } + if (unit.Type->UnitType != UnitTypeFly) { + return true; + } + if (unit.TeamSelected) { // Somebody else onteam has this unit + return true; + } + //Wyrmgus start + if (unit.Type->Building) { //this selection mode is not for buildings + return true; + } + //Wyrmgus end + return false; + }); + table.resize(std::min(table.size(), MaxSelectable)); + + // Add the units to selected. + for (unsigned int i = 0; i < table.size() && Selected.size() < MaxSelectable; ++i) { + SelectUnit(*table[i]); + } + return Selected.size(); } @@ -1081,10 +1048,9 @@ void CleanSelections() */ static int CclSetGroupId(lua_State *l) { - int old; - LuaCheckArgs(l, 1); - old = GroupId; + + const int old = GroupId; GroupId = LuaToNumber(l, 1); lua_pushnumber(l, old); From b9a8f0ad5a202f1b8a5b92c7e213ef3826766771 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Wed, 18 Oct 2023 23:45:40 +0200 Subject: [PATCH 03/17] Use reference to array (with full size) instead of pointer of unknown size. --- src/include/fow.h | 4 +++- src/map/fow.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/include/fow.h b/src/include/fow.h index f3af8caa3c..d764ad7522 100644 --- a/src/include/fow.h +++ b/src/include/fow.h @@ -94,7 +94,9 @@ class CFogOfWar void InitEnhanced(); void DrawEnhanced(CViewport &viewport); - void GenerateUpscaleTables(uint32_t (*table)[4], const uint8_t alphaFrom, const uint8_t alphaTo); + void GenerateUpscaleTables(uint32_t (&table)[16][4], + const uint8_t alphaFrom, + const uint8_t alphaTo); void GenerateFog(); void FogUpscale4x4(); diff --git a/src/map/fow.cpp b/src/map/fow.cpp index 6cf03171ec..4bf6223074 100644 --- a/src/map/fow.cpp +++ b/src/map/fow.cpp @@ -70,7 +70,7 @@ void CFogOfWar::SetTiledFogGraphic(const fs::path &fogGraphicFile) } /// Calculate values of upscale table for explored/unexplored tiles -void CFogOfWar::GenerateUpscaleTables(uint32_t (*table)[4], const uint8_t alphaFrom, const uint8_t alphaTo) +void CFogOfWar::GenerateUpscaleTables(uint32_t (&table)[16][4], const uint8_t alphaFrom, const uint8_t alphaTo) { for (auto i = 0; i < 16; i++) { for (auto j = 0; j < 4; j++) { From 0dcb4f803069e7920ae80c140fc064e1220b8af5 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 00:24:36 +0200 Subject: [PATCH 04/17] Use for-range. --- src/action/actions.cpp | 12 ++++---- src/ai/ai.cpp | 64 +++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/src/action/actions.cpp b/src/action/actions.cpp index bc91b020fa..51b489af82 100644 --- a/src/action/actions.cpp +++ b/src/action/actions.cpp @@ -327,18 +327,18 @@ static void HandleBuffsEachCycle(CUnit &unit) if (!unit.Type->CanCastSpell.empty()) { // decrease spell countdown timers - for (unsigned int i = 0; i < SpellTypeTable.size(); ++i) { - if (unit.SpellCoolDownTimers[i] > 0) { - --unit.SpellCoolDownTimers[i]; + for (auto &timer : unit.SpellCoolDownTimers) { + if (timer > 0) { + --timer; } } } const int SpellEffects[] = {BLOODLUST_INDEX, HASTE_INDEX, SLOW_INDEX, INVISIBLE_INDEX, UNHOLYARMOR_INDEX, POISON_INDEX}; // decrease spells effects time. - for (unsigned int i = 0; i < sizeof(SpellEffects) / sizeof(int); ++i) { - unit.Variable[SpellEffects[i]].Increase = -1; - IncreaseVariable(unit, SpellEffects[i]); + for (int index : SpellEffects) { + unit.Variable[index].Increase = -1; + IncreaseVariable(unit, index); } } diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 2084a40356..3f30c5f575 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -193,24 +193,23 @@ static void AiCheckUnits() // Count the already made build requests. auto counter = AiGetBuildRequestsCount(*AiPlayer); - const int *unit_types_count = AiPlayer->Player->UnitTypesAiActiveCount; + const int(&unit_types_count)[UnitTypeMax] = AiPlayer->Player->UnitTypesAiActiveCount; // Look if some unit-types are missing. - int n = AiPlayer->UnitTypeRequests.size(); - for (int i = 0; i < n; ++i) { - const unsigned int t = AiPlayer->UnitTypeRequests[i].Type->Slot; - const int x = AiPlayer->UnitTypeRequests[i].Count; + for (AiRequestType &requestType : AiPlayer->UnitTypeRequests) { + const unsigned int t = requestType.Type->Slot; + const int x = requestType.Count; // Add equivalent units int e = unit_types_count[t]; if (t < AiHelpers.Equiv().size()) { - for (unsigned int j = 0; j < AiHelpers.Equiv()[t].size(); ++j) { - e += unit_types_count[AiHelpers.Equiv()[t][j]->Slot]; + for (const auto *equivType : AiHelpers.Equiv()[t]) { + e += unit_types_count[equivType->Slot]; } } const int requested = x - e - counter[t]; if (requested > 0) { // Request it. - AiAddUnitTypeRequest(*AiPlayer->UnitTypeRequests[i].Type, requested); + AiAddUnitTypeRequest(*requestType.Type, requested); counter[t] += requested; } counter[t] -= x; @@ -219,32 +218,30 @@ static void AiCheckUnits() AiPlayer->Force.CheckUnits(counter); // Look if some upgrade-to are missing. - n = AiPlayer->UpgradeToRequests.size(); - for (int i = 0; i < n; ++i) { - const unsigned int t = AiPlayer->UpgradeToRequests[i]->Slot; + for (CUnitType *unitType : AiPlayer->UpgradeToRequests) { + const unsigned int t = unitType->Slot; const int x = 1; // Add equivalent units int e = unit_types_count[t]; if (t < AiHelpers.Equiv().size()) { - for (unsigned int j = 0; j < AiHelpers.Equiv()[t].size(); ++j) { - e += unit_types_count[AiHelpers.Equiv()[t][j]->Slot]; + for (const auto *equivType : AiHelpers.Equiv()[t]) { + e += unit_types_count[equivType->Slot]; } } const int requested = x - e - counter[t]; if (requested > 0) { // Request it. - AiAddUpgradeToRequest(*AiPlayer->UpgradeToRequests[i]); + AiAddUpgradeToRequest(*unitType); counter[t] += requested; } counter[t] -= x; } // Look if some researches are missing. - n = (int)AiPlayer->ResearchRequests.size(); - for (int i = 0; i < n; ++i) { - if (UpgradeIdAllowed(*AiPlayer->Player, AiPlayer->ResearchRequests[i]->ID) == 'A') { - AiAddResearchRequest(AiPlayer->ResearchRequests[i]); + for (CUpgrade *upgrade : AiPlayer->ResearchRequests) { + if (UpgradeIdAllowed(*AiPlayer->Player, upgrade->ID) == 'A') { + AiAddResearchRequest(upgrade); } } } @@ -290,17 +287,12 @@ static void SaveAiPlayer(CFile &file, int plynr, const PlayerAi &ai) } file.printf("\n \"types\", { "); - const size_t unitTypesCounst = ai.Force[i].UnitTypes.size(); - for (size_t j = 0; j != unitTypesCounst; ++j) { - const AiUnitType &aut = ai.Force[i].UnitTypes[j]; + for (const AiUnitType &aut : ai.Force[i].UnitTypes) { file.printf("%d, \"%s\", ", aut.Want, aut.Type->Ident.c_str()); } file.printf("},\n \"units\", {"); - const size_t unitsCount = ai.Force[i].Units.size(); - for (size_t j = 0; j != unitsCount; ++j) { - const CUnit &aiunit = *ai.Force[i].Units[j]; - file.printf(" %d, \"%s\",", UnitNumber(aiunit), - aiunit.Type->Ident.c_str()); + for (const CUnit *aiunit : ai.Force[i].Units) { + file.printf(" %d, \"%s\",", UnitNumber(*aiunit), aiunit->Type->Ident.c_str()); } file.printf("},\n \"state\", %d, \"goalx\", %d, \"goaly\", %d,", ai.Force[i].State, ai.Force[i].GoalPos.x, ai.Force[i].GoalPos.y); @@ -345,9 +337,7 @@ static void SaveAiPlayer(CFile &file, int plynr, const PlayerAi &ai) // Requests if (!ai.FirstExplorationRequest.empty()) { file.printf(" \"exploration\", {"); - const size_t FirstExplorationRequestCount = ai.FirstExplorationRequest.size(); - for (size_t i = 0; i != FirstExplorationRequestCount; ++i) { - const AiExplorationRequest &ptr = ai.FirstExplorationRequest[i]; + for (const AiExplorationRequest &ptr : ai.FirstExplorationRequest) { file.printf("{%d, %d, %d}, ", ptr.pos.x, ptr.pos.y, ptr.Mask); } file.printf("},\n"); @@ -355,24 +345,20 @@ static void SaveAiPlayer(CFile &file, int plynr, const PlayerAi &ai) file.printf(" \"last-exploration-cycle\", %lu,\n", ai.LastExplorationGameCycle); file.printf(" \"last-can-not-move-cycle\", %lu,\n", ai.LastCanNotMoveGameCycle); file.printf(" \"unit-type\", {"); - const size_t unitTypeRequestsCount = ai.UnitTypeRequests.size(); - for (size_t i = 0; i != unitTypeRequestsCount; ++i) { - file.printf("\"%s\", ", ai.UnitTypeRequests[i].Type->Ident.c_str()); - file.printf("%d, ", ai.UnitTypeRequests[i].Count); + for (const auto& requestType : ai.UnitTypeRequests) { + file.printf("\"%s\", %d, ", requestType.Type->Ident.c_str(), requestType.Count); } file.printf("},\n"); file.printf(" \"upgrade\", {"); - const size_t upgradeToRequestsCount = ai.UpgradeToRequests.size(); - for (size_t i = 0; i != upgradeToRequestsCount; ++i) { - file.printf("\"%s\", ", ai.UpgradeToRequests[i]->Ident.c_str()); + for (const CUnitType *unitType : ai.UpgradeToRequests) { + file.printf("\"%s\", ", unitType->Ident.c_str()); } file.printf("},\n"); file.printf(" \"research\", {"); - const size_t researchRequestsCount = ai.ResearchRequests.size(); - for (size_t i = 0; i != researchRequestsCount; ++i) { - file.printf("\"%s\", ", ai.ResearchRequests[i]->Ident.c_str()); + for (const CUpgrade *upgrade : ai.ResearchRequests) { + file.printf("\"%s\", ", upgrade->Ident.c_str()); } file.printf("},\n"); From 0f6e604e88cb5acead34216408dde314ccd83f2b Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 00:31:01 +0200 Subject: [PATCH 05/17] Use `ranges::iota` for `AiResetUnitTypeEquiv()`. --- src/ai/ai_force.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp index 1eef844719..111e4d7041 100644 --- a/src/ai/ai_force.cpp +++ b/src/ai/ai_force.cpp @@ -209,9 +209,7 @@ int UnitTypeEquivs[UnitTypeMax + 1]; /// equivalence between unittypes */ void AiResetUnitTypeEquiv() { - for (int i = 0; i <= UnitTypeMax; ++i) { - UnitTypeEquivs[i] = i; - } + ranges::iota(UnitTypeEquivs, 0); } /** From 669f06bed5eae576df6cbc852b7eebac54b7ff65 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 00:52:51 +0200 Subject: [PATCH 06/17] Use `std::vector` for `AiFindUnitTypeEquiv`/`AiFindAvailableUnitTypeEquiv`. --- src/ai/ai.cpp | 14 ++++++-------- src/ai/ai_force.cpp | 37 ++++++++++++++----------------------- src/ai/ai_local.h | 6 +++--- src/ai/ai_resource.cpp | 23 +++++++---------------- 4 files changed, 30 insertions(+), 50 deletions(-) diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 3f30c5f575..cd16cfabc3 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -540,10 +540,9 @@ static void AiRemoveFromBuilt(PlayerAi &pai, const CUnitType &type) } // This could happen if an upgrade is ready, look for equivalent units. - int equivalents[UnitTypeMax + 1]; - const int equivalentsCount = AiFindUnitTypeEquiv(type, equivalents); - for (int i = 0; i < equivalentsCount; ++i) { - if (AiRemoveFromBuilt2(pai, *UnitTypes[equivalents[i]])) { + const auto equivalents = AiFindUnitTypeEquiv(type); + for (int typeIndex : equivalents) { + if (AiRemoveFromBuilt2(pai, *UnitTypes[typeIndex])) { return; } } @@ -586,11 +585,10 @@ void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type) return; } // This could happen if an upgrade is ready, look for equivalent units. - int equivs[UnitTypeMax + 1]; - const unsigned int equivnb = AiFindUnitTypeEquiv(type, equivs); + const auto equivs = AiFindUnitTypeEquiv(type); - for (unsigned int i = 0; i < equivnb; ++i) { - if (AiReduceMadeInBuilt2(pai, *UnitTypes[equivs[i]])) { + for (int typeIndex : equivs) { + if (AiReduceMadeInBuilt2(pai, *UnitTypes[typeIndex])) { return; } } diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp index 111e4d7041..b960629f0e 100644 --- a/src/ai/ai_force.cpp +++ b/src/ai/ai_force.cpp @@ -241,23 +241,21 @@ void AiNewUnitTypeEquiv(const CUnitType &a, const CUnitType &b) ** Find All unittypes equivalent to a given one ** ** @param unittype the unittype to find equivalence for -** @param result int array which will hold the result. (Size UnitTypeMax+1) ** -** @return the number of unittype found +** @return the unittypes found */ -int AiFindUnitTypeEquiv(const CUnitType &unittype, int *result) +std::vector AiFindUnitTypeEquiv(const CUnitType &unittype) { const int search = UnitTypeEquivs[unittype.Slot]; - int count = 0; + std::vector result; for (int i = 0; i < UnitTypeMax + 1; ++i) { if (UnitTypeEquivs[i] == search) { // Found one - result[count] = i; - ++count; + result.push_back(i); } } - return count; + return result; } class UnitTypePrioritySorter_Decreasing @@ -271,30 +269,23 @@ class UnitTypePrioritySorter_Decreasing /** ** Find All unittypes equivalent to a given one, and which are available -** UnitType are returned in the preferred order (ie palladin >> knight...) +** UnitType are returned in the preferred order (ie paladin >> knight...) ** ** @param unittype The unittype to find equivalence for -** @param usableTypes int array which will hold the result. (Size UnitTypeMax+1) ** -** @return the number of unittype found +** @return the unittypes found */ -int AiFindAvailableUnitTypeEquiv(const CUnitType &unittype, int *usableTypes) +std::vector AiFindAvailableUnitTypeEquiv(const CUnitType &unittype) { // 1 - Find equivalents - int usableTypesCount = AiFindUnitTypeEquiv(unittype, usableTypes); + auto usableTypes = AiFindUnitTypeEquiv(unittype); // 2 - Remove unavailable unittypes - for (int i = 0; i < usableTypesCount;) { - if (!CheckDependByIdent(*AiPlayer->Player, UnitTypes[usableTypes[i]]->Ident)) { - // Not available, remove it - usableTypes[i] = usableTypes[usableTypesCount - 1]; - --usableTypesCount; - } else { - ++i; - } - } + ranges::erase_if(usableTypes, [&](int typeIndex) { + return !CheckDependByIdent(*AiPlayer->Player, UnitTypes[typeIndex]->Ident); + }); // 3 - Sort by level - std::sort(usableTypes, usableTypes + usableTypesCount, UnitTypePrioritySorter_Decreasing()); - return usableTypesCount; + ranges::sort(usableTypes, UnitTypePrioritySorter_Decreasing()); + return usableTypes; } /* =========================== FORCES ========================== */ diff --git a/src/ai/ai_local.h b/src/ai/ai_local.h index 9d7728b018..8514378407 100644 --- a/src/ai/ai_local.h +++ b/src/ai/ai_local.h @@ -406,10 +406,10 @@ extern void AiExplore(const Vec2i &pos, int exploreMask); extern void AiNewUnitTypeEquiv(const CUnitType &a, const CUnitType &b); /// Remove any equivalence between unittypes extern void AiResetUnitTypeEquiv(); -/// Finds all equivalents units to a given one -extern int AiFindUnitTypeEquiv(const CUnitType &type, int *result); +/// Finds all equivalents unittypes to a given one +extern std::vector AiFindUnitTypeEquiv(const CUnitType &type); /// Finds all available equivalents units to a given one, in the preferred order -extern int AiFindAvailableUnitTypeEquiv(const CUnitType &type, int *result); +extern std::vector AiFindAvailableUnitTypeEquiv(const CUnitType &type); extern std::array AiGetBuildRequestsCount(const PlayerAi &pai); extern void AiNewDepotRequest(CUnit &worker); diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp index 7521fea6be..2739f847eb 100644 --- a/src/ai/ai_resource.cpp +++ b/src/ai/ai_resource.cpp @@ -627,31 +627,22 @@ static bool AiTrainUnit(const CUnitType &type, CUnitType &what) static bool AiMakeUnit(CUnitType &typeToMake, const Vec2i &nearPos) { // Find equivalents unittypes. - int usableTypes[UnitTypeMax + 1]; - const int usableTypesCount = AiFindAvailableUnitTypeEquiv(typeToMake, usableTypes); + const auto usableTypes = AiFindAvailableUnitTypeEquiv(typeToMake); // Iterate them - for (int currentType = 0; currentType < usableTypesCount; ++currentType) { - CUnitType &type = *UnitTypes[usableTypes[currentType]]; - int n; - std::vector > *tablep; + for (int typeIndex : usableTypes) { + CUnitType &type = *UnitTypes[typeIndex]; // // Check if we have a place for building or a unit to build. // - if (type.Building) { - n = AiHelpers.Build().size(); - tablep = &AiHelpers.Build(); - } else { - n = AiHelpers.Train().size(); - tablep = &AiHelpers.Train(); - } - if (type.Slot > n) { // Oops not known. + const std::vector > &tablep = type.Building ? AiHelpers.Build() : AiHelpers.Train(); + if (type.Slot > tablep.size()) { // Oops not known. DebugPrint("%d: AiMakeUnit I: Nothing known about '%s'\n", AiPlayer->Player->Index, type.Ident.c_str()); continue; } - std::vector &table = (*tablep)[type.Slot]; + const std::vector &table = tablep[type.Slot]; if (table.empty()) { // Oops not known. DebugPrint("%d: AiMakeUnit II: Nothing known about '%s'\n", AiPlayer->Player->Index, @@ -660,7 +651,7 @@ static bool AiMakeUnit(CUnitType &typeToMake, const Vec2i &nearPos) } const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount; - for (CUnitType *unitType : table) { + for (const CUnitType *unitType : table) { // // The type for builder/trainer is available // From e3273e999adcc4d5c72c0645092ac1d288bde7d0 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 10:22:02 +0200 Subject: [PATCH 07/17] Replace `std::sort` by `ranges::sort` in include/unittype.h --- src/include/unittype.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/include/unittype.h b/src/include/unittype.h index b62ce32509..c15d7f582f 100644 --- a/src/include/unittype.h +++ b/src/include/unittype.h @@ -52,6 +52,7 @@ #include "luacallback.h" #include "missileconfig.h" #include "spells.h" +#include "util.h" #include "vec2i.h" #include @@ -748,7 +749,7 @@ class CUnitTypeVar void Init() { - std::sort(buildin, buildin + SIZE, DataKey::key_pred); + ranges::sort(buildin, DataKey::key_pred); } std::string_view operator[](int index) From 7f7da0d86b09ef58eb0dd8038bea12b4c4c5991d Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 10:23:51 +0200 Subject: [PATCH 08/17] Use ranges algorithm in spell/spell_spawnmissile.cpp --- src/spell/spell_spawnmissile.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/spell/spell_spawnmissile.cpp b/src/spell/spell_spawnmissile.cpp index 126ec03394..02f1c9cff6 100644 --- a/src/spell/spell_spawnmissile.cpp +++ b/src/spell/spell_spawnmissile.cpp @@ -197,18 +197,15 @@ int Spell_SpawnMissile::Cast(CUnit &caster, if (this->Missile->Class == MissileClass::DeathCoil) { const Vec2i offset(2, 2); std::vector table = Select(goalPos - offset, goalPos + offset); - int count = 0; - for (CUnit *unitPtr : table) { - CUnit &unit = *unitPtr; - - if (unit.Type->BoolFlag[ORGANIC_INDEX].value && unit.IsEnemy(caster)) { - table[count++] = &unit; - } - } - if (count > 0) { - std::sort(table.begin(), table.begin() + count, CompareUnitDistance(caster)); + ranges::erase_if(table, [&](const CUnit *unit) { + return !unit->Type->BoolFlag[ORGANIC_INDEX].value || !unit->IsEnemy(caster); + }); + if (!table.empty()) { + ranges::sort(table, CompareUnitDistance(caster)); int damageLeft = this->Damage; - for (std::vector::iterator it = table.begin(); it != table.begin() + count && damageLeft > 0; ++it) { + for (std::vector::iterator it = table.begin(); + it != table.end() && damageLeft > 0; + ++it) { CUnit &unit = **it; if (unit.IsAliveOnMap()) { const PixelPos startPos = EvaluateMissileLocation(this->StartPoint, caster, &unit, unit.tilePos); @@ -216,7 +213,7 @@ int Spell_SpawnMissile::Cast(CUnit &caster, ::Missile *missile = MakeMissile(*this->Missile, startPos, endPos); missile->TTL = this->TTL; missile->Delay = this->Delay; - if (it + 1 == table.begin() + count) { + if (it + 1 == table.end()) { missile->Damage = damageLeft; damageLeft = 0; } else { From 841fdf49d5ea468231c59c2592908f1c6c7dbbdb Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 11:37:41 +0200 Subject: [PATCH 09/17] Use `ranges::find` instead of manual loop in include/unittype.h --- src/include/unittype.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/include/unittype.h b/src/include/unittype.h index c15d7f582f..045262a511 100644 --- a/src/include/unittype.h +++ b/src/include/unittype.h @@ -754,15 +754,11 @@ class CUnitTypeVar std::string_view operator[](int index) { - for (unsigned int i = 0; i < SIZE; ++i) { - if (buildin[i].offset == index) { - return buildin[i].key; - } + if (auto it = ranges::find(buildin, index, &DataKey::offset); it != std::end(buildin)) { + return it->key; } - for (const auto &[key, value] : user) { - if (value == index) { - return key; - } + if (auto it = ranges::find(user, index, &std::pair::second); it != user.end()) { + return it->first; } return ""; // Not found } From 4f77310bdc9ea5cc1678974d8c271e7c4f8c3532 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 11:38:43 +0200 Subject: [PATCH 10/17] Use range loop in `MapFixWallNeighbors`. --- src/map/map_wall.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/map/map_wall.cpp b/src/map/map_wall.cpp index 436af976fb..1ea7a4ebc3 100644 --- a/src/map/map_wall.cpp +++ b/src/map/map_wall.cpp @@ -200,10 +200,8 @@ void MapFixWallTile(const Vec2i &pos) */ static void MapFixWallNeighbors(const Vec2i &pos) { - const Vec2i offset[] = {Vec2i(1, 0), Vec2i(-1, 0), Vec2i(0, 1), Vec2i(0, -1)}; - - for (unsigned int i = 0; i < sizeof(offset) / sizeof(*offset); ++i) { - MapFixWallTile(pos + offset[i]); + for (const Vec2i &offset : {Vec2i(1, 0), Vec2i(-1, 0), Vec2i(0, 1), Vec2i(0, -1)}) { + MapFixWallTile(pos + offset); } } From f1fd97a2866b52dfc00d86f2e0cf76d3ff668aef Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 11:40:59 +0200 Subject: [PATCH 11/17] Use for loop and ranges algorithm in ai/script_ai.cpp --- src/ai/script_ai.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/ai/script_ai.cpp b/src/ai/script_ai.cpp index d067deb851..89dd410b38 100644 --- a/src/ai/script_ai.cpp +++ b/src/ai/script_ai.cpp @@ -459,14 +459,8 @@ static void InsertUnitTypeRequests(CUnitType *type, int count) */ static AiRequestType *FindInUnitTypeRequests(const CUnitType *type) { - const size_t n = AiPlayer->UnitTypeRequests.size(); - - for (size_t i = 0; i < n; ++i) { - if (AiPlayer->UnitTypeRequests[i].Type == type) { - return &AiPlayer->UnitTypeRequests[i]; - } - } - return nullptr; + const auto it = ranges::find(AiPlayer->UnitTypeRequests, type, &AiRequestType::Type); + return it != AiPlayer->UnitTypeRequests.end() ? &*it : nullptr; } /** @@ -1521,22 +1515,19 @@ static int CclAiDump(lua_State *l) // // Requests // - size_t n = aip.Ai->UnitTypeRequests.size(); - printf("UnitTypeRequests(%u):\n", static_cast(n)); - for (size_t i = 0; i < n; ++i) { - printf("%s ", aip.Ai->UnitTypeRequests[i].Type->Ident.c_str()); + printf("UnitTypeRequests(%u):\n", static_cast(aip.Ai->UnitTypeRequests.size())); + for (const auto &requestType : aip.Ai->UnitTypeRequests) { + printf("%s ", requestType.Type->Ident.c_str()); } printf("\n"); - n = aip.Ai->UpgradeToRequests.size(); - printf("UpgradeToRequests(%u):\n", static_cast(n)); - for (size_t i = 0; i < n; ++i) { - printf("%s ", aip.Ai->UpgradeToRequests[i]->Ident.c_str()); + printf("UpgradeToRequests(%u):\n", static_cast(aip.Ai->UpgradeToRequests.size())); + for (const auto *unittype : aip.Ai->UpgradeToRequests) { + printf("%s ", unittype->Ident.c_str()); } printf("\n"); - n = aip.Ai->ResearchRequests.size(); - printf("ResearchRequests(%u):\n", static_cast(n)); - for (size_t i = 0; i < n; ++i) { - printf("%s ", aip.Ai->ResearchRequests[i]->Ident.c_str()); + printf("ResearchRequests(%u):\n", static_cast(aip.Ai->ResearchRequests.size())); + for (const auto *upgrade : aip.Ai->ResearchRequests) { + printf("%s ", upgrade->Ident.c_str()); } printf("\n"); From e7e499cd9f31905a2f96626fd3c1c4fb729ba8df Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 11:42:47 +0200 Subject: [PATCH 12/17] Use for loop and ranges algorithm in ai/ai_resource.cpp --- src/ai/ai_resource.cpp | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp index 2739f847eb..b7112a2c69 100644 --- a/src/ai/ai_resource.cpp +++ b/src/ai/ai_resource.cpp @@ -78,12 +78,9 @@ static bool AiMakeUnit(CUnitType &type, const Vec2i &nearPos); static int AiCheckCosts(const int (&costs)[MaxCosts]) { // FIXME: the used costs shouldn't be calculated here - int *used = AiPlayer->Used; - - for (int i = 1; i < MaxCosts; ++i) { - used[i] = 0; - } + int(&used)[MaxCosts] = AiPlayer->Used; + ranges::fill(used, 0); for (CUnit *unit : AiPlayer->Player->GetUnits()) { for (const auto &order : unit->Orders) { if (order->Action == UnitAction::Build) { @@ -362,15 +359,11 @@ void AiNewDepotRequest(CUnit &worker) // Count the already made build requests. const auto counter = AiGetBuildRequestsCount(*worker.Player->Ai); - const int n = AiHelpers.Depots()[resource - 1].size(); - - for (int i = 0; i < n; ++i) { - CUnitType &type = *AiHelpers.Depots()[resource - 1][i]; - - if (counter[type.Slot]) { // Already ordered. + for (CUnitType *type : AiHelpers.Depots()[resource - 1]) { + if (counter[type->Slot]) { // Already ordered. return; } - if (!AiRequestedTypeAllowed(*worker.Player, type)) { + if (!AiRequestedTypeAllowed(*worker.Player, *type)) { continue; } @@ -378,11 +371,11 @@ void AiNewDepotRequest(CUnit &worker) //int needmask = AiCheckUnitTypeCosts(type); int cost = 0; for (int c = 1; c < MaxCosts; ++c) { - cost += type.Stats[worker.Player->Index].Costs[c]; + cost += type->Stats[worker.Player->Index].Costs[c]; } if (best_type == nullptr || (cost < best_cost)) { - best_type = &type; + best_type = type; best_cost = cost; //best_mask = needmask; } @@ -510,9 +503,8 @@ static bool AiRequestSupply() int j = 0; const int n = AiHelpers.UnitLimit()[0].size(); - for (int i = 0; i < n; ++i) { - CUnitType &type = *AiHelpers.UnitLimit()[0][i]; - if (counter[type.Slot]) { // Already ordered. + for (CUnitType *type : AiHelpers.UnitLimit()[0]) { + if (counter[type->Slot]) { // Already ordered. #if defined(DEBUG) && defined(DebugRequestSupply) DebugPrint("%d: AiRequestSupply: Supply already build in %s\n", AiPlayer->Player->Index, type->Name.c_str()); @@ -520,21 +512,21 @@ static bool AiRequestSupply() return false; } - if (!AiRequestedTypeAllowed(*AiPlayer->Player, type)) { + if (!AiRequestedTypeAllowed(*AiPlayer->Player, *type)) { continue; } // // Check if resources available. // - cache[j].needmask = AiCheckUnitTypeCosts(type); + cache[j].needmask = AiCheckUnitTypeCosts(*type); for (int c = 1; c < MaxCosts; ++c) { - cache[j].unit_cost += type.Stats[AiPlayer->Player->Index].Costs[c]; + cache[j].unit_cost += type->Stats[AiPlayer->Player->Index].Costs[c]; } - cache[j].unit_cost += type.Stats[AiPlayer->Player->Index].Variables[SUPPLY_INDEX].Value - 1; - cache[j].unit_cost /= type.Stats[AiPlayer->Player->Index].Variables[SUPPLY_INDEX].Value; - cache[j++].type = &type; + cache[j].unit_cost += type->Stats[AiPlayer->Player->Index].Variables[SUPPLY_INDEX].Value - 1; + cache[j].unit_cost /= type->Stats[AiPlayer->Player->Index].Variables[SUPPLY_INDEX].Value; + cache[j++].type = type; Assert(j < 16); } From 3dcf9615d0ef9343f4830174ae528fa09474ecce Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 11:43:40 +0200 Subject: [PATCH 13/17] Use for-range in ai_plan.cpp --- src/ai/ai_plan.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ai/ai_plan.cpp b/src/ai/ai_plan.cpp index 80c778ce2d..5b0322ae50 100644 --- a/src/ai/ai_plan.cpp +++ b/src/ai/ai_plan.cpp @@ -400,11 +400,9 @@ bool AiForce::PlanAttack() // Verify we have enough transporter. // @note: Minimal check for unitType (flyers...) - for (unsigned int i = 0; i < Size(); ++i) { - CUnit &unit = *Units[i]; - - if (CanTransport(*transporter, unit)) { - totalBoardCapacity -= unit.Type->BoardSize; + for (const CUnit *unit : Units) { + if (CanTransport(*transporter, *unit)) { + totalBoardCapacity -= unit->Type->BoardSize; } } if (totalBoardCapacity < 0) { // Not enough transporter. From df4b6379a41a271d59a750fa28d171bf5a059999 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 11:47:01 +0200 Subject: [PATCH 14/17] Use for-range and ranges algorithm for ai/ai_force.cpp --- src/ai/ai_force.cpp | 79 ++++++++++++++------------------------------- src/include/util.h | 4 ++- 2 files changed, 28 insertions(+), 55 deletions(-) diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp index b960629f0e..a774dc2e8e 100644 --- a/src/ai/ai_force.cpp +++ b/src/ai/ai_force.cpp @@ -554,10 +554,10 @@ std::optional AiForceManager::GetForce(const CUnit &unit) for (unsigned int i = 0; i < forces.size(); ++i) { AiForce &force = forces[i]; - for (CUnit *aiunit : force.Units) { - if (UnitNumber(unit) == UnitNumber(*aiunit)) { - return i; - } + if (ranges::any_of(force.Units, [&](const CUnit *aiunit) { + return UnitNumber(unit) == UnitNumber(*aiunit); + })) { + return i; } } return std::nullopt; @@ -803,7 +803,6 @@ static void AiGroupAttackerForTransport(AiForce &aiForce) unsigned int nbToTransport = 0; unsigned int transporterIndex = 0; - bool forceIsReady = true; for (; transporterIndex < aiForce.Size(); ++transporterIndex) { const CUnit &unit = *aiForce.Units[transporterIndex]; @@ -817,21 +816,17 @@ static void AiGroupAttackerForTransport(AiForce &aiForce) aiForce.State = AiForceAttackingState::AttackingWithTransporter; return ; } - for (unsigned int i = 0; i < aiForce.Size(); ++i) { - const CUnit &unit = *aiForce.Units[i]; + const bool forceIsReady = ranges::none_of(aiForce.Units, [&](const CUnit *unit) { const CUnit &transporter = *aiForce.Units[transporterIndex]; - if (CanTransport(transporter, unit) && unit.Container == nullptr) { - forceIsReady = false; - break; - } - } + return CanTransport(transporter, *unit) && unit->Container == nullptr; + }); if (forceIsReady == true) { aiForce.State = AiForceAttackingState::AttackingWithTransporter; return ; } - for (unsigned int i = 0; i < aiForce.Size(); ++i) { - CUnit &unit = *aiForce.Units[i]; + for (CUnit *unitPtr : aiForce.Units) { + CUnit &unit = *unitPtr; CUnit &transporter = *aiForce.Units[transporterIndex]; if (unit.CurrentAction() == UnitAction::Board @@ -881,15 +876,7 @@ void AiForce::Update() } return; } - Attacking = false; - for (unsigned int i = 0; i < Size(); ++i) { - CUnit *aiunit = Units[i]; - - if (aiunit->Type->CanAttack) { - Attacking = true; - break; - } - } + Attacking = ranges::any_of(Units, [](const CUnit *aiunit) { return aiunit->Type->CanAttack; }); if (Attacking == false) { if (!Defending && State > AiForceAttackingState::Waiting) { DebugPrint("%d: Attack force #%lu has lost all agresive units, giving up\n", @@ -919,12 +906,10 @@ void AiForce::Update() // Move transporters to goalpos std::vector transporters; bool emptyTrans = true; - for (unsigned int i = 0; i != Size(); ++i) { - CUnit &aiunit = *Units[i]; - - if (aiunit.CanMove() && aiunit.Type->MaxOnBoard) { - transporters.push_back(&aiunit); - if (aiunit.BoardCount > 0) { + for (CUnit *aiunit : Units) { + if (aiunit->CanMove() && aiunit->Type->MaxOnBoard) { + transporters.push_back(aiunit); + if (aiunit->BoardCount > 0) { emptyTrans = false; } } @@ -950,13 +935,8 @@ void AiForce::Update() return; } CUnit *leader = nullptr; - for (unsigned int i = 0; i != Size(); ++i) { - CUnit &aiunit = *Units[i]; - - if (aiunit.IsAgressive()) { - leader = &aiunit; - break; - } + if (auto it = ranges::find_if(Units, &CUnit::IsAgressive); it != Units.end()) { + leader = *it; } const int thresholdDist = 5; // Hard coded value @@ -966,8 +946,8 @@ void AiForce::Update() int minDist = Units[0]->MapDistanceTo(this->GoalPos); int maxDist = minDist; - for (size_t i = 0; i != Size(); ++i) { - const int distance = Units[i]->MapDistanceTo(this->GoalPos); + for (const CUnit *unit : Units) { + const int distance = unit->MapDistanceTo(this->GoalPos); minDist = std::min(minDist, distance); maxDist = std::max(maxDist, distance); } @@ -1013,13 +993,7 @@ void AiForce::Update() } std::vector idleUnits; - for (unsigned int i = 0; i != Size(); ++i) { - CUnit &aiunit = *Units[i]; - - if (aiunit.IsIdle()) { - idleUnits.push_back(&aiunit); - } - } + ranges::copy_if(Units, std::back_inserter(idleUnits), &CUnit::IsIdle); if (idleUnits.empty()) { return; @@ -1109,8 +1083,8 @@ void AiForceManager::Update() force.ReturnToHome(); } else { // Check if some unit from force reached goal point - for (unsigned int i = 0; i != force.Size(); ++i) { - if (force.Units[i]->MapDistanceTo(force.GoalPos) <= nearDist) { + for (const CUnit *aiunit : force.Units) { + if (aiunit->MapDistanceTo(force.GoalPos) <= nearDist) { // Look if still enemies in attack range. const CUnit *dummy = nullptr; maxPathing--; @@ -1136,13 +1110,10 @@ void AiForceManager::Update() force.ReturnToHome(); } else { std::vector idleUnits; - for (unsigned int i = 0; i != force.Size(); ++i) { - CUnit &aiunit = *force.Units[i]; - - if (aiunit.IsIdle() && aiunit.IsAliveOnMap()) { - idleUnits.push_back(&aiunit); - } - } + ranges::copy_if( + force.Units, std::back_inserter(idleUnits), [](const CUnit *aiunit) { + return aiunit->IsIdle() && aiunit->IsAliveOnMap(); + }); for (unsigned int i = 0; i != idleUnits.size(); ++i) { CUnit *const unit = idleUnits[i]; diff --git a/src/include/util.h b/src/include/util.h index e434b7e7c6..a37755c7b2 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -295,7 +295,9 @@ namespace ranges template auto copy_if(const Range &range, OutputIt copy_to, UnaryPredicate pred) { - return std::copy_if(std::begin(range), std::end(range), copy_to, pred); + return std::copy_if(std::begin(range), std::end(range), copy_to, [&](const auto &elem) { + return std::invoke(std::forward(pred), elem); + }); } template From 1fe995418bb6481a09331d445a7571b407afba14 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 12:04:51 +0200 Subject: [PATCH 15/17] Use for-range in sound/unitsound.cpp --- src/sound/unitsound.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sound/unitsound.cpp b/src/sound/unitsound.cpp index f49ae45e13..da061cc477 100644 --- a/src/sound/unitsound.cpp +++ b/src/sound/unitsound.cpp @@ -109,16 +109,16 @@ static void MapAnimSounds(CUnitType &type) MapAnimSounds2(type.Animations->Attack); MapAnimSounds2(type.Animations->RangedAttack); MapAnimSounds2(type.Animations->SpellCast); - for (int i = 0; i <= ANIMATIONS_DEATHTYPES; ++i) { - MapAnimSounds2(type.Animations->Death[i]); + for (auto& soundConfig : type.Animations->Death) { + MapAnimSounds2(soundConfig); } MapAnimSounds2(type.Animations->Repair); MapAnimSounds2(type.Animations->Train); MapAnimSounds2(type.Animations->Research); MapAnimSounds2(type.Animations->Upgrade); MapAnimSounds2(type.Animations->Build); - for (int i = 0; i < MaxCosts; ++i) { - MapAnimSounds2(type.Animations->Harvest[i]); + for (auto& soundConfig : type.Animations->Harvest) { + MapAnimSounds2(soundConfig); } } @@ -133,8 +133,8 @@ void MapUnitSounds() return; } // Parse all units sounds. - for (std::vector::size_type i = 0; i < UnitTypes.size(); ++i) { - CUnitType &type = *UnitTypes[i]; + for (CUnitType *typePtr : UnitTypes) { + CUnitType &type = *typePtr; MapAnimSounds(type); @@ -146,15 +146,15 @@ void MapUnitSounds() type.MapSound.Ready.MapSound(); type.MapSound.Ready.SetSoundRange(INFINITE_SOUND_RANGE); type.MapSound.Repair.MapSound(); - for (int i = 0; i < MaxCosts; ++i) { - type.MapSound.Harvest[i].MapSound(); + for (auto &soundConfig : type.MapSound.Harvest) { + soundConfig.MapSound(); } type.MapSound.Help.MapSound(); type.MapSound.Help.SetSoundRange(INFINITE_SOUND_RANGE); type.MapSound.WorkComplete.MapSound(); - for (int i = 0; i <= ANIMATIONS_DEATHTYPES; ++i) { - type.MapSound.Dead[i].MapSound(); + for (auto &soundConfig : type.MapSound.Dead) { + soundConfig.MapSound(); } } } From 25b90df4730d7fe06b2255c40fc91f5174436071 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 12:05:46 +0200 Subject: [PATCH 16/17] Use for-range in map/script_tileset.cpp --- src/map/script_tileset.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/map/script_tileset.cpp b/src/map/script_tileset.cpp index 8584f0d6f2..8984eaf064 100644 --- a/src/map/script_tileset.cpp +++ b/src/map/script_tileset.cpp @@ -77,9 +77,9 @@ bool CTileset::ModifyFlag(std::string_view flagName, tile_flags *flag, const int {"non-mixing", MapFieldNonMixing} }; - for (unsigned int i = 0; i != sizeof(flags) / sizeof(*flags); ++i) { - if (flagName == flags[i].name) { - *flag |= flags[i].flag; + for (const auto& [name, tileFlag] : flags) { + if (flagName == name) { + *flag |= tileFlag; return true; } } @@ -93,9 +93,9 @@ bool CTileset::ModifyFlag(std::string_view flagName, tile_flags *flag, const int {"slow", 2}, {"slower", 3} }; - for (unsigned int i = 0; i != sizeof(speeds) / sizeof(*speeds); ++i) { - if (flagName == speeds[i].name) { - *flag = (*flag & ~MapFieldSpeedMask) | speeds[i].speed; + for (const auto& [name, speed] : speeds) { + if (flagName == name) { + *flag = (*flag & ~MapFieldSpeedMask) | speed; return true; } } From 5b8d532a61e7e7dc914fcdfddb63c4becf6d5232 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Thu, 19 Oct 2023 14:44:27 +0200 Subject: [PATCH 17/17] Fix gcc compilation. --- src/stratagus/selection.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/stratagus/selection.cpp b/src/stratagus/selection.cpp index 623caf6dfc..b736f2d9d3 100644 --- a/src/stratagus/selection.cpp +++ b/src/stratagus/selection.cpp @@ -623,7 +623,7 @@ static bool SelectOrganicUnitsInTable(std::vector &table, bool added_ta //Wyrmgus end return false; }); - table.resize(std::min(table.size(), MaxSelectable)); + table.resize(std::min(table.size(), MaxSelectable)); return !table.empty(); } @@ -819,7 +819,7 @@ int SelectGroundUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos //Wyrmgus end return false; }); - table.resize(std::min(table.size(), MaxSelectable)); + table.resize(std::min(table.size(), MaxSelectable)); if (!table.empty()) { ChangeSelectedUnits(&table[0], table.size()); } @@ -865,7 +865,7 @@ int SelectAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &co //Wyrmgus end return false; }); - table.resize(std::min(table.size(), MaxSelectable)); + table.resize(std::min(table.size(), MaxSelectable)); if (!table.empty()) { ChangeSelectedUnits(&table[0], table.size()); } @@ -931,7 +931,7 @@ int AddSelectedGroundUnitsInRectangle(const PixelPos &corner_topleft, const Pixe return false; }); - table.resize(std::min(table.size(), MaxSelectable)); + table.resize(std::min(table.size(), MaxSelectable)); // Add the units to selected. for (unsigned int i = 0; i < table.size() && Selected.size() < MaxSelectable; ++i) { @@ -996,7 +996,7 @@ int AddSelectedAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPo //Wyrmgus end return false; }); - table.resize(std::min(table.size(), MaxSelectable)); + table.resize(std::min(table.size(), MaxSelectable)); // Add the units to selected. for (unsigned int i = 0; i < table.size() && Selected.size() < MaxSelectable; ++i) {