commit cff92952d74eae62c588122fc4e6e012e2c92609
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Mar 20 16:09:02 2023 +0100

    Progess with Skewb solver.

diff --git a/src/main/java/org/distorted/solvers/SolverCube2.java b/src/main/java/org/distorted/solvers/SolverCube2.java
index 35387619..059158ef 100644
--- a/src/main/java/org/distorted/solvers/SolverCube2.java
+++ b/src/main/java/org/distorted/solvers/SolverCube2.java
@@ -148,10 +148,8 @@ public class SolverCube2 extends SolverTablebase
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int tablebaseIndex(TwistyObject object)
+  private void getCorners(TwistyObject object, int[][] corners)
     {
-    int[][] corners= new int[8][3];
-
     corners[0][0] = object.getCubitFaceStickerIndex(0,1);
     corners[0][1] = object.getCubitFaceStickerIndex(0,3);
     corners[0][2] = object.getCubitFaceStickerIndex(0,5);
@@ -183,6 +181,14 @@ public class SolverCube2 extends SolverTablebase
     corners[7][0] = object.getCubitFaceStickerIndex(7,1);
     corners[7][1] = object.getCubitFaceStickerIndex(7,3);
     corners[7][2] = object.getCubitFaceStickerIndex(7,5);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int tablebaseIndex(TwistyObject object)
+    {
+    int[][] corners= new int[8][3];
+    getCorners(object,corners);
 
     int result0 = computeFaceColors(corners);
     if( result0<0 ) return result0;
diff --git a/src/main/java/org/distorted/solvers/SolverPyraminxDuo.java b/src/main/java/org/distorted/solvers/SolverPyraminxDuo.java
index ac0c1f14..c2b8d2e4 100644
--- a/src/main/java/org/distorted/solvers/SolverPyraminxDuo.java
+++ b/src/main/java/org/distorted/solvers/SolverPyraminxDuo.java
@@ -31,7 +31,7 @@ public class SolverPyraminxDuo extends SolverTablebase
   private static final int ERROR_CENTER_B_MISSING = -7;
   private static final int ERROR_CENTER_R_MISSING = -8;
 
-  private static final int ERROR_TWO_CENTERS_SWAP = -9;
+  private static final int ERROR_TWO_CENTERS      = -9;
   private static final int ERROR_CORNER_TWISTED   = -10;
 
   private static final int ERROR_CORNERS_CANNOT   = -11;
@@ -227,7 +227,7 @@ public class SolverPyraminxDuo extends SolverTablebase
     int twist_gr = computeCenterTwist(centers,faces[1],faces[2]);
     int twist_ry = computeCenterTwist(centers,faces[2],faces[0]);
 
-    if( (twist_ry-twist_gr+1)%3 != 0 ) return ERROR_TWO_CENTERS_SWAP;
+    if( (twist_ry-twist_gr+1)%3 != 0 ) return ERROR_TWO_CENTERS;
 
     int total_twist=0;
 
@@ -275,7 +275,7 @@ public class SolverPyraminxDuo extends SolverTablebase
                                      return res.getString(R.string.solver_generic_missing_center,colorB);
       case ERROR_CENTER_R_MISSING  : String colorR = res.getString(R.string.color_red2);
                                      return res.getString(R.string.solver_generic_missing_center,colorR);
-      case ERROR_TWO_CENTERS_SWAP  : return res.getString(R.string.solver_generic_two_centers);
+      case ERROR_TWO_CENTERS       : return res.getString(R.string.solver_generic_two_centers);
       case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
       case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
       }
diff --git a/src/main/java/org/distorted/solvers/SolverSkewb.java b/src/main/java/org/distorted/solvers/SolverSkewb.java
index f01e960f..f841fb49 100644
--- a/src/main/java/org/distorted/solvers/SolverSkewb.java
+++ b/src/main/java/org/distorted/solvers/SolverSkewb.java
@@ -15,6 +15,7 @@ import org.distorted.main.R;
 import org.distorted.objectlib.main.ObjectSignatures;
 import org.distorted.objectlib.main.TwistyObject;
 import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
+import org.distorted.objectlib.tablebases.TablebaseHelpers;
 import org.distorted.objectlib.tablebases.TablebasesAbstract;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -42,73 +43,306 @@ public class SolverSkewb extends SolverTablebase
   private static final int ERROR_TWO_CENTERS        = -17;
   private static final int ERROR_TWO_CORNERS        = -18;
 
+  private static final int ERROR_IMPOSSIBLE         = -19;
+
   private TablebasesAbstract mSolver;
-  private int[] mFaceColors;
+  private final int[] mFaceColors;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public SolverSkewb(Resources res, TwistyObject object)
     {
     super(res,object);
+    mFaceColors = new int[6];
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void getCorners(TwistyObject object, int[][] corners)
     {
+    for(int i=0; i<8; i++)
+      for(int j=0; j<3; j++)
+        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void getCenters(TwistyObject object, int[] centers)
+    {
+    int[] map = {12,13,10,11,8,9};
 
+    for(int i=0; i<6; i++)
+      centers[i] = object.getCubitFaceStickerIndex(map[i],0) - 6;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private int checkAllCornersPresent(int[][] corners)
+  private int commonCornerColor(int[] c1, int[] c2)
+    {
+    int theSame = 0;
+    int index   = 0;
+
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++)
+        if( c1[i]==c2[j] )
+          {
+          index = i;
+          theSame++;
+          }
+
+    return theSame==1 ? c1[index] : ERROR_CORNERS_CANNOT;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int computeFaceColors(int[][] corners, int[] output)
     {
+    final int[][] map = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
+
+    for(int i=0; i<6; i++)
+      {
+      int c1 = map[i][0];
+      int c2 = map[i][1];
+      output[i] = commonCornerColor(corners[c1],corners[c2]);
+      if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
+      }
+
     return 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private int[] computeFaceColors(int[][] corners)
+  private boolean cornerIs(int[] corner, int c0, int c1, int c2)
     {
-    return null;
+    return ( (corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) ||
+             (corner[1]==c0 && corner[2]==c1 && corner[0]==c2 ) ||
+             (corner[2]==c0 && corner[0]==c1 && corner[1]==c2 )  );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void getCenters(TwistyObject object, int[] centers)
+  private int checkAllCornersPresent(int[][] corners)
     {
+    boolean[] present = new boolean[8];
+
+    for(int i=0; i<8; i++)
+      {
+      if( cornerIs(corners[i],4,2,0) ) present[0]=true;
+      if( cornerIs(corners[i],2,5,0) ) present[1]=true;
+      if( cornerIs(corners[i],3,4,0) ) present[2]=true;
+      if( cornerIs(corners[i],5,3,0) ) present[3]=true;
+      if( cornerIs(corners[i],1,2,4) ) present[4]=true;
+      if( cornerIs(corners[i],5,2,1) ) present[5]=true;
+      if( cornerIs(corners[i],4,3,1) ) present[6]=true;
+      if( cornerIs(corners[i],1,3,5) ) present[7]=true;
+      }
+
+    if( !present[0] ) return ERROR_CORNER_024_MISSING;
+    if( !present[1] ) return ERROR_CORNER_025_MISSING;
+    if( !present[2] ) return ERROR_CORNER_034_MISSING;
+    if( !present[3] ) return ERROR_CORNER_035_MISSING;
+    if( !present[4] ) return ERROR_CORNER_124_MISSING;
+    if( !present[5] ) return ERROR_CORNER_125_MISSING;
+    if( !present[6] ) return ERROR_CORNER_134_MISSING;
+    if( !present[7] ) return ERROR_CORNER_135_MISSING;
 
+    return 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private int checkAllCentersPresent(int[] centers)
     {
+    boolean[] present = new boolean[6];
+    for(int i=0; i<6; i++) present[centers[i]]= true;
+
+    if( !present[0] ) return ERROR_CENTER_4_MISSING;
+    if( !present[1] ) return ERROR_CENTER_5_MISSING;
+    if( !present[2] ) return ERROR_CENTER_2_MISSING;
+    if( !present[3] ) return ERROR_CENTER_3_MISSING;
+    if( !present[4] ) return ERROR_CENTER_0_MISSING;
+    if( !present[5] ) return ERROR_CENTER_1_MISSING;
+
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// free corners: 1,2,4,7
+
+  private int retCornerPermutation(int[] perm, int[][] corners)
+    {
+    int[] map = {1,2,4,7};
+
+    perm[0] =  0;
+    perm[1] = -1;
+    perm[2] = -1;
+    perm[3] =  3;
+    perm[4] = -1;
+    perm[5] =  5;
+    perm[6] =  6;
+    perm[7] = -1;
+
+    for(int i=0; i<4; i++)
+      {
+      int index = map[i];
+      int[] cor = corners[index];
+
+      if( cornerIs(cor,2,5,0) ) perm[1] = index;
+      if( cornerIs(cor,3,4,0) ) perm[2] = index;
+      if( cornerIs(cor,1,2,4) ) perm[4] = index;
+      if( cornerIs(cor,1,3,5) ) perm[7] = index;
+      }
+
+    if( perm[1]==-1 ) return ERROR_CORNER_025_MISSING;
+    if( perm[2]==-1 ) return ERROR_CORNER_034_MISSING;
+    if( perm[4]==-1 ) return ERROR_CORNER_124_MISSING;
+    if( perm[7]==-1 ) return ERROR_CORNER_135_MISSING;
+
     return 0;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void fillCornerTwists(int[] output, int[][] corners, int[] perm)
+    {
+    final int[] map = { 4,2,3,5,1,5,4,1 };
+
+    for(int i=0; i<8; i++)
+      {
+      int color = mFaceColors[map[i]];
+      int[] c = corners[perm[i]];
+
+           if( c[0]==color ) output[i] = 0;
+      else if( c[1]==color ) output[i] = 1;
+      else                   output[i] = 2;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int computeCenterTwist(int p1, int p2)
+    {
+    if( p1==1 )
+      {
+      switch(p2)
+        {
+        case 2: return 2;
+        case 4: return 1;
+        case 7: return 0;
+        }
+      }
+    if( p1==2 )
+      {
+      switch(p2)
+        {
+        case 1: return 2;
+        case 4: return 0;
+        case 7: return 1;
+        }
+      }
+    if( p1==4 )
+      {
+      switch(p2)
+        {
+        case 1: return 1;
+        case 2: return 0;
+        case 7: return 2;
+        }
+      }
+    if( p1==7 )
+      {
+      switch(p2)
+        {
+        case 1: return 0;
+        case 2: return 1;
+        case 4: return 2;
+        }
+      }
+
+    return ERROR_IMPOSSIBLE;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int positionOfFirstCorner(int[] perm, int[] twist)
+    {
+    int total_fixed_twist = twist[0]+twist[3]+twist[5]+twist[6];
+
+    int twist_42 = computeCenterTwist(perm[4],perm[2]);
+    int twist_21 = computeCenterTwist(perm[2],perm[1]);
+
+    if( twist_42<0 || twist_21<0 ) return ERROR_IMPOSSIBLE;
+
+
+android.util.Log.e("D", "twist42 "+twist_42+" twist21 "+twist_21+" total: "+total_fixed_twist);
+
+    if( (twist_21-twist_42+1)%3 != 0 ) return ERROR_TWO_CORNERS;
+    if( (total_fixed_twist-twist_42)%3 !=0 ) return ERROR_CORNER_TWISTED;
+
+    switch(perm[1])
+      {
+      case 1: return 0;
+      case 2: return 1;
+      case 4: return 2;
+      case 7: return 3;
+      }
+
+    return ERROR_IMPOSSIBLE;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int tablebaseIndex(TwistyObject object)
     {
-    int[][] corners   = new int[6][3];
-    int[] centers     = new int[6];
-    int[] corner_twist= new int[6];
+    int[][] corners= new int[8][3];
+    int[] centers  = new int[6];
+    int[] twist    = new int[8];
+    int[] perm     = new int[8];
 
     getCorners(object,corners);
 
-    int result1 = checkAllCornersPresent(corners);
+    int result1 = computeFaceColors(corners,mFaceColors);
     if( result1<0 ) return result1;
 
-    mFaceColors = computeFaceColors(corners);
+    int result2 = checkAllCornersPresent(corners);
+    if( result2<0 ) return result2;
 
     getCenters(object,centers);
-    int result2 = checkAllCentersPresent(centers);
-    if( result2<0 ) return result2;
+    int result3 = checkAllCentersPresent(centers);
+    if( result3<0 ) return result3;
+/*
+for(int i=0; i<8; i++)
+  for(int j=0; j<3; j++) android.util.Log.e("D", "corner "+i+" face "+j+" : "+corners[i][j]);
 
-    // TODO...
+for(int i=0; i<6; i++) android.util.Log.e("D", "center "+i+" : "+centers[i]);
+for(int i=0; i<6; i++) android.util.Log.e("D", "face "+i+" : "+mFaceColors[i]);
+*/
+    if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
+    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
 
-    return 0;
+    int result4 = retCornerPermutation(perm,corners);
+    if( result4<0 ) return result4;
+
+    fillCornerTwists(twist,corners,perm);
+
+for(int i=0; i<8; i++) android.util.Log.e("D", "perm  "+i+" : "+perm[i]);
+for(int i=0; i<8; i++) android.util.Log.e("D", "twist "+i+" : "+twist[i]);
+
+    int totalTwist = 0;
+    for(int i=0; i<8; i++) totalTwist += twist[i];
+
+android.util.Log.e("D", "total twist "+totalTwist);
+
+    if( (totalTwist%3)!=0 ) return ERROR_CORNER_TWISTED;
+
+    int total = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
+
+    int corner1 = positionOfFirstCorner(perm,twist);
+    if( corner1<0 ) return ERROR_TWO_CORNERS;
+
+android.util.Log.e("D", "corner1:  "+corner1+" center perm: "+center_perm_num+" twist: "+total);
+
+    return corner1 + 4*(center_perm_num + 360*total);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
