v1.3.0: improved item drop consistency for seeded runs
This commit is contained in:
@@ -220,10 +220,10 @@ public class Eye extends Mob {
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
loot = Generator.random(Generator.Category.SEED);
|
||||
loot = Generator.randomUsingDefaults(Generator.Category.SEED);
|
||||
break;
|
||||
case 3:
|
||||
loot = Generator.random(Generator.Category.STONE);
|
||||
loot = Generator.randomUsingDefaults(Generator.Category.STONE);
|
||||
break;
|
||||
}
|
||||
return loot;
|
||||
|
||||
@@ -789,7 +789,7 @@ public abstract class Mob extends Char {
|
||||
Item item;
|
||||
if (loot instanceof Generator.Category) {
|
||||
|
||||
item = Generator.random( (Generator.Category)loot );
|
||||
item = Generator.randomUsingDefaults( (Generator.Category)loot );
|
||||
|
||||
} else if (loot instanceof Class<?>) {
|
||||
|
||||
|
||||
@@ -140,11 +140,11 @@ public class Warlock extends Mob implements Callback {
|
||||
Dungeon.LimitedDrops.WARLOCK_HP.count++;
|
||||
return new PotionOfHealing();
|
||||
} else {
|
||||
Item i = Generator.random(Generator.Category.POTION);
|
||||
Item i = Generator.randomUsingDefaults(Generator.Category.POTION);
|
||||
int healingTried = 0;
|
||||
while (i instanceof PotionOfHealing){
|
||||
healingTried++;
|
||||
i = Generator.random(Generator.Category.POTION);
|
||||
i = Generator.randomUsingDefaults(Generator.Category.POTION);
|
||||
}
|
||||
|
||||
//return the attempted healing potion drops to the pool
|
||||
|
||||
@@ -215,9 +215,14 @@ public class Generator {
|
||||
//Artifacts in particular don't reset, no duplicates!
|
||||
public float[] probs;
|
||||
public float[] defaultProbs = null;
|
||||
//These variables are used as a part of the deck system, to ensure that drops are consistent
|
||||
// regardless of when they occur (either as part of seeded levelgen, or random item drops)
|
||||
public Long seed = null;
|
||||
public int dropped = 0;
|
||||
|
||||
//game has two decks of 35 items for overall category probs
|
||||
//one deck has a ring and extra armor, the other has an artifact and extra thrown weapon
|
||||
//Note that pure random drops only happen as part of levelgen atm, so no seed is needed here
|
||||
public float firstProb;
|
||||
public float secondProb;
|
||||
public Class<? extends Item> superClass;
|
||||
@@ -480,6 +485,10 @@ public class Generator {
|
||||
generalReset();
|
||||
for (Category cat : Category.values()) {
|
||||
reset(cat);
|
||||
if (cat.defaultProbs != null) {
|
||||
cat.seed = Random.Long();
|
||||
cat.dropped = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +510,15 @@ public class Generator {
|
||||
cat = Random.chances( categoryProbs );
|
||||
}
|
||||
categoryProbs.put( cat, categoryProbs.get( cat ) - 1);
|
||||
return random( cat );
|
||||
|
||||
if (cat == Category.SEED) {
|
||||
//We specifically use defaults for seeds here because, unlike other item categories
|
||||
// their predominant source of drops is grass, not levelgen. This way the majority
|
||||
// of seed drops still use a deck, but the few that are spawned by levelgen are consistent
|
||||
return randomUsingDefaults(cat);
|
||||
} else {
|
||||
return random(cat);
|
||||
}
|
||||
}
|
||||
|
||||
public static Item random( Category cat ) {
|
||||
@@ -517,20 +534,32 @@ public class Generator {
|
||||
//if we're out of artifacts, return a ring instead.
|
||||
return item != null ? item : random(Category.RING);
|
||||
default:
|
||||
if (cat.defaultProbs != null && cat.seed != null){
|
||||
Random.pushGenerator(cat.seed);
|
||||
for (int i = 0; i < cat.dropped; i++) Random.Long();
|
||||
}
|
||||
|
||||
int i = Random.chances(cat.probs);
|
||||
if (i == -1) {
|
||||
reset(cat);
|
||||
i = Random.chances(cat.probs);
|
||||
}
|
||||
if (cat.defaultProbs != null) cat.probs[i]--;
|
||||
|
||||
if (cat.defaultProbs != null && cat.seed != null){
|
||||
Random.popGenerator();
|
||||
cat.dropped++;
|
||||
}
|
||||
|
||||
return ((Item) Reflection.newInstance(cat.classes[i])).random();
|
||||
}
|
||||
}
|
||||
|
||||
//overrides any deck systems and always uses default probs
|
||||
// except for artifacts, which must always use a deck
|
||||
public static Item randomUsingDefaults( Category cat ){
|
||||
if (cat.defaultProbs == null) {
|
||||
return random(cat); //currently covers weapons/armor/missiles
|
||||
if (cat.defaultProbs == null || cat == Category.ARTIFACT) {
|
||||
return random(cat);
|
||||
} else {
|
||||
return ((Item) Reflection.newInstance(cat.classes[Random.chances(cat.defaultProbs)])).random();
|
||||
}
|
||||
@@ -601,8 +630,19 @@ public class Generator {
|
||||
public static Artifact randomArtifact() {
|
||||
|
||||
Category cat = Category.ARTIFACT;
|
||||
|
||||
if (cat.defaultProbs != null && cat.seed != null){
|
||||
Random.pushGenerator(cat.seed);
|
||||
for (int i = 0; i < cat.dropped; i++) Random.Long();
|
||||
}
|
||||
|
||||
int i = Random.chances( cat.probs );
|
||||
|
||||
if (cat.defaultProbs != null && cat.seed != null){
|
||||
Random.popGenerator();
|
||||
cat.dropped++;
|
||||
}
|
||||
|
||||
//if no artifacts are left, return null
|
||||
if (i == -1){
|
||||
return null;
|
||||
@@ -627,7 +667,9 @@ public class Generator {
|
||||
private static final String FIRST_DECK = "first_deck";
|
||||
private static final String GENERAL_PROBS = "general_probs";
|
||||
private static final String CATEGORY_PROBS = "_probs";
|
||||
|
||||
private static final String CATEGORY_SEED = "_seed";
|
||||
private static final String CATEGORY_DROPPED = "_dropped";
|
||||
|
||||
public static void storeInBundle(Bundle bundle) {
|
||||
bundle.put(FIRST_DECK, usingFirstDeck);
|
||||
|
||||
@@ -640,16 +682,11 @@ public class Generator {
|
||||
|
||||
for (Category cat : Category.values()){
|
||||
if (cat.defaultProbs == null) continue;
|
||||
boolean needsStore = false;
|
||||
for (int i = 0; i < cat.probs.length; i++){
|
||||
if (cat.probs[i] != cat.defaultProbs[i]){
|
||||
needsStore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsStore){
|
||||
bundle.put(cat.name().toLowerCase() + CATEGORY_PROBS, cat.probs);
|
||||
bundle.put(cat.name().toLowerCase() + CATEGORY_PROBS, cat.probs);
|
||||
if (cat.seed != null) {
|
||||
bundle.put(cat.name().toLowerCase() + CATEGORY_SEED, cat.seed);
|
||||
bundle.put(cat.name().toLowerCase() + CATEGORY_DROPPED, cat.dropped);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -672,6 +709,10 @@ public class Generator {
|
||||
if (cat.defaultProbs != null && probs.length == cat.defaultProbs.length){
|
||||
cat.probs = probs;
|
||||
}
|
||||
if (bundle.contains(cat.name().toLowerCase() + CATEGORY_SEED)){
|
||||
cat.seed = bundle.getLong(cat.name().toLowerCase() + CATEGORY_SEED);
|
||||
cat.dropped = bundle.getInt(cat.name().toLowerCase() + CATEGORY_DROPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class Berry extends Food {
|
||||
super.satisfy(hero);
|
||||
SeedCounter counter = Buff.count(hero, SeedCounter.class, 1);
|
||||
if (counter.count() >= 2){
|
||||
Dungeon.level.drop(Generator.random(Generator.Category.SEED), hero.pos).sprite.drop();
|
||||
Dungeon.level.drop(Generator.randomUsingDefaults(Generator.Category.SEED), hero.pos).sprite.drop();
|
||||
counter.detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,11 +197,11 @@ public class RingOfWealth extends Ring {
|
||||
Item i = new Gold().random();
|
||||
return i.quantity(i.quantity()/2);
|
||||
case 1:
|
||||
return Generator.random(Generator.Category.STONE);
|
||||
return Generator.randomUsingDefaults(Generator.Category.STONE);
|
||||
case 2:
|
||||
return Generator.random(Generator.Category.POTION);
|
||||
return Generator.randomUsingDefaults(Generator.Category.POTION);
|
||||
case 3:
|
||||
return Generator.random(Generator.Category.SCROLL);
|
||||
return Generator.randomUsingDefaults(Generator.Category.SCROLL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ public class ScrollOfTransmutation extends InventoryScroll {
|
||||
Plant.Seed n;
|
||||
|
||||
do {
|
||||
n = (Plant.Seed)Generator.random( Generator.Category.SEED );
|
||||
n = (Plant.Seed)Generator.randomUsingDefaults( Generator.Category.SEED );
|
||||
} while (n.getClass() == s.getClass());
|
||||
|
||||
return n;
|
||||
@@ -277,7 +277,7 @@ public class ScrollOfTransmutation extends InventoryScroll {
|
||||
Runestone n;
|
||||
|
||||
do {
|
||||
n = (Runestone) Generator.random( Generator.Category.STONE );
|
||||
n = (Runestone) Generator.randomUsingDefaults( Generator.Category.STONE );
|
||||
} while (n.getClass() == r.getClass());
|
||||
|
||||
return n;
|
||||
|
||||
@@ -64,19 +64,19 @@ public class Recycle extends InventorySpell {
|
||||
Item result;
|
||||
do {
|
||||
if (item instanceof Potion) {
|
||||
result = Generator.random(Generator.Category.POTION);
|
||||
result = Generator.randomUsingDefaults(Generator.Category.POTION);
|
||||
if (item instanceof ExoticPotion){
|
||||
result = Reflection.newInstance(ExoticPotion.regToExo.get(result.getClass()));
|
||||
}
|
||||
} else if (item instanceof Scroll) {
|
||||
result = Generator.random(Generator.Category.SCROLL);
|
||||
result = Generator.randomUsingDefaults(Generator.Category.SCROLL);
|
||||
if (item instanceof ExoticScroll){
|
||||
result = Reflection.newInstance(ExoticScroll.regToExo.get(result.getClass()));
|
||||
}
|
||||
} else if (item instanceof Plant.Seed) {
|
||||
result = Generator.random(Generator.Category.SEED);
|
||||
result = Generator.randomUsingDefaults(Generator.Category.SEED);
|
||||
} else if (item instanceof Runestone) {
|
||||
result = Generator.random(Generator.Category.STONE);
|
||||
result = Generator.randomUsingDefaults(Generator.Category.STONE);
|
||||
} else {
|
||||
result = TippedDart.randomTipped(1);
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ public class WandOfRegrowth extends Wand {
|
||||
|
||||
for (int i = 0; i < nSeeds && !candidates.isEmpty(); i++){
|
||||
Integer c = Random.element(candidates);
|
||||
Dungeon.level.drop(Generator.random(Generator.Category.SEED), c).sprite.drop(pos);
|
||||
Dungeon.level.drop(Generator.randomUsingDefaults(Generator.Category.SEED), c).sprite.drop(pos);
|
||||
candidates.remove(c);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user