commit bbc6471ca49d9ddeeab72218f59e7655f37f6e93
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat Mar 20 00:36:12 2021 +0100

    Change the automatic scramble API in the TwistyObject - in preparation for automatic scrambles in the Bandaged Objects.

diff --git a/src/main/java/org/distorted/effects/scramble/ScrambleEffect.java b/src/main/java/org/distorted/effects/scramble/ScrambleEffect.java
index 38bf43c8..c2c7695e 100644
--- a/src/main/java/org/distorted/effects/scramble/ScrambleEffect.java
+++ b/src/main/java/org/distorted/effects/scramble/ScrambleEffect.java
@@ -49,7 +49,7 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
       }
     }
 
-  private static int NUM_EFFECTS = Type.values().length;
+  private static final int NUM_EFFECTS = Type.values().length;
   private static final int FAKE_EFFECT_ID  = -3;
   private static final Type[] types;
 
@@ -72,7 +72,7 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
   private int mNumDoubleScramblesLeft, mNumScramblesLeft;
   private int mLastRotAxis, mLastRow;
   private long mDurationSingleTurn;
-  private Random mRnd;
+  private final Random mRnd;
   private int mBasicAngle;
 
   TwistyObject mObject;
@@ -81,12 +81,15 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
   Effect[] mCubeEffects;
   int[] mCubeEffectPosition;
   int mCubeEffectNumber, mNodeEffectNumber;
+  int mNumScrambles;
+  int[] mScramble;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   ScrambleEffect()
     {
     mRnd = new Random( System.currentTimeMillis() );
+    mScramble = new int[3];
     mLastRotAxis = START_AXIS;
     }
 
@@ -125,6 +128,7 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
       }
 
     mDurationSingleTurn = duration/(mNumScramblesLeft+mNumDoubleScramblesLeft);
+    mNumScrambles = 0;
 
     addNewScramble();
     }
@@ -136,12 +140,15 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
     {
     if( mNumScramblesLeft>0 )
       {
-      int lastRotAxis = mLastRotAxis;
-      mLastRotAxis = mObject.randomizeNewRotAxis(mRnd,mLastRotAxis);
-      mLastRow = mObject.randomizeNewRow(mRnd,lastRotAxis,mLastRow,mLastRotAxis);
+      mNumScrambles++;
+
+      mObject.randomizeNewScramble(mScramble, mRnd,mLastRotAxis, mLastRow, mNumScrambles,
+                                  mNumScramblesLeft, mNumDoubleScramblesLeft);
+      mLastRotAxis = mScramble[0];
+      mLastRow     = mScramble[1];
+      int angle    = mScramble[2];
 
       int rowBitmap  = (1<<mLastRow);
-      int angle= randomizeAngle();
       int absAngle = (angle<0 ? -angle : angle);
       long durationMillis = absAngle*mDurationSingleTurn;
 
@@ -166,18 +173,6 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
       }
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// only works for basicAngle<=5.
-
-  private int randomizeAngle()
-    {
-    int random = mRnd.nextInt(mNumScramblesLeft);
-    int result = random<mNumDoubleScramblesLeft ? 2:1;
-    int sign   = mRnd.nextInt(2);
-
-    return sign==0 ? result : -result;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void assignEffects()
diff --git a/src/main/java/org/distorted/objects/ObjectList.java b/src/main/java/org/distorted/objects/ObjectList.java
index 5c2ffbc2..df3c02a4 100644
--- a/src/main/java/org/distorted/objects/ObjectList.java
+++ b/src/main/java/org/distorted/objects/ObjectList.java
@@ -61,7 +61,7 @@ public enum ObjectList
 
   DIAM (
          new int[][] {
-                       {2 , 10, R.raw.diamond, R.drawable.ui_small_diam, R.drawable.ui_medium_diam, R.drawable.ui_big_diam, R.drawable.ui_huge_diam} ,
+                       {2 , 12, R.raw.diamond, R.drawable.ui_small_diam, R.drawable.ui_medium_diam, R.drawable.ui_big_diam, R.drawable.ui_huge_diam} ,
                      },
          TwistyDiamond.class,
          new MovementDiamond(),
@@ -71,7 +71,7 @@ public enum ObjectList
 
   DINO (
          new int[][] {
-                       {3 , 10, R.raw.dino, R.drawable.ui_small_dino, R.drawable.ui_medium_dino, R.drawable.ui_big_dino, R.drawable.ui_huge_dino} ,
+                       {3 , 12, R.raw.dino, R.drawable.ui_small_dino, R.drawable.ui_medium_dino, R.drawable.ui_big_dino, R.drawable.ui_huge_dino} ,
                      },
          TwistyDino6.class,
          new MovementDino(),
@@ -91,7 +91,7 @@ public enum ObjectList
 
   REDI (
          new int[][] {
-                       {3 , 14, R.raw.redi, R.drawable.ui_small_redi, R.drawable.ui_medium_redi, R.drawable.ui_big_redi, R.drawable.ui_huge_redi} ,
+                       {3 , 18, R.raw.redi, R.drawable.ui_small_redi, R.drawable.ui_medium_redi, R.drawable.ui_big_redi, R.drawable.ui_huge_redi} ,
                      },
          TwistyRedi.class,
          new MovementRedi(),
@@ -101,7 +101,7 @@ public enum ObjectList
 
   HELI (
          new int[][] {
-                       {3 , 18, R.raw.heli, R.drawable.ui_small_heli, R.drawable.ui_medium_heli, R.drawable.ui_big_heli, R.drawable.ui_huge_heli} ,
+                       {3 , 20, R.raw.heli, R.drawable.ui_small_heli, R.drawable.ui_medium_heli, R.drawable.ui_big_heli, R.drawable.ui_huge_heli} ,
                      },
          TwistyHelicopter.class,
          new MovementHelicopter(),
@@ -111,8 +111,8 @@ public enum ObjectList
 
   SKEW (
          new int[][] {
-                       {2 , 11, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
-                       {3 , 17, R.raw.skewm, R.drawable.ui_small_skewm, R.drawable.ui_medium_skewm, R.drawable.ui_big_skewm, R.drawable.ui_huge_skewm} ,
+                       {2 , 12, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
+                       {3 , 21, R.raw.skewm, R.drawable.ui_small_skewm, R.drawable.ui_medium_skewm, R.drawable.ui_big_skewm, R.drawable.ui_huge_skewm} ,
                      },
          TwistySkewb.class,
          new MovementSkewb(),
@@ -132,7 +132,7 @@ public enum ObjectList
 
   REX  (
          new int[][] {
-                       {3 , 16, R.raw.rex, R.drawable.ui_small_rex, R.drawable.ui_medium_rex, R.drawable.ui_big_rex, R.drawable.ui_huge_rex} ,
+                       {3 , 18, R.raw.rex, R.drawable.ui_small_rex, R.drawable.ui_medium_rex, R.drawable.ui_big_rex, R.drawable.ui_huge_rex} ,
                      },
          TwistyRex.class,
          new MovementRex(),
@@ -152,7 +152,7 @@ public enum ObjectList
 
   MEGA (
          new int[][] {
-                       {3 , 21, R.raw.mega3, R.drawable.ui_small_mega3, R.drawable.ui_medium_mega3, R.drawable.ui_big_mega3, R.drawable.ui_huge_mega3} ,
+                       {3 , 24, R.raw.mega3, R.drawable.ui_small_mega3, R.drawable.ui_medium_mega3, R.drawable.ui_big_mega3, R.drawable.ui_huge_mega3} ,
                        {5 , 35, R.raw.mega5, R.drawable.ui_small_mega5, R.drawable.ui_medium_mega5, R.drawable.ui_big_mega5, R.drawable.ui_huge_mega5} ,
                      },
          TwistyMegaminx.class,
diff --git a/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java b/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
index 7edd24dc..bea33921 100644
--- a/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
+++ b/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
@@ -29,8 +29,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 class TwistyBandaged2Bar extends TwistyBandagedAbstract
@@ -102,34 +100,36 @@ class TwistyBandaged2Bar extends TwistyBandagedAbstract
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 // TODO
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
-    {
-    int numAxis = ROTATION_AXIS.length;
 
-    if( oldRotAxis == START_AXIS )
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
+    {
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
-
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java b/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java
index 179fa109..8fed7e19 100644
--- a/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java
+++ b/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java
@@ -29,8 +29,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 class TwistyBandaged3Plate extends TwistyBandagedAbstract
@@ -108,34 +106,36 @@ class TwistyBandaged3Plate extends TwistyBandagedAbstract
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 // TODO
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
-    {
-    int numAxis = ROTATION_AXIS.length;
 
-    if( oldRotAxis == START_AXIS )
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
+    {
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyBandagedEvil.java b/src/main/java/org/distorted/objects/TwistyBandagedEvil.java
index 2101b1ff..cb03fd46 100644
--- a/src/main/java/org/distorted/objects/TwistyBandagedEvil.java
+++ b/src/main/java/org/distorted/objects/TwistyBandagedEvil.java
@@ -29,8 +29,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 class TwistyBandagedEvil extends TwistyBandagedAbstract
@@ -120,34 +118,36 @@ class TwistyBandagedEvil extends TwistyBandagedAbstract
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 // TODO
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
-    {
-    int numAxis = ROTATION_AXIS.length;
 
-    if( oldRotAxis == START_AXIS )
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
+    {
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
-
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyBandagedFused.java b/src/main/java/org/distorted/objects/TwistyBandagedFused.java
index de893538..ca1ba9f8 100644
--- a/src/main/java/org/distorted/objects/TwistyBandagedFused.java
+++ b/src/main/java/org/distorted/objects/TwistyBandagedFused.java
@@ -101,35 +101,36 @@ class TwistyBandagedFused extends TwistyBandagedAbstract
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyCube.java b/src/main/java/org/distorted/objects/TwistyCube.java
index eae64ba1..dbae693f 100644
--- a/src/main/java/org/distorted/objects/TwistyCube.java
+++ b/src/main/java/org/distorted/objects/TwistyCube.java
@@ -33,8 +33,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 class TwistyCube extends TwistyObject
@@ -256,33 +254,35 @@ class TwistyCube extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyDiamond.java b/src/main/java/org/distorted/objects/TwistyDiamond.java
index 543917e4..dfee2c28 100644
--- a/src/main/java/org/distorted/objects/TwistyDiamond.java
+++ b/src/main/java/org/distorted/objects/TwistyDiamond.java
@@ -35,8 +35,6 @@ import org.distorted.main.RubikSurfaceView;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyDiamond extends TwistyObject
@@ -293,33 +291,35 @@ public class TwistyDiamond extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyDino.java b/src/main/java/org/distorted/objects/TwistyDino.java
index de26b728..1afcf646 100644
--- a/src/main/java/org/distorted/objects/TwistyDino.java
+++ b/src/main/java/org/distorted/objects/TwistyDino.java
@@ -32,10 +32,6 @@ import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.main.RubikSurfaceView;
 
-import java.util.Random;
-
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public abstract class TwistyDino extends TwistyObject
@@ -250,23 +246,6 @@ public abstract class TwistyDino extends TwistyObject
     return 3;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
-    {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
-      {
-      return rnd.nextInt(numAxis);
-      }
-    else
-      {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
-      }
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // only needed for solvers - there are no Dino solvers ATM)
 
diff --git a/src/main/java/org/distorted/objects/TwistyDino4.java b/src/main/java/org/distorted/objects/TwistyDino4.java
index 2c0802cb..fb0124c6 100644
--- a/src/main/java/org/distorted/objects/TwistyDino4.java
+++ b/src/main/java/org/distorted/objects/TwistyDino4.java
@@ -29,8 +29,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyDino4 extends TwistyDino
@@ -68,9 +66,26 @@ public class TwistyDino4 extends TwistyDino
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    return (oldRotAxis==START_AXIS) ? ((newRotAxis==1 || newRotAxis==2) ? 0:2) : (oldRotAxis+newRotAxis==3 ? 2-oldRow : oldRow);
+    if( numScramble==1 )
+      {
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
+      }
+    else
+      {
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
+      }
+
+    scramble[1] = (numScramble==1) ? ((scramble[0]==1 || scramble[0]==2) ? 0:2) : (oldRotAxis+scramble[0]==3 ? 2-oldRow : oldRow);
+
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyDino6.java b/src/main/java/org/distorted/objects/TwistyDino6.java
index 9e75dadc..1b9e9753 100644
--- a/src/main/java/org/distorted/objects/TwistyDino6.java
+++ b/src/main/java/org/distorted/objects/TwistyDino6.java
@@ -29,8 +29,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyDino6 extends TwistyDino
@@ -68,9 +66,26 @@ public class TwistyDino6 extends TwistyDino
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    return (oldRotAxis==START_AXIS) ? (rnd.nextFloat()<=0.5f ? 0:2) : (oldRotAxis+newRotAxis==3 ? 2-oldRow : oldRow);
+    if( numScramble==1 )
+      {
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
+      }
+    else
+      {
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
+      }
+
+    scramble[1] = (numScramble==1) ? (rnd.nextFloat()<=0.5f ? 0:2) : (oldRotAxis+scramble[0]==3 ? 2-oldRow : oldRow);
+
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyHelicopter.java b/src/main/java/org/distorted/objects/TwistyHelicopter.java
index 5b60eaa0..c3094d58 100644
--- a/src/main/java/org/distorted/objects/TwistyHelicopter.java
+++ b/src/main/java/org/distorted/objects/TwistyHelicopter.java
@@ -35,8 +35,6 @@ import org.distorted.main.RubikSurfaceView;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyHelicopter extends TwistyObject
@@ -337,41 +335,46 @@ public class TwistyHelicopter extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-2);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-2);
 
       switch(oldRotAxis)
         {
         case  0:
-        case  1: return newVector+2;
+        case  1: scramble[0] = newVector+2;
+                 break;
         case  2:
-        case  3: return (newVector==0 || newVector==1) ? newVector:newVector+2;
-        default: return newVector;
+        case  3: scramble[0] = (newVector==0 || newVector==1) ? newVector:newVector+2;
+                 break;
+        default: scramble[0] = newVector;
+                 break;
         }
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyIvy.java b/src/main/java/org/distorted/objects/TwistyIvy.java
index 94b98cc0..4e7fe6c9 100644
--- a/src/main/java/org/distorted/objects/TwistyIvy.java
+++ b/src/main/java/org/distorted/objects/TwistyIvy.java
@@ -35,8 +35,6 @@ import org.distorted.main.RubikSurfaceView;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyIvy extends TwistyObject
@@ -283,33 +281,35 @@ public class TwistyIvy extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyMinx.java b/src/main/java/org/distorted/objects/TwistyMinx.java
index 3b23c30e..82baffae 100644
--- a/src/main/java/org/distorted/objects/TwistyMinx.java
+++ b/src/main/java/org/distorted/objects/TwistyMinx.java
@@ -29,8 +29,6 @@ import org.distorted.library.type.Static4D;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 abstract class TwistyMinx extends TwistyObject
@@ -282,45 +280,47 @@ abstract class TwistyMinx extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
-    if( oldRotAxis<0 )
+    if( numScramble==1 )
       {
       float rowFloat = rnd.nextFloat();
 
       for(int row=0; row<mRowChances.length; row++)
         {
-        if( rowFloat<=mRowChances[row] ) return row;
+        if( rowFloat<=mRowChances[row] )
+          {
+          scramble[1] = row;
+          break;
+          }
         }
-
-      return 0;
       }
     else
       {
       int size = mRowChances.length;
       int num = (size-1)/2;
       int row = rnd.nextInt(num);
-      boolean opposite = OPPOSITE_ROWS[oldRotAxis][newRotAxis];
+      boolean opposite = OPPOSITE_ROWS[oldRotAxis][scramble[0]];
       boolean low = opposite^(oldRow<num);
-      return low ? row : size-1-row;
+      scramble[1] = low ? row : size-1-row;
       }
+
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyObject.java b/src/main/java/org/distorted/objects/TwistyObject.java
index c3e67ef6..e1f2056b 100644
--- a/src/main/java/org/distorted/objects/TwistyObject.java
+++ b/src/main/java/org/distorted/objects/TwistyObject.java
@@ -913,8 +913,7 @@ public abstract class TwistyObject extends DistortedNode
   public abstract Static3D[] getRotationAxis();
   public abstract int getBasicAngle();
   public abstract String retObjectString();
-  public abstract int randomizeNewRotAxis(Random rnd, int oldRotAxis);
-  public abstract int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis);
+  public abstract void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow, int numScramble, int remScrambles, int remDoubleScrambles);
   public abstract int getObjectName(int numLayers);
   public abstract int getInventor(int numLayers);
   public abstract int getComplexity(int numLayers);
diff --git a/src/main/java/org/distorted/objects/TwistyPyraminx.java b/src/main/java/org/distorted/objects/TwistyPyraminx.java
index 3d30b2d5..720a64fb 100644
--- a/src/main/java/org/distorted/objects/TwistyPyraminx.java
+++ b/src/main/java/org/distorted/objects/TwistyPyraminx.java
@@ -33,8 +33,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyPyraminx extends TwistyObject
@@ -288,33 +286,35 @@ public class TwistyPyraminx extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyRedi.java b/src/main/java/org/distorted/objects/TwistyRedi.java
index 50e81b35..b8088e26 100644
--- a/src/main/java/org/distorted/objects/TwistyRedi.java
+++ b/src/main/java/org/distorted/objects/TwistyRedi.java
@@ -34,8 +34,6 @@ import org.distorted.main.R;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyRedi extends TwistyObject
@@ -330,26 +328,26 @@ public class TwistyRedi extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    scramble[1] = (numScramble==1) ? (rnd.nextFloat()<=0.5f ? 0:2) : (oldRotAxis+scramble[0]==3 ? 2-oldRow : oldRow);
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
-    return (oldRotAxis==START_AXIS) ? (rnd.nextFloat()<=0.5f ? 0:2) : (oldRotAxis+newRotAxis==3 ? 2-oldRow : oldRow);
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyRex.java b/src/main/java/org/distorted/objects/TwistyRex.java
index 5749a339..aa47497d 100644
--- a/src/main/java/org/distorted/objects/TwistyRex.java
+++ b/src/main/java/org/distorted/objects/TwistyRex.java
@@ -35,7 +35,6 @@ import org.distorted.main.RubikSurfaceView;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 import static org.distorted.objects.FactoryCubit.REX_D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -393,33 +392,35 @@ public class TwistyRex extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistySkewb.java b/src/main/java/org/distorted/objects/TwistySkewb.java
index b2af4b62..8fbb4b94 100644
--- a/src/main/java/org/distorted/objects/TwistySkewb.java
+++ b/src/main/java/org/distorted/objects/TwistySkewb.java
@@ -37,8 +37,6 @@ import org.distorted.main.RubikSurfaceView;
 
 import java.util.Random;
 
-import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistySkewb extends TwistyObject
@@ -541,33 +539,35 @@ public class TwistySkewb extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
+  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
+                                   int numScramble, int remScrambles, int remDoubleScrambles)
     {
-    int numAxis = ROTATION_AXIS.length;
-
-    if( oldRotAxis == START_AXIS )
+    if( numScramble==1 )
       {
-      return rnd.nextInt(numAxis);
+      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
       }
     else
       {
-      int newVector = rnd.nextInt(numAxis-1);
-      return (newVector>=oldRotAxis ? newVector+1 : newVector);
+      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
+      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
       }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
-    {
     float rowFloat = rnd.nextFloat();
 
     for(int row=0; row<mRowChances.length; row++)
       {
-      if( rowFloat<=mRowChances[row] ) return row;
+      if( rowFloat<=mRowChances[row] )
+        {
+        scramble[1] = row;
+        break;
+        }
       }
 
-    return 0;
+    int random = rnd.nextInt(remScrambles);
+    int result = random<remDoubleScrambles ? 2:1;
+    int sign   = rnd.nextInt(2);
+
+    scramble[2] = sign==0 ? result : -result;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
