Skip to content

Commit

Permalink
implement fixed difficulty distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
RasmusAntons committed Jun 6, 2024
1 parent 84f407b commit dab87d6
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ private static int startGame(CommandContext<CommandSourceStack> context) throws
try {
board = BingoBoard.generate(
size,
difficulty.difficulty().number(),
difficulty.difficulty(),
teams.size(),
RandomSource.create(seed),
gamemode::isGoalAllowed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.gaming32.bingo.Bingo;
import io.github.gaming32.bingo.util.ResourceLocations;
import it.unimi.dsi.fastutil.floats.FloatList;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.RegistryOps;
Expand All @@ -29,20 +30,22 @@
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.List;

public record BingoDifficulty(int number, @Nullable String fallbackName) {
public record BingoDifficulty(int number, @Nullable String fallbackName, @Nullable List<Float> distribution) {
public static final Codec<BingoDifficulty> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("number").forGetter(BingoDifficulty::number),
Codec.STRING.optionalFieldOf("fallback_name").forGetter(d -> Optional.ofNullable(d.fallbackName))
Codec.STRING.optionalFieldOf("fallback_name").forGetter(d -> Optional.ofNullable(d.fallbackName)),
Codec.FLOAT.listOf().optionalFieldOf("distribution").forGetter(dist -> Optional.ofNullable(dist.distribution))
).apply(instance, BingoDifficulty::new)
);

private static Map<ResourceLocation, Holder> byId = Map.of();
private static NavigableMap<Integer, Holder> byNumber = ImmutableSortedMap.of();

private BingoDifficulty(int number, Optional<String> fallbackName) {
this(number, fallbackName.orElse(null));
private BingoDifficulty(int number, Optional<String> fallbackName, Optional<List<Float>> distribution) {
this(number, fallbackName.orElse(null), distribution.orElse(null));
}

public static Builder builder(ResourceLocation id) {
Expand Down Expand Up @@ -96,6 +99,7 @@ public static final class Builder {
private final ResourceLocation id;
private Integer number;
private String fallbackName;
private List<Float> distribution;

private Builder(ResourceLocation id) {
this.id = id;
Expand All @@ -111,10 +115,24 @@ public Builder fallbackName(String name) {
return this;
}

public Builder distribution(int... scaledBy5x5) {
final float[] unscaled = new float[scaledBy5x5.length];
for (int i = 0; i < scaledBy5x5.length; i++) {
unscaled[i] = scaledBy5x5[i] / 25f;
}
return this.distribution(unscaled);
}

public Builder distribution(float... unscaledDistribution) {
this.distribution = FloatList.of(unscaledDistribution);
return this;
}

public Holder build() {
return new Holder(id, new BingoDifficulty(
Objects.requireNonNull(number, "number"),
fallbackName
fallbackName,
distribution
));
}

Expand Down
50 changes: 30 additions & 20 deletions common/src/main/java/io/github/gaming32/bingo/game/BingoBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private static BingoBoard create(int size, Teams[] states, ActiveGoal[] goals) {

public static BingoBoard generate(
int size,
int difficulty,
BingoDifficulty difficulty,
int teamCount,
RandomSource rand,
BiPredicate<BingoGoal.Holder, Boolean> isAllowedGoal,
Expand Down Expand Up @@ -109,7 +109,7 @@ public static BingoBoard generate(

public static BingoGoal.Holder[] generateGoals(
int size,
int difficulty,
BingoDifficulty difficulty,
RandomSource rand,
BiPredicate<BingoGoal.Holder, Boolean> isAllowedGoal,
List<BingoGoal.Holder> requiredGoals,
Expand All @@ -131,7 +131,7 @@ public static BingoGoal.Holder[] generateGoals(
final Set<String> catalysts = new HashSet<>();

for (final BingoTag.Holder tag : excludedTags) {
tagCount.put(tag.id(), tag.tag().getMaxForDifficulty(difficulty, size));
tagCount.put(tag.id(), tag.tag().getMaxForDifficulty(difficulty.number(), size));
}

for (int i = 0; i < size * size; i++) {
Expand Down Expand Up @@ -188,7 +188,7 @@ public static BingoGoal.Holder[] generateGoals(

if (!goalCandidate.goal().getTags().isEmpty()) {
for (final BingoTag.Holder tag : goalCandidate.goal().getTags()) {
if (tagCount.getInt(tag.id()) >= tag.tag().getMaxForDifficulty(difficulty, size)) {
if (tagCount.getInt(tag.id()) >= tag.tag().getMaxForDifficulty(difficulty.number(), size)) {
continue goalGen;
}
}
Expand Down Expand Up @@ -267,25 +267,35 @@ private static boolean isOnSameLine(int size, int a, int b) {
return false;
}

private static int[] generateDifficulty(int size, int difficulty, RandomSource rand) {
private static int[] generateDifficulty(int size, BingoDifficulty difficulty, RandomSource rand) {
final int[] layout = new int[size * size];

final Iterator<Integer> available = BingoDifficulty.getNumbers()
.headSet(difficulty, true)
.descendingIterator();
if (!available.hasNext()) {
throw new IllegalArgumentException("No difficulty exists with number " + difficulty);
}
final int difficulty1 = available.next();
if (!available.hasNext()) {
Arrays.fill(layout, difficulty1);
if (difficulty.distribution() != null) {
List<Integer> scaledDistribution = difficulty.distribution().stream().map(f -> Math.round(f * size * size)).toList();
int p = 0;
for (int difficultyLevel = 0; difficultyLevel < scaledDistribution.size(); ++difficultyLevel) {
for (int i = 0; i < scaledDistribution.get(difficultyLevel) && p < layout.length; ++i)
layout[p++] = difficultyLevel;
}
BingoUtil.shuffle(layout, rand);
} else {
final int difficulty2 = available.next();
final int amountOf1 = rand.nextInt(size * size * 3 / 5, size * size * 3 / 5 + size);
final int[] indices = BingoUtil.shuffle(BingoUtil.generateIntArray(size * size), rand);
Arrays.fill(layout, difficulty2);
for (int i = 0; i < amountOf1; i++) {
layout[indices[i]] = difficulty1;
final Iterator<Integer> available = BingoDifficulty.getNumbers()
.headSet(difficulty.number(), true)
.descendingIterator();
if (!available.hasNext()) {
throw new IllegalArgumentException("No difficulty exists with number " + difficulty);
}
final int difficulty1 = available.next();
if (!available.hasNext()) {
Arrays.fill(layout, difficulty1);
} else {
final int difficulty2 = available.next();
final int amountOf1 = rand.nextInt(size * size * 3 / 5, size * size * 3 / 5 + size);
final int[] indices = BingoUtil.shuffle(BingoUtil.generateIntArray(size * size), rand);
Arrays.fill(layout, difficulty2);
for (int i = 0; i < amountOf1; i++) {
layout[indices[i]] = difficulty1;
}
}
}
return layout;
Expand Down

0 comments on commit dab87d6

Please sign in to comment.