commit e50d46688dbdea3111bf255a214a72d67a2874bc
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Mar 21 19:01:43 2021 +0100

    1) in case of several obejct, we need return to the original max num of scrambles - otherwise the records in the DB do not show.
    2) implement proper automatic scrambling of the 2Bar and the 3Plate bandaged cubes.

diff --git a/src/main/java/org/distorted/objects/ObjectList.java b/src/main/java/org/distorted/objects/ObjectList.java
index df3c02a4..5c2ffbc2 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 , 12, R.raw.diamond, R.drawable.ui_small_diam, R.drawable.ui_medium_diam, R.drawable.ui_big_diam, R.drawable.ui_huge_diam} ,
+                       {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} ,
                      },
          TwistyDiamond.class,
          new MovementDiamond(),
@@ -71,7 +71,7 @@ public enum ObjectList
 
   DINO (
          new int[][] {
-                       {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} ,
+                       {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} ,
                      },
          TwistyDino6.class,
          new MovementDino(),
@@ -91,7 +91,7 @@ public enum ObjectList
 
   REDI (
          new int[][] {
-                       {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} ,
+                       {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} ,
                      },
          TwistyRedi.class,
          new MovementRedi(),
@@ -101,7 +101,7 @@ public enum ObjectList
 
   HELI (
          new int[][] {
-                       {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} ,
+                       {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} ,
                      },
          TwistyHelicopter.class,
          new MovementHelicopter(),
@@ -111,8 +111,8 @@ public enum ObjectList
 
   SKEW (
          new int[][] {
-                       {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} ,
+                       {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} ,
                      },
          TwistySkewb.class,
          new MovementSkewb(),
@@ -132,7 +132,7 @@ public enum ObjectList
 
   REX  (
          new int[][] {
-                       {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} ,
+                       {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} ,
                      },
          TwistyRex.class,
          new MovementRex(),
@@ -152,7 +152,7 @@ public enum ObjectList
 
   MEGA (
          new int[][] {
-                       {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} ,
+                       {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} ,
                        {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 5d4a193c..dedeb5d6 100644
--- a/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
+++ b/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
@@ -99,37 +99,39 @@ class TwistyBandaged2Bar extends TwistyBandagedAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
-// TODO
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
     {
     if( num==0 )
       {
-      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
+      int random = rnd.nextInt(4);
+
+      scramble[num][0] = 1;
+      scramble[num][1] = random>1      ?  2:0;
+      scramble[num][2] = random%2 == 0 ? -1:1;
       }
     else
       {
-      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
-      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
-      }
+      boolean even = ((num%2) == 0);
+      int angle = rnd.nextInt(4);
 
-    float rowFloat = rnd.nextFloat();
+      scramble[num][0] = even ? 1 : scramble[0][1];
+      scramble[num][1] = rnd.nextInt(3);
 
-    for(int row=0; row<mRowChances.length; row++)
-      {
-      if( rowFloat<=mRowChances[row] )
+      if( even == (scramble[num][1]==1) )
         {
-        scramble[num][1] = row;
-        break;
+        switch(angle)
+          {
+          case 0: scramble[num][2] = -2; break;
+          case 1: scramble[num][2] = -1; break;
+          case 2: scramble[num][2] =  1; break;
+          case 3: scramble[num][2] =  2; break;
+          }
+        }
+      else
+        {
+        scramble[num][2] = angle>1 ? 2:-2;
         }
-      }
-
-    switch( rnd.nextInt(4) )
-      {
-      case 0: scramble[num][2] = -2; break;
-      case 1: scramble[num][2] = -1; break;
-      case 2: scramble[num][2] =  1; break;
-      case 3: scramble[num][2] =  2; break;
       }
     }
 
diff --git a/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java b/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java
index 0158d8e2..5387f196 100644
--- a/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java
+++ b/src/main/java/org/distorted/objects/TwistyBandaged3Plate.java
@@ -33,6 +33,127 @@ import java.util.Random;
 
 class TwistyBandaged3Plate extends TwistyBandagedAbstract
 {
+  private int mCurrState;
+  private boolean mUseX;
+  private boolean mUseY;
+  private boolean mUseZ;
+
+  private static class State
+    {
+    private final int mNumX, mNumY, mNumZ;
+    private final int[] mInfo;
+    private final int[] mTmp;
+    private final int LEN = 4;
+
+    State(int[] x, int[] y, int[] z)
+      {
+      mTmp = new int[LEN];
+
+      mNumX = x==null ? 0 : x.length/(LEN-1);
+      mNumY = y==null ? 0 : y.length/(LEN-1);
+      mNumZ = z==null ? 0 : z.length/(LEN-1);
+
+      mInfo = new int[LEN*(mNumX+mNumY+mNumZ)];
+      int start = 0;
+
+      for(int i=0; i<mNumX; i++)
+        {
+        mInfo[LEN*i   + start] = 0;
+        mInfo[LEN*i+1 + start] = x[(LEN-1)*i  ];
+        mInfo[LEN*i+2 + start] = x[(LEN-1)*i+1];
+        mInfo[LEN*i+3 + start] = x[(LEN-1)*i+2];
+        }
+
+      start = LEN*mNumX;
+
+      for(int i=0; i<mNumY; i++)
+        {
+        mInfo[LEN*i   + start] = 1;
+        mInfo[LEN*i+1 + start] = y[(LEN-1)*i  ];
+        mInfo[LEN*i+2 + start] = y[(LEN-1)*i+1];
+        mInfo[LEN*i+3 + start] = y[(LEN-1)*i+2];
+        }
+
+      start = LEN*(mNumX+mNumY);
+
+      for(int i=0; i<mNumZ; i++)
+        {
+        mInfo[LEN*i   + start] = 2;
+        mInfo[LEN*i+1 + start] = z[(LEN-1)*i  ];
+        mInfo[LEN*i+2 + start] = z[(LEN-1)*i+1];
+        mInfo[LEN*i+3 + start] = z[(LEN-1)*i+2];
+        }
+      }
+
+    private int getIndex(int num, boolean useX, boolean useY, boolean useZ)
+      {
+      int current= -1, total= mNumX + mNumY + mNumZ;
+
+      for(int i=0; i<total; i++)
+        {
+        if( (mInfo[LEN*i]==0 && useX) || (mInfo[LEN*i]==1 && useY) || (mInfo[LEN*i]==2 && useZ) )
+          {
+          if( ++current==num ) return i;
+          }
+        }
+
+      return -1;
+      }
+
+    int getTotal(boolean useX, boolean useY, boolean useZ)
+      {
+      int total = 0;
+
+      if( useX ) total += mNumX;
+      if( useY ) total += mNumY;
+      if( useZ ) total += mNumZ;
+
+      return total;
+      }
+
+    int[] getInfo(int num, boolean useX, boolean useY, boolean useZ)
+      {
+      int index = getIndex(num,useX,useY,useZ);
+
+      mTmp[0] = mInfo[LEN*index  ];   // axis
+      mTmp[1] = mInfo[LEN*index+1];   // row
+      mTmp[2] = mInfo[LEN*index+2];   // angle
+      mTmp[3] = mInfo[LEN*index+3];   // next state
+
+      return mTmp;
+      }
+    }
+
+  // The 16 'significant' states of the 3Plate bandaged cube.
+  // One State means one arrangement of the three 2x2 'plates'. Such State precisely defines which
+  // rotations of the Cube are possible.
+  // There are 27 such states in total, but 2 of them are unreachable from the initial State, and
+  // 9 more and 'insignificant' - i.e. States which only permit rotation along a single axis.
+  // When doing an automatic scramble, we never want to enter such 'insignificant' states because
+  // that would mean we'd have to do two rotations in a row along the same axis.
+
+  private final State[] mStates = new State[]
+      {
+         new State( new int[] { 2,-1, 1, 2, 1, 6                  }, new int[] { 0,-1, 5, 0, 1, 3                  }, new int[] { 2,-1, 2, 2, 1, 4                  } ),
+         new State( new int[] { 2, 1, 0                           }, null                                           , new int[] { 2, 1,10, 2, 2, 7                  } ),
+         new State( null                                           , new int[] { 0,-1,11, 0, 2, 8                  }, new int[] { 2, 1, 0                           } ),
+         new State( new int[] { 2, 1,12, 2, 2, 9                  }, new int[] { 0,-1, 0                           }, null                                            ),
+         new State( new int[] { 2,-1,10, 2, 2,13                  }, null                                           , new int[] { 2,-1, 0                           } ),
+         new State( null                                           , new int[] { 0, 1, 0                           }, new int[] { 2,-1,11, 2, 2,14                  } ),
+         new State( new int[] { 2,-1, 0                           }, new int[] { 0, 1,12, 0, 2,15                  }, null                                            ),
+         new State( null                                           , new int[] { 2,-2, 7, 2,-1, 7, 2, 1, 7, 2, 2, 7}, new int[] { 2,-1,10, 2, 2, 1                  } ),
+         new State( new int[] { 0,-2, 8, 0,-1, 8, 0, 1, 8, 0, 2, 8}, new int[] { 0, 1,11, 0, 2, 2                  }, null                                            ),
+         new State( new int[] { 2,-1,12, 2, 2, 3                  }, null                                           , new int[] { 0,-2, 9, 0,-1, 9, 0, 1, 9, 0, 2, 9} ),
+         new State( new int[] { 2,-1,13, 2, 1, 4                  }, new int[] { 2,-2,10, 2,-1,10, 2, 1,10, 2, 2,10}, new int[] { 2,-1, 1, 2, 1, 7                  } ),
+         new State( new int[] { 0,-2,11, 0,-1,11, 0, 1,11, 0, 2,11}, new int[] { 0,-1, 8, 0, 1, 2                  }, new int[] { 2,-1,14, 2, 1, 5                  } ),
+         new State( new int[] { 2,-1, 3, 2, 1, 9                  }, new int[] { 0,-1, 6, 0, 1,15                  }, new int[] { 0,-2,12, 0,-1,12, 0, 1,12, 0, 2,12} ),
+         new State( new int[] { 2, 1,10, 2, 2, 4                  }, new int[] { 2,-2,13, 2,-1,13, 2, 1,13, 2, 2,13}, null                                            ),
+         new State( new int[] { 0,-2,14, 0,-1,14, 0, 1,14, 0, 2,14}, null                                           , new int[] { 2, 1,11, 2, 2, 5                  } ),
+         new State( null                                           , new int[] { 0, 1,12, 0, 2, 6                  }, new int[] { 0,-2,15, 0,-1,15, 0, 1,15, 0, 2,15} )
+      };
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
   TwistyBandaged3Plate(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
                        DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
     {
@@ -105,37 +226,32 @@ class TwistyBandaged3Plate extends TwistyBandagedAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
-// TODO
 
   public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
     {
     if( num==0 )
       {
-      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
-      }
-    else
-      {
-      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
-      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
+      mCurrState = 0;
+      mUseX = true;
+      mUseY = true;
+      mUseZ = true;
       }
 
-    float rowFloat = rnd.nextFloat();
+    int total = mStates[mCurrState].getTotal(mUseX,mUseY,mUseZ);
+    int random= rnd.nextInt(total);
+    int[] info= mStates[mCurrState].getInfo(random,mUseX,mUseY,mUseZ);
 
-    for(int row=0; row<mRowChances.length; row++)
-      {
-      if( rowFloat<=mRowChances[row] )
-        {
-        scramble[num][1] = row;
-        break;
-        }
-      }
+    scramble[num][0] = info[0];
+    scramble[num][1] = info[1];
+    scramble[num][2] = info[2];
+
+    mCurrState = info[3];
 
-    switch( rnd.nextInt(4) )
+    switch(info[0])
       {
-      case 0: scramble[num][2] = -2; break;
-      case 1: scramble[num][2] = -1; break;
-      case 2: scramble[num][2] =  1; break;
-      case 3: scramble[num][2] =  2; break;
+      case 0: mUseX = false; mUseY = true ; mUseZ = true ; break;
+      case 1: mUseX = true ; mUseY = false; mUseZ = true ; break;
+      case 2: mUseX = true ; mUseY = true ; mUseZ = false; break;
       }
     }
 
