From a778a07af20d9572da01fa70bbe450d9a041993a Mon Sep 17 00:00:00 2001 From: Spikeone Date: Sat, 19 Feb 2022 12:54:54 +0100 Subject: [PATCH 01/15] AI: do no longer treat inexhaustible granite mines like it was intended (inexhaustible = everywhere) --- libs/s25main/ai/aijh/AIPlayerJH.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libs/s25main/ai/aijh/AIPlayerJH.cpp b/libs/s25main/ai/aijh/AIPlayerJH.cpp index cd80887511..e110361365 100644 --- a/libs/s25main/ai/aijh/AIPlayerJH.cpp +++ b/libs/s25main/ai/aijh/AIPlayerJH.cpp @@ -977,13 +977,8 @@ MapPoint AIPlayerJH::FindPositionForBuildingAround(BuildingType type, const MapP foundPos = FindBestPosition(around, AIResource::Ironore, BuildingQuality::Mine, searchRadius); break; case BuildingType::GraniteMine: - if(!ggs.isEnabled( - AddonId::INEXHAUSTIBLE_GRANITEMINES)) // inexhaustible granite mines do not require granite - foundPos = FindBestPosition(around, AIResource::Granite, BuildingQuality::Mine, searchRadius); - else - foundPos = SimpleFindPosition(around, BuildingQuality::Mine, searchRadius); + foundPos = FindBestPosition(around, AIResource::Granite, BuildingQuality::Mine, searchRadius); break; - case BuildingType::Fishery: foundPos = FindBestPosition(around, AIResource::Fish, BUILDING_SIZE[type], searchRadius); if(foundPos.isValid() && !ValidFishInRange(foundPos)) From 088db978643369f8982dad6279066f330e42f802 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Sat, 19 Feb 2022 16:49:11 +0100 Subject: [PATCH 02/15] Addons: Add options for each mine type for changing the behavior --- libs/s25main/GlobalGameSettings.cpp | 4 + libs/s25main/addons/AddonMinesCoal.h | 27 +++++++ libs/s25main/addons/AddonMinesGold.h | 27 +++++++ libs/s25main/addons/AddonMinesGranite.h | 28 +++++++ libs/s25main/addons/AddonMinesIron.h | 27 +++++++ libs/s25main/addons/Addons.h | 7 +- libs/s25main/addons/const_addons.h | 5 ++ libs/s25main/buildings/nobUsual.h | 3 + libs/s25main/figures/nofMiner.cpp | 99 ++++++++++++++++++++++--- libs/s25main/figures/nofMiner.h | 3 +- libs/s25main/figures/nofWorkman.cpp | 12 ++- libs/s25main/figures/nofWorkman.h | 3 + 12 files changed, 233 insertions(+), 12 deletions(-) create mode 100644 libs/s25main/addons/AddonMinesCoal.h create mode 100644 libs/s25main/addons/AddonMinesGold.h create mode 100644 libs/s25main/addons/AddonMinesGranite.h create mode 100644 libs/s25main/addons/AddonMinesIron.h diff --git a/libs/s25main/GlobalGameSettings.cpp b/libs/s25main/GlobalGameSettings.cpp index b186bbff27..55a0978e63 100644 --- a/libs/s25main/GlobalGameSettings.cpp +++ b/libs/s25main/GlobalGameSettings.cpp @@ -66,6 +66,10 @@ void GlobalGameSettings::registerAllAddons() AddonBurnDuration, AddonCatapultGraphics, AddonChangeGoldDeposits, + AddonMinesGranite, + AddonMinesGold, + AddonMinesIron, + AddonMinesCoal, AddonCharburner, AddonCoinsCapturedBld, AddonCustomBuildSequence, diff --git a/libs/s25main/addons/AddonMinesCoal.h b/libs/s25main/addons/AddonMinesCoal.h new file mode 100644 index 0000000000..db3ab013fb --- /dev/null +++ b/libs/s25main/addons/AddonMinesCoal.h @@ -0,0 +1,27 @@ +// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "AddonList.h" +#include "mygettext/mygettext.h" + +class AddonMinesCoal : public AddonList +{ +public: + AddonMinesCoal() + : AddonList(AddonId::MINES_COAL, AddonGroup::Economy, _("Change coal mine behavior"), + _("This addon lets you control mining behavior.\n\n" + "No change: Original behavior\n" + "Settlers IV: Mines never deplete, but mining becomes less successfull\n" + "Inexhaustible: Mines never deplete\n" + "Everywhere: Mines never deplete, can mine everywhere"), + { + _("No change"), + _("Settlers IV"), + _("Inexhaustible"), + _("Everywhere"), + }) + {} +}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMinesGold.h b/libs/s25main/addons/AddonMinesGold.h new file mode 100644 index 0000000000..7a9b37f1de --- /dev/null +++ b/libs/s25main/addons/AddonMinesGold.h @@ -0,0 +1,27 @@ +// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "AddonList.h" +#include "mygettext/mygettext.h" + +class AddonMinesGold : public AddonList +{ +public: + AddonMinesGold() + : AddonList(AddonId::MINES_GOLD, AddonGroup::Economy, _("Change gold mine behavior"), + _("This addon lets you control mining behavior.\n\n" + "No change: Original behavior\n" + "Settlers IV: Mines never deplete, but mining becomes less successfull\n" + "Inexhaustible: Mines never deplete\n" + "Everywhere: Mines never deplete, can mine everywhere"), + { + _("No change"), + _("Settlers IV"), + _("Inexhaustible"), + _("Everywhere"), + }) + {} +}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMinesGranite.h b/libs/s25main/addons/AddonMinesGranite.h new file mode 100644 index 0000000000..a75d9396b2 --- /dev/null +++ b/libs/s25main/addons/AddonMinesGranite.h @@ -0,0 +1,28 @@ +// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "AddonList.h" +#include "mygettext/mygettext.h" + +class AddonMinesGranite : public AddonList +{ +public: + AddonMinesGranite() + : AddonList(AddonId::MINES_GRANITE, AddonGroup::Economy, + _("Change granite mine behavior"), + _("This addon lets you control mining behavior.\n\n" + "No change: Original behavior\n" + "Settlers IV: Mines never deplete, but mining becomes less successfull\n" + "Inexhaustible: Mines never deplete\n" + "Everywhere: Mines never deplete, can mine everywhere"), + { + _("No change"), + _("Settlers IV"), + _("Inexhaustible"), + _("Everywhere"), + }) + {} +}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMinesIron.h b/libs/s25main/addons/AddonMinesIron.h new file mode 100644 index 0000000000..057cf2fe22 --- /dev/null +++ b/libs/s25main/addons/AddonMinesIron.h @@ -0,0 +1,27 @@ +// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "AddonList.h" +#include "mygettext/mygettext.h" + +class AddonMinesIron : public AddonList +{ +public: + AddonMinesIron() + : AddonList(AddonId::MINES_IRON, AddonGroup::Economy, _("Change iron mine behavior"), + _("This addon lets you control mining behavior.\n\n" + "No change: Original behavior\n" + "Settlers IV: Mines never deplete, but mining becomes less successfull\n" + "Inexhaustible: Mines never deplete\n" + "Everywhere: Mines never deplete, can mine everywhere"), + { + _("No change"), + _("Settlers IV"), + _("Inexhaustible"), + _("Everywhere"), + }) + {} +}; \ No newline at end of file diff --git a/libs/s25main/addons/Addons.h b/libs/s25main/addons/Addons.h index 8ac5366105..917495affd 100644 --- a/libs/s25main/addons/Addons.h +++ b/libs/s25main/addons/Addons.h @@ -34,11 +34,16 @@ #include "addons/AddonToolOrdering.h" #include "addons/AddonInexhaustibleFish.h" -#include "addons/AddonInexhaustibleGraniteMines.h" #include "addons/AddonMaxRank.h" #include "addons/AddonMilitaryAid.h" #include "addons/AddonSeaAttack.h" +#include "addons/AddonInexhaustibleGraniteMines.h" +#include "addons/AddonMinesGranite.h" +#include "addons/AddonMinesGold.h" +#include "addons/AddonMinesIron.h" +#include "addons/AddonMinesCoal.h" + #include "addons/AddonBattlefieldPromotion.h" #include "addons/AddonBurnDuration.h" #include "addons/AddonHalfCostMilEquip.h" diff --git a/libs/s25main/addons/const_addons.h b/libs/s25main/addons/const_addons.h index 376d3aaec3..58bdb0fee0 100644 --- a/libs/s25main/addons/const_addons.h +++ b/libs/s25main/addons/const_addons.h @@ -55,6 +55,11 @@ ENUM_WITH_STRING(AddonId, LIMIT_CATAPULTS = 0x00000000, INEXHAUSTIBLE_MINES = 0x INEXHAUSTIBLE_GRANITEMINES = 0x00800000, + MINES_GRANITE = 0x00800001, + MINES_GOLD = 0x00800002, + MINES_IRON = 0x00800003, + MINES_COAL = 0x00800004, + MAX_RANK = 0x00900000, SEA_ATTACK = 0x00900001, INEXHAUSTIBLE_FISH = 0x00900002, MORE_ANIMALS = 0x00900003, BURN_DURATION = 0x00900004, NO_ALLIED_PUSH = 0x00900005, BATTLEFIELD_PROMOTION = 0x00900006, HALF_COST_MIL_EQUIP = 0x00900007, MILITARY_CONTROL = 0x00900008, diff --git a/libs/s25main/buildings/nobUsual.h b/libs/s25main/buildings/nobUsual.h index 5b7cf0da1a..93fe33e2c9 100644 --- a/libs/s25main/buildings/nobUsual.h +++ b/libs/s25main/buildings/nobUsual.h @@ -57,6 +57,9 @@ class nobUsual : public noBuilding /// Wird gerade gearbeitet oder nicht? bool is_working; + /// is this an empty cycle? (use wares but produce nothing) + bool is_emptyCycle; + ~nobUsual() override; void Serialize(SerializedGameData& sgd) const override; diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 912619b58a..0c2fc8ca81 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -11,6 +11,7 @@ #include "network/GameClient.h" #include "ogl/glArchivItem_Bitmap_Player.h" #include "world/GameWorld.h" +#include nofMiner::nofMiner(const MapPoint pos, const unsigned char player, nobUsual* workplace) : nofWorkman(Job::Miner, pos, player, workplace) @@ -71,20 +72,100 @@ helpers::OptionalEnum nofMiner::ProduceWare() bool nofMiner::AreWaresAvailable() const { + // FindPointWithResource triggeres outofresource message + if(GetAddonSetting() == 3) + return true; + return nofWorkman::AreWaresAvailable() && FindPointWithResource(GetRequiredResType()).isValid(); } -bool nofMiner::StartWorking() +unsigned int nofMiner::GetAddonSetting() const { - MapPoint resPt = FindPointWithResource(GetRequiredResType()); - if(!resPt.isValid()) - return false; const GlobalGameSettings& settings = world->GetGGS(); - bool inexhaustibleRes = settings.isEnabled(AddonId::INEXHAUSTIBLE_MINES) - || (workplace->GetBuildingType() == BuildingType::GraniteMine - && settings.isEnabled(AddonId::INEXHAUSTIBLE_GRANITEMINES)); - if(!inexhaustibleRes) - world->ReduceResource(resPt); + + switch(workplace->GetBuildingType()) + { + case BuildingType::GoldMine: return settings.getSelection(AddonId::MINES_GOLD); + case BuildingType::IronMine: return settings.getSelection(AddonId::MINES_IRON); + case BuildingType::CoalMine: return settings.getSelection(AddonId::MINES_COAL); + case BuildingType::GraniteMine: return settings.getSelection(AddonId::MINES_GRANITE); + default: return 0; + } +} + +bool nofMiner::StartWorking() +{ + workplace->is_emptyCycle = false; + + // needs to have at least one resource spot + // 0 = is exhaustible + // 1 = settlers IV like + // 2 = inexhaustible + // 3 = everywhere + unsigned int addonSettings = GetAddonSetting(); + + switch (addonSettings) + { + case 1: // settlers IV style + { + int sumResAmount = 0; + MapPoint useResPt; + + std::vector resPts = FindAllPointsWithResource(GetRequiredResType()); + + // iterate over all points + for each(MapPoint curPt in resPts) + { + // calculate the absolute amount of resource beneath + uint8_t resAmount = world->GetNode(curPt).resources.getAmount(); + sumResAmount += resAmount; + + // if there is one with more than 1 quantity, keep it (for reducing) + if(resAmount > 1 && !useResPt.isValid()) + useResPt = curPt; + } + + // no resources left (mine was built on invalid spot) + if(sumResAmount == 0) + return false; + + // 19 = amount of nodes a mine can reach + // 7 = maximum resource amount a node possibly has + if(RANDOM.Rand(RANDOM_CONTEXT(), 19 * 7) > sumResAmount) + { + // failed, use food and start working - but produce nothing + workplace->is_emptyCycle = true; + } else + { + // if success, use 1 quantity if any + if(!useResPt.isValid()) + world->ReduceResource(useResPt); + } + } + break; + case 2: // inexhaustible + { + MapPoint resPt = FindPointWithResource(GetRequiredResType()); + if(!resPt.isValid()) + return false; + } + break; + case 3: // inexhaustible, everywhere + { + } + break; + case 0: // original behavior + default: + { + MapPoint resPt = FindPointWithResource(GetRequiredResType()); + if(!resPt.isValid()) + return false; + + world->ReduceResource(resPt); + } + break; + } + return nofWorkman::StartWorking(); } diff --git a/libs/s25main/figures/nofMiner.h b/libs/s25main/figures/nofMiner.h index c3fdc810ad..6241d26f80 100644 --- a/libs/s25main/figures/nofMiner.h +++ b/libs/s25main/figures/nofMiner.h @@ -9,7 +9,7 @@ class SerializedGameData; class nobUsual; -/// Klasse für den Schreiner +/// Klasse für den Miner class nofMiner : public nofWorkman { protected: @@ -23,6 +23,7 @@ class nofMiner : public nofWorkman bool AreWaresAvailable() const override; bool StartWorking() override; ResourceType GetRequiredResType() const; + unsigned int GetAddonSetting() const; public: nofMiner(MapPoint pos, unsigned char player, nobUsual* workplace); diff --git a/libs/s25main/figures/nofWorkman.cpp b/libs/s25main/figures/nofWorkman.cpp index 61f7a8a2f9..c3f37e1da5 100644 --- a/libs/s25main/figures/nofWorkman.cpp +++ b/libs/s25main/figures/nofWorkman.cpp @@ -55,7 +55,7 @@ void nofWorkman::HandleStateWaiting2() { current_ev = nullptr; // Ware erzeugen... (noch nicht "richtig"!, sondern nur viruell erstmal) - if(!(ware = ProduceWare()).has_value()) + if(!(ware = ProduceWare()).has_value() || workplace->is_emptyCycle) { // Soll keine erzeugt werden --> wieder anfangen zu arbeiten TryToWork(); @@ -110,3 +110,13 @@ MapPoint nofWorkman::FindPointWithResource(ResourceType type) const return MapPoint::Invalid(); } + +std::vector nofWorkman::FindAllPointsWithResource(ResourceType type) const +{ + // int maxResults = (int)((MINER_RADIUS * MINER_RADIUS + MINER_RADIUS) * 3u + 1u); + + const std::vector pts = + world->GetMatchingPointsInRadius<19>(pos, MINER_RADIUS, NodeHasResource(*world, type), true); + + return pts; +} \ No newline at end of file diff --git a/libs/s25main/figures/nofWorkman.h b/libs/s25main/figures/nofWorkman.h index 9621d2f072..d2a8499a4b 100644 --- a/libs/s25main/figures/nofWorkman.h +++ b/libs/s25main/figures/nofWorkman.h @@ -8,6 +8,7 @@ #include "nofBuildingWorker.h" #include "gameTypes/GoodTypes.h" #include "gameTypes/Resource.h" +#include class SerializedGameData; class nobBaseWarehouse; class nobUsual; @@ -38,6 +39,8 @@ class nofWorkman : public nofBuildingWorker /// Looks for a point with a given resource on the node MapPoint FindPointWithResource(ResourceType type) const; + /// Looks for all points with a given resource on the node + std::vector FindAllPointsWithResource(ResourceType type) const; public: /// Going to workplace From 174c99bf1f7605ee84cae0ab57a41bb4cc3c8377 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 21 Feb 2022 09:46:40 +0100 Subject: [PATCH 03/15] use one base class for mining overhaul addons --- libs/s25main/GlobalGameSettings.cpp | 8 ++-- libs/s25main/addons/AddonMinesCoal.h | 27 ------------ libs/s25main/addons/AddonMinesGold.h | 27 ------------ libs/s25main/addons/AddonMinesGranite.h | 28 ------------ libs/s25main/addons/AddonMinesIron.h | 27 ------------ libs/s25main/addons/AddonMiningOverhaul.h | 52 +++++++++++++++++++++++ libs/s25main/addons/Addons.h | 5 +-- libs/s25main/addons/const_addons.h | 6 +-- libs/s25main/figures/nofMiner.cpp | 9 ++-- 9 files changed, 64 insertions(+), 125 deletions(-) delete mode 100644 libs/s25main/addons/AddonMinesCoal.h delete mode 100644 libs/s25main/addons/AddonMinesGold.h delete mode 100644 libs/s25main/addons/AddonMinesGranite.h delete mode 100644 libs/s25main/addons/AddonMinesIron.h create mode 100644 libs/s25main/addons/AddonMiningOverhaul.h diff --git a/libs/s25main/GlobalGameSettings.cpp b/libs/s25main/GlobalGameSettings.cpp index 55a0978e63..96631342d3 100644 --- a/libs/s25main/GlobalGameSettings.cpp +++ b/libs/s25main/GlobalGameSettings.cpp @@ -66,10 +66,6 @@ void GlobalGameSettings::registerAllAddons() AddonBurnDuration, AddonCatapultGraphics, AddonChangeGoldDeposits, - AddonMinesGranite, - AddonMinesGold, - AddonMinesIron, - AddonMinesCoal, AddonCharburner, AddonCoinsCapturedBld, AddonCustomBuildSequence, @@ -92,6 +88,10 @@ void GlobalGameSettings::registerAllAddons() AddonMilitaryAid, AddonMilitaryControl, AddonMilitaryHitpoints, + AddonMiningOverhaulCoal, + AddonMiningOverhaulGold, + AddonMiningOverhaulGranite, + AddonMiningOverhaulIron, AddonMoreAnimals, AddonNoAlliedPush, AddonNoCoinsDefault, diff --git a/libs/s25main/addons/AddonMinesCoal.h b/libs/s25main/addons/AddonMinesCoal.h deleted file mode 100644 index db3ab013fb..0000000000 --- a/libs/s25main/addons/AddonMinesCoal.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) -// -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "AddonList.h" -#include "mygettext/mygettext.h" - -class AddonMinesCoal : public AddonList -{ -public: - AddonMinesCoal() - : AddonList(AddonId::MINES_COAL, AddonGroup::Economy, _("Change coal mine behavior"), - _("This addon lets you control mining behavior.\n\n" - "No change: Original behavior\n" - "Settlers IV: Mines never deplete, but mining becomes less successfull\n" - "Inexhaustible: Mines never deplete\n" - "Everywhere: Mines never deplete, can mine everywhere"), - { - _("No change"), - _("Settlers IV"), - _("Inexhaustible"), - _("Everywhere"), - }) - {} -}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMinesGold.h b/libs/s25main/addons/AddonMinesGold.h deleted file mode 100644 index 7a9b37f1de..0000000000 --- a/libs/s25main/addons/AddonMinesGold.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) -// -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "AddonList.h" -#include "mygettext/mygettext.h" - -class AddonMinesGold : public AddonList -{ -public: - AddonMinesGold() - : AddonList(AddonId::MINES_GOLD, AddonGroup::Economy, _("Change gold mine behavior"), - _("This addon lets you control mining behavior.\n\n" - "No change: Original behavior\n" - "Settlers IV: Mines never deplete, but mining becomes less successfull\n" - "Inexhaustible: Mines never deplete\n" - "Everywhere: Mines never deplete, can mine everywhere"), - { - _("No change"), - _("Settlers IV"), - _("Inexhaustible"), - _("Everywhere"), - }) - {} -}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMinesGranite.h b/libs/s25main/addons/AddonMinesGranite.h deleted file mode 100644 index a75d9396b2..0000000000 --- a/libs/s25main/addons/AddonMinesGranite.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) -// -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "AddonList.h" -#include "mygettext/mygettext.h" - -class AddonMinesGranite : public AddonList -{ -public: - AddonMinesGranite() - : AddonList(AddonId::MINES_GRANITE, AddonGroup::Economy, - _("Change granite mine behavior"), - _("This addon lets you control mining behavior.\n\n" - "No change: Original behavior\n" - "Settlers IV: Mines never deplete, but mining becomes less successfull\n" - "Inexhaustible: Mines never deplete\n" - "Everywhere: Mines never deplete, can mine everywhere"), - { - _("No change"), - _("Settlers IV"), - _("Inexhaustible"), - _("Everywhere"), - }) - {} -}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMinesIron.h b/libs/s25main/addons/AddonMinesIron.h deleted file mode 100644 index 057cf2fe22..0000000000 --- a/libs/s25main/addons/AddonMinesIron.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) -// -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "AddonList.h" -#include "mygettext/mygettext.h" - -class AddonMinesIron : public AddonList -{ -public: - AddonMinesIron() - : AddonList(AddonId::MINES_IRON, AddonGroup::Economy, _("Change iron mine behavior"), - _("This addon lets you control mining behavior.\n\n" - "No change: Original behavior\n" - "Settlers IV: Mines never deplete, but mining becomes less successfull\n" - "Inexhaustible: Mines never deplete\n" - "Everywhere: Mines never deplete, can mine everywhere"), - { - _("No change"), - _("Settlers IV"), - _("Inexhaustible"), - _("Everywhere"), - }) - {} -}; \ No newline at end of file diff --git a/libs/s25main/addons/AddonMiningOverhaul.h b/libs/s25main/addons/AddonMiningOverhaul.h new file mode 100644 index 0000000000..d07b974b6a --- /dev/null +++ b/libs/s25main/addons/AddonMiningOverhaul.h @@ -0,0 +1,52 @@ +// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "AddonList.h" +#include "mygettext/mygettext.h" + +class AddonMiningOverhaulBase : public AddonList +{ +protected: + AddonMiningOverhaulBase(AddonId addonId, const std::string& addonName) + : AddonList(addonId, AddonGroup::Economy, addonName, + _("This addon lets you control mining behavior.\n\n" + "No change: Original behavior\n" + "Settlers IV: Mines never deplete. Range is decreased to 1. Chance for production depends on " + "resource amount in range.\n" + "Inexhaustible: Mines never deplete\n" + "Everywhere: Mines never deplete, can mine everywhere"), + { + _("No change"), + _("Settlers IV"), + _("Inexhaustible"), + _("Everywhere"), + }) + {} +}; + +class AddonMiningOverhaulCoal : public AddonMiningOverhaulBase +{ +public: + AddonMiningOverhaulCoal() : AddonMiningOverhaulBase(AddonId::MINING_OVERHAUL_COAL, _("Mining overhaul: Coal")) {} +}; + +class AddonMiningOverhaulGold : public AddonMiningOverhaulBase +{ +public: + AddonMiningOverhaulGold() : AddonMiningOverhaulBase(AddonId::MINING_OVERHAUL_GOLD, _("Mining overhaul: Gold")) {} +}; + +class AddonMiningOverhaulGranite : public AddonMiningOverhaulBase +{ +public: + AddonMiningOverhaulGranite() : AddonMiningOverhaulBase(AddonId::MINING_OVERHAUL_GRANITE, _("Mining overhaul: Granite")) {} +}; + +class AddonMiningOverhaulIron : public AddonMiningOverhaulBase +{ +public: + AddonMiningOverhaulIron() : AddonMiningOverhaulBase(AddonId::MINING_OVERHAUL_IRON, _("Mining overhaul: Iron")) {} +}; \ No newline at end of file diff --git a/libs/s25main/addons/Addons.h b/libs/s25main/addons/Addons.h index 917495affd..fe7c075630 100644 --- a/libs/s25main/addons/Addons.h +++ b/libs/s25main/addons/Addons.h @@ -39,10 +39,7 @@ #include "addons/AddonSeaAttack.h" #include "addons/AddonInexhaustibleGraniteMines.h" -#include "addons/AddonMinesGranite.h" -#include "addons/AddonMinesGold.h" -#include "addons/AddonMinesIron.h" -#include "addons/AddonMinesCoal.h" +#include "addons/AddonMiningOverhaul.h" #include "addons/AddonBattlefieldPromotion.h" #include "addons/AddonBurnDuration.h" diff --git a/libs/s25main/addons/const_addons.h b/libs/s25main/addons/const_addons.h index 58bdb0fee0..55f66521a9 100644 --- a/libs/s25main/addons/const_addons.h +++ b/libs/s25main/addons/const_addons.h @@ -55,10 +55,8 @@ ENUM_WITH_STRING(AddonId, LIMIT_CATAPULTS = 0x00000000, INEXHAUSTIBLE_MINES = 0x INEXHAUSTIBLE_GRANITEMINES = 0x00800000, - MINES_GRANITE = 0x00800001, - MINES_GOLD = 0x00800002, - MINES_IRON = 0x00800003, - MINES_COAL = 0x00800004, + MINING_OVERHAUL_COAL = 0x00800001, MINING_OVERHAUL_GOLD = 0x00800002, + MINING_OVERHAUL_GRANITE = 0x00800003, MINING_OVERHAUL_IRON = 0x00800004, MAX_RANK = 0x00900000, SEA_ATTACK = 0x00900001, INEXHAUSTIBLE_FISH = 0x00900002, MORE_ANIMALS = 0x00900003, BURN_DURATION = 0x00900004, NO_ALLIED_PUSH = 0x00900005, diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 0c2fc8ca81..86fb5a682b 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -85,10 +85,10 @@ unsigned int nofMiner::GetAddonSetting() const switch(workplace->GetBuildingType()) { - case BuildingType::GoldMine: return settings.getSelection(AddonId::MINES_GOLD); - case BuildingType::IronMine: return settings.getSelection(AddonId::MINES_IRON); - case BuildingType::CoalMine: return settings.getSelection(AddonId::MINES_COAL); - case BuildingType::GraniteMine: return settings.getSelection(AddonId::MINES_GRANITE); + case BuildingType::GoldMine: return settings.getSelection(AddonId::MINING_OVERHAUL_GOLD); + case BuildingType::IronMine: return settings.getSelection(AddonId::MINING_OVERHAUL_IRON); + case BuildingType::CoalMine: return settings.getSelection(AddonId::MINING_OVERHAUL_COAL); + case BuildingType::GraniteMine: return settings.getSelection(AddonId::MINING_OVERHAUL_GRANITE); default: return 0; } } @@ -135,6 +135,7 @@ bool nofMiner::StartWorking() { // failed, use food and start working - but produce nothing workplace->is_emptyCycle = true; + //ProduceWare = boost::none; } else { // if success, use 1 quantity if any From 33bd9ab777d20e73e5304bb92af170bb2b9b76fe Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 21 Feb 2022 10:02:42 +0100 Subject: [PATCH 04/15] use enum --- libs/s25main/addons/AddonMiningOverhaul.h | 8 +++++ libs/s25main/figures/nofMiner.cpp | 39 ++++++++++------------- libs/s25main/figures/nofMiner.h | 2 +- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/libs/s25main/addons/AddonMiningOverhaul.h b/libs/s25main/addons/AddonMiningOverhaul.h index d07b974b6a..3be4febc16 100644 --- a/libs/s25main/addons/AddonMiningOverhaul.h +++ b/libs/s25main/addons/AddonMiningOverhaul.h @@ -7,6 +7,14 @@ #include "AddonList.h" #include "mygettext/mygettext.h" +enum class MiningBehavior +{ + Normal, + S4Like, + Inexhaustible, + AlwaysAvailable +}; + class AddonMiningOverhaulBase : public AddonList { protected: diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 86fb5a682b..c8bbcbcf87 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -12,6 +12,7 @@ #include "ogl/glArchivItem_Bitmap_Player.h" #include "world/GameWorld.h" #include +#include nofMiner::nofMiner(const MapPoint pos, const unsigned char player, nobUsual* workplace) : nofWorkman(Job::Miner, pos, player, workplace) @@ -72,24 +73,26 @@ helpers::OptionalEnum nofMiner::ProduceWare() bool nofMiner::AreWaresAvailable() const { - // FindPointWithResource triggeres outofresource message - if(GetAddonSetting() == 3) + if(!nofWorkman::AreWaresAvailable()) + return false; + + if(GetMiningBehavior() == MiningBehavior::AlwaysAvailable) return true; - return nofWorkman::AreWaresAvailable() && FindPointWithResource(GetRequiredResType()).isValid(); + return FindPointWithResource(GetRequiredResType()).isValid(); } -unsigned int nofMiner::GetAddonSetting() const +MiningBehavior nofMiner::GetMiningBehavior() const { const GlobalGameSettings& settings = world->GetGGS(); switch(workplace->GetBuildingType()) { - case BuildingType::GoldMine: return settings.getSelection(AddonId::MINING_OVERHAUL_GOLD); - case BuildingType::IronMine: return settings.getSelection(AddonId::MINING_OVERHAUL_IRON); - case BuildingType::CoalMine: return settings.getSelection(AddonId::MINING_OVERHAUL_COAL); - case BuildingType::GraniteMine: return settings.getSelection(AddonId::MINING_OVERHAUL_GRANITE); - default: return 0; + case BuildingType::GoldMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_GOLD); + case BuildingType::IronMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_IRON); + case BuildingType::CoalMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_COAL); + case BuildingType::GraniteMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_GRANITE); + default: return MiningBehavior::Normal; } } @@ -97,16 +100,11 @@ bool nofMiner::StartWorking() { workplace->is_emptyCycle = false; - // needs to have at least one resource spot - // 0 = is exhaustible - // 1 = settlers IV like - // 2 = inexhaustible - // 3 = everywhere - unsigned int addonSettings = GetAddonSetting(); + MiningBehavior addonSettings = GetMiningBehavior(); switch (addonSettings) { - case 1: // settlers IV style + case MiningBehavior::S4Like: { int sumResAmount = 0; MapPoint useResPt; @@ -144,18 +142,15 @@ bool nofMiner::StartWorking() } } break; - case 2: // inexhaustible + case MiningBehavior::Inexhaustible: { MapPoint resPt = FindPointWithResource(GetRequiredResType()); if(!resPt.isValid()) return false; } break; - case 3: // inexhaustible, everywhere - { - } - break; - case 0: // original behavior + case MiningBehavior::AlwaysAvailable: break; + case MiningBehavior::Normal: default: { MapPoint resPt = FindPointWithResource(GetRequiredResType()); diff --git a/libs/s25main/figures/nofMiner.h b/libs/s25main/figures/nofMiner.h index 6241d26f80..acd64fce81 100644 --- a/libs/s25main/figures/nofMiner.h +++ b/libs/s25main/figures/nofMiner.h @@ -23,7 +23,7 @@ class nofMiner : public nofWorkman bool AreWaresAvailable() const override; bool StartWorking() override; ResourceType GetRequiredResType() const; - unsigned int GetAddonSetting() const; + MiningBehavior GetMiningBehavior() const; public: nofMiner(MapPoint pos, unsigned char player, nobUsual* workplace); From 3c205866ede7b8fbd4395831965e76565a710a33 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 21 Feb 2022 10:31:27 +0100 Subject: [PATCH 05/15] fixup local build failing due to includes, remove workplace changes --- libs/s25main/buildings/nobUsual.h | 3 --- libs/s25main/figures/nofMiner.cpp | 8 ++++---- libs/s25main/figures/nofMiner.h | 4 +++- libs/s25main/figures/nofWorkman.cpp | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/libs/s25main/buildings/nobUsual.h b/libs/s25main/buildings/nobUsual.h index 93fe33e2c9..5b7cf0da1a 100644 --- a/libs/s25main/buildings/nobUsual.h +++ b/libs/s25main/buildings/nobUsual.h @@ -57,9 +57,6 @@ class nobUsual : public noBuilding /// Wird gerade gearbeitet oder nicht? bool is_working; - /// is this an empty cycle? (use wares but produce nothing) - bool is_emptyCycle; - ~nobUsual() override; void Serialize(SerializedGameData& sgd) const override; diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index c8bbcbcf87..97ceb78f3b 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -12,12 +12,12 @@ #include "ogl/glArchivItem_Bitmap_Player.h" #include "world/GameWorld.h" #include -#include nofMiner::nofMiner(const MapPoint pos, const unsigned char player, nobUsual* workplace) - : nofWorkman(Job::Miner, pos, player, workplace) + : nofWorkman(Job::Miner, pos, player, workplace), isAlteredWorkcycle(false) {} +// TODO: need to look into saving/loading to correctly load the work cycle nofMiner::nofMiner(SerializedGameData& sgd, const unsigned obj_id) : nofWorkman(sgd, obj_id) {} void nofMiner::DrawWorking(DrawPoint drawPt) @@ -98,7 +98,7 @@ MiningBehavior nofMiner::GetMiningBehavior() const bool nofMiner::StartWorking() { - workplace->is_emptyCycle = false; + isAlteredWorkcycle = false; MiningBehavior addonSettings = GetMiningBehavior(); @@ -132,7 +132,7 @@ bool nofMiner::StartWorking() if(RANDOM.Rand(RANDOM_CONTEXT(), 19 * 7) > sumResAmount) { // failed, use food and start working - but produce nothing - workplace->is_emptyCycle = true; + isAlteredWorkcycle = true; //ProduceWare = boost::none; } else { diff --git a/libs/s25main/figures/nofMiner.h b/libs/s25main/figures/nofMiner.h index acd64fce81..4056569ab1 100644 --- a/libs/s25main/figures/nofMiner.h +++ b/libs/s25main/figures/nofMiner.h @@ -5,11 +5,11 @@ #pragma once #include "nofWorkman.h" +#include "addons/AddonMiningOverhaul.h" class SerializedGameData; class nobUsual; -/// Klasse für den Miner class nofMiner : public nofWorkman { protected: @@ -19,6 +19,8 @@ class nofMiner : public nofWorkman unsigned short GetCarryID() const override; /// Der Arbeiter erzeugt eine Ware helpers::OptionalEnum ProduceWare() override; + /// alter workcycle (addon) + bool isAlteredWorkcycle; bool AreWaresAvailable() const override; bool StartWorking() override; diff --git a/libs/s25main/figures/nofWorkman.cpp b/libs/s25main/figures/nofWorkman.cpp index c3f37e1da5..8c28a34e44 100644 --- a/libs/s25main/figures/nofWorkman.cpp +++ b/libs/s25main/figures/nofWorkman.cpp @@ -55,7 +55,7 @@ void nofWorkman::HandleStateWaiting2() { current_ev = nullptr; // Ware erzeugen... (noch nicht "richtig"!, sondern nur viruell erstmal) - if(!(ware = ProduceWare()).has_value() || workplace->is_emptyCycle) + if(!(ware = ProduceWare()).has_value()) { // Soll keine erzeugt werden --> wieder anfangen zu arbeiten TryToWork(); From 40a9160a19046a284e4a468e994584c985b8850f Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 21 Feb 2022 11:25:21 +0100 Subject: [PATCH 06/15] rework coding for settlers iv like mining, remove some magic numbers --- libs/s25main/figures/nofMiner.cpp | 58 ++++++++++++++++------------- libs/s25main/figures/nofMiner.h | 1 + libs/s25main/figures/nofWorkman.cpp | 17 +++------ libs/s25main/figures/nofWorkman.h | 3 +- libs/s25main/gameData/GameConsts.h | 4 ++ libs/s25main/world/MapBase.cpp | 6 +++ libs/s25main/world/MapBase.h | 5 +-- 7 files changed, 52 insertions(+), 42 deletions(-) diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 97ceb78f3b..d4458987cf 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -62,6 +62,9 @@ unsigned short nofMiner::GetCarryID() const helpers::OptionalEnum nofMiner::ProduceWare() { + if(isAlteredWorkcycle) + return boost::none; + switch(workplace->GetBuildingType()) { case BuildingType::GoldMine: return GoodType::Gold; @@ -76,10 +79,16 @@ bool nofMiner::AreWaresAvailable() const if(!nofWorkman::AreWaresAvailable()) return false; - if(GetMiningBehavior() == MiningBehavior::AlwaysAvailable) + const MiningBehavior addonSetting = GetMiningBehavior(); + + if(addonSetting == MiningBehavior::AlwaysAvailable) return true; - return FindPointWithResource(GetRequiredResType()).isValid(); + // TODO: Skip this check if siv like mines and worked at least once? + if(addonSetting == MiningBehavior::S4Like) + return FindPointWithResource(GetRequiredResType(), MINER_RADIUS_SETTLERSIV).isValid(); + else + return FindPointWithResource(GetRequiredResType()).isValid(); } MiningBehavior nofMiner::GetMiningBehavior() const @@ -107,44 +116,43 @@ bool nofMiner::StartWorking() case MiningBehavior::S4Like: { int sumResAmount = 0; - MapPoint useResPt; - std::vector resPts = FindAllPointsWithResource(GetRequiredResType()); + MapPoint nonMinumResPt; - // iterate over all points - for each(MapPoint curPt in resPts) + const std::vector reachablePts = + world->GetPointsInRadiusWithCenter(workplace->GetPos(), MINER_RADIUS_SETTLERSIV); + + for(const MapPoint curPt : reachablePts) { - // calculate the absolute amount of resource beneath - uint8_t resAmount = world->GetNode(curPt).resources.getAmount(); + const Resource resPt = world->GetNode(curPt).resources; + + if(resPt.getType() != GetRequiredResType()) + continue; + + const auto resAmount = resPt.getAmount(); + sumResAmount += resAmount; - // if there is one with more than 1 quantity, keep it (for reducing) - if(resAmount > 1 && !useResPt.isValid()) - useResPt = curPt; + if(resAmount > 1u && !nonMinumResPt.isValid()) + nonMinumResPt = curPt; } - // no resources left (mine was built on invalid spot) - if(sumResAmount == 0) - return false; - - // 19 = amount of nodes a mine can reach - // 7 = maximum resource amount a node possibly has - if(RANDOM.Rand(RANDOM_CONTEXT(), 19 * 7) > sumResAmount) + // depending on remaining resources, roll if this workcycle needs to be altered or not + if(RANDOM_RAND(world->numPointsRadius(MINER_RADIUS_SETTLERSIV, true) * MINER_MAX_QUANTITY) + > sumResAmount) { - // failed, use food and start working - but produce nothing isAlteredWorkcycle = true; - //ProduceWare = boost::none; } else { - // if success, use 1 quantity if any - if(!useResPt.isValid()) - world->ReduceResource(useResPt); + if(nonMinumResPt.isValid()) + world->ReduceResource(nonMinumResPt); } } break; + // TODO: Is this required? FindPointWithResource checks if there is at least one case MiningBehavior::Inexhaustible: { - MapPoint resPt = FindPointWithResource(GetRequiredResType()); + const MapPoint resPt = FindPointWithResource(GetRequiredResType()); if(!resPt.isValid()) return false; } @@ -153,7 +161,7 @@ bool nofMiner::StartWorking() case MiningBehavior::Normal: default: { - MapPoint resPt = FindPointWithResource(GetRequiredResType()); + const MapPoint resPt = FindPointWithResource(GetRequiredResType()); if(!resPt.isValid()) return false; diff --git a/libs/s25main/figures/nofMiner.h b/libs/s25main/figures/nofMiner.h index 4056569ab1..bddc2113b7 100644 --- a/libs/s25main/figures/nofMiner.h +++ b/libs/s25main/figures/nofMiner.h @@ -6,6 +6,7 @@ #include "nofWorkman.h" #include "addons/AddonMiningOverhaul.h" +#include class SerializedGameData; class nobUsual; diff --git a/libs/s25main/figures/nofWorkman.cpp b/libs/s25main/figures/nofWorkman.cpp index 8c28a34e44..50bf74c808 100644 --- a/libs/s25main/figures/nofWorkman.cpp +++ b/libs/s25main/figures/nofWorkman.cpp @@ -100,23 +100,16 @@ struct NodeHasResource MapPoint nofWorkman::FindPointWithResource(ResourceType type) const { - // Alle Punkte durchgehen, bis man einen findet, wo man graben kann + return FindPointWithResource(type, MINER_RADIUS); +} + +MapPoint nofWorkman::FindPointWithResource(ResourceType type, unsigned radius) const { const std::vector pts = - world->GetMatchingPointsInRadius<1>(pos, MINER_RADIUS, NodeHasResource(*world, type), true); + world->GetMatchingPointsInRadius<1>(pos, radius, NodeHasResource(*world, type), true); if(!pts.empty()) return pts.front(); workplace->OnOutOfResources(); return MapPoint::Invalid(); -} - -std::vector nofWorkman::FindAllPointsWithResource(ResourceType type) const -{ - // int maxResults = (int)((MINER_RADIUS * MINER_RADIUS + MINER_RADIUS) * 3u + 1u); - - const std::vector pts = - world->GetMatchingPointsInRadius<19>(pos, MINER_RADIUS, NodeHasResource(*world, type), true); - - return pts; } \ No newline at end of file diff --git a/libs/s25main/figures/nofWorkman.h b/libs/s25main/figures/nofWorkman.h index d2a8499a4b..3e257fb030 100644 --- a/libs/s25main/figures/nofWorkman.h +++ b/libs/s25main/figures/nofWorkman.h @@ -39,8 +39,7 @@ class nofWorkman : public nofBuildingWorker /// Looks for a point with a given resource on the node MapPoint FindPointWithResource(ResourceType type) const; - /// Looks for all points with a given resource on the node - std::vector FindAllPointsWithResource(ResourceType type) const; + MapPoint FindPointWithResource(ResourceType type, unsigned radius) const; public: /// Going to workplace diff --git a/libs/s25main/gameData/GameConsts.h b/libs/s25main/gameData/GameConsts.h index 51f7fdf1bf..c671a5cd1e 100644 --- a/libs/s25main/gameData/GameConsts.h +++ b/libs/s25main/gameData/GameConsts.h @@ -20,6 +20,10 @@ constexpr GameSpeed referenceSpeed = GameSpeed::Normal; /// Reichweite der Bergarbeiter constexpr unsigned MINER_RADIUS = 2; +constexpr unsigned MINER_RADIUS_SETTLERSIV = 1u; + +/// maximum quantity for ores +constexpr unsigned MINER_MAX_QUANTITY = 7u; /// Konstante für die Pfadrichtung bei einer Schiffsverbindung constexpr unsigned char SHIP_DIR = 100; diff --git a/libs/s25main/world/MapBase.cpp b/libs/s25main/world/MapBase.cpp index 612b46a463..561a29e27d 100644 --- a/libs/s25main/world/MapBase.cpp +++ b/libs/s25main/world/MapBase.cpp @@ -182,3 +182,9 @@ MapPoint MapBase::MakeMapPoint(Position pt) const { return ::MakeMapPoint(pt, size_); } + +unsigned MapBase::numPointsRadius(unsigned radius, bool includePt) const { + // For every additional radius we get 6 * curRadius more points. Hence we have 6 * sum(1..radius) points + the + // center point if requested This can be reduced via the gauss formula to the following: + return (radius * radius + radius) * 3u + (includePt ? 1u : 0u); +} \ No newline at end of file diff --git a/libs/s25main/world/MapBase.h b/libs/s25main/world/MapBase.h index cb0d9a1454..484cb773b1 100644 --- a/libs/s25main/world/MapBase.h +++ b/libs/s25main/world/MapBase.h @@ -95,6 +95,7 @@ class MapBase unsigned CalcMaxDistance() const; /// Return the direction for ships for going from one point to another ShipDirection GetShipDir(MapPoint fromPt, MapPoint toPt) const; + unsigned numPointsRadius(unsigned radius, bool includePt) const; }; ////////////////////////////////////////////////////////////////////////// @@ -122,9 +123,7 @@ detail::GetPointsResult_t MapBase::GetPointsInRadius(const MapPoi result.reserve(T_maxResults); else if(std::is_same::value) { - // For every additional radius we get 6 * curRadius more points. Hence we have 6 * sum(1..radius) points + the - // center point if requested This can be reduced via the gauss formula to the following: - result.reserve((radius * radius + radius) * 3u + (includePt ? 1u : 0u)); + result.reserve(numPointsRadius(radius, includePt)); } if(includePt) { From 4e5a182bddd849a4c710c8f9ad123597f3328116 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 09:45:11 +0100 Subject: [PATCH 07/15] add new line in mapbase.cpp --- libs/s25main/world/MapBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/s25main/world/MapBase.cpp b/libs/s25main/world/MapBase.cpp index 561a29e27d..8e9465a846 100644 --- a/libs/s25main/world/MapBase.cpp +++ b/libs/s25main/world/MapBase.cpp @@ -187,4 +187,4 @@ unsigned MapBase::numPointsRadius(unsigned radius, bool includePt) const { // For every additional radius we get 6 * curRadius more points. Hence we have 6 * sum(1..radius) points + the // center point if requested This can be reduced via the gauss formula to the following: return (radius * radius + radius) * 3u + (includePt ? 1u : 0u); -} \ No newline at end of file +} From 65f7e39b024d835ec6655cddcdab4c2bb5de5a16 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 09:57:01 +0100 Subject: [PATCH 08/15] rename numPointsRadius to GetNumPointsInRadius to match other naming, make it constexpr --- libs/s25main/figures/nofMiner.cpp | 2 +- libs/s25main/world/MapBase.cpp | 6 ------ libs/s25main/world/MapBase.h | 12 ++++++++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index d4458987cf..6570dcd3e8 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -138,7 +138,7 @@ bool nofMiner::StartWorking() } // depending on remaining resources, roll if this workcycle needs to be altered or not - if(RANDOM_RAND(world->numPointsRadius(MINER_RADIUS_SETTLERSIV, true) * MINER_MAX_QUANTITY) + if(RANDOM_RAND(world->GetNumPointsInRadius(MINER_RADIUS_SETTLERSIV, true) * MINER_MAX_QUANTITY) > sumResAmount) { isAlteredWorkcycle = true; diff --git a/libs/s25main/world/MapBase.cpp b/libs/s25main/world/MapBase.cpp index 8e9465a846..612b46a463 100644 --- a/libs/s25main/world/MapBase.cpp +++ b/libs/s25main/world/MapBase.cpp @@ -182,9 +182,3 @@ MapPoint MapBase::MakeMapPoint(Position pt) const { return ::MakeMapPoint(pt, size_); } - -unsigned MapBase::numPointsRadius(unsigned radius, bool includePt) const { - // For every additional radius we get 6 * curRadius more points. Hence we have 6 * sum(1..radius) points + the - // center point if requested This can be reduced via the gauss formula to the following: - return (radius * radius + radius) * 3u + (includePt ? 1u : 0u); -} diff --git a/libs/s25main/world/MapBase.h b/libs/s25main/world/MapBase.h index 484cb773b1..a983b08dd7 100644 --- a/libs/s25main/world/MapBase.h +++ b/libs/s25main/world/MapBase.h @@ -86,6 +86,15 @@ class MapBase template bool CheckPointsInRadius(MapPoint pt, unsigned radius, T_IsValidPt&& isValid, bool includePt) const; + /// Returns number of points in the given radius + /// If includePt is true, then the point itself is also counted + constexpr unsigned GetNumPointsInRadius(unsigned radius, bool includePt) const + { + // For every additional radius we get 6 * curRadius more points. Hence we have 6 * sum(1..radius) points + the + // center point if requested This can be reduced via the gauss formula to the following: + return (radius * radius + radius) * 3u + (includePt ? 1u : 0u); + } + /// Return the distance between 2 points on the map (includes wrapping around map borders) unsigned CalcDistance(const Position& p1, const Position& p2) const; unsigned CalcDistance(const MapPoint p1, const MapPoint p2) const @@ -95,7 +104,6 @@ class MapBase unsigned CalcMaxDistance() const; /// Return the direction for ships for going from one point to another ShipDirection GetShipDir(MapPoint fromPt, MapPoint toPt) const; - unsigned numPointsRadius(unsigned radius, bool includePt) const; }; ////////////////////////////////////////////////////////////////////////// @@ -123,7 +131,7 @@ detail::GetPointsResult_t MapBase::GetPointsInRadius(const MapPoi result.reserve(T_maxResults); else if(std::is_same::value) { - result.reserve(numPointsRadius(radius, includePt)); + result.reserve(GetNumPointsInRadius(radius, includePt)); } if(includePt) { From a25a950a68bffb13548025113add61d616a8d627 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 10:02:14 +0100 Subject: [PATCH 09/15] rename new consts --- libs/s25main/figures/nofMiner.cpp | 6 +++--- libs/s25main/gameData/GameConsts.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 6570dcd3e8..8110a36daf 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -86,7 +86,7 @@ bool nofMiner::AreWaresAvailable() const // TODO: Skip this check if siv like mines and worked at least once? if(addonSetting == MiningBehavior::S4Like) - return FindPointWithResource(GetRequiredResType(), MINER_RADIUS_SETTLERSIV).isValid(); + return FindPointWithResource(GetRequiredResType(), MINER_ORE_RADIUS_SETTLERSIV).isValid(); else return FindPointWithResource(GetRequiredResType()).isValid(); } @@ -120,7 +120,7 @@ bool nofMiner::StartWorking() MapPoint nonMinumResPt; const std::vector reachablePts = - world->GetPointsInRadiusWithCenter(workplace->GetPos(), MINER_RADIUS_SETTLERSIV); + world->GetPointsInRadiusWithCenter(workplace->GetPos(), MINER_ORE_RADIUS_SETTLERSIV); for(const MapPoint curPt : reachablePts) { @@ -138,7 +138,7 @@ bool nofMiner::StartWorking() } // depending on remaining resources, roll if this workcycle needs to be altered or not - if(RANDOM_RAND(world->GetNumPointsInRadius(MINER_RADIUS_SETTLERSIV, true) * MINER_MAX_QUANTITY) + if(RANDOM_RAND(world->GetNumPointsInRadius(MINER_ORE_RADIUS_SETTLERSIV, true) * MAX_ORE_QUANTITY) > sumResAmount) { isAlteredWorkcycle = true; diff --git a/libs/s25main/gameData/GameConsts.h b/libs/s25main/gameData/GameConsts.h index c671a5cd1e..b001904599 100644 --- a/libs/s25main/gameData/GameConsts.h +++ b/libs/s25main/gameData/GameConsts.h @@ -20,10 +20,10 @@ constexpr GameSpeed referenceSpeed = GameSpeed::Normal; /// Reichweite der Bergarbeiter constexpr unsigned MINER_RADIUS = 2; -constexpr unsigned MINER_RADIUS_SETTLERSIV = 1u; +constexpr unsigned MINER_ORE_RADIUS_SETTLERSIV = 1u; /// maximum quantity for ores -constexpr unsigned MINER_MAX_QUANTITY = 7u; +constexpr unsigned MAX_ORE_QUANTITY = 7u; /// Konstante für die Pfadrichtung bei einer Schiffsverbindung constexpr unsigned char SHIP_DIR = 100; From 833f17a14105f8aad22a2fea62031e5370d28419 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 10:03:42 +0100 Subject: [PATCH 10/15] remove unused include --- libs/s25main/figures/nofWorkman.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/s25main/figures/nofWorkman.h b/libs/s25main/figures/nofWorkman.h index 3e257fb030..0c6ccf4cf6 100644 --- a/libs/s25main/figures/nofWorkman.h +++ b/libs/s25main/figures/nofWorkman.h @@ -8,7 +8,6 @@ #include "nofBuildingWorker.h" #include "gameTypes/GoodTypes.h" #include "gameTypes/Resource.h" -#include class SerializedGameData; class nobBaseWarehouse; class nobUsual; From bf302f2d30e3ab20a4f9861212135b38030f7a63 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 10:14:26 +0100 Subject: [PATCH 11/15] move include --- libs/s25main/figures/nofMiner.cpp | 1 + libs/s25main/figures/nofMiner.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 8110a36daf..9b61bf021b 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -12,6 +12,7 @@ #include "ogl/glArchivItem_Bitmap_Player.h" #include "world/GameWorld.h" #include +#include nofMiner::nofMiner(const MapPoint pos, const unsigned char player, nobUsual* workplace) : nofWorkman(Job::Miner, pos, player, workplace), isAlteredWorkcycle(false) diff --git a/libs/s25main/figures/nofMiner.h b/libs/s25main/figures/nofMiner.h index bddc2113b7..4056569ab1 100644 --- a/libs/s25main/figures/nofMiner.h +++ b/libs/s25main/figures/nofMiner.h @@ -6,7 +6,6 @@ #include "nofWorkman.h" #include "addons/AddonMiningOverhaul.h" -#include class SerializedGameData; class nobUsual; From df850e36791995807d950c42a4e9ff815e68f7a3 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 10:27:49 +0100 Subject: [PATCH 12/15] improve main implementation --- libs/s25main/figures/nofMiner.cpp | 52 +++++++++++++++++-------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index 9b61bf021b..c82e7f2c91 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -85,7 +85,6 @@ bool nofMiner::AreWaresAvailable() const if(addonSetting == MiningBehavior::AlwaysAvailable) return true; - // TODO: Skip this check if siv like mines and worked at least once? if(addonSetting == MiningBehavior::S4Like) return FindPointWithResource(GetRequiredResType(), MINER_ORE_RADIUS_SETTLERSIV).isValid(); else @@ -96,71 +95,76 @@ MiningBehavior nofMiner::GetMiningBehavior() const { const GlobalGameSettings& settings = world->GetGGS(); + auto miningBehavior = MiningBehavior::Normal; + switch(workplace->GetBuildingType()) { - case BuildingType::GoldMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_GOLD); - case BuildingType::IronMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_IRON); - case BuildingType::CoalMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_COAL); - case BuildingType::GraniteMine: return (MiningBehavior)settings.getSelection(AddonId::MINING_OVERHAUL_GRANITE); - default: return MiningBehavior::Normal; + case BuildingType::GoldMine: + miningBehavior = static_cast(settings.getSelection(AddonId::MINING_OVERHAUL_GOLD)); + break; + case BuildingType::IronMine: + miningBehavior = static_cast(settings.getSelection(AddonId::MINING_OVERHAUL_IRON)); + break; + case BuildingType::CoalMine: + miningBehavior = static_cast(settings.getSelection(AddonId::MINING_OVERHAUL_COAL)); + break; + case BuildingType::GraniteMine: + miningBehavior = static_cast(settings.getSelection(AddonId::MINING_OVERHAUL_GRANITE)); + break; + default: miningBehavior = MiningBehavior::Normal; } + + return miningBehavior; } bool nofMiner::StartWorking() { isAlteredWorkcycle = false; - MiningBehavior addonSettings = GetMiningBehavior(); - - switch (addonSettings) + switch(GetMiningBehavior()) { case MiningBehavior::S4Like: { int sumResAmount = 0; - - MapPoint nonMinumResPt; + MapPoint nonMinimumResPt; const std::vector reachablePts = world->GetPointsInRadiusWithCenter(workplace->GetPos(), MINER_ORE_RADIUS_SETTLERSIV); for(const MapPoint curPt : reachablePts) { - const Resource resPt = world->GetNode(curPt).resources; + const Resource resource = world->GetNode(curPt).resources; - if(resPt.getType() != GetRequiredResType()) + if(resource.getType() != GetRequiredResType()) continue; - const auto resAmount = resPt.getAmount(); - + const auto resAmount = resource.getAmount(); sumResAmount += resAmount; - if(resAmount > 1u && !nonMinumResPt.isValid()) - nonMinumResPt = curPt; + if(resAmount > 1u && !nonMinimumResPt.isValid()) + nonMinimumResPt = curPt; } // depending on remaining resources, roll if this workcycle needs to be altered or not - if(RANDOM_RAND(world->GetNumPointsInRadius(MINER_ORE_RADIUS_SETTLERSIV, true) * MAX_ORE_QUANTITY) + if(RANDOM_RAND(reachablePts.size() * MAX_ORE_QUANTITY) > sumResAmount) { isAlteredWorkcycle = true; } else { - if(nonMinumResPt.isValid()) - world->ReduceResource(nonMinumResPt); + if(nonMinimumResPt.isValid()) + world->ReduceResource(nonMinimumResPt); } } break; - // TODO: Is this required? FindPointWithResource checks if there is at least one case MiningBehavior::Inexhaustible: { - const MapPoint resPt = FindPointWithResource(GetRequiredResType()); - if(!resPt.isValid()) + if(!FindPointWithResource(GetRequiredResType()).isValid()) return false; } break; case MiningBehavior::AlwaysAvailable: break; case MiningBehavior::Normal: - default: { const MapPoint resPt = FindPointWithResource(GetRequiredResType()); if(!resPt.isValid()) From 8d58bd575d838042a718bf55d0071dfdcd978b80 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 10:43:03 +0100 Subject: [PATCH 13/15] improve addon description --- libs/s25main/addons/AddonMiningOverhaul.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/s25main/addons/AddonMiningOverhaul.h b/libs/s25main/addons/AddonMiningOverhaul.h index 3be4febc16..ee2dec7807 100644 --- a/libs/s25main/addons/AddonMiningOverhaul.h +++ b/libs/s25main/addons/AddonMiningOverhaul.h @@ -20,10 +20,10 @@ class AddonMiningOverhaulBase : public AddonList protected: AddonMiningOverhaulBase(AddonId addonId, const std::string& addonName) : AddonList(addonId, AddonGroup::Economy, addonName, - _("This addon lets you control mining behavior.\n\n" + _("This addon allows you to change the ore mining behavior.\n\n" "No change: Original behavior\n" - "Settlers IV: Mines never deplete. Range is decreased to 1. Chance for production depends on " - "resource amount in range.\n" + "Settlers IV: Mines never fully deplete. Range is decreased to 1. Chance for production" + " depends on remaining resource amount in range.\n" "Inexhaustible: Mines never deplete\n" "Everywhere: Mines never deplete, can mine everywhere"), { From b44986b77cc47a2a0d2da6b50e27ae91778a2ecd Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 11:03:07 +0100 Subject: [PATCH 14/15] add saving and loading of isAlteredWorkcycle --- libs/s25main/SerializedGameData.cpp | 21 +++++++++++---------- libs/s25main/figures/nofMiner.cpp | 18 ++++++++++++++++-- libs/s25main/figures/nofMiner.h | 2 ++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/libs/s25main/SerializedGameData.cpp b/libs/s25main/SerializedGameData.cpp index f43774af01..0abd822bf4 100644 --- a/libs/s25main/SerializedGameData.cpp +++ b/libs/s25main/SerializedGameData.cpp @@ -86,16 +86,17 @@ /// Then reset this number to 1. /// TODO: Let GO_Type start at 0 again when resetting this /// Changelog: -/// 2: All player buildings together, variable width size for containers and ship names -/// 3: Landscape and terrain names stored as strings -/// 4: HunterWaitingForAnimalReady introduced as sub-state of HunterFindingShootingpoint -/// 5: Make RoadPathDirection contiguous and use optional for ware in nofBuildingWorker -/// 6: Make TradeDirection contiguous, Serialize only nobUsuals in BuildingRegister::buildings, -/// include water and fish in geologists resourceFound -/// 7: Use helpers::push/popContainer (uses var size) -/// 8: noFlag::Wares converted to static_vector -/// 9: Drop serialization of node BQ -static const unsigned currentGameDataVersion = 9; +/// 2: All player buildings together, variable width size for containers and ship names +/// 3: Landscape and terrain names stored as strings +/// 4: HunterWaitingForAnimalReady introduced as sub-state of HunterFindingShootingpoint +/// 5: Make RoadPathDirection contiguous and use optional for ware in nofBuildingWorker +/// 6: Make TradeDirection contiguous, Serialize only nobUsuals in BuildingRegister::buildings, +/// include water and fish in geologists resourceFound +/// 7: Use helpers::push/popContainer (uses var size) +/// 8: noFlag::Wares converted to static_vector +/// 9: Drop serialization of node BQ +/// 10: nofMiner saves isAlteredWorkcycle boolean variable +static const unsigned currentGameDataVersion = 10; // clang-format on std::unique_ptr SerializedGameData::Create_GameObject(const GO_Type got, const unsigned obj_id) diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index c82e7f2c91..cf63c0ebaa 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -13,13 +13,18 @@ #include "world/GameWorld.h" #include #include +#include "SerializedGameData.h" nofMiner::nofMiner(const MapPoint pos, const unsigned char player, nobUsual* workplace) : nofWorkman(Job::Miner, pos, player, workplace), isAlteredWorkcycle(false) {} -// TODO: need to look into saving/loading to correctly load the work cycle -nofMiner::nofMiner(SerializedGameData& sgd, const unsigned obj_id) : nofWorkman(sgd, obj_id) {} +nofMiner::nofMiner(SerializedGameData& sgd, const unsigned obj_id) : nofWorkman(sgd, obj_id) { + if(sgd.GetGameDataVersion() >= 10) + isAlteredWorkcycle = sgd.PopBool(); + else + isAlteredWorkcycle = false; +} void nofMiner::DrawWorking(DrawPoint drawPt) { @@ -188,3 +193,12 @@ ResourceType nofMiner::GetRequiredResType() const default: return ResourceType::Granite; } } + +void nofMiner::Serialize(SerializedGameData& sgd) const +{ + nofWorkman::Serialize(sgd); + + sgd.PushBool(isAlteredWorkcycle); + + sgd.GetGameDataVersion(); +} diff --git a/libs/s25main/figures/nofMiner.h b/libs/s25main/figures/nofMiner.h index 4056569ab1..906cf23a2a 100644 --- a/libs/s25main/figures/nofMiner.h +++ b/libs/s25main/figures/nofMiner.h @@ -32,4 +32,6 @@ class nofMiner : public nofWorkman nofMiner(SerializedGameData& sgd, unsigned obj_id); GO_Type GetGOT() const final { return GO_Type::NofMiner; } + + void Serialize(SerializedGameData& sgd) const override; }; From ae9e40f413e7afdb1a33e27437bf9926e33d3023 Mon Sep 17 00:00:00 2001 From: Spikeone Date: Mon, 28 Feb 2022 15:19:05 +0100 Subject: [PATCH 15/15] ctrl + k, ctrl + d for all files that failed formatting tests --- libs/s25main/addons/AddonMiningOverhaul.h | 4 +++- libs/s25main/addons/const_addons.h | 2 +- libs/s25main/figures/nofMiner.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libs/s25main/addons/AddonMiningOverhaul.h b/libs/s25main/addons/AddonMiningOverhaul.h index ee2dec7807..bc78d6d8b9 100644 --- a/libs/s25main/addons/AddonMiningOverhaul.h +++ b/libs/s25main/addons/AddonMiningOverhaul.h @@ -50,7 +50,9 @@ class AddonMiningOverhaulGold : public AddonMiningOverhaulBase class AddonMiningOverhaulGranite : public AddonMiningOverhaulBase { public: - AddonMiningOverhaulGranite() : AddonMiningOverhaulBase(AddonId::MINING_OVERHAUL_GRANITE, _("Mining overhaul: Granite")) {} + AddonMiningOverhaulGranite() + : AddonMiningOverhaulBase(AddonId::MINING_OVERHAUL_GRANITE, _("Mining overhaul: Granite")) + {} }; class AddonMiningOverhaulIron : public AddonMiningOverhaulBase diff --git a/libs/s25main/addons/const_addons.h b/libs/s25main/addons/const_addons.h index 55f66521a9..9971e93628 100644 --- a/libs/s25main/addons/const_addons.h +++ b/libs/s25main/addons/const_addons.h @@ -55,7 +55,7 @@ ENUM_WITH_STRING(AddonId, LIMIT_CATAPULTS = 0x00000000, INEXHAUSTIBLE_MINES = 0x INEXHAUSTIBLE_GRANITEMINES = 0x00800000, - MINING_OVERHAUL_COAL = 0x00800001, MINING_OVERHAUL_GOLD = 0x00800002, + MINING_OVERHAUL_COAL = 0x00800001, MINING_OVERHAUL_GOLD = 0x00800002, MINING_OVERHAUL_GRANITE = 0x00800003, MINING_OVERHAUL_IRON = 0x00800004, MAX_RANK = 0x00900000, SEA_ATTACK = 0x00900001, INEXHAUSTIBLE_FISH = 0x00900002, diff --git a/libs/s25main/figures/nofMiner.cpp b/libs/s25main/figures/nofMiner.cpp index cf63c0ebaa..67fea3dd65 100644 --- a/libs/s25main/figures/nofMiner.cpp +++ b/libs/s25main/figures/nofMiner.cpp @@ -5,21 +5,22 @@ #include "nofMiner.h" #include "GlobalGameSettings.h" #include "Loader.h" +#include "SerializedGameData.h" #include "SoundManager.h" #include "addons/const_addons.h" #include "buildings/nobUsual.h" #include "network/GameClient.h" #include "ogl/glArchivItem_Bitmap_Player.h" #include "world/GameWorld.h" -#include #include -#include "SerializedGameData.h" +#include nofMiner::nofMiner(const MapPoint pos, const unsigned char player, nobUsual* workplace) : nofWorkman(Job::Miner, pos, player, workplace), isAlteredWorkcycle(false) {} -nofMiner::nofMiner(SerializedGameData& sgd, const unsigned obj_id) : nofWorkman(sgd, obj_id) { +nofMiner::nofMiner(SerializedGameData& sgd, const unsigned obj_id) : nofWorkman(sgd, obj_id) +{ if(sgd.GetGameDataVersion() >= 10) isAlteredWorkcycle = sgd.PopBool(); else @@ -151,8 +152,7 @@ bool nofMiner::StartWorking() } // depending on remaining resources, roll if this workcycle needs to be altered or not - if(RANDOM_RAND(reachablePts.size() * MAX_ORE_QUANTITY) - > sumResAmount) + if(RANDOM_RAND(reachablePts.size() * MAX_ORE_QUANTITY) > sumResAmount) { isAlteredWorkcycle = true; } else