commit e1dc336632fe472c08bebcd0287fc5bc79b54638
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Aug 31 17:46:49 2021 +0200

    Introduce pseudorandom balancing into scrambling to all the other already converted objects, i.e. everytihng except for Pyraminxes, Squares, Minxes and the Redi.

diff --git a/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java b/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java
index d68d4084..1b566505 100644
--- a/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java
+++ b/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java
@@ -154,6 +154,8 @@ abstract class TwistyBandagedAbstract extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -447,6 +449,33 @@ abstract class TwistyBandagedAbstract extends TwistyObject
     return getNumLayers();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void initializeScrambling()
+    {
+    int numLayers = getNumLayers();
+
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
+
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 
@@ -456,11 +485,10 @@ abstract class TwistyBandagedAbstract extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
diff --git a/src/main/java/org/distorted/objects/TwistyCube.java b/src/main/java/org/distorted/objects/TwistyCube.java
index 38fee4b6..9f6284aa 100644
--- a/src/main/java/org/distorted/objects/TwistyCube.java
+++ b/src/main/java/org/distorted/objects/TwistyCube.java
@@ -132,6 +132,8 @@ class TwistyCube extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -370,6 +372,33 @@ class TwistyCube extends TwistyObject
     return BASIC_ANGLE;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void initializeScrambling()
+    {
+    int numLayers = getNumLayers();
+
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
+
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
@@ -378,11 +407,10 @@ class TwistyCube extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
diff --git a/src/main/java/org/distorted/objects/TwistyDiamond.java b/src/main/java/org/distorted/objects/TwistyDiamond.java
index 4b8376ba..9e2067e9 100644
--- a/src/main/java/org/distorted/objects/TwistyDiamond.java
+++ b/src/main/java/org/distorted/objects/TwistyDiamond.java
@@ -139,6 +139,8 @@ public class TwistyDiamond extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -518,21 +520,34 @@ public class TwistyDiamond extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -540,11 +555,10 @@ public class TwistyDiamond extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -554,6 +568,20 @@ public class TwistyDiamond extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
diff --git a/src/main/java/org/distorted/objects/TwistyHelicopter.java b/src/main/java/org/distorted/objects/TwistyHelicopter.java
index 155596c7..04383cb6 100644
--- a/src/main/java/org/distorted/objects/TwistyHelicopter.java
+++ b/src/main/java/org/distorted/objects/TwistyHelicopter.java
@@ -239,6 +239,8 @@ public class TwistyHelicopter extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -415,21 +417,34 @@ public class TwistyHelicopter extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -437,11 +452,10 @@ public class TwistyHelicopter extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -451,6 +465,20 @@ public class TwistyHelicopter extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
diff --git a/src/main/java/org/distorted/objects/TwistyIvy.java b/src/main/java/org/distorted/objects/TwistyIvy.java
index 7e117111..afeebf0a 100644
--- a/src/main/java/org/distorted/objects/TwistyIvy.java
+++ b/src/main/java/org/distorted/objects/TwistyIvy.java
@@ -120,6 +120,8 @@ public class TwistyIvy extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -446,21 +448,34 @@ public class TwistyIvy extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -468,11 +483,10 @@ public class TwistyIvy extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -482,6 +496,20 @@ public class TwistyIvy extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
diff --git a/src/main/java/org/distorted/objects/TwistyJing.java b/src/main/java/org/distorted/objects/TwistyJing.java
index b248f41f..f4a3f322 100644
--- a/src/main/java/org/distorted/objects/TwistyJing.java
+++ b/src/main/java/org/distorted/objects/TwistyJing.java
@@ -219,6 +219,8 @@ public class TwistyJing extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -396,21 +398,34 @@ public class TwistyJing extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -418,11 +433,10 @@ public class TwistyJing extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -432,6 +446,20 @@ public class TwistyJing extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
diff --git a/src/main/java/org/distorted/objects/TwistyRex.java b/src/main/java/org/distorted/objects/TwistyRex.java
index 668b4074..e260dbf1 100644
--- a/src/main/java/org/distorted/objects/TwistyRex.java
+++ b/src/main/java/org/distorted/objects/TwistyRex.java
@@ -156,6 +156,8 @@ public class TwistyRex extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -477,21 +479,34 @@ public class TwistyRex extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -499,11 +514,10 @@ public class TwistyRex extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -513,6 +527,20 @@ public class TwistyRex extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
diff --git a/src/main/java/org/distorted/objects/TwistySkewb.java b/src/main/java/org/distorted/objects/TwistySkewb.java
index adb05f40..4a891927 100644
--- a/src/main/java/org/distorted/objects/TwistySkewb.java
+++ b/src/main/java/org/distorted/objects/TwistySkewb.java
@@ -193,6 +193,8 @@ public class TwistySkewb extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -595,21 +597,34 @@ public class TwistySkewb extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -617,11 +632,10 @@ public class TwistySkewb extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -631,6 +645,20 @@ public class TwistySkewb extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
diff --git a/src/main/java/org/distorted/objects/TwistyUltimate.java b/src/main/java/org/distorted/objects/TwistyUltimate.java
index e69c7953..61e6f570 100644
--- a/src/main/java/org/distorted/objects/TwistyUltimate.java
+++ b/src/main/java/org/distorted/objects/TwistyUltimate.java
@@ -236,6 +236,8 @@ class TwistyUltimate extends TwistyObject
   private int mCurrState;
   private int mIndexExcluded;
   private final ScrambleState[] mStates;
+  private int[][] mScrambleTable;
+  private int[] mNumOccurences;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -412,21 +414,34 @@ class TwistyUltimate extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public Static3D[] getRotationAxis()
+  private void initializeScrambling()
     {
-    return ROT_AXIS;
-    }
+    int numLayers = getNumLayers();
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    if( mScrambleTable ==null )
+      {
+      mScrambleTable = new int[NUM_AXIS][numLayers];
+      }
+    if( mNumOccurences ==null )
+      {
+      int max=0;
 
-  public int[] getBasicAngle()
-    {
-    return BASIC_ANGLE;
+      for (ScrambleState mState : mStates)
+        {
+        int tmp = mState.getTotal(-1);
+        if (max < tmp) max = tmp;
+        }
+
+      mNumOccurences = new int[max];
+      }
+
+    for(int i=0; i<NUM_AXIS; i++)
+      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
     {
@@ -434,11 +449,10 @@ class TwistyUltimate extends TwistyObject
       {
       mCurrState     = 0;
       mIndexExcluded =-1;
+      initializeScrambling();
       }
 
-    int total = mStates[mCurrState].getTotal(mIndexExcluded);
-    int random= rnd.nextInt(total);
-    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
+    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
 
     scramble[curr][0] = info[0];
     scramble[curr][1] = info[1];
@@ -448,6 +462,20 @@ class TwistyUltimate extends TwistyObject
     mIndexExcluded = info[0];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static3D[] getRotationAxis()
+    {
+    return ROT_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[] getBasicAngle()
+    {
+    return BASIC_ANGLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getObjectName(int numLayers)
