Skip to content

Configurable mine resource behavior#1942

Open
DevOpsOfChaos wants to merge 12 commits into
Return-To-The-Roots:masterfrom
DevOpsOfChaos:sidequest/configurable-mine-resource-behavior
Open

Configurable mine resource behavior#1942
DevOpsOfChaos wants to merge 12 commits into
Return-To-The-Roots:masterfrom
DevOpsOfChaos:sidequest/configurable-mine-resource-behavior

Conversation

@DevOpsOfChaos
Copy link
Copy Markdown
Contributor

@DevOpsOfChaos DevOpsOfChaos commented May 21, 2026

Summary

This PR builds on #1920 and implements a cleaned-up replacement path for the broader configurable mine-resource behavior direction from #1501.

It adds configurable per-mine resource behavior settings for coal, iron, gold, and granite mines, including default behavior, S4-like exhaustion, inexhaustible resources, and work-everywhere behavior.

It also preserves the split granite mine behavior from #1920 so inexhaustible granite mines and granite work-everywhere remain separate options.

Details

  • Add per-mine configurable resource behavior addons
  • Add S4-like mine exhaustion based on remaining resource amount
  • Add configurable no-output fallback behavior for failed S4-like production cycles
  • Add finite work-everywhere resource creation for configured mines
  • Teach AI resource rating and mine planning about configured mine behavior
  • Adjust displayed mine productivity for S4-like resource chance
  • Add integration coverage for granite split behavior, S4-like production, fallback output, AI awareness, and productivity display

Preservation of #1920 behavior

  • INEXHAUSTIBLE_GRANITEMINES prevents granite resource depletion only
  • GRANITEMINES_WORK_EVERYWHERE enables granite mine work-everywhere behavior
  • Inexhaustible granite mines do not imply work-everywhere behavior
  • Granite work-everywhere remains finite unless paired with inexhaustible behavior

Relation to #1501

This is not a direct continuation of the old #1501 branch. It implements the same broader direction in a new cleaned-up form, including the previously missing AI handling, alternative no-output production cycle, and productivity display adjustment.

Validation

  • clang-format version 10.0.0
  • Built Test_integration
  • Built Test_UI
  • Passed Test_integration --run_test=Production
    • 16 test cases
    • 183 assertions
  • Passed Test_integration --run_test=AI
    • 11 test cases
    • 21375 assertions
  • git diff --check upstream/master...HEAD passed

Copy link
Copy Markdown
Member

@Flamefire Flamefire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_EVERYWHERE is 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"
  • FindPointWithResourceQuiet duplicates code already present -> Reuse existing one, can be done by simply adding a default bool parameter notify
  • INEXHAUSTIBLE_MINES addon 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 CalcAverageDisplayProductivity please, why the extra methods?
  • Isn't there already a method to convert AIResource to Resource so GetMineBuildingType doesn't need to be (fully) implemented twice?
  • CanCreateWorkEverywhereResource looks 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 search
  • IsMineResourceDepletable shouldn't use GetConfiguredMineResourceBehavior, 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.

@DevOpsOfChaos
Copy link
Copy Markdown
Contributor Author

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_EVERYWHERE is 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"
  • FindPointWithResourceQuiet duplicates code already present -> Reuse existing one, can be done by simply adding a default bool parameter notify
  • INEXHAUSTIBLE_MINES addon 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 CalcAverageDisplayProductivity please, why the extra methods?
  • Isn't there already a method to convert AIResource to Resource so GetMineBuildingType doesn't need to be (fully) implemented twice?
  • CanCreateWorkEverywhereResource looks 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 search
  • IsMineResourceDepletable shouldn't use GetConfiguredMineResourceBehavior, 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:

  • fold the existing INEXHAUSTIBLE_* addon IDs into the new per-mine behavior list settings
  • keep OFF == Default and map the old ON value to the new Inexhaustible behavior
  • remove the extra granite-specific work-everywhere addon path
  • remove the old global INEXHAUSTIBLE_MINES behavior as an active setting and migrate it during loading to the new per-mine settings, keeping its ID only for compatibility/TODO until the gamedata version can be increased
  • avoid helper duplication such as FindPointWithResourceQuiet
  • treat WorkEverywhere as “ignore ground resources”, not “create resources in the world”
  • simplify the effective behavior/depletion helper logic

My current S4-like behavior implementation is intended to work like this:

  • each mine type can be configured independently
  • for S4-like behavior, a mine can attempt production based on the remaining matching resources in its mining radius
  • the production chance is derived from remaining resource amount compared to the relevant possible resource capacity around the mine
  • resources are depleted only down to 1, not to 0
  • if the chance check fails, the mine runs a no-output cycle
  • the no-output cycle can either produce nothing or use the configured fallback production behavior

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.

@Flamefire
Copy link
Copy Markdown
Member

  • for S4-like behavior, a mine can attempt production based on the remaining matching resources in its mining radius

  • the production chance is derived from remaining resource amount compared to the relevant possible resource capacity around the mine

  • resources are depleted only down to 1, not to 0

  • if the chance check fails, the mine runs a no-output cycle

  • the no-output cycle can either produce nothing or use the configured fallback production behavior

@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)
The code should be clear here, the 5% looks random. The chance could be e.g. directly calculated from the points and use the number of points and max amount. Or the constant derived from something like that.

@DevOpsOfChaos
Copy link
Copy Markdown
Contributor Author

  • for S4-like behavior, a mine can attempt production based on the remaining matching resources in its mining radius
  • the production chance is derived from remaining resource amount compared to the relevant possible resource capacity around the mine
  • resources are depleted only down to 1, not to 0
  • if the chance check fails, the mine runs a no-output cycle
  • the no-output cycle can either produce nothing or use the configured fallback production behavior

@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) The code should be clear here, the 5% looks random. The chance could be e.g. directly calculated from the points and use the number of points and max amount. Or the constant derived from something like that.

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 5% per remaining resource effectively means:

  • 20 remaining matching resources => 100% production chance
  • depletion continues reducing the chance below that point

I agree the current formulation makes the 5% look arbitrary in code and in the PR description.

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.

@Flamefire
Copy link
Copy Markdown
Member

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.

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.
I'm not decided on what makes sense, but it needs to be explained in the code where the constant is defined with a short sentence.
And as the initial version was by @Spikeone I'd follow his preference if he has any.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants