mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 08:07:42 +00:00
Compacted biome selection
- Biome and carving children share compact rarity selection - Weighted choices preserve alternating insertion order - Rarity totals use long counts without expanded lists - Natural child selection preserves its existing noise calls - Differential tests cover normal and extreme rarity values
This commit is contained in:
1 parent
17c927acdd
commit
534c844a7d
6 files changed
+273
-140
No files matched your search
@@ -13,8 +13,12 @@ import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class IrisComplexImplodeParityTest {
|
||||
private static Method childSelectionCreateMethod;
|
||||
@@ -48,6 +52,27 @@ public class IrisComplexImplodeParityTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extremeCountsKeepTheRareBiomeReachableAcrossTheIntIndexBoundary() {
|
||||
IrisBiome rare = createBiome(Integer.MAX_VALUE);
|
||||
IrisBiome common = createBiome(1);
|
||||
CNG generator = mock(CNG.class);
|
||||
doReturn(1_073_741_824).when(generator).fit2D(0, Integer.MAX_VALUE, 12D, -32D);
|
||||
IrisComplex.ChildSelectionPlan pair = IrisComplex.ChildSelectionPlan.create(new KList<>(rare, common));
|
||||
|
||||
assertSame(rare, pair.select(generator, 12D, -32D));
|
||||
verify(generator).fit2D(0, Integer.MAX_VALUE, 12D, -32D);
|
||||
verify(generator, never()).noiseFast2D(anyDouble(), anyDouble());
|
||||
|
||||
CNG largeGenerator = mock(CNG.class);
|
||||
doReturn(0.5D).when(largeGenerator).noiseFast2D(12D, -32D);
|
||||
IrisComplex.ChildSelectionPlan large = IrisComplex.ChildSelectionPlan.create(
|
||||
new KList<>(rare, common, createBiome(2)));
|
||||
assertSame(rare, large.select(largeGenerator, 12D, -32D));
|
||||
verify(largeGenerator).noiseFast2D(12D, -32D);
|
||||
verify(largeGenerator, never()).fit2D(anyInt(), anyInt(), anyDouble(), anyDouble());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptySelectionPlanMatchesLegacyEmptyBehavior() throws Exception {
|
||||
KList<IrisBiome> options = new KList<>();
|
||||
|
||||
+30
@@ -35,11 +35,16 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Answers.CALLS_REAL_METHODS;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class IrisDimensionCarvingResolverParityTest {
|
||||
private static final int MAX_CHILD_DEPTH = 32;
|
||||
@@ -71,6 +76,31 @@ public class IrisDimensionCarvingResolverParityTest {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extremeChildRarityRemainsReachableWithOneNoiseSample() {
|
||||
Fixture fixture = createFixture();
|
||||
Engine engine = fixture.engine;
|
||||
IrisData data = engine.getData();
|
||||
IrisBiome rare = data.getBiomeLoader().load("child-a");
|
||||
IrisBiome common = data.getBiomeLoader().load("child-b");
|
||||
IrisBiome parentBiome = data.getBiomeLoader().load("root-low");
|
||||
doReturn(Integer.MAX_VALUE).when(rare).getRarity();
|
||||
doReturn(1).when(common).getRarity();
|
||||
doReturn(2).when(parentBiome).getRarity();
|
||||
IrisDimensionCarvingEntry parent = spy(engine.getDimension().getCarvingEntryIndex().get("root-low"));
|
||||
parent.setChildRecursionDepth(1);
|
||||
CNG generator = mock(CNG.class);
|
||||
doReturn(0.5D).when(generator).noiseFast2D(-17D, 23D);
|
||||
doReturn(generator).when(parent).getChildrenGenerator(anyLong(), any(IrisData.class));
|
||||
|
||||
IrisDimensionCarvingEntry selected = IrisDimensionCarvingResolver.resolveFromRoot(
|
||||
engine, parent, -17, 23, new IrisDimensionCarvingResolver.State());
|
||||
|
||||
assertSame(engine.getDimension().getCarvingEntryIndex().get("child-a"), selected);
|
||||
verify(generator).noiseFast2D(-17D, 23D);
|
||||
verify(generator, never()).fit2D(anyInt(), anyInt(), anyDouble(), anyDouble());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolverStatefulOverloadsMatchLegacyResolverAcrossSampleGrid() {
|
||||
Fixture fixture = createFixture();
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
public class IrisRaritySelectionTest {
|
||||
@Test
|
||||
public void everyIndexMatchesExpandedInsertionOrderForRandomizedChoices() {
|
||||
Random random = new Random(718938L);
|
||||
for (int scenario = 0; scenario < 500; scenario++) {
|
||||
ArrayList<Choice> choices = new ArrayList<>();
|
||||
int count = random.nextInt(12);
|
||||
for (int index = 0; index < count; index++) {
|
||||
choices.add(random.nextInt(7) == 0 ? null : new Choice(index, random.nextInt(35) - 3));
|
||||
}
|
||||
List<Choice> expanded = expand(choices);
|
||||
IrisRaritySelection<Choice> selection = IrisRaritySelection.create(choices);
|
||||
assertEquals(expanded.size(), selection.size());
|
||||
if (expanded.isEmpty()) {
|
||||
assertNull(selection.get(0));
|
||||
continue;
|
||||
}
|
||||
for (int index = 0; index < expanded.size(); index++) {
|
||||
assertSame(expanded.get(index), selection.get(index));
|
||||
}
|
||||
assertSame(expanded.getFirst(), selection.get(Long.MIN_VALUE));
|
||||
assertSame(expanded.getLast(), selection.get(Long.MAX_VALUE));
|
||||
for (double sample : new double[]{-3D, -0D, 0.125D, 0.5D, 0.875D, 1D, 3D,
|
||||
Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY}) {
|
||||
int index = (int) Math.round(sample * (expanded.size() - 1));
|
||||
assertSame(expanded.get(Math.max(0, Math.min(expanded.size() - 1, index))), selection.select(sample));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void maximumRarityCountsStayPositiveWithoutExpandingBillionsOfEntries() {
|
||||
Choice rare = new Choice(0, Integer.MAX_VALUE);
|
||||
Choice common = new Choice(1, 1);
|
||||
Choice next = new Choice(2, 2);
|
||||
IrisRaritySelection<Choice> selection = IrisRaritySelection.create(List.of(rare, common, next));
|
||||
|
||||
assertEquals(4_294_967_294L, selection.size());
|
||||
assertSame(next, selection.get(0L));
|
||||
assertSame(common, selection.get(2_147_483_646L));
|
||||
assertSame(rare, selection.get(2_147_483_647L));
|
||||
assertSame(common, selection.get(2_147_483_648L));
|
||||
assertSame(next, selection.get(selection.size() - 1L));
|
||||
assertSame(rare, selection.select(0.5D));
|
||||
assertSame(next, selection.select(0D));
|
||||
assertSame(next, selection.select(1D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalMaximumRaritiesRetainEveryChoice() {
|
||||
Choice first = new Choice(0, Integer.MAX_VALUE);
|
||||
Choice second = new Choice(1, Integer.MAX_VALUE);
|
||||
Choice third = new Choice(2, Integer.MAX_VALUE);
|
||||
IrisRaritySelection<Choice> selection = IrisRaritySelection.create(List.of(first, second, third));
|
||||
|
||||
assertEquals(3L, selection.size());
|
||||
assertSame(second, selection.get(0L));
|
||||
assertSame(first, selection.get(1L));
|
||||
assertSame(third, selection.get(2L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicateChoicesKeepTheirSeparateInsertionPositions() {
|
||||
Choice repeated = new Choice(0, 1);
|
||||
Choice other = new Choice(1, 3);
|
||||
List<Choice> choices = List.of(repeated, other, repeated);
|
||||
IrisRaritySelection<Choice> selection = IrisRaritySelection.create(choices);
|
||||
List<Choice> expanded = expand(choices);
|
||||
for (int index = 0; index < expanded.size(); index++) {
|
||||
assertSame(expanded.get(index), selection.get(index));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializedRuntimeRarityValuesUseTheExistingMinimumClamp() {
|
||||
Gson gson = new Gson();
|
||||
IrisBiome zero = gson.fromJson("{\"rarity\":0}", IrisBiome.class);
|
||||
IrisBiome negative = gson.fromJson("{\"rarity\":-2147483648}", IrisBiome.class);
|
||||
IrisBiome maximum = gson.fromJson("{\"rarity\":2147483647}", IrisBiome.class);
|
||||
IrisRaritySelection<IrisBiome> selection = IrisRaritySelection.create(List.of(zero, negative, maximum));
|
||||
|
||||
assertEquals(4_294_967_295L, selection.size());
|
||||
assertSame(zero, selection.get(2_147_483_647L));
|
||||
assertSame(maximum, selection.get(selection.size() - 1L));
|
||||
assertEquals(0, zero.getRarity());
|
||||
assertEquals(Integer.MIN_VALUE, negative.getRarity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAndEmptyOptionsDoNotProduceCandidates() {
|
||||
assertNull(IrisRaritySelection.<Choice>create(List.of()).select(0.5D));
|
||||
assertNull(IrisRaritySelection.<Choice>create(Arrays.asList(null, null)).get(0L));
|
||||
}
|
||||
|
||||
private static List<Choice> expand(List<Choice> choices) {
|
||||
int maximum = 1;
|
||||
for (Choice choice : choices) {
|
||||
if (choice != null) {
|
||||
maximum = Math.max(maximum, choice.rarity());
|
||||
}
|
||||
}
|
||||
ArrayList<Choice> expanded = new ArrayList<>();
|
||||
boolean append = false;
|
||||
for (Choice choice : choices) {
|
||||
if (choice == null) {
|
||||
continue;
|
||||
}
|
||||
int count = maximum + 1 - Math.max(1, choice.rarity());
|
||||
for (int index = 0; index < count; index++) {
|
||||
append = !append;
|
||||
if (append) {
|
||||
expanded.add(choice);
|
||||
} else {
|
||||
expanded.add(0, choice);
|
||||
}
|
||||
}
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
|
||||
private record Choice(int id, int rarity) implements IRare {
|
||||
@Override
|
||||
public int getRarity() {
|
||||
return rarity;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user