v1.3.0: improved how the game handles seeds and PRNG internally
This commit is contained in:
@@ -49,7 +49,20 @@ public class Random {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void pushGenerator( long seed ){
|
public static synchronized void pushGenerator( long seed ){
|
||||||
generators.push( new java.util.Random( seed ) );
|
generators.push( new java.util.Random( scrambleSeed(seed) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//scrambles a given seed, this helps eliminate patterns between the outputs of similar seeds
|
||||||
|
//Algorithm used is MX3 by Jon Maiga (jonkagstrom.com), CC0 license.
|
||||||
|
private static synchronized long scrambleSeed( long seed ){
|
||||||
|
seed ^= seed >>> 32;
|
||||||
|
seed *= 0xbea225f9eb34556dL;
|
||||||
|
seed ^= seed >>> 29;
|
||||||
|
seed *= 0xbea225f9eb34556dL;
|
||||||
|
seed ^= seed >>> 32;
|
||||||
|
seed *= 0xbea225f9eb34556dL;
|
||||||
|
seed ^= seed >>> 29;
|
||||||
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void popGenerator(){
|
public static synchronized void popGenerator(){
|
||||||
|
|||||||
@@ -190,8 +190,9 @@ public class Dungeon {
|
|||||||
|
|
||||||
Actor.clear();
|
Actor.clear();
|
||||||
Actor.resetNextID();
|
Actor.resetNextID();
|
||||||
|
|
||||||
Random.pushGenerator( seed );
|
//offset seed slightly to avoid output patterns
|
||||||
|
Random.pushGenerator( seed+1 );
|
||||||
|
|
||||||
Scroll.initLabels();
|
Scroll.initLabels();
|
||||||
Potion.initColors();
|
Potion.initColors();
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ public class YogDzewa extends Mob {
|
|||||||
private ArrayList<Class> fistSummons = new ArrayList<>();
|
private ArrayList<Class> fistSummons = new ArrayList<>();
|
||||||
private ArrayList<Class> challengeSummons = new ArrayList<>();
|
private ArrayList<Class> challengeSummons = new ArrayList<>();
|
||||||
{
|
{
|
||||||
Random.pushGenerator(Dungeon.seedCurDepth());
|
//offset seed slightly to avoid output patterns
|
||||||
|
Random.pushGenerator(Dungeon.seedCurDepth()+1);
|
||||||
fistSummons.add(Random.Int(2) == 0 ? YogFist.BurningFist.class : YogFist.SoiledFist.class);
|
fistSummons.add(Random.Int(2) == 0 ? YogFist.BurningFist.class : YogFist.SoiledFist.class);
|
||||||
fistSummons.add(Random.Int(2) == 0 ? YogFist.RottingFist.class : YogFist.RustedFist.class);
|
fistSummons.add(Random.Int(2) == 0 ? YogFist.RottingFist.class : YogFist.RustedFist.class);
|
||||||
fistSummons.add(Random.Int(2) == 0 ? YogFist.BrightFist.class : YogFist.DarkFist.class);
|
fistSummons.add(Random.Int(2) == 0 ? YogFist.BrightFist.class : YogFist.DarkFist.class);
|
||||||
|
|||||||
@@ -387,7 +387,8 @@ public abstract class RegularLevel extends Level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//use a separate generator for this to prevent held items, meta progress, and talents from affecting levelgen
|
//use a separate generator for this to prevent held items, meta progress, and talents from affecting levelgen
|
||||||
Random.pushGenerator( Dungeon.seedCurDepth() );
|
//we can use a random long for the seed as it will be the same long every time
|
||||||
|
Random.pushGenerator( Random.Long() );
|
||||||
|
|
||||||
Item item = Bones.get();
|
Item item = Bones.get();
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
|
|||||||
@@ -270,10 +270,12 @@ public class ShopRoom extends SpecialRoom {
|
|||||||
itemsToSpawn.add( rare );
|
itemsToSpawn.add( rare );
|
||||||
|
|
||||||
//hard limit is 63 items + 1 shopkeeper, as shops can't be bigger than 8x8=64 internally
|
//hard limit is 63 items + 1 shopkeeper, as shops can't be bigger than 8x8=64 internally
|
||||||
if (itemsToSpawn.size() > 63)
|
if (itemsToSpawn.size() > 63) {
|
||||||
throw new RuntimeException("Shop attempted to carry more than 63 items!");
|
throw new RuntimeException("Shop attempted to carry more than 63 items!");
|
||||||
|
}
|
||||||
|
|
||||||
//use a new generator here to prevent items in shop stock affecting levelgen RNG (e.g. sandbags)
|
//use a new generator here to prevent items in shop stock affecting levelgen RNG (e.g. sandbags)
|
||||||
|
//we can use a random long for the seed as it will be the same long every time
|
||||||
Random.pushGenerator(Random.Long());
|
Random.pushGenerator(Random.Long());
|
||||||
Random.shuffle(itemsToSpawn);
|
Random.shuffle(itemsToSpawn);
|
||||||
Random.popGenerator();
|
Random.popGenerator();
|
||||||
|
|||||||
@@ -526,7 +526,8 @@ public class GameScene extends PixelScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//50%/75% chance, use level's seed so that we get the same result for the same level
|
//50%/75% chance, use level's seed so that we get the same result for the same level
|
||||||
Random.pushGenerator(Dungeon.seedCurDepth());
|
//offset seed slightly to avoid output patterns
|
||||||
|
Random.pushGenerator(Dungeon.seedCurDepth()+1);
|
||||||
if (reqSecrets <= 0 && Random.Int(4) <= Dungeon.hero.pointsInTalent(Talent.ROGUES_FORESIGHT)){
|
if (reqSecrets <= 0 && Random.Int(4) <= Dungeon.hero.pointsInTalent(Talent.ROGUES_FORESIGHT)){
|
||||||
GLog.p(Messages.get(this, "secret_hint"));
|
GLog.p(Messages.get(this, "secret_hint"));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user