Configurable mine resource behavior#1942
Conversation
Flamefire
left a comment
There was a problem hiding this comment.
Thanks for taking care of that.
Please remove duplications and check back with what was discussed before. This includes:
- There is no need for multiple addons for a single mine type:
GRANITEMINES_WORK_EVERYWHEREis superflous and all the existing "inexhaustible*" addons should be integrated into this ones and use the same IDs: The OFF setting should be "Default" and ON (the new) "inexhaustible" FindPointWithResourceQuietduplicates code already present -> Reuse existing one, can be done by simply adding a default bool parameternotifyINEXHAUSTIBLE_MINESaddon should be removed: When detected during loading it should set the new addons accordingly, keep ID for that with a TODO for gamedata version increasing- Explain
CalcAverageDisplayProductivityplease, why the extra methods? - Isn't there already a method to convert AIResource to Resource so
GetMineBuildingTypedoesn't need to be (fully) implemented twice? CanCreateWorkEverywhereResourcelooks odd: "Work everywhere" should be just that: Ignore any resource in the ground, not add resources to the world, doesn't it? So just skip the searchIsMineResourceDepletableshouldn't useGetConfiguredMineResourceBehavior, in fact it seems only a single function is required, i.e. both Get... combined.
Maybe more.
Please give a quick summary of how "s4 like behavior" is supposed to work, so @Spikeone can verify it is what he intended in #1501 and we can verify it is implemented according to that spec.
Thanks, that direction makes sense. My understanding of the requested cleanup is:
My current S4-like behavior implementation is intended to work like this:
I’ll rework the implementation toward the existing-ID/list-setting approach and remove the duplicated/intermediate pieces instead of stacking this on top of the old addon set. |
@Spikeone Looks correct to me. Can you confirm? "possible resource capacity" isn't fully clear to me. There are 7 points considered and currently each resource gives 5% chance. I.e. when all have at least 3 resources we will have 100%. IIRC the max amount of resources per node is 7 (we should have a constant for that if we don't already have one) |
Good point. The current implementation intentionally models the existing S4-like “full productivity around ~20 remaining resources” behavior rather than deriving 100% from the absolute theoretical map capacity. The current
I agree the current formulation makes the I will rework this to express the behavior through named constants / derived calculation so the intended reference point becomes explicit instead of looking like a magic number. |
Yes, its 100% at (exactly) 20 resources, but why 20 and not 10, 30 or 40 when 49 is the theoretical maximum? Or even as low as 7 which would be 1 node with full resources. |
|
Updated the PR to address the requested architecture cleanup and the S4-like chance clarity point. Main changes:
S4-like behavior after the rework:
Validation:
|
Flamefire
left a comment
There was a problem hiding this comment.
Most things are now readability:
TODO(Replay)and/orTODO(Savegame)allows to quickly find all places- "display"productivity seems odd
- less code is usually better: Reduce C&P and avoid enum constraints where not necessary or document why
- The new
notifyparam forFindPointWithResourcenow looks redundant so notification might get moved out which is better for SRP as a "find" should not "notify"
| * now selects the inexhaustible behavior. | ||
| */ | ||
| class AddonInexhaustibleGraniteMines : public AddonBool | ||
| class AddonInexhaustibleGraniteMines : public AddonMineResourceBehaviorBase |
There was a problem hiding this comment.
Please move this class to the other ones to avoid missing it. And you can rename the addon id to match the new ones if you keep the value.
|
|
||
| /** | ||
| * Addon for allowing to have unlimited resources. | ||
| * Deprecated global mine setting. |
There was a problem hiding this comment.
Add TODO(Replay) TODO(Savegame) so it can be found when updating
| // | ||
| // Add the #include for your AddonXXX.h in Addons.h! | ||
| // | ||
| // TODO: INEXHAUSTIBLE_MINES is kept only for loading old settings/savegames until the gamedata version can be raised. |
There was a problem hiding this comment.
| // TODO: INEXHAUSTIBLE_MINES is kept only for loading old settings/savegames until the gamedata version can be raised. | |
| // TODO(Replay) TODO(Savegame): INEXHAUSTIBLE_MINES is kept only for loading old settings/savegames until the gamedata version can be raised. |
|
|
||
| MineResourceBehavior GetMineResourceBehavior(const GlobalGameSettings& settings, const BuildingType buildingType) | ||
| { | ||
| switch(static_cast<MineResourceBehavior>(settings.getSelection(GetMineResourceBehaviorAddonId(buildingType)))) |
There was a problem hiding this comment.
What is the reason for this switch? I should at least be explained by a short comment.
If it is only validation (why necessary?) then I'd rather have a auto result = ...; switch(result){case X:caseY:case Z:break /*or return*/; default: result=default}-like code to avoid having to read all this C&P
| } | ||
| } | ||
|
|
||
| unsigned GetS4LikeMineFullProductivityResourceAmount() |
There was a problem hiding this comment.
Why have a function that returns a constant?
|
|
||
| MineNoOutputFallback GetConfiguredNoOutputFallback(const GlobalGameSettings& settings) | ||
| { | ||
| switch(static_cast<MineNoOutputFallback>(settings.getSelection(AddonId::MINE_NO_OUTPUT_FALLBACK))) |
There was a problem hiding this comment.
Similar to the other method: At least avoid C&P by using a variable and directly returning or doing nothing in the "success" case
|
|
||
| std::vector<MapPoint> GetPointsWithResource(const GameWorld& world, const MapPoint pos, const ResourceType type) | ||
| { | ||
| return world.GetMatchingPointsInRadius<1>( |
There was a problem hiding this comment.
This will only return a single point, which is not what you want, do you?
| if(FindPointWithResource(GetRequiredResType(), false).isValid()) | ||
| return true; | ||
|
|
||
| workplace->OnOutOfResources(); | ||
| return false; |
There was a problem hiding this comment.
Why not
| if(FindPointWithResource(GetRequiredResType(), false).isValid()) | |
| return true; | |
| workplace->OnOutOfResources(); | |
| return false; | |
| return FindPointWithResource(GetRequiredResType()).isValid(); |
Wasn't that the reason for the notify param? Or is that not required and we could always notify in the caller (which might be cleaner anyway)?
|
|
||
| #pragma once | ||
|
|
||
| enum class MineNoOutputFallback : unsigned |
There was a problem hiding this comment.
do you need this to have an explicit type? Or is the default enough, i.e.:
| enum class MineNoOutputFallback : unsigned | |
| enum class MineNoOutputFallback |
Only cases where I can imagine explicit types are serialized enums that need a fixed-size type or when you rely on overflow etc.
|
|
||
| enum class MineResourceBehavior : unsigned | ||
| { | ||
| Default = 0, |
There was a problem hiding this comment.
Why the explicit type and values?
Summary
This PR implements configurable mine resource behavior as a cleaned-up replacement path for the broader #1501 direction.
It adds per-mine resource behavior settings for coal, iron, gold, and granite mines, while reusing existing inexhaustible mine addon IDs where appropriate instead of stacking additional addons on top.
Details
INEXHAUSTIBLE_*addon IDs as per-mine behavior list settings where possibleONvalues to the newInexhaustiblebehaviorINEXHAUSTIBLE_MINESsettings to per-mine inexhaustible behavior when loading old settingsWork everywhereas ignoring ground-resource requirements instead of creating resources in the worldS4-like behavior
For S4-like behavior:
Work-everywhere behavior
Work everywheremeans that the mine skips the ground-resource requirement.It does not create temporary resources in the world and does not deplete such generated resources.
Validation
clang-format version 10.0.0Test_integrationTest_UITest_integration --run_test=ProductionTest_integration --run_test=AITest_integration --run_test=Serializationctest --test-dir .\build-vs-x64-debug-local -C Debug -R "^Test_integration$" --output-on-failureTest_UI.exe --report_level=shortgit diff --check upstream/master...HEADpassed