diff --git a/SPD-classes/src/main/java/com/watabou/utils/Random.java b/SPD-classes/src/main/java/com/watabou/utils/Random.java index df7e53bfc..93a648a0a 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/Random.java +++ b/SPD-classes/src/main/java/com/watabou/utils/Random.java @@ -21,6 +21,9 @@ package com.watabou.utils; +import com.watabou.noosa.Game; + +import java.util.ArrayDeque; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -28,19 +31,38 @@ import java.util.List; public class Random { - private static java.util.Random rand = new java.util.Random(); - - public static void seed( ){ - rand = new java.util.Random(); + //we store a stack of random number generators, which may be seeded deliberately or randomly. + //top of the stack is what is currently being used to generate new numbers. + //the base generator is always created with no seed, and cannot be popped. + private static ArrayDeque generators; + static { + resetGenerators(); } - public static void seed( long seed ){ - rand.setSeed(seed); + public static void resetGenerators(){ + generators = new ArrayDeque<>(); + generators.push(new java.util.Random()); + } + + public static void pushGenerator(){ + generators.push( new java.util.Random() ); + } + + public static void pushGenerator( long seed ){ + generators.push( new java.util.Random( seed ) ); + } + + public static void popGenerator(){ + if (generators.size() == 1){ + Game.reportException( new RuntimeException("tried to pop the last random number generator!")); + } else { + generators.pop(); + } } //returns a uniformly distributed float in the range [0, 1) public static float Float() { - return rand.nextFloat(); + return generators.peek().nextFloat(); } //returns a uniformly distributed float in the range [0, max) @@ -60,7 +82,7 @@ public class Random { //returns a uniformly distributed int in the range [0, max) public static int Int( int max ) { - return max > 0 ? rand.nextInt(max) : 0; + return max > 0 ? generators.peek().nextInt(max) : 0; } //returns a uniformly distributed int in the range [min, max) @@ -80,7 +102,7 @@ public class Random { //returns a uniformly distributed long in the range [-2^63, 2^63) public static long Long() { - return rand.nextLong(); + return generators.peek().nextLong(); } //returns a uniformly distributed long in the range [0, max) @@ -169,7 +191,7 @@ public class Random { } public static void shuffle( List list){ - Collections.shuffle(list, rand); + Collections.shuffle(list, generators.peek()); } public static void shuffle( T[] array ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index 057eda516..e5f8500db 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -173,7 +173,7 @@ public class Dungeon { Actor.clear(); Actor.resetNextID(); - Random.seed( seed ); + Random.pushGenerator( seed ); Scroll.initLabels(); Potion.initColors(); @@ -182,7 +182,7 @@ public class Dungeon { SpecialRoom.initForRun(); SecretRoom.initForRun(); - Random.seed(); + Random.resetGenerators(); Statistics.reset(); Notes.reset(); @@ -313,11 +313,14 @@ public class Dungeon { } public static long seedForDepth(int depth){ - Random.seed( seed ); - for (int i = 0; i < depth; i ++) - Random.Long(); //we don't care about these values, just need to go through them - long result = Random.Long(); - Random.seed(); + Random.pushGenerator( seed ); + + for (int i = 0; i < depth; i ++) { + Random.Long(); //we don't care about these values, just need to go through them + } + long result = Random.Long(); + + Random.popGenerator(); return result; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index 21e2d6dbc..7d3550fe2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -169,7 +169,7 @@ public abstract class Level implements Bundlable { public void create() { - Random.seed( Dungeon.seedCurDepth() ); + Random.pushGenerator( Dungeon.seedCurDepth() ); if (!(Dungeon.bossLevel() || Dungeon.depth == 21) /*final shop floor*/) { @@ -261,7 +261,7 @@ public abstract class Level implements Bundlable { createMobs(); createItems(); - Random.seed(); + Random.popGenerator(); } public void setSize(int w, int h){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java index 4392b8c47..f838e3c5d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java @@ -392,11 +392,14 @@ public class DungeonTileSheet { public static byte[] tileVariance; public static void setupVariance(int size, long seed){ - Random.seed( seed ); - tileVariance = new byte[size]; - for (int i = 0; i < tileVariance.length; i++) - tileVariance[i] = (byte)Random.Int(100); - Random.seed(); + Random.pushGenerator( seed ); + + tileVariance = new byte[size]; + for (int i = 0; i < tileVariance.length; i++) { + tileVariance[i] = (byte) Random.Int(100); + } + + Random.popGenerator(); } //These alt visuals will trigger 50% of the time (45% of the time if a rare alt is also present)