mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
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
This commit is contained in:
@@ -153,22 +153,21 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
|
||||
private DepositPlan plan(IrisDepositGenerator generator, RNG rng) {
|
||||
if (generator.getSpawnChance() < rng.d()) {
|
||||
return new DepositPlan(generator, rng, false, 0);
|
||||
return new DepositPlan(generator, rng.getSeed(), false, 0);
|
||||
}
|
||||
boolean ore = generator.isOre(getData());
|
||||
int attempts = rng.i(generator.getMinPerChunk(), generator.getMaxPerChunk() + 1);
|
||||
return new DepositPlan(generator, rng, ore, attempts);
|
||||
return new DepositPlan(generator, rng.getSeed(), ore, attempts);
|
||||
}
|
||||
|
||||
private PreparedDeposit prepare(DepositPlan plan, int first, int limit, int cx, int cz, HeightMap he, ChunkContext context) {
|
||||
IrisDepositGenerator k = plan.generator();
|
||||
RNG rng = plan.rng();
|
||||
boolean oreDeposit = plan.ore();
|
||||
boolean needsCaveBiome = oreDeposit || k.usesCaveBiomeFilter();
|
||||
IrisDimensionCarvingResolver.State carvingState = needsCaveBiome ? new IrisDimensionCarvingResolver.State() : null;
|
||||
List<PreparedClump> 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<PlatformBlockSta
|
||||
return null;
|
||||
}
|
||||
|
||||
private record DepositPlan(IrisDepositGenerator generator, RNG rng, boolean ore, int attempts) {
|
||||
static long clumpSeed(long seed, int attempt) {
|
||||
long mixed = seed + 0x9e3779b97f4a7c15L * (attempt + 1L);
|
||||
mixed = (mixed ^ (mixed >>> 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<PreparedClump> clumps) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+36
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user