From 723426177c120bb89b6245dde1f8b9737cb87334 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Sun, 6 Sep 2026 04:16:09 -0400 Subject: [PATCH] Separated deposit chance samples - Clump seeds mix the generator seed and attempt index before sampling - Deposit plans share immutable seeds across preparation workers - Probability checks cover generator independence and adjacent clumps across batch boundaries --- .../engine/modifier/IrisDepositModifier.java | 16 ++++++--- .../IrisDepositModifierContextTest.java | 2 -- .../IrisDepositModifierOrderingTest.java | 2 +- .../IrisDepositModifierProbabilityTest.java | 36 +++++++++++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierProbabilityTest.java diff --git a/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java b/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java index 6dbd40b16..5872cf1dc 100644 --- a/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java +++ b/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java @@ -153,22 +153,21 @@ public class IrisDepositModifier extends EngineAssignedModifier clumps = new ArrayList<>(limit - first); for (int l = first; l < limit; l++) { - RNG clumpRng = rng.nextParallelRNG(l + 1L); + RNG clumpRng = new RNG(clumpSeed(plan.seed(), l)); if (k.getPerClumpSpawnChance() < clumpRng.d()) { continue; } @@ -492,7 +491,14 @@ public class IrisDepositModifier extends EngineAssignedModifier>> 30)) * 0xbf58476d1ce4e5b9L; + mixed = (mixed ^ (mixed >>> 27)) * 0x94d049bb133111ebL; + return mixed ^ (mixed >>> 31); + } + + private record DepositPlan(IrisDepositGenerator generator, long seed, boolean ore, int attempts) { } private record PreparedDeposit(IrisDepositGenerator generator, boolean ore, List clumps) { diff --git a/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierContextTest.java b/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierContextTest.java index 1dd7cb627..29ce34f42 100644 --- a/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierContextTest.java +++ b/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierContextTest.java @@ -37,7 +37,6 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -103,7 +102,6 @@ public class IrisDepositModifierContextTest { RNG rng = mock(RNG.class); when(rng.d()).thenReturn(0.5D); when(rng.i(0, 5)).thenReturn(4, 0); - when(rng.nextParallelRNG(anyLong())).thenReturn(rng); new IrisDepositModifier(engine).generate(generator, null, null, rng, 0, 0, false, null); diff --git a/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierOrderingTest.java b/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierOrderingTest.java index 59f022235..d077db0ae 100644 --- a/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierOrderingTest.java +++ b/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierOrderingTest.java @@ -88,7 +88,7 @@ public class IrisDepositModifierOrderingTest { RNG generatorRng = new RNG(0L).nextParallelRNG(0L); for (String name : List.of("dimension", "region", "biome")) { for (int i = 0; i < 25; i++) { - expectedSamples.add(name + ":" + generatorRng.nextParallelRNG(i + 1L).getSeed()); + expectedSamples.add(name + ":" + IrisDepositModifier.clumpSeed(generatorRng.getSeed(), i)); } } Collections.sort(expectedSamples); diff --git a/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierProbabilityTest.java b/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierProbabilityTest.java new file mode 100644 index 000000000..2daf21f0c --- /dev/null +++ b/core/src/test/java/art/arcane/iris/engine/modifier/IrisDepositModifierProbabilityTest.java @@ -0,0 +1,36 @@ +package art.arcane.iris.engine.modifier; + +import art.arcane.volmlib.util.math.RNG; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class IrisDepositModifierProbabilityTest { + @Test + public void generatorAndClumpChancesRemainIndependent() { + int samples = 100_000; + int accepted = 0; + for (int seed = 0; seed < samples; seed++) { + if (new RNG(seed).d() <= 0.2D + && new RNG(IrisDepositModifier.clumpSeed(seed, 0)).d() <= 0.2D) { + accepted++; + } + } + assertEquals(0.04D, accepted / (double) samples, 0.003D); + } + + @Test + public void neighboringClumpChancesRemainIndependentAcrossBatchBoundaries() { + int samples = 100_000; + for (int first : new int[]{0, 7, 31}) { + int accepted = 0; + for (int seed = 0; seed < samples; seed++) { + if (new RNG(IrisDepositModifier.clumpSeed(seed, first)).d() <= 0.2D + && new RNG(IrisDepositModifier.clumpSeed(seed, first + 1)).d() <= 0.2D) { + accepted++; + } + } + assertEquals("Clump pair at " + first, 0.04D, accepted / (double) samples, 0.003D); + } + } +}