commit 94ce8e5359a10b862cf2fc8d511af1f5c7b3acab
Author: leszek <leszek@koltunski.pl>
Date:   Fri Dec 27 13:03:01 2024 +0100

    Properly define and separate the interface between the App and the 'solver' part of the objectlib. Move the 'position verifiers' to the objectlib.

diff --git a/src/main/java/org/distorted/dialogs/RubikDialogSolverView.java b/src/main/java/org/distorted/dialogs/RubikDialogSolverView.java
index c80e9717..d4f81a37 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogSolverView.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogSolverView.java
@@ -9,7 +9,6 @@
 
 package org.distorted.dialogs;
 
-import android.content.res.Resources;
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.Button;
@@ -19,8 +18,10 @@ import android.widget.TextView;
 import org.distorted.main.R;
 import org.distorted.objectlib.helpers.OperatingSystemInterface;
 import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.solvers.SolvingList;
-import org.distorted.solvers.SolvingThread;
+import org.distorted.objectlib.solvers.verifiers.SolverAbstract;
+import org.distorted.objectlib.solvers.verifiers.SolvingList;
+import org.distorted.solverui.ScreenList;
+import org.distorted.solverui.ScreenSolver;
 import org.distorted.solverui.SolverActivity;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -56,10 +57,17 @@ public class RubikDialogSolverView
         dialog.dismiss();
         SolvingList list = SolvingList.getSolver(solverOrdinal);
         OperatingSystemInterface os = act.getInterface();
-        Resources res = act.getResources();
         TwistyObject object = act.getObject();
-        SolvingThread solver = new SolvingThread( os,res,object,list );
-        solver.start();
+        SolverAbstract solver = list.create(os,object);
+        ScreenSolver screen = (ScreenSolver)ScreenList.SVER.getScreenClass();
+
+        if( solver!=null )
+          {
+          int[] result = solver.validatePosition(object);
+          if( result[0]>=0 ) solver.solve(screen,result);
+          else screen.displayImpossibleDialog(result,solver.getFaceColors());
+          }
+        else screen.displayErrorDialog(act.getString(R.string.solver_generic_not_implemented));
         }
       });
 
diff --git a/src/main/java/org/distorted/dialogs/RubikDialogSolvers.java b/src/main/java/org/distorted/dialogs/RubikDialogSolvers.java
index da6ac5ca..95ac4dfe 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogSolvers.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogSolvers.java
@@ -23,7 +23,7 @@ import androidx.fragment.app.FragmentActivity;
 import org.distorted.main.R;
 import org.distorted.objectlib.metadata.ListObjects;
 import org.distorted.solverui.SolverActivity;
-import org.distorted.solvers.SolvingList;
+import org.distorted.objectlib.solvers.verifiers.SolvingList;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/main/java/org/distorted/objects/RubikObject.java b/src/main/java/org/distorted/objects/RubikObject.java
index 45235429..71592db5 100644
--- a/src/main/java/org/distorted/objects/RubikObject.java
+++ b/src/main/java/org/distorted/objects/RubikObject.java
@@ -27,7 +27,7 @@ import org.distorted.main.R;
 import org.distorted.objectlib.metadata.ListObjects;
 import org.distorted.objectlib.metadata.Metadata;
 import org.distorted.objectlib.patterns.RubikPatternList;
-import org.distorted.solvers.SolvingList;
+import org.distorted.objectlib.solvers.verifiers.SolvingList;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/main/java/org/distorted/solvers/SolverAlgorithmic.java b/src/main/java/org/distorted/solvers/SolverAlgorithmic.java
deleted file mode 100644
index b5f2eb24..00000000
--- a/src/main/java/org/distorted/solvers/SolverAlgorithmic.java
+++ /dev/null
@@ -1,107 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2024 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.objectlib.algsolvers.SolutionListener;
-import org.distorted.objectlib.algsolvers.SolvedObject;
-import org.distorted.objectlib.algsolvers.implemented.PhasedSolver3x3Beginner;
-import org.distorted.objectlib.algsolvers.implemented.PhasedSolverAbstract;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.solverui.ScreenList;
-import org.distorted.solverui.ScreenPhasedSolution;
-import org.distorted.solverui.ScreenSolver;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public abstract class SolverAlgorithmic implements SolvingInterface, SolutionListener
-{
-  private final SolvedObject mSolvedObject;
-  private final PhasedSolverAbstract mSolver;
-  private final OperatingSystemInterface mOS;
-  private final Resources mRes;
-  private final TwistyObject mObject;
-  private long mTime;
-  private ScreenSolver mScreen;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverAlgorithmic(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    mOS     = os;
-    mRes    = res;
-    mObject = object;
-    mSolver = new PhasedSolver3x3Beginner();
-    mSolvedObject = mSolver.getObject();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  abstract int[] validatePosition(TwistyObject object);
-  abstract String getError(Resources res);
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void solve(ScreenSolver screen)
-    {
-    mScreen = screen;
-    int[] quats = validatePosition(mObject);
-
-    if( quats!=null )
-      {
-      int numPhases = mSolver.getNumPhases();
-      String[] names = new String[numPhases];
-      for(int p=0; p<numPhases; p++) names[p] = mSolver.getPhaseName(p);
-      ScreenPhasedSolution solScreen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass();
-      solScreen.updateNames(names);
-      mTime = System.currentTimeMillis();
-      mSolver.solution(this,quats);
-      }
-    else
-      {
-      String error = getError(mRes);
-      screen.displayImpossibleDialog(error);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void receiveSolution(int[] solution, int phaseNumber)
-    {
-    if( solution==null )
-      {
-      String message = "Phase "+phaseNumber+": FAIL";
-      System.out.println(message);
-      }
-    else
-      {
-      int numMoves = solution[0];
-      int[][] moves = new int[numMoves][];
-      int index = 0;
-
-      for(int m=1; m<=numMoves; m++)
-        moves[index++] = mSolvedObject.findMove(solution[m]);
-
-      int[][] subphases = mSolver.getSubPhases(phaseNumber);
-      mScreen.setSolved(moves,phaseNumber,subphases);
-      }
-
-    long time = System.currentTimeMillis();
-    long diff = time - mTime;
-    mTime = time;
-
-    System.out.println("Phase "+phaseNumber+" solved in "+diff+"ms. Moves: "+(solution==null ? 0:solution[0]));
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverAlgorithmicCUBE3.java b/src/main/java/org/distorted/solvers/SolverAlgorithmicCUBE3.java
deleted file mode 100644
index 5fa5ffd4..00000000
--- a/src/main/java/org/distorted/solvers/SolverAlgorithmicCUBE3.java
+++ /dev/null
@@ -1,43 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2024 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.solverui.SolverActivity;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverAlgorithmicCUBE3 extends SolverAlgorithmic
-{
-  public SolverAlgorithmicCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  int[] validatePosition(TwistyObject object)
-    {
-    int numCubits = object.getNumCubits();
-    int[] ret = new int[numCubits];   // mockup
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  String getError(Resources res)
-    {
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverKociembaCUBE3.java b/src/main/java/org/distorted/solvers/SolverKociembaCUBE3.java
deleted file mode 100644
index 20364843..00000000
--- a/src/main/java/org/distorted/solvers/SolverKociembaCUBE3.java
+++ /dev/null
@@ -1,220 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.solverui.ScreenSolver;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.kociemba.SolverSearch;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverKociembaCUBE3 implements SolvingInterface
-{
-  private final Resources mRes;
-  private final OperatingSystemInterface mOS;
-  private final TwistyObject mObject;
-  private int mColorID;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int mapCubitToFace(int cubit, int face)
-    {
-    if( cubit<8 )
-      {
-      switch(face)
-        {
-        case 0: return 1;
-        case 1: if( cubit==2 ) return 5;
-                if( cubit==1 ) return 3;
-                return 1;
-        case 2: return cubit==7 ? 5 : 3;
-        case 3: if( cubit==1 ) return 1;
-                return cubit==4 ? 5 : 3;
-        case 4: return cubit==7 ? 3 : 5;
-        case 5: if( cubit==2 ) return 1;
-                if( cubit==4 ) return 3;
-                return 5;
-        }
-      }
-
-    if( cubit>19 ) return 4;
-
-    switch(face)
-      {
-      case 0: return cubit==15 || cubit==18 ? 3 : 5;
-      case 1: return cubit==13 || cubit==16 ? 3 : 5;
-      case 2: return cubit==10              ? 5 : 3;
-      case 3: return cubit== 8              ? 3 : 5;
-      case 4: return cubit== 9              ? 3 : 5;
-      case 5: return cubit== 8              ? 5 : 3;
-      }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkPosition(String position)
-    {
-    int[] numColors = new int[6];
-    int len = position.length();
-
-    for(int i=0; i<len; i++)
-      {
-      char ch = position.charAt(i);
-
-      switch(ch)
-        {
-        case 'R': numColors[0]++; break;
-        case 'L': numColors[1]++; break;
-        case 'U': numColors[2]++; break;
-        case 'D': numColors[3]++; break;
-        case 'F': numColors[4]++; break;
-        case 'B': numColors[5]++; break;
-        }
-      }
-
-    if( numColors[0]<9 ) { mColorID = R.string.color_yellow1; return numColors[0]; }
-    if( numColors[1]<9 ) { mColorID = R.string.color_white1 ; return numColors[1]; }
-    if( numColors[2]<9 ) { mColorID = R.string.color_blue1  ; return numColors[2]; }
-    if( numColors[3]<9 ) { mColorID = R.string.color_green1 ; return numColors[3]; }
-    if( numColors[4]<9 ) { mColorID = R.string.color_red1   ; return numColors[4]; }
-    if( numColors[5]<9 ) { mColorID = R.string.color_orange1; return numColors[5]; }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// order: Up --> Right --> Front --> Down --> Left --> Back
-// (because the first implemented Solver - the two-phase Cube3 one - expects such order)
-//
-// Solved 3x3x3 Cube maps to "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"
-
-  private String preparePosition()
-    {
-    StringBuilder objectString = new StringBuilder();
-
-    final int R = 0;
-    final int L = 1;
-    final int U = 2;
-    final int D = 3;
-    final int F = 4;
-    final int B = 5;
-
-    // 'I' - interior, theoretically can happen
-    final char[] FACE_NAMES = { 'R', 'L', 'U', 'D', 'F', 'B', 'I'};
-
-    final int[] U_INDEX = { 2,10, 6,17,22,19, 3,11, 7};
-    final int[] R_INDEX = { 7,19, 6,15,20,14, 5,18, 4};
-    final int[] F_INDEX = { 3,11, 7,13,24,15, 1, 9, 5};
-    final int[] D_INDEX = { 1, 9, 5,16,23,18, 0, 8, 4};
-    final int[] L_INDEX = { 2,17, 3,12,21,13, 0,16, 1};
-    final int[] B_INDEX = { 6,10, 2,14,25,12, 4, 8, 0};
-
-    for(int i=0; i<9; i++)
-      {
-      int face = mapCubitToFace(U_INDEX[i],U);
-      int color = mObject.getCubitFaceStickerIndex(U_INDEX[i], face);
-      objectString.append(FACE_NAMES[color]);
-      }
-    for(int i=0; i<9; i++)
-      {
-      int face = mapCubitToFace(R_INDEX[i],R);
-      int color = mObject.getCubitFaceStickerIndex(R_INDEX[i], face);
-      objectString.append(FACE_NAMES[color]);
-      }
-    for(int i=0; i<9; i++)
-      {
-      int face = mapCubitToFace(F_INDEX[i],F);
-      int color = mObject.getCubitFaceStickerIndex(F_INDEX[i], face);
-      objectString.append(FACE_NAMES[color]);
-      }
-    for(int i=0; i<9; i++)
-      {
-      int face = mapCubitToFace(D_INDEX[i],D);
-      int color = mObject.getCubitFaceStickerIndex(D_INDEX[i], face);
-      objectString.append(FACE_NAMES[color]);
-      }
-    for(int i=0; i<9; i++)
-      {
-      int face = mapCubitToFace(L_INDEX[i],L);
-      int color = mObject.getCubitFaceStickerIndex(L_INDEX[i], face);
-      objectString.append(FACE_NAMES[color]);
-      }
-    for(int i=0; i<9; i++)
-      {
-      int face = mapCubitToFace(B_INDEX[i],B);
-      int color = mObject.getCubitFaceStickerIndex(B_INDEX[i], face);
-      objectString.append(FACE_NAMES[color]);
-      }
-
-    return objectString.toString();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverKociembaCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    mRes   = res;
-    mOS    = os;
-    mObject= object;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void solve(ScreenSolver solver)
-    {
-    String result;
-
-    SolverSearch.prepare(mOS);
-    String objectPosition = preparePosition();
-    int check = checkPosition(objectPosition);
-
-    if( check<0 )
-      {
-      result = SolverSearch.solution(objectPosition, 24, 20);
-
-      if( result.contains("Error") )
-        {
-        switch( result.charAt(result.length()-1) )
-          {
-          case '1': result = mRes.getString(R.string.solver_cube3_error1); break;
-          case '2': result = mRes.getString(R.string.solver_cube3_error2); break;
-          case '3': result = mRes.getString(R.string.solver_generic_edge_twist); break;
-          case '4': result = mRes.getString(R.string.solver_cube3_error4); break;
-          case '5': result = mRes.getString(R.string.solver_generic_corner_twist); break;
-          case '6': result = mRes.getString(R.string.solver_cube3_error6); break;
-          case '7': result = mRes.getString(R.string.solver_cube3_error7); break;
-          case '8': result = mRes.getString(R.string.solver_cube3_error8); break;
-          case '9': result = mRes.getString(R.string.solver_cube3_error9); break;
-          }
-
-        solver.displayImpossibleDialog(result);
-        }
-      else
-        {
-        solver.setSolved(result);
-        }
-      }
-    else
-      {
-      String color = mRes.getString(mColorID);
-      result = mRes.getString(R.string.solver_cube3_error1,check,color);
-      solver.displayImpossibleDialog(result);
-      }
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebase.java b/src/main/java/org/distorted/solvers/SolverTablebase.java
deleted file mode 100644
index 2be5c228..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebase.java
+++ /dev/null
@@ -1,105 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
-import org.distorted.objectlib.tablebases.TablebasesAbstract;
-import org.distorted.solverui.ScreenSolver;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public abstract class SolverTablebase implements SolvingInterface
-{
-  private static final int[][] colorsHex =
-    {
-      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
-      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
-      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
-      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
-      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
-      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
-    };
-  private static final int[][] colorsTet =
-    {
-      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
-      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
-      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
-      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
-    };
-  private static final int[][] colorsOct =
-    {
-      {R.string.color_violet1,R.string.color_violet2,R.string.color_violet3,R.string.color_violet4,R.string.color_violet5,R.string.color_violet6,R.string.color_violet7 },
-      {R.string.color_grey1  ,R.string.color_grey2  ,R.string.color_grey3  ,R.string.color_grey4  ,R.string.color_grey5  ,R.string.color_grey6  ,R.string.color_grey7   },
-      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
-      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
-      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
-      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
-      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
-      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
-    };
-
-  private final OperatingSystemInterface mOS;
-  private final Resources mRes;
-  private final TwistyObject mObject;
-  private TablebasesAbstract mSolver;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public abstract int tablebaseIndex(TwistyObject object);
-  public abstract String error(int index, Resources res);
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebase(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    mOS    = os;
-    mRes   = res;
-    mObject= object;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  int getHexColor(int color,int variant) { return colorsHex[color][variant]; }
-  int getTetColor(int color,int variant) { return colorsTet[color][variant]; }
-  int getOctColor(int color,int variant) { return colorsOct[color][variant]; }
-  int[] getExtra() { return null; }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void solve(ScreenSolver screen)
-    {
-    int index = tablebaseIndex(mObject);
-
-    if( index>=0 )
-      {
-      if( mSolver==null )
-        {
-        mSolver = ImplementedTablebasesList.createPacked(mOS, mObject.getShortName() );
-        }
-
-      mSolver.initialize();
-      int[][] moves = mSolver!=null ? mSolver.solution(index,getExtra(),mOS) : null;
-      screen.setSolved(moves);
-      }
-    else
-      {
-      String error = error(index,mRes);
-      screen.displayImpossibleDialog(error);
-      }
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseCU232.java b/src/main/java/org/distorted/solvers/SolverTablebaseCU232.java
deleted file mode 100644
index 8b61ab90..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseCU232.java
+++ /dev/null
@@ -1,328 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseCU232 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING = -1;
-  private static final int ERROR_EDGE_MISSING   = -2;
-  private static final int ERROR_CORNERS_CANNOT = -3;
-  private static final int ERROR_EDGE_TWISTED   = -4;
-  private static final int ERROR_CORNER_TWISTED = -5;
-
-  private final int[] mFaceColors;
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int edgeIs(int[] edge, int i0, int i1)
-    {
-    int c0 = mFaceColors[i0];
-    int c1 = mFaceColors[i1];
-
-    if( edge[0]==c0 && edge[1]==c1 ) return 0;
-    if( edge[0]==c1 && edge[1]==c0 ) return 1;
-    return 2;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retEdgePermutation(int[] output, int[][] edges)
-    {
-    for(int i=0; i<4; i++) output[i] = -1;
-
-    for(int i=0; i<4; i++)
-      {
-      int edge0 = edgeIs(edges[i],1,5);
-           if( edge0==0 ) output[0]=i;
-      else if( edge0==1 ) return ERROR_EDGE_TWISTED;
-
-      int edge1 = edgeIs(edges[i],1,4);
-           if( edge1==0 ) output[1]=i;
-      else if( edge1==1 ) return ERROR_EDGE_TWISTED;
-
-      int edge2 = edgeIs(edges[i],0,5);
-           if( edge2==0 ) output[2]=i;
-      else if( edge2==1 ) return ERROR_EDGE_TWISTED;
-
-      int edge3 = edgeIs(edges[i],0,4);
-           if( edge3==0 ) output[3]=i;
-      else if( edge3==1 ) return ERROR_EDGE_TWISTED;
-      }
-
-    if( output[0]==-1 ) { mErrColor1=1; mErrColor2=5; return ERROR_EDGE_MISSING; }
-    if( output[1]==-1 ) { mErrColor1=1; mErrColor2=4; return ERROR_EDGE_MISSING; }
-    if( output[2]==-1 ) { mErrColor1=0; mErrColor2=5; return ERROR_EDGE_MISSING; }
-    if( output[3]==-1 ) { mErrColor1=0; mErrColor2=4; return ERROR_EDGE_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int cornerIs(int[] corner, int i0, int i1, int i2)
-    {
-    int c0 = mFaceColors[i0];
-    int c1 = mFaceColors[i1];
-    int c2 = mFaceColors[i2];
-
-    if( corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return 0;
-
-    if( corner[0]==c0 && corner[1]==c2 && corner[2]==c1 ||
-        corner[0]==c1 && corner[1]==c0 && corner[2]==c2 ||
-        corner[0]==c1 && corner[1]==c2 && corner[2]==c0 ||
-        corner[0]==c2 && corner[1]==c0 && corner[2]==c1 ||
-        corner[0]==c2 && corner[1]==c1 && corner[2]==c0  ) return 1;
-
-    return 2;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCornerPermutation(int[] output, int[][] corners)
-    {
-    for(int i=0; i<8; i++) output[i] = -1;
-
-    for(int i=0; i<8; i++)
-      {
-      int corner7 = cornerIs(corners[i],2,4,0);
-           if( corner7==0 ) output[7]=i;
-      else if( corner7==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner6 = cornerIs(corners[i],2,0,5);
-           if( corner6==0 ) output[6]=i;
-      else if( corner6==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner5 = cornerIs(corners[i],3,0,4);
-           if( corner5==0 ) output[5]=i;
-      else if( corner5==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner4 = cornerIs(corners[i],3,5,0);
-           if( corner4==0 ) output[4]=i;
-      else if( corner4==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner3 = cornerIs(corners[i],2,1,4);
-           if( corner3==0 ) output[3]=i;
-      else if( corner3==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner2 = cornerIs(corners[i],2,5,1);
-           if( corner2==0 ) output[2]=i;
-      else if( corner2==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner1 = cornerIs(corners[i],3,4,1);
-           if( corner1==0 ) output[1]=i;
-      else if( corner1==1 ) return ERROR_CORNER_TWISTED;
-
-      int corner0 = cornerIs(corners[i],3,1,5);
-           if( corner0==0 ) output[0]=i;
-      else if( corner0==1 ) return ERROR_CORNER_TWISTED;
-      }
-
-    if( output[0]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( output[1]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( output[2]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( output[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( output[4]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( output[5]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( output[6]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( output[7]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeFaceColors(int[][] corners, int[][] edges)
-    {
-    mFaceColors[1] = edges[1][0];
-    mFaceColors[4] = edges[1][1];
-
-         if( edges[0][0]==mFaceColors[1] ) mFaceColors[5] = edges[0][1];
-    else if( edges[2][0]==mFaceColors[1] ) mFaceColors[5] = edges[2][1];
-    else if( edges[3][0]==mFaceColors[1] ) mFaceColors[5] = edges[3][1];
-    else return ERROR_EDGE_TWISTED;
-
-         if( edges[0][1]==mFaceColors[4] ) mFaceColors[0] = edges[0][0];
-    else if( edges[2][1]==mFaceColors[4] ) mFaceColors[0] = edges[2][0];
-    else if( edges[3][1]==mFaceColors[4] ) mFaceColors[0] = edges[3][0];
-    else return ERROR_EDGE_TWISTED;
-
-    boolean found2 = false;
-    boolean found3 = false;
-
-    for(int c=0; c<8; c++)
-      {
-      if( !found3 && corners[c][1]==mFaceColors[4] && corners[c][2]==mFaceColors[1] )
-        {
-        found3=true;
-        mFaceColors[3] = corners[c][0];
-        }
-      if( !found2 && corners[c][1]==mFaceColors[1] && corners[c][2]==mFaceColors[4] )
-        {
-        found2=true;
-        mFaceColors[2] = corners[c][0];
-        }
-      }
-
-    if( !found2 || !found3 ) return ERROR_CORNERS_CANNOT;
-
-    for(int i=0; i<6; i++)
-      for(int j=i+1; j<6; j++)
-        if( mFaceColors[i]==mFaceColors[j] ) return ERROR_CORNERS_CANNOT;
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] correctEdgePerm(int[] perm)
-    {
-    int[] ret = new int[3];
-
-    ret[0] = perm[0];
-    ret[1] = perm[2];
-    ret[2] = perm[3];
-
-    if( ret[0]>1 ) ret[0]--;
-    if( ret[1]>1 ) ret[1]--;
-    if( ret[2]>1 ) ret[2]--;
-
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseCU232(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    mFaceColors = new int[6];
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners= new int[8][3];
-    int[][] edges  = new int[4][2];
-
-    corners[0][0] = object.getCubitFaceStickerIndex(0,3);
-    corners[0][1] = object.getCubitFaceStickerIndex(0,1);
-    corners[0][2] = object.getCubitFaceStickerIndex(0,5);
-
-    corners[1][0] = object.getCubitFaceStickerIndex(1,1);
-    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
-    corners[1][2] = object.getCubitFaceStickerIndex(1,3);
-
-    corners[2][0] = object.getCubitFaceStickerIndex(2,3);
-    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
-    corners[2][2] = object.getCubitFaceStickerIndex(2,5);
-
-    corners[3][0] = object.getCubitFaceStickerIndex(3,3);
-    corners[3][1] = object.getCubitFaceStickerIndex(3,1);
-    corners[3][2] = object.getCubitFaceStickerIndex(3,5);
-
-    corners[4][0] = object.getCubitFaceStickerIndex(4,5);
-    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
-    corners[4][2] = object.getCubitFaceStickerIndex(4,1);
-
-    corners[5][0] = object.getCubitFaceStickerIndex(5,3);
-    corners[5][1] = object.getCubitFaceStickerIndex(5,1);
-    corners[5][2] = object.getCubitFaceStickerIndex(5,5);
-
-    corners[6][0] = object.getCubitFaceStickerIndex(6,3);
-    corners[6][1] = object.getCubitFaceStickerIndex(6,1);
-    corners[6][2] = object.getCubitFaceStickerIndex(6,5);
-
-    corners[7][0] = object.getCubitFaceStickerIndex(7,5);
-    corners[7][1] = object.getCubitFaceStickerIndex(7,3);
-    corners[7][2] = object.getCubitFaceStickerIndex(7,1);
-
-    edges[0][0] = object.getCubitFaceStickerIndex(8,5);
-    edges[0][1] = object.getCubitFaceStickerIndex(8,3);
-    edges[1][0] = object.getCubitFaceStickerIndex(9,3);
-    edges[1][1] = object.getCubitFaceStickerIndex(9,5);
-    edges[2][0] = object.getCubitFaceStickerIndex(10,5);
-    edges[2][1] = object.getCubitFaceStickerIndex(10,3);
-    edges[3][0] = object.getCubitFaceStickerIndex(11,3);
-    edges[3][1] = object.getCubitFaceStickerIndex(11,5);
-
-    int result0 = computeFaceColors(corners, edges);
-    if( result0<0 ) return result0;
-
-    int[] corner_perm = new int[8];
-    int result1 = retCornerPermutation(corner_perm,corners);
-    if( result1<0 ) return result1;
-
-    int[] edge_perm = new int[4];
-    int result2 = retEdgePermutation(edge_perm,edges);
-    if( result2<0 ) return result2;
-
-    int[] edge_perm2 = correctEdgePerm(edge_perm); // edge1 is fixed!
-
-    int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm);
-    int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm2);
-
-    return edge_perm_num + 6*corner_perm_num;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeError(Resources res, int face0, int face1)
-    {
-    int j0 = getHexColor(face0,3);
-    int j1 = getHexColor(face1,6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int face0, int face1, int face2)
-    {
-    int j0 = getHexColor(face0,3);
-    int j1 = getHexColor(face1,3);
-    int j2 = getHexColor(face2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING: return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_EDGE_MISSING  : return edgeError(res,mErrColor1,mErrColor2);
-      case ERROR_CORNERS_CANNOT: return res.getString(R.string.solver_generic_corners_cannot);
-      case ERROR_EDGE_TWISTED  : return res.getString(R.string.solver_generic_edge_twist);
-      case ERROR_CORNER_TWISTED: return res.getString(R.string.solver_generic_corner_twist);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseCU323.java b/src/main/java/org/distorted/solvers/SolverTablebaseCU323.java
deleted file mode 100644
index d371ec31..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseCU323.java
+++ /dev/null
@@ -1,370 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TBCuboid323;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// a few cu_323 max (depth 18) indices: 1180633, 1180642, 1182044, 1190482, 128151851, 128190028
-
-public class SolverTablebaseCU323 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING = -1;
-  private static final int ERROR_EDGE_MISSING   = -2;
-  private static final int ERROR_CORNERS_CANNOT = -3;
-  private static final int ERROR_EDGE_TWISTED   = -4;
-  private static final int ERROR_CORNER_TWISTED = -5;
-
-  private final int[] mFaceColors;
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseCU323(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    mFaceColors = new int[6];
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int findCorner(int[][] corners, int c1, int c2)
-    {
-    for(int i=0; i<8; i++)
-      {
-      int[] c = corners[i];
-
-      if( c[0]==c1 && c[1]==c2 ) return c[2];
-      if( c[1]==c1 && c[2]==c2 ) return c[0];
-      if( c[2]==c1 && c[0]==c2 ) return c[1];
-      }
-
-    return ERROR_CORNERS_CANNOT;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int missingColor()
-    {
-    boolean[] present = new boolean[6];
-    for(int i=0; i<5; i++) present[mFaceColors[i]] = true;
-
-    int indexFalse = -1;
-
-    for(int i=0; i<6; i++)
-      if( !present[i] )
-        {
-        if( indexFalse<0 ) indexFalse=i;
-        else return ERROR_CORNERS_CANNOT;
-        }
-
-    return indexFalse;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int edgePresent(int[][] edges, int f0, int f1)
-    {
-    int c0 = mFaceColors[f0];
-    int c1 = mFaceColors[f1];
-
-    for(int i=0; i<8; i++ )
-      {
-      int[] edge = edges[i];
-
-      if( edge[0]==c0 && edge[1]==c1 ) return i;
-      if( edge[0]==c1 && edge[1]==c0 )
-        {
-        mErrColor1 = c0;
-        mErrColor2 = c1;
-        return ERROR_EDGE_TWISTED;
-        }
-      }
-
-    mErrColor1 = c0;
-    mErrColor2 = c1;
-    return ERROR_EDGE_MISSING;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int cornerPresent(int[][] corners, int f0, int f1, int f2)
-    {
-    int c0 = mFaceColors[f0];
-    int c1 = mFaceColors[f1];
-    int c2 = mFaceColors[f2];
-
-    for(int i=0; i<8; i++)
-      {
-      int[] corner = corners[i];
-
-      if(  corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return i;
-      if( (corner[0]==c1 && corner[1]==c2 && corner[2]==c0 ) ||
-          (corner[0]==c2 && corner[1]==c0 && corner[2]==c1 )  )
-        {
-        mErrColor1 = c0;
-        mErrColor2 = c1;
-        mErrColor3 = c2;
-        return ERROR_CORNER_TWISTED;
-        }
-      }
-
-    mErrColor1 = c0;
-    mErrColor2 = c1;
-    mErrColor3 = c2;
-    return ERROR_CORNER_MISSING;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retEdgePermutation(int[] output, int[][] edges)
-    {
-    int[][] e = { {5,3}, {4,3}, {5,2}, {4,2}, {1,3}, {1,2}, {0,3}, {0,2} };
-
-    for(int i=0; i<8; i++)
-      {
-      int[] ee = e[i];
-      output[i] = edgePresent(edges,ee[0],ee[1]);
-      if( output[i]<0 ) return output[i];
-      }
-
-    return 0;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCornerPermutation(int[] output, int[][] corners)
-    {
-    int[][] c = { {5,1,3}, {1,4,3}, {1,5,2}, {4,1,2}, {0,5,3}, {4,0,3}, {5,0,2}, {0,4,2} };
-
-    for(int i=0; i<8; i++)
-      {
-      int[] cc = c[i];
-      output[i] = cornerPresent(corners,cc[0],cc[1],cc[2]);
-      if( output[i]<0 ) return output[i];
-      }
-
-    return 0;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeFaceColors(int[][] corners, int[][] edges, int[] centers)
-    {
-    mFaceColors[4] = edges[1][0];
-    mFaceColors[3] = edges[1][1];
-
-         if( centers[0]!=mFaceColors[3] ) mFaceColors[2] = centers[0];
-    else if( centers[1]!=mFaceColors[3] ) mFaceColors[2] = centers[1];
-    else return ERROR_CORNERS_CANNOT;
-
-    mFaceColors[0] = findCorner(corners,mFaceColors[4],mFaceColors[2]);
-    if( mFaceColors[0]<0 ) return mFaceColors[0];
-
-    mFaceColors[1] = findCorner(corners,mFaceColors[2],mFaceColors[4]);
-    if( mFaceColors[1]<0 ) return mFaceColors[1];
-
-    mFaceColors[5] = missingColor();
-    if( mFaceColors[5]<0 ) return mFaceColors[5];
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCorners(TwistyObject object, int[][] corners)
-    {
-    corners[0][0] = object.getCubitFaceStickerIndex(0,5);
-    corners[0][1] = object.getCubitFaceStickerIndex(0,1);
-    corners[0][2] = object.getCubitFaceStickerIndex(0,3);
-
-    corners[1][0] = object.getCubitFaceStickerIndex(1,3);
-    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
-    corners[1][2] = object.getCubitFaceStickerIndex(1,1);
-
-    corners[2][0] = object.getCubitFaceStickerIndex(2,5);
-    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
-    corners[2][2] = object.getCubitFaceStickerIndex(2,3);
-
-    corners[3][0] = object.getCubitFaceStickerIndex(3,5);
-    corners[3][1] = object.getCubitFaceStickerIndex(3,1);
-    corners[3][2] = object.getCubitFaceStickerIndex(3,3);
-
-    corners[4][0] = object.getCubitFaceStickerIndex(4,1);
-    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
-    corners[4][2] = object.getCubitFaceStickerIndex(4,5);
-
-    corners[5][0] = object.getCubitFaceStickerIndex(5,5);
-    corners[5][1] = object.getCubitFaceStickerIndex(5,1);
-    corners[5][2] = object.getCubitFaceStickerIndex(5,3);
-
-    corners[6][0] = object.getCubitFaceStickerIndex(6,5);
-    corners[6][1] = object.getCubitFaceStickerIndex(6,1);
-    corners[6][2] = object.getCubitFaceStickerIndex(6,3);
-
-    corners[7][0] = object.getCubitFaceStickerIndex(7,1);
-    corners[7][1] = object.getCubitFaceStickerIndex(7,3);
-    corners[7][2] = object.getCubitFaceStickerIndex(7,5);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getEdges(TwistyObject object, int[][] edges)
-    {
-    edges[0][0] = object.getCubitFaceStickerIndex(8,5);
-    edges[0][1] = object.getCubitFaceStickerIndex(8,3);
-    edges[1][0] = object.getCubitFaceStickerIndex(9,3);
-    edges[1][1] = object.getCubitFaceStickerIndex(9,5);
-    edges[2][0] = object.getCubitFaceStickerIndex(10,3);
-    edges[2][1] = object.getCubitFaceStickerIndex(10,5);
-    edges[3][0] = object.getCubitFaceStickerIndex(11,5);
-    edges[3][1] = object.getCubitFaceStickerIndex(11,3);
-    edges[4][0] = object.getCubitFaceStickerIndex(12,3);
-    edges[4][1] = object.getCubitFaceStickerIndex(12,5);
-    edges[5][0] = object.getCubitFaceStickerIndex(13,5);
-    edges[5][1] = object.getCubitFaceStickerIndex(13,3);
-    edges[6][0] = object.getCubitFaceStickerIndex(14,3);
-    edges[6][1] = object.getCubitFaceStickerIndex(14,5);
-    edges[7][0] = object.getCubitFaceStickerIndex(15,5);
-    edges[7][1] = object.getCubitFaceStickerIndex(15,3);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCenters(TwistyObject object, int[] centers)
-    {
-    centers[0] = object.getCubitFaceStickerIndex(16,4);
-    centers[1] = object.getCubitFaceStickerIndex(17,4);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners= new int[8][3];
-    int[][] edges  = new int[8][2];
-    int[] centers  = new int[2];
-
-    getCorners(object,corners);
-    getEdges(object,edges);
-    getCenters(object,centers);
-
-//for(int i=0; i<8; i++) android.util.Log.e("D", "corner: "+i+" : "+corners[i][0]+" "+corners[i][1]+" "+corners[i][2]);
-//for(int i=0; i<8; i++) android.util.Log.e("D", "edge: "+i+" : "+edges[i][0]+" "+edges[i][1]);
-
-    int result0 = computeFaceColors(corners, edges, centers);
-    if( result0<0 ) return result0;
-
-    int[] corner_perm = new int[8];
-    int result1 = retCornerPermutation(corner_perm,corners);
-    if( result1<0 ) return result1;
-
-//android.util.Log.e("D", "upper: "+mUpper);
-//for(int i=0; i<6; i++) android.util.Log.e("D", "face color: "+mFaceColors[i]);
-
-    int[] edge_perm8 = new int[8];
-    int result2 = retEdgePermutation(edge_perm8,edges);
-    if( result2<0 ) return result2;
-
-    int[] edge_perm7 = TBCuboid323.edgePermTo7(edge_perm8);
-/*
-    TablebaseHelpers.displayTable(corner_perm, "CORNER PERM");
-    TablebaseHelpers.displayTable(edge_perm8, "EDGE PERM8");
-    TablebaseHelpers.displayTable(edge_perm7, "EDGE PERM7");
-*/
-    int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm);
-    int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm7);
-    int centersInPlace = (centers[0]==mFaceColors[2]) ? 0 : 1;
-
-//android.util.Log.e("D", "corner_perm_num: "+corner_perm_num+" edge_perm_num: "+edge_perm_num+" inPlace: "+centersInPlace);
-//android.util.Log.e("D", "index="+(corner_perm_num + 40320*( centersInPlace + 2*edge_perm_num)));
-
-    return corner_perm_num + 40320*( centersInPlace + 2*edge_perm_num);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeTwistedError(Resources res, int color0, int color1)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerTwistedError(Resources res, int color0, int color1, int color2)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,3);
-    int j2 = getHexColor(color2,5);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_twisted_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeMissingError(Resources res, int color0, int color1)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerMissingError(Resources res, int color0, int color1, int color2)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,3);
-    int j2 = getHexColor(color2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING : return cornerMissingError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_EDGE_MISSING   : return edgeMissingError(res,mErrColor1,mErrColor2);
-      case ERROR_CORNERS_CANNOT : return res.getString(R.string.solver_generic_corners_cannot);
-      case ERROR_EDGE_TWISTED   : return edgeTwistedError(res,mErrColor1,mErrColor2);
-      case ERROR_CORNER_TWISTED : return cornerTwistedError(res,mErrColor1,mErrColor2,mErrColor3);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseCUBE2.java b/src/main/java/org/distorted/solvers/SolverTablebaseCUBE2.java
deleted file mode 100644
index 7febc1f0..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseCUBE2.java
+++ /dev/null
@@ -1,234 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-import org.distorted.objectlib.tablebases.TBCube2;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseCUBE2 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING = -1;
-  private static final int ERROR_CORNERS_CANNOT = -2;
-  private static final int ERROR_CORNER_TWISTED = -3;
-
-  private final int[] mFaceColors;
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private void fillCornerTwists(int[] output, int[][] corners, int[] perm)
-    {
-    for(int i=0; i<8; i++)
-      {
-      int[] c = corners[perm[i]];
-
-           if( c[0]==mFaceColors[0] || c[0]==mFaceColors[1] ) output[i] = 0;
-      else if( c[1]==mFaceColors[0] || c[1]==mFaceColors[1] ) output[i] = 1;
-      else                                                    output[i] = 2;
-      }
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int cornerIndex(int[][] corners, int i1, int i2, int i3)
-    {
-    int c1 = mFaceColors[i1];
-    int c2 = mFaceColors[i2];
-    int c3 = mFaceColors[i3];
-
-    for(int i=0; i<8; i++)
-      {
-      int[] cor = corners[i];
-
-      if( (cor[0]==c1 && cor[1]==c2 && cor[2]==c3) ||
-          (cor[0]==c2 && cor[1]==c3 && cor[2]==c1) ||
-          (cor[0]==c3 && cor[1]==c1 && cor[2]==c2)  ) return i;
-      }
-
-    return -1;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCornerPermutation(int[] output, int[][] corners)
-    {
-    for(int i=0; i<8; i++) output[i] = -1;
-
-    output[0] = cornerIndex(corners, 1,2,5);
-    output[1] = cornerIndex(corners, 1,4,2);
-    output[2] = cornerIndex(corners, 1,5,3);
-    output[3] = cornerIndex(corners, 1,3,4);
-    output[4] = cornerIndex(corners, 0,5,2);
-    output[5] = cornerIndex(corners, 0,2,4);
-    output[6] = cornerIndex(corners, 0,3,5);
-    output[7] = cornerIndex(corners, 0,4,3);
-
-    if( output[0]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( output[1]==-1 ) { mErrColor1=1; mErrColor2=4; mErrColor3=2; return ERROR_CORNER_MISSING; }
-    if( output[2]==-1 ) { mErrColor1=1; mErrColor2=5; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( output[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( output[4]==-1 ) { mErrColor1=0; mErrColor2=5; mErrColor3=2; return ERROR_CORNER_MISSING; }
-    if( output[5]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( output[6]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( output[7]==-1 ) { mErrColor1=0; mErrColor2=4; mErrColor3=3; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int findColor(int[][] corners, int c1, int c2)
-    {
-    for(int i=0; i<8; i++)
-      {
-      int[] cor = corners[i];
-
-      if( cor[0]==c1 && cor[1]==c2 ) return cor[2];
-      if( cor[1]==c1 && cor[2]==c2 ) return cor[0];
-      if( cor[2]==c1 && cor[0]==c2 ) return cor[1];
-      }
-
-    return -1;
-    }
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeFaceColors(int[][] corners)
-    {
-    mFaceColors[1] = corners[1][0];
-    mFaceColors[2] = corners[1][2];
-    mFaceColors[4] = corners[1][1];
-
-    mFaceColors[0] = findColor(corners,mFaceColors[2],mFaceColors[4]);
-    mFaceColors[3] = findColor(corners,mFaceColors[4],mFaceColors[1]);
-    mFaceColors[5] = findColor(corners,mFaceColors[1],mFaceColors[2]);
-
-    for(int i=0; i<6; i++)
-      {
-      int color = mFaceColors[i];
-      if( color<0 ) return ERROR_CORNERS_CANNOT;
-
-      for(int j=i+1; j<6; j++)
-        if( mFaceColors[j]==color ) return ERROR_CORNERS_CANNOT;
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseCUBE2(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    mFaceColors = new int[6];
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCorners(TwistyObject object, int[][] corners)
-    {
-    corners[0][0] = object.getCubitFaceStickerIndex(0,1);
-    corners[0][1] = object.getCubitFaceStickerIndex(0,3);
-    corners[0][2] = object.getCubitFaceStickerIndex(0,5);
-
-    corners[1][0] = object.getCubitFaceStickerIndex(1,3);
-    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
-    corners[1][2] = object.getCubitFaceStickerIndex(1,1);
-
-    corners[2][0] = object.getCubitFaceStickerIndex(2,5);
-    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
-    corners[2][2] = object.getCubitFaceStickerIndex(2,3);
-
-    corners[3][0] = object.getCubitFaceStickerIndex(3,1);
-    corners[3][1] = object.getCubitFaceStickerIndex(3,3);
-    corners[3][2] = object.getCubitFaceStickerIndex(3,5);
-
-    corners[4][0] = object.getCubitFaceStickerIndex(4,1);
-    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
-    corners[4][2] = object.getCubitFaceStickerIndex(4,5);
-
-    corners[5][0] = object.getCubitFaceStickerIndex(5,1);
-    corners[5][1] = object.getCubitFaceStickerIndex(5,3);
-    corners[5][2] = object.getCubitFaceStickerIndex(5,5);
-
-    corners[6][0] = object.getCubitFaceStickerIndex(6,1);
-    corners[6][1] = object.getCubitFaceStickerIndex(6,3);
-    corners[6][2] = object.getCubitFaceStickerIndex(6,5);
-
-    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;
-
-    int[] perm = new int[8];
-    int result1 = retCornerPermutation(perm,corners);
-    if( result1<0 ) return result1;
-
-    int[] perm7 = TBCube2.shrinkPerm(perm);
-    int permNum = TablebaseHelpers.computePermutationNum(perm7);
-    int[] twist = new int[8];
-    fillCornerTwists(twist,corners,perm);
-
-    int totalTwist = 0;
-    for(int i=0; i<8; i++) totalTwist += twist[i];
-    if( ((totalTwist)%3) != 0 ) return ERROR_CORNER_TWISTED;
-
-    int twistNum = twist[0] + 3*(twist[2] + 3*(twist[3] + 3*(twist[4] + 3*(twist[5] + 3*twist[6]))));
-
-    return twistNum + 729*permNum;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int face0, int face1, int face2)
-    {
-    int j0 = getHexColor(face0,3);
-    int j1 = getHexColor(face1,3);
-    int j2 = getHexColor(face2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING: return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_CORNERS_CANNOT: return res.getString(R.string.solver_generic_corners_cannot);
-      case ERROR_CORNER_TWISTED: return res.getString(R.string.solver_generic_corner_twist);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseDIAM2.java b/src/main/java/org/distorted/solvers/SolverTablebaseDIAM2.java
deleted file mode 100644
index ebad7a65..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseDIAM2.java
+++ /dev/null
@@ -1,397 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseDIAM2 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING   = -1;
-  private static final int ERROR_CENTER_MISSING   = -2;
-  private static final int ERROR_TWO_CORNERS      = -3;
-  private static final int ERROR_TWO_CENTERS      = -4;
-  private static final int ERROR_CORNER_TWIST_90  = -5;
-  private static final int ERROR_CORNER_TWIST_180 = -6;
-  private static final int ERROR_CORNERS_CANNOT   = -7;
-
-  private final int[] mFaceColors;
-  private int mErrColor1, mErrColor2;
-  private static final int[] FREE_CENTERS = {0,2,5,7};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseDIAM2(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    mFaceColors = new int[8];
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCorner(int[][] corners, int c1, int c2)
-    {
-    for(int i=0; i<6; i++)
-      {
-      int[] cor = corners[i];
-      int twist = retCornerTwist(cor,c1,c2);
-      if( twist>=0 ) return i;
-      }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] getCornersPermutation(int[][] corners)
-    {
-    int[] perm = new int[6];
-
-    perm[0] = retCorner(corners,mFaceColors[1],mFaceColors[4]);
-    perm[1] = retCorner(corners,mFaceColors[1],mFaceColors[6]);
-    perm[2] = retCorner(corners,mFaceColors[3],mFaceColors[6]);
-    perm[3] = retCorner(corners,mFaceColors[3],mFaceColors[4]);
-    perm[4] = retCorner(corners,mFaceColors[1],mFaceColors[3]);
-    perm[5] = retCorner(corners,mFaceColors[4],mFaceColors[6]);
-
-    return perm;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeCornerTwist(int[] corner, int color )
-    {
-    if( corner[3]==color ) return 0;
-    if( corner[2]==color ) return 1;
-    if( corner[1]==color ) return 2;
-    if( corner[0]==color ) return 3;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] getCornersTwist(int[] corners_perm, int[][] corners)
-    {
-    int[] twist = new int[6];
-
-    twist[0] = computeCornerTwist( corners[corners_perm[0]], mFaceColors[1] );
-    twist[1] = computeCornerTwist( corners[corners_perm[1]], mFaceColors[1] );
-    twist[2] = computeCornerTwist( corners[corners_perm[2]], mFaceColors[3] );
-    twist[3] = computeCornerTwist( corners[corners_perm[3]], mFaceColors[3] );
-    twist[4] = computeCornerTwist( corners[corners_perm[4]], mFaceColors[1] );
-    twist[5] = computeCornerTwist( corners[corners_perm[5]], mFaceColors[4] );
-
-    return twist;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCenter(int color, int[] centers)
-    {
-    for(int i=0; i<4; i++ )
-      if( centers[FREE_CENTERS[i]]==color ) return i;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] getFreeCentersPermutation(int[] centers)
-    {
-    int[] perm = new int[4];
-
-    for(int i=0; i<4; i++ )
-      perm[i] = retCenter(mFaceColors[FREE_CENTERS[i]],centers);
-
-    return perm;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getTotalTwist(int[] twist)
-    {
-    int total = 0;
-    boolean even = true;
-
-    for(int i=0; i<6; i++)
-      {
-      int t= twist[i];
-
-      if( t==1 || t==3 ) return ERROR_CORNER_TWIST_90;
-      if( t==2 )
-        {
-        if( i<5 ) total+=(1<<i);
-        even = !even;
-        }
-      }
-
-    return even ? total : ERROR_CORNER_TWIST_180;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCornerTwist(int[] corner, int c1, int c2)
-    {
-    if( corner[0]==c1 && corner[2]==c2 ) return 1;
-    if( corner[1]==c1 && corner[3]==c2 ) return 2;
-    if( corner[2]==c1 && corner[0]==c2 ) return 3;
-    if( corner[3]==c1 && corner[1]==c2 ) return 0;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int figureOutColor(int[][] corners, int c1, int c2)
-    {
-    for(int i=0; i<6; i++)
-      {
-      int[] cor = corners[i];
-      int twist = retCornerTwist(cor,c1,c2);
-      if( twist>=0 ) return cor[twist];
-      }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// We only move the UR, UR, DR & DB faces --> those centers are fixed and determine the colors of
-// the faces.
-
-  private int figureOutFaceColors(int[] output, int[] centers, int[][] corners)
-    {
-    output[1] = centers[1];
-    output[3] = centers[3];
-    output[4] = centers[4];
-    output[6] = centers[6];
-
-    int color01 = figureOutColor(corners,output[4],output[1]);
-    if( color01<0 ) { mErrColor1=4; mErrColor2=1; return ERROR_CORNER_MISSING; }
-    int color02 = figureOutColor(corners,output[3],output[4]);
-    if( color02<0 ) { mErrColor1=3; mErrColor2=4; return ERROR_CORNER_MISSING; }
-    int color03 = figureOutColor(corners,output[1],output[3]);
-    if( color03<0 ) { mErrColor1=1; mErrColor2=3; return ERROR_CORNER_MISSING; }
-    if( color01!=color02 || color01!=color03 ) return ERROR_CORNERS_CANNOT;
-    output[0] = color01;
-
-    int color21 = figureOutColor(corners,output[1],output[6]);
-    if( color21<0 ) { mErrColor1=1; mErrColor2=6; return ERROR_CORNER_MISSING; }
-    int color22 = figureOutColor(corners,output[6],output[3]);
-    if( color22<0 ) { mErrColor1=6; mErrColor2=3; return ERROR_CORNER_MISSING; }
-    int color23 = figureOutColor(corners,output[3],output[1]);
-    if( color23<0 ) { mErrColor1=3; mErrColor2=1; return ERROR_CORNER_MISSING; }
-    if( color21!=color22 || color21!=color23 ) return ERROR_CORNERS_CANNOT;
-    output[2] = color21;
-
-    int color51 = figureOutColor(corners,output[1],output[4]);
-    if( color51<0 ) { mErrColor1=1; mErrColor2=4; return ERROR_CORNER_MISSING; }
-    int color52 = figureOutColor(corners,output[6],output[1]);
-    if( color52<0 ) { mErrColor1=6; mErrColor2=1; return ERROR_CORNER_MISSING; }
-    int color53 = figureOutColor(corners,output[4],output[6]);
-    if( color53<0 ) { mErrColor1=4; mErrColor2=6; return ERROR_CORNER_MISSING; }
-    if( color51!=color52 || color51!=color53 ) return ERROR_CORNERS_CANNOT;
-    output[5] = color51;
-
-    int color71 = figureOutColor(corners,output[3],output[6]);
-    if( color71<0 ) { mErrColor1=3; mErrColor2=6; return ERROR_CORNER_MISSING; }
-    int color72 = figureOutColor(corners,output[4],output[3]);
-    if( color72<0 ) { mErrColor1=4; mErrColor2=3; return ERROR_CORNER_MISSING; }
-    int color73 = figureOutColor(corners,output[6],output[4]);
-    if( color73<0 ) { mErrColor1=6; mErrColor2=4; return ERROR_CORNER_MISSING; }
-    if( color71!=color72 || color71!=color73 ) return ERROR_CORNERS_CANNOT;
-    output[7] = color71;
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllColorsDifferent()
-    {
-    for(int i=0; i<8; i++)
-      {
-      boolean present = false;
-
-      for(int j=0; j<8; j++)
-        if( mFaceColors[j]==i )
-          {
-          present=true;
-          break;
-          }
-
-      if( !present ) return ERROR_CORNERS_CANNOT;
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCentersPresent(int[] centers)
-    {
-    for(int i=0; i<8; i++)
-      {
-      boolean present = false;
-
-      for(int j=0; j<8; j++)
-        if( centers[j]==i )
-          {
-          present=true;
-          break;
-          }
-
-      if( !present ) { mErrColor1=i; return ERROR_CENTER_MISSING; }
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCorners(TwistyObject object, int[][] corners)
-    {
-    corners[0][0] = object.getCubitFaceStickerIndex( 0,5); // FR
-    corners[0][1] = object.getCubitFaceStickerIndex( 0,4);
-    corners[0][2] = object.getCubitFaceStickerIndex( 0,0);
-    corners[0][3] = object.getCubitFaceStickerIndex( 0,1);
-
-    corners[1][0] = object.getCubitFaceStickerIndex( 1,2); // BR
-    corners[1][1] = object.getCubitFaceStickerIndex( 1,6);
-    corners[1][2] = object.getCubitFaceStickerIndex( 1,5);
-    corners[1][3] = object.getCubitFaceStickerIndex( 1,1);
-
-    corners[2][0] = object.getCubitFaceStickerIndex( 2,7); // BL
-    corners[2][1] = object.getCubitFaceStickerIndex( 2,6);
-    corners[2][2] = object.getCubitFaceStickerIndex( 2,2);
-    corners[2][3] = object.getCubitFaceStickerIndex( 2,3);
-
-    corners[3][0] = object.getCubitFaceStickerIndex( 3,0); // FL
-    corners[3][1] = object.getCubitFaceStickerIndex( 3,4);
-    corners[3][2] = object.getCubitFaceStickerIndex( 3,7);
-    corners[3][3] = object.getCubitFaceStickerIndex( 3,3);
-
-    corners[4][0] = object.getCubitFaceStickerIndex( 4,0); // U
-    corners[4][1] = object.getCubitFaceStickerIndex( 4,3);
-    corners[4][2] = object.getCubitFaceStickerIndex( 4,2);
-    corners[4][3] = object.getCubitFaceStickerIndex( 4,1);
-
-    corners[5][0] = object.getCubitFaceStickerIndex( 5,5); // D
-    corners[5][1] = object.getCubitFaceStickerIndex( 5,6);
-    corners[5][2] = object.getCubitFaceStickerIndex( 5,7);
-    corners[5][3] = object.getCubitFaceStickerIndex( 5,4);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCenters(TwistyObject object, int[] centers)
-    {
-    centers[0] = object.getCubitFaceStickerIndex( 9,0); // UF
-    centers[1] = object.getCubitFaceStickerIndex( 6,0); // UR
-    centers[2] = object.getCubitFaceStickerIndex( 7,0); // UB
-    centers[3] = object.getCubitFaceStickerIndex( 8,0); // UL
-    centers[4] = object.getCubitFaceStickerIndex(13,0); // DF
-    centers[5] = object.getCubitFaceStickerIndex(10,1); // DR
-    centers[6] = object.getCubitFaceStickerIndex(11,0); // DB
-    centers[7] = object.getCubitFaceStickerIndex(12,0); // DL
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners = new int[6][4];
-    int[] centers = new int[8];
-
-    getCorners(object,corners);
-    getCenters(object,centers);
-
-    int result1 = checkAllCentersPresent(centers);
-    if( result1<0 ) return result1;
-
-    int result2 = figureOutFaceColors(mFaceColors,centers,corners);
-    if( result2<0 ) return result2;
-
-    int result3 = checkAllColorsDifferent();
-    if( result3<0 ) return result3;
-
-    int[] corners_perm = getCornersPermutation(corners);
-    boolean even1 = TablebaseHelpers.permutationIsEven(corners_perm);
-    if( !even1 ) return ERROR_TWO_CORNERS;
-
-    int[] free_centers_perm = getFreeCentersPermutation(centers);
-    boolean even2 = TablebaseHelpers.permutationIsEven(free_centers_perm);
-    if( !even2 ) return ERROR_TWO_CENTERS;
-
-    int[] corners_twist = getCornersTwist(corners_perm, corners);
-/*
-android.util.Log.e("D", "faces: "+mFaceColors[0]+" "+mFaceColors[1]+" "+mFaceColors[2]+" "
-+mFaceColors[3]+" "+mFaceColors[4]+" "+mFaceColors[5]+" "+mFaceColors[6]+" "+mFaceColors[7]);
-
-android.util.Log.e("D", "corn perm: "+corners_perm[0]+" "+corners_perm[1]+" "+corners_perm[2]+" "
-+corners_perm[3]+" "+corners_perm[4]+" "+corners_perm[5]);
-
-android.util.Log.e("D", "corn twist: "+corners_twist[0]+" "+corners_twist[1]+" "+corners_twist[2]+" "
-+corners_twist[3]+" "+corners_twist[4]+" "+corners_twist[5]);
-*/
-    int totalTwist = getTotalTwist(corners_twist);
-    if( totalTwist<0 ) return totalTwist;
-
-    int corners_perm_num = TablebaseHelpers.computeEvenPermutationNum(corners_perm);
-    int centers_perm_num = TablebaseHelpers.computeEvenPermutationNum(free_centers_perm);
-
-    return centers_perm_num + 12*(totalTwist + 32*corners_perm_num);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String centerError(Resources res, int face)
-    {
-    int index = getOctColor(face,2);
-    String color = res.getString(index);
-    return res.getString(R.string.solver_generic_missing_center,color);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int f1, int f2)
-    {
-    int i1 = getOctColor(f1,3);
-    int i2 = getOctColor(f2,4);
-    String c1 = res.getString(i1);
-    String c2 = res.getString(i2);
-    return res.getString(R.string.solver_generic_missing_corner2,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING   : return cornerError(res,mErrColor1,mErrColor2);
-      case ERROR_CENTER_MISSING   : return centerError(res,mErrColor1);
-      case ERROR_TWO_CORNERS      : return res.getString(R.string.solver_generic_two_corners);
-      case ERROR_TWO_CENTERS      : return res.getString(R.string.solver_generic_two_centers);
-      case ERROR_CORNER_TWIST_90  : return res.getString(R.string.solver_generic_corner_twist) + " (90)";
-      case ERROR_CORNER_TWIST_180 : return res.getString(R.string.solver_generic_corner_twist) + " (180)";
-      case ERROR_CORNERS_CANNOT   : return res.getString(R.string.solver_generic_corners_cannot);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseDINO4.java b/src/main/java/org/distorted/solvers/SolverTablebaseDINO4.java
deleted file mode 100644
index c29347dd..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseDINO4.java
+++ /dev/null
@@ -1,169 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.shape.ShapeColors;
-import org.distorted.objectlib.shape.ShapeHexahedron;
-import org.distorted.objectlib.tablebases.TBDino4;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseDINO4 extends SolverTablebase
-{
-  private static final int ERROR_EDGE_THREE  = -1;
-  private int mErrorColor;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseDINO4(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os, res,object);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getEdges(TwistyObject object, int[][] edges)
-    {
-    for(int i=0; i<12; i++)
-      {
-      edges[0][i] = object.getCubitFaceStickerIndex(i,0);
-      edges[1][i] = object.getCubitFaceStickerIndex(i,1);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkEdges(int[][] edges)
-    {
-    int numB=0,numR=0, numY=0, numW=0;
-    int indB=0,indY=0, indW=0, indR=0;
-
-    int[] hexColors = ShapeHexahedron.FACE_COLORS;
-
-    for(int i=0; i<6; i++)
-      {
-      int color = hexColors[i];
-
-      if( color == ShapeColors.COLOR_WHITE) indW = i;
-      if( color == ShapeColors.COLOR_YELLOW) indY = i;
-      if( color == ShapeColors.COLOR_RED) indR = i;
-      if( color == ShapeColors.COLOR_BLUE) indB = i;
-      }
-
-    for(int i=0; i<12; i++)
-      {
-      int e = edges[0][i];
-
-      if( e==edges[1][i] )
-        {
-        if( e==indY ) numY++;
-        if( e==indW ) numW++;
-        if( e==indR ) numR++;
-        if( e==indB ) numB++;
-        }
-      }
-
-    if( numY !=3 ) { mErrorColor=0; return ERROR_EDGE_THREE; }
-    if( numW !=3 ) { mErrorColor=1; return ERROR_EDGE_THREE; }
-    if( numB !=3 ) { mErrorColor=2; return ERROR_EDGE_THREE; }
-    if( numR !=3 ) { mErrorColor=3; return ERROR_EDGE_THREE; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void remap(int[] perm, int[] edges, int index, int section)
-    {
-    int val = edges[index];
-
-    for(int i=index;i<12; i++)
-      if( edges[i]==val )
-        {
-        edges[i]=-1;
-        perm[i] = section;
-        }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] getPermutation(int[] edges)
-    {
-    int[] perm = new int[12];
-
-    int index0 = 0;
-    remap(perm,edges,index0,0);
-
-    int index1 = index0+1;
-
-    for(;index1<12;index1++)
-      if( edges[index1]>=0 ) break;
-    remap(perm,edges,index1,1);
-
-    int index2 = index1+1;
-
-    for(;index2<12;index2++)
-      if( edges[index2]>=0 ) break;
-    remap(perm,edges,index2,2);
-
-    int index3 = index2+1;
-
-    for(;index3<12;index3++)
-      if( edges[index3]>=0 ) break;
-    remap(perm,edges,index3,3);
-
-    return perm;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] edges = new int[2][12];
-    getEdges(object,edges);
-
-    int result1 = checkEdges(edges);
-    if( result1<0 ) return result1;
-
-    int[] perm = getPermutation(edges[0]);
-    return TBDino4.indexFromPartition(perm);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getColorIndex7(int color)
-    {
-    switch(color)
-      {
-      case 0: return R.string.color_yellow7;
-      case 1: return R.string.color_white7;
-      case 2: return R.string.color_blue7;
-      case 3: return R.string.color_red7;
-      }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    int i = getColorIndex7(mErrorColor);
-    String color = res.getString(i);
-
-    return res.getString(R.string.solver_generic_edge_three,color);
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseDINO6.java b/src/main/java/org/distorted/solvers/SolverTablebaseDINO6.java
deleted file mode 100644
index c6a134af..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseDINO6.java
+++ /dev/null
@@ -1,401 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TBDino6;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseDINO6 extends SolverTablebase
-{
-  private static final int ERROR_EDGE_MISSING        = -1;
-  private static final int ERROR_EDGE_CANNOT         = -2;
-  private static final int ERROR_EDGE_TWISTED        = -3;
-  private static final int ERROR_EDGE_MONOCHROMATIC  = -4;
-  private static final int ERROR_EDGE_TWICE          = -5;
-  private static final int ERROR_TWO_EDGES           = -6;
-
-  int[][] EDGE_MAP = {
-                      {4,2},{0,4},{4,3},{1,4},
-                      {2,0},{3,0},{3,1},{2,1},
-                      {5,2},{0,5},{5,3},{1,5}
-                     };
-
-  private final int[] mFaceColors;
-  private int mErrorColor1, mErrorColor2;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseDINO6(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    mFaceColors = new int[6];
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getEdges(TwistyObject object, int[][] edges)
-    {
-    for(int i=0; i<12; i++)
-      {
-      edges[i][0] = object.getCubitFaceStickerIndex(i,0);
-      edges[i][1] = object.getCubitFaceStickerIndex(i,1);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeOpposite(int color, int[][] edges)
-    {
-    int[] buffer = new int[6];
-    for(int i=0; i<6; i++) buffer[i] = 0;
-
-    for(int i=0; i<12; i++)
-      {
-      int e0 = edges[i][0];
-      int e1 = edges[i][1];
-
-      if( e0==color && e1==color)
-        {
-        mErrorColor1 = color;
-        return ERROR_EDGE_MONOCHROMATIC;
-        }
-
-      if( e0==color )
-        {
-        buffer[e1]++;
-
-        if( buffer[e1]>1 )
-          {
-          mErrorColor1 = color;
-          mErrorColor2 = e1;
-          return ERROR_EDGE_TWICE;
-          }
-        }
-
-      if( e1==color )
-        {
-        buffer[e0]++;
-
-        if( buffer[e0]>1 )
-          {
-          mErrorColor1 = color;
-          mErrorColor2 = e0;
-          return ERROR_EDGE_TWICE;
-          }
-        }
-      }
-
-    int total = 0;
-
-    for(int i=0; i<6; i++)
-      if( buffer[i]==1 )
-        {
-        if( i!=color) total++;
-        else
-          {
-          mErrorColor1 = i;
-          return ERROR_EDGE_MONOCHROMATIC;
-          }
-        }
-
-    if( total==4 )
-      for(int i=0; i<6; i++)
-        if( buffer[i]==0 && i!=color ) return i;
-
-    return ERROR_EDGE_CANNOT;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int fillUpRemainingFaceColors(boolean[] buffer)
-    {
-    for(int i=0; i<6; i++)
-      {
-      buffer[i] = false;
-      }
-    for(int i=0; i<6; i++)
-      {
-      int color = mFaceColors[i];
-      if( color>=0 ) buffer[color] = true;
-      }
-
-    int total = 0;
-    for(int i=0; i<6; i++)
-      if( buffer[i] ) total++;
-
-    if( total==4 )
-      {
-      for(int i=0; i<6; i++)
-        if( !buffer[i] )
-          {
-          buffer[i]=true;
-          mFaceColors[0] = i;
-          break;
-          }
-      for(int i=0; i<6; i++)
-        if( !buffer[i] )
-          {
-          buffer[i]=true;
-          mFaceColors[1] = i;
-          break;
-          }
-
-      return 0;
-      }
-
-    return ERROR_EDGE_CANNOT;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int figureOutFaceColors(int[][] edges)
-    {
-    boolean[] present = new boolean[6];
-
-    for(int i=0; i<6; i++) mFaceColors[i] = -1;
-
-    for(int i=0; i<12; i++)
-      {
-      int[] edge = edges[i];
-      int c0 = edge[0];
-      int c1 = edge[1];
-
-      if( c0>=0 && c0<6 ) present[c0] = true;
-      if( c1>=0 && c1<6 ) present[c1] = true;
-      }
-
-    for(int i=0; i<6; i++)
-      if( !present[i] )
-        {
-        mErrorColor1 = i;
-        mErrorColor2 = (i<4 ? i+2 : i-2 );
-        return ERROR_EDGE_MISSING;
-        }
-
-    if( edges[0][0]==edges[0][1] ) return ERROR_EDGE_CANNOT;
-
-    mFaceColors[4] = edges[0][0];
-    mFaceColors[2] = edges[0][1];
-    mFaceColors[5] = computeOpposite(mFaceColors[4], edges);
-    if( mFaceColors[5]<0 ) return mFaceColors[5];
-
-    mFaceColors[3] = computeOpposite(mFaceColors[2], edges);
-    if( mFaceColors[3]<0 ) return mFaceColors[3];
-
-    int success = fillUpRemainingFaceColors(present);
-    if( success<0 ) return success;
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean notPresent(int face0, int face1, int[][] edges)
-    {
-    int c0=mFaceColors[face0];
-    int c1=mFaceColors[face1];
-
-    for(int i=0; i<12; i++)
-      {
-      int[] edge = edges[i];
-      if( edge[0]==c0 && edge[1]==c1 ) return false;
-      if( edge[0]==c1 && edge[1]==c0 ) return false;
-      }
-    return true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int checkAllPresent(int[][] edges)
-    {
-    for(int i=0; i<12; i++)
-      {
-      int[] map = EDGE_MAP[i];
-      int m1 = map[0];
-      int m2 = map[1];
-
-      if( notPresent(m1,m2,edges) )
-        {
-        mErrorColor1 = mFaceColors[m1];
-        mErrorColor2 = mFaceColors[m2];
-        return ERROR_EDGE_MISSING;
-        }
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean wrongTwist(int face0, int face1, int[][] edges)
-    {
-    int c0=mFaceColors[face0];
-    int c1=mFaceColors[face1];
-
-    for(int i=0; i<12; i++)
-      {
-      int[] edge = edges[i];
-      if( edge[1]==c0 && edge[0]==c1 ) return true;
-      }
-    return false;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int checkTwist(int[][] edges)
-    {
-    for(int i=0; i<12; i++)
-      {
-      int[] map = EDGE_MAP[i];
-      int m1 = map[0];
-      int m2 = map[1];
-
-      if( wrongTwist(m1,m2,edges) )
-        {
-        mErrorColor1 = mFaceColors[m1];
-        mErrorColor2 = mFaceColors[m2];
-        return ERROR_EDGE_TWISTED;
-        }
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getPerm(int face0, int face1, int[][] edges)
-    {
-    int c0=mFaceColors[face0];
-    int c1=mFaceColors[face1];
-
-    for(int i=0; i<12; i++)
-      {
-      int[] edge = edges[i];
-      if( edge[0]==c0 && edge[1]==c1 ) return i;
-      }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computePermutation(int[][] edges, int[] perm)
-    {
-    for(int i=0; i<12; i++)
-      {
-      int[] map = EDGE_MAP[i];
-      int m1 = map[0];
-      int m2 = map[1];
-      perm[i] = getPerm(m1,m2,edges);
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] edges = new int[12][2];
-    getEdges(object,edges);
-
-    int result1 = figureOutFaceColors(edges);
-    if( result1<0 ) return result1;
-
-    int result2 = checkAllPresent(edges);
-    if( result2<0 ) return result2;
-
-    int result3 = checkTwist(edges);
-    if( result3<0 ) return result3;
-
-    int[] perm = new int[12];
-    int result4 = computePermutation(edges,perm);
-    if( result4<0 ) return result4;
-
-    if( !TablebaseHelpers.permutationIsEven(perm) ) return ERROR_TWO_EDGES;
-
-    return TBDino6.getIndexFromPerm(perm);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeMissingError(Resources res, int color0, int color1)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeTwistedError(Resources res, int color0, int color1)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeMonoError(Resources res, int color)
-    {
-    int j0 = getHexColor(color,3);
-    int j1 = getHexColor(color,6);
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_edge_mono,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeTwiceError(Resources res, int color0, int color1)
-    {
-    int j0 = getHexColor(color0,3);
-    int j1 = getHexColor(color1,6);
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_edge_twice,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_EDGE_MISSING      : return edgeMissingError(res,mErrorColor1,mErrorColor2);
-      case ERROR_EDGE_TWISTED      : return edgeTwistedError(res,mErrorColor1,mErrorColor2);
-      case ERROR_EDGE_MONOCHROMATIC: return edgeMonoError(res,mErrorColor1);
-      case ERROR_EDGE_TWICE        : return edgeTwiceError(res,mErrorColor1,mErrorColor2);
-      case ERROR_EDGE_CANNOT       : return res.getString(R.string.solver_generic_edges_cannot);
-      case ERROR_TWO_EDGES         : return res.getString(R.string.solver_generic_two_edges);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseIVY2.java b/src/main/java/org/distorted/solvers/SolverTablebaseIVY2.java
deleted file mode 100644
index b0075323..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseIVY2.java
+++ /dev/null
@@ -1,221 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseIVY2 extends SolverTablebase
-{
-  private static final int ERROR_CENTER_MISSING   = -1;
-  private static final int ERROR_TWO_CENTERS_SWAP = -2;
-  private static final int ERROR_CORNERS_CANNOT   = -3;
-
-  private int mErrorColor;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCentersPresent(int[] centers)
-    {
-    int numCenters = centers.length;
-
-    for(int color=0; color<numCenters; color++)
-      {
-      boolean error = true;
-      int center;
-
-      for(center=0; center<numCenters; center++)
-        if( centers[center]==color )
-          {
-          error = false;
-          break;
-          }
-
-      if( error ) { mErrorColor=color; return ERROR_CENTER_MISSING; }
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean checkCommonColor(int[] buffer, int index, int[] c1, int[] c2)
-    {
-    if( c1[0]==c1[1] || c1[0]==c1[2] || c1[1]==c1[2] ) return false;
-    if( c2[0]==c2[1] || c2[0]==c2[2] || c2[1]==c2[2] ) return false;
-
-    if( c1[0]==c2[0] && c1[1]!=c2[1] && c1[1]!=c2[2] && c1[2]!=c2[1] && c1[2]!=c2[2] )
-      {
-      buffer[index] = c1[0];
-      return true;
-      }
-    if( c1[0]==c2[1] && c1[1]!=c2[0] && c1[1]!=c2[2] && c1[2]!=c2[0] && c1[2]!=c2[2] )
-      {
-      buffer[index] = c1[0];
-      return true;
-      }
-    if( c1[0]==c2[2] && c1[1]!=c2[0] && c1[1]!=c2[1] && c1[2]!=c2[0] && c1[2]!=c2[1] )
-      {
-      buffer[index] = c1[0];
-      return true;
-      }
-
-    if( c1[1]==c2[0] && c1[0]!=c2[1] && c1[0]!=c2[2] && c1[2]!=c2[1] && c1[2]!=c2[2] )
-      {
-      buffer[index] = c1[1];
-      return true;
-      }
-    if( c1[1]==c2[1] && c1[0]!=c2[0] && c1[0]!=c2[2] && c1[2]!=c2[0] && c1[2]!=c2[2] )
-      {
-      buffer[index] = c1[1];
-      return true;
-      }
-    if( c1[1]==c2[2] && c1[0]!=c2[0] && c1[0]!=c2[1] && c1[2]!=c2[0] && c1[2]!=c2[1] )
-      {
-      buffer[index] = c1[1];
-      return true;
-      }
-
-    if( c1[2]==c2[0] && c1[1]!=c2[1] && c1[1]!=c2[2] && c1[0]!=c2[1] && c1[0]!=c2[2] )
-      {
-      buffer[index] = c1[2];
-      return true;
-      }
-    if( c1[2]==c2[1] && c1[1]!=c2[0] && c1[1]!=c2[2] && c1[0]!=c2[0] && c1[0]!=c2[2] )
-      {
-      buffer[index] = c1[2];
-      return true;
-      }
-    if( c1[2]==c2[2] && c1[1]!=c2[0] && c1[1]!=c2[1] && c1[0]!=c2[0] && c1[0]!=c2[1] )
-      {
-      buffer[index] = c1[2];
-      return true;
-      }
-
-    return false;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeFaceColor(int[] buffer, int[][] corners)
-    {
-    boolean success0 = checkCommonColor(buffer,0,corners[0],corners[3]);
-    if( !success0 ) return ERROR_CORNERS_CANNOT;
-    boolean success1 = checkCommonColor(buffer,1,corners[1],corners[2]);
-    if( !success1 ) return ERROR_CORNERS_CANNOT;
-    boolean success2 = checkCommonColor(buffer,2,corners[0],corners[1]);
-    if( !success2 ) return ERROR_CORNERS_CANNOT;
-    boolean success3 = checkCommonColor(buffer,3,corners[2],corners[3]);
-    if( !success3 ) return ERROR_CORNERS_CANNOT;
-    boolean success4 = checkCommonColor(buffer,4,corners[0],corners[2]);
-    if( !success4 ) return ERROR_CORNERS_CANNOT;
-    boolean success5 = checkCommonColor(buffer,5,corners[1],corners[3]);
-    if( !success5 ) return ERROR_CORNERS_CANNOT;
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeCenterColors(int[] buffer, int[] faceColors, int[] centers)
-    {
-    int numCenters = faceColors.length;
-
-    for(int color=0; color<numCenters; color++)
-      for(int center=0; center<numCenters; center++)
-        if( centers[center]==faceColors[color] )
-          {
-          buffer[center]=color;
-          }
-
-    return TablebaseHelpers.permutationIsEven(buffer) ? 0 : ERROR_TWO_CENTERS_SWAP;
-    }
-////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeCornerTwist(int[] corner, int color)
-    {
-    if( corner[0]==color ) return 0;
-    if( corner[1]==color ) return 1;
-    return 2;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseIVY2(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners     = new int[4][3];
-    int[] centers       = new int[6];
-    int[] twist         = new int[4];
-    int[] face_colors   = new int[6];
-    int[] center_colors = new int[6];
-
-    for(int i=0; i<4; i++)
-      for(int j=0; j<3; j++)
-        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
-
-    for(int i=0; i<6; i++)
-      centers[i] = object.getCubitFaceStickerIndex(i+4,0) - 6;
-
-    int result1 = checkAllCentersPresent(centers);
-    if( result1<0 ) return result1;
-
-    int result2 = computeFaceColor(face_colors,corners);
-    if( result2<0 ) return result2;
-
-    int result3 = computeCenterColors(center_colors, face_colors, centers);
-    if( result3<0 ) return result3;
-
-    twist[0] = computeCornerTwist(corners[0],face_colors[4]);
-    twist[1] = computeCornerTwist(corners[1],face_colors[5]);
-    twist[2] = computeCornerTwist(corners[2],face_colors[4]);
-    twist[3] = computeCornerTwist(corners[3],face_colors[5]);
-
-    int perm_num = TablebaseHelpers.computeEvenPermutationNum(center_colors);
-
-    return perm_num + 360*(twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*twist[3])));
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String centerError(Resources res, int face)
-    {
-    int j = getHexColor(face,2);
-    String c = res.getString(j);
-    return res.getString(R.string.solver_generic_missing_center,c);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CENTER_MISSING  : return centerError(res,mErrorColor);
-      case ERROR_TWO_CENTERS_SWAP: return res.getString(R.string.solver_generic_two_centers);
-      case ERROR_CORNERS_CANNOT  : return res.getString(R.string.solver_generic_corners_cannot);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseJING2.java b/src/main/java/org/distorted/solvers/SolverTablebaseJING2.java
deleted file mode 100644
index 38c3afcb..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseJING2.java
+++ /dev/null
@@ -1,437 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TBPyraminx;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseJING2 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING = -1;
-  private static final int ERROR_EDGE_MISSING   = -2;
-  private static final int ERROR_CENTER_MISSING = -3;
-  private static final int ERROR_CORNERS_CANNOT = -4;
-  private static final int ERROR_EDGE_TWISTED   = -5;
-  private static final int ERROR_CORNER_TWISTED = -6;
-  private static final int ERROR_TWO_EDGES      = -7;
-  private static final int ERROR_TWO_CENTERS    = -8;
-
-  private int[] mFaceColors;
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseJING2(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean pieceEqual3(int[] piece, int c1, int c2, int c3)
-    {
-    return ( (piece[0]==c1 && piece[1]==c2 && piece[2]==c3) ||
-             (piece[0]==c1 && piece[2]==c2 && piece[1]==c3) ||
-             (piece[1]==c1 && piece[0]==c2 && piece[2]==c3) ||
-             (piece[1]==c1 && piece[2]==c2 && piece[0]==c3) ||
-             (piece[2]==c1 && piece[1]==c2 && piece[0]==c3) ||
-             (piece[2]==c1 && piece[0]==c2 && piece[1]==c3)  );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean pieceEqual2(int[] piece, int[] colors)
-    {
-    return ( (piece[0]==colors[0] && piece[1]==colors[1]) ||
-             (piece[0]==colors[1] && piece[1]==colors[0])  );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCornersPresent(int[][] corners)
-    {
-    boolean ybr = false;
-    boolean gbr = false;
-    boolean gyr = false;
-    boolean gyb = false;
-
-    for(int i=0; i<4; i++)
-      {
-      if( pieceEqual3(corners[i],0,1,2) ) gyb = true;
-      if( pieceEqual3(corners[i],0,1,3) ) gyr = true;
-      if( pieceEqual3(corners[i],0,2,3) ) gbr = true;
-      if( pieceEqual3(corners[i],1,2,3) ) ybr = true;
-      }
-
-    if( !ybr ) { mErrColor1=1; mErrColor2=2; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gbr ) { mErrColor1=0; mErrColor2=2; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gyr ) { mErrColor1=0; mErrColor2=1; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gyb ) { mErrColor1=0; mErrColor2=1; mErrColor3=2; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllEdgesPresent(int[][] edges, int[][] edgeColors)
-    {
-    boolean[] present = new boolean[6];
-    for(int i=0; i<6; i++) present[i] = false;
-
-    for(int i=0; i<6; i++)
-      for(int j=0; j<6; j++)
-        if( pieceEqual2(edges[i], edgeColors[j]) )
-          {
-          present[j] = true;
-          break;
-          }
-
-    if( !present[0] ) { mErrColor1=3; mErrColor2=2; return ERROR_EDGE_MISSING; }
-    if( !present[1] ) { mErrColor1=3; mErrColor2=1; return ERROR_EDGE_MISSING; }
-    if( !present[2] ) { mErrColor1=2; mErrColor2=1; return ERROR_EDGE_MISSING; }
-    if( !present[3] ) { mErrColor1=3; mErrColor2=0; return ERROR_EDGE_MISSING; }
-    if( !present[4] ) { mErrColor1=2; mErrColor2=0; return ERROR_EDGE_MISSING; }
-    if( !present[5] ) { mErrColor1=1; mErrColor2=0; return ERROR_EDGE_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCentersPresent(int[] centers)
-    {
-    boolean[] present = new boolean[4];
-    for(int i=0; i<4; i++) present[i] = false;
-    for(int i=0; i<4; i++) present[centers[i]]= true;
-
-    if( !present[0] ) { mErrColor1=0; return ERROR_CENTER_MISSING; }
-    if( !present[1] ) { mErrColor1=1; return ERROR_CENTER_MISSING; }
-    if( !present[2] ) { mErrColor1=2; return ERROR_CENTER_MISSING; }
-    if( !present[3] ) { mErrColor1=3; return ERROR_CENTER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] computeFaceColors(int[][] corners)
-    {
-    int[] ret = new int[4];
-
-    for(int i=0; i<4; i++)
-      for(int j=0; j<4; j++)
-        if( corners[i][0]!=j && corners[i][1]!=j && corners[i][2]!=j ) ret[i]=j;
-
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computePieceTwist(int index, int[] corner, int[] faceColor)
-    {
-    int twist1=0, twist2=0, twist3=0;
-
-    switch(index)
-      {
-      case 0: if( corner[1]==faceColor[1] ) twist1=1;
-              if( corner[2]==faceColor[1] ) twist1=2;
-              if( corner[0]==faceColor[2] ) twist2=2;
-              if( corner[2]==faceColor[2] ) twist2=1;
-              if( corner[0]==faceColor[3] ) twist3=1;
-              if( corner[1]==faceColor[3] ) twist3=2;
-              break;
-      case 1: if( corner[1]==faceColor[0] ) twist1=1;
-              if( corner[2]==faceColor[0] ) twist1=2;
-              if( corner[0]==faceColor[2] ) twist2=1;
-              if( corner[1]==faceColor[2] ) twist2=2;
-              if( corner[0]==faceColor[3] ) twist3=2;
-              if( corner[2]==faceColor[3] ) twist3=1;
-              break;
-      case 2: if( corner[1]==faceColor[0] ) twist1=1;
-              if( corner[2]==faceColor[0] ) twist1=2;
-              if( corner[0]==faceColor[1] ) twist2=2;
-              if( corner[2]==faceColor[1] ) twist2=1;
-              if( corner[0]==faceColor[3] ) twist3=1;
-              if( corner[1]==faceColor[3] ) twist3=2;
-              break;
-      case 3: if( corner[1]==faceColor[0] ) twist1=1;
-              if( corner[2]==faceColor[0] ) twist1=2;
-              if( corner[0]==faceColor[1] ) twist2=1;
-              if( corner[1]==faceColor[1] ) twist2=2;
-              if( corner[0]==faceColor[2] ) twist3=2;
-              if( corner[2]==faceColor[2] ) twist3=1;
-              break;
-      }
-
-    return ( twist1!=twist2 || twist1!=twist3 ) ? ERROR_CORNERS_CANNOT : twist1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int locateEdge(int[][] edges, int[] colors)
-    {
-    for(int i=0; i<6; i++)
-      if( edges[i][0]==colors[0] && edges[i][1]==colors[1] ||
-          edges[i][0]==colors[1] && edges[i][1]==colors[0]  ) return i;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int edgeTwist(int[] edge, int[] colors)
-    {
-    return edge[0]==colors[0] ? 0:1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] computeEdgeQuats(int[][] edges, int[][] edgeColors)
-    {
-    int[] quats = new int[6];
-
-    for(int i=0; i<6; i++)
-      {
-      int pos   = locateEdge(edges,edgeColors[i]);
-      int twist = edgeTwist(edges[pos],edgeColors[i]);
-      quats[i]  = TBPyraminx.EDGE_QUATS[pos][twist];
-      }
-
-    return quats;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// GRB YBR YGB YRG
-
-  private void getCorners(TwistyObject object, int[][] corners)
-    {
-    for(int i=0; i<4; i++)
-      for(int j=0; j<3; j++)
-        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// RB GB RG YB RY GY
-
-  private void getEdges(TwistyObject object, int[][] edges)
-    {
-    for(int i=0; i<6; i++)
-      for(int j=0; j<2; j++)
-        edges[i][j] = object.getCubitFaceStickerIndex(i+4,j) -4;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// G Y B R
-
-  private void getCenters(TwistyObject object, int[] centers)
-    {
-    for(int i=0; i<4; i++)
-      centers[i] = object.getCubitFaceStickerIndex(i+10,0) - 8;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[][] computeEdgeColors(int[] faceColor)
-    {
-    // The first pair being (2,3) means 'the first edge's first face is on the tetrahedron
-    // face which opposes corner number 2, and its second face on tetra face which opposes
-    // corner number 3'
-    // Order of those pairs determines edge twist.
-
-    final int[][] edgeColorIndices = new int[][] { {2,3},{1,3},{2,1},{0,3},{2,0},{1,0}  };
-    int[][] ret = new int[6][2];
-
-    for(int i=0; i<6; i++)
-      {
-      ret[i][0] = faceColor[edgeColorIndices[i][0]];
-      ret[i][1] = faceColor[edgeColorIndices[i][1]];
-      }
-
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeCenterTwist(int[] centers, int color1, int color2)
-    {
-    if( centers[0]==color1 )
-      {
-      if( centers[1]==color2 ) return 1;
-      if( centers[2]==color2 ) return 2;
-      if( centers[3]==color2 ) return 0;
-
-      return -1;
-      }
-    if( centers[1]==color1 )
-      {
-      if( centers[0]==color2 ) return 1;
-      if( centers[2]==color2 ) return 0;
-      if( centers[3]==color2 ) return 2;
-
-      return -1;
-      }
-    if( centers[2]==color1 )
-      {
-      if( centers[0]==color2 ) return 2;
-      if( centers[1]==color2 ) return 0;
-      if( centers[3]==color2 ) return 1;
-
-      return -1;
-      }
-    if( centers[3]==color1 )
-      {
-      if( centers[0]==color2 ) return 0;
-      if( centers[1]==color2 ) return 2;
-      if( centers[2]==color2 ) return 1;
-
-      return -1;
-      }
-
-    return -2;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getFaceOfCenter(int color, int[] centers)
-    {
-    if( centers[0]==color ) return 0;
-    if( centers[1]==color ) return 1;
-    if( centers[2]==color ) return 2;
-    if( centers[3]==color ) return 3;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners   = new int[4][3];
-    int[][] edges     = new int[6][2];
-    int[] centers     = new int[4];
-    int[] corner_twist= new int[4];
-
-    getCorners(object,corners);
-
-    int result1 = checkAllCornersPresent(corners);
-    if( result1<0 ) return result1;
-
-    mFaceColors = computeFaceColors(corners);
-    int[][] edgeColors = computeEdgeColors(mFaceColors);
-
-    getEdges(object,edges);
-    int result2 = checkAllEdgesPresent(edges,edgeColors);
-    if( result2<0 ) return result2;
-
-    getCenters(object,centers);
-    int result3 = checkAllCentersPresent(centers);
-    if( result3<0 ) return result3;
-
-    for(int i=0; i<4; i++)
-      {
-      corner_twist[i] = computePieceTwist(i,corners[i],mFaceColors);
-      if( corner_twist[i]<0 ) return ERROR_CORNERS_CANNOT;
-      }
-
-    int[] quats = computeEdgeQuats(edges,edgeColors);
-    int[] permutation = new int[6];
-    TBPyraminx.getEdgePermutation(permutation,quats,0);
-    boolean even = TablebaseHelpers.permutationIsEven(permutation);
-    if( !even ) return ERROR_TWO_EDGES;
-    int[] edge_twist = new int[6];
-    TBPyraminx.getEdgeTwist(edge_twist,quats,0);
-
-    int twist_gr = computeCenterTwist(centers,mFaceColors[1],mFaceColors[2]);
-    int twist_ry = computeCenterTwist(centers,mFaceColors[2],mFaceColors[0]);
-
-    if( (twist_ry-twist_gr+1)%3 != 0 ) return ERROR_TWO_CENTERS;
-
-    int total_twist=0;
-    for(int i=0; i<4; i++) total_twist += corner_twist[i];
-
-    if( (total_twist-twist_gr)%3 !=0 ) return ERROR_CORNER_TWISTED;
-
-    int green_face = getFaceOfCenter(mFaceColors[1],centers);
-
-    int totalEdgeTwist=0;
-    for(int i=0; i<6; i++) totalEdgeTwist += edge_twist[i];
-    if( (totalEdgeTwist%2)!=0 ) return ERROR_EDGE_TWISTED;
-
-    int vertexTwist = corner_twist[0]+ 3*(corner_twist[1]+ 3*(corner_twist[2]+ 3*corner_twist[3]));
-    int edgeTwist = edge_twist[0]+ 2*(edge_twist[1]+ 2*(edge_twist[2]+ 2*(edge_twist[3]+ 2*edge_twist[4])));
-    int perm_num = TablebaseHelpers.computeEvenPermutationNum(permutation);
-
-    return green_face + 4*(vertexTwist + 81*(edgeTwist + 32*perm_num));
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int color0, int color1, int color2)
-    {
-    int j0 = getTetColor(color0,3);
-    int j1 = getTetColor(color1,3);
-    int j2 = getTetColor(color2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeError(Resources res, int face0, int face1)
-    {
-    int j0 = getTetColor(mFaceColors[face0],3);
-    int j1 = getTetColor(mFaceColors[face1],6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String centerError(Resources res, int face)
-    {
-    int j = getTetColor(face,2);
-    String c = res.getString(j);
-    return res.getString(R.string.solver_generic_missing_center,c);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING: return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_EDGE_MISSING  : return edgeError(res,mErrColor1,mErrColor2);
-      case ERROR_CENTER_MISSING: return centerError(res,mErrColor1);
-      case ERROR_CORNER_TWISTED: return res.getString(R.string.solver_generic_corner_twist);
-      case ERROR_EDGE_TWISTED  : return res.getString(R.string.solver_generic_edge_twist);
-      case ERROR_CORNERS_CANNOT: return res.getString(R.string.solver_generic_corners_cannot);
-      case ERROR_TWO_EDGES     : return res.getString(R.string.solver_generic_two_edges);
-      case ERROR_TWO_CENTERS   : return res.getString(R.string.solver_generic_two_centers);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebasePDIA3.java b/src/main/java/org/distorted/solvers/SolverTablebasePDIA3.java
deleted file mode 100644
index 651361ad..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebasePDIA3.java
+++ /dev/null
@@ -1,252 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebasePDIA3 extends SolverTablebase
-{
-  private static final int ERROR_CENTER_MISSING = -1;
-  private static final int ERROR_TWO_CENTERS    = -2;
-  private static final int ERROR_CORNERS_CANNOT = -3;
-
-  private final int[] mFaceColors;
-  private int mErrColor;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebasePDIA3(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    mFaceColors = new int[8];
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retCenter(int color, int[] centers)
-    {
-    for(int i=0; i<8; i++ )
-      if( centers[i]==color ) return i;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] getCentersPermutation(int[] centers)
-    {
-    int[] perm = new int[8];
-
-    for(int i=0; i<8; i++ )
-      perm[i] = retCenter(mFaceColors[i],centers);
-
-    return perm;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean isTwistEven(int[] twist)
-    {
-    int total = twist[0]+twist[1]+twist[2]+twist[3]+twist[4]+twist[5];
-    return ((total%2)==0);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int indexOf(int[] corner, int color )
-    {
-    if( corner[0]==color ) return 0;
-    if( corner[1]==color ) return 1;
-    if( corner[2]==color ) return 2;
-    if( corner[3]==color ) return 3;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] getCornersTwist(int[][] corners)
-    {
-    int[] twist = new int[6];
-
-    twist[0] = indexOf(corners[0],mFaceColors[0]);
-    twist[1] = indexOf(corners[1],mFaceColors[5]);
-    twist[2] = indexOf(corners[2],mFaceColors[2]);
-    twist[3] = indexOf(corners[3],mFaceColors[4]);
-    twist[4] = indexOf(corners[4],mFaceColors[2]);
-    twist[5] = indexOf(corners[5],mFaceColors[6]);
-
-
-    return twist;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllColorsDifferent()
-    {
-    for(int i=0; i<8; i++)
-      {
-      boolean present = false;
-
-      for(int j=0; j<8; j++)
-        if( mFaceColors[j]==i )
-          {
-          present=true;
-          break;
-          }
-
-      if( !present ) return ERROR_CORNERS_CANNOT;
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCentersPresent(int[] centers)
-    {
-    for(int i=0; i<8; i++)
-      {
-      boolean present = false;
-
-      for(int j=0; j<8; j++)
-        if( centers[j]==i )
-          {
-          present=true;
-          break;
-          }
-
-      if( !present ) { mErrColor=i; return ERROR_CENTER_MISSING; }
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int commonColor(int[][] corners, int index1, int index2, int index3)
-    {
-    int[] c1 = corners[index1];
-    int[] c2 = corners[index2];
-    int[] c3 = corners[index3];
-
-    for(int i=0; i<4; i++)
-      {
-      int c = c1[i];
-
-      if( (c2[0]==c || c2[1]==c || c2[2]==c || c2[3]==c) &&
-          (c3[0]==c || c3[1]==c || c3[2]==c || c3[3]==c)  ) return c;
-      }
-
-    return ERROR_CORNERS_CANNOT;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int figureOutFaceColors(int[] output, int[][] corners)
-    {
-    int[][] commonCorners = {{0,2,4},{0,3,5},{1,2,4},{1,3,5},{0,2,3},{1,2,3},{0,4,5},{1,4,5}};
-
-    for(int i=0; i<8; i++)
-      {
-      int[] common = commonCorners[i];
-      output[i] = commonColor(corners,common[0],common[1],common[2]);
-      if( output[i]<0 ) return output[i];
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCorners(TwistyObject object, int[][] corners)
-    {
-    for(int i=0; i<6; i++)
-      for(int j=0; j<4; j++)
-         corners[i][j] = object.getCubitFaceStickerIndex(i,j);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCenters(TwistyObject object, int[] centers)
-    {
-    for(int i=0; i<8; i++)
-       centers[i] = object.getCubitFaceStickerIndex(6+i,0)-8;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners = new int[6][4];
-    int[] centers = new int[8];
-
-    getCorners(object,corners);
-    getCenters(object,centers);
-
-    int result1 = figureOutFaceColors(mFaceColors,corners);
-    if( result1<0 ) return result1;
-
-    int result2 = checkAllCentersPresent(centers);
-    if( result2<0 ) return result2;
-
-    int result3 = checkAllColorsDifferent();
-    if( result3<0 ) return result3;
-
-    int[] twist = getCornersTwist(corners);
-    boolean even1 = isTwistEven(twist);
-
-    int[] centers_perm = getCentersPermutation(centers);
-    boolean even2 = TablebaseHelpers.permutationIsEven(centers_perm);
-    if( even1^even2 ) return ERROR_TWO_CENTERS;
-
-    int centers_perm_num = TablebaseHelpers.computePermutationNum(centers_perm);
-    int total_twist = twist[0]+ 4*(twist[1]+ 4*(twist[2]+ 4*(twist[3]+ 4*(twist[4]+ 4*(twist[5]>1 ? 1:0)))));
-
-/*
-android.util.Log.e("D", "faces: "+mFaceColors[0]+" "+mFaceColors[1]+" "+mFaceColors[2]+" "
-+mFaceColors[3]+" "+mFaceColors[4]+" "+mFaceColors[5]+" "+mFaceColors[6]+" "+mFaceColors[7]);
-android.util.Log.e("D", "corn twist: "+twist[0]+" "+twist[1]+" "+twist[2]+" "+twist[3]+" "+twist[4]+" "+twist[5]);
-android.util.Log.e("D", "ret="+(total_twist + 2048*centers_perm_num) );
-*/
-    return total_twist + 2048*centers_perm_num;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String centerError(Resources res, int face)
-    {
-    int index = getOctColor(face,2);
-    String color = res.getString(index);
-    return res.getString(R.string.solver_generic_missing_center,color);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CENTER_MISSING : return centerError(res,mErrColor);
-      case ERROR_TWO_CENTERS    : return res.getString(R.string.solver_generic_two_centers);
-      case ERROR_CORNERS_CANNOT : return res.getString(R.string.solver_generic_corners_cannot);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebasePDUO2.java b/src/main/java/org/distorted/solvers/SolverTablebasePDUO2.java
deleted file mode 100644
index 9a731e1b..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebasePDUO2.java
+++ /dev/null
@@ -1,276 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebasePDUO2 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING = -1;
-  private static final int ERROR_CENTER_MISSING = -2;
-  private static final int ERROR_TWO_CENTERS    = -3;
-  private static final int ERROR_CORNER_TWISTED = -4;
-  private static final int ERROR_CORNERS_CANNOT = -5;
-
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean cornerEqual(int[] corner, int c1, int c2, int c3)
-    {
-    return ( (corner[0]==c1 && corner[1]==c2 && corner[2]==c3) ||
-             (corner[0]==c1 && corner[2]==c2 && corner[1]==c3) ||
-             (corner[1]==c1 && corner[0]==c2 && corner[2]==c3) ||
-             (corner[1]==c1 && corner[2]==c2 && corner[0]==c3) ||
-             (corner[2]==c1 && corner[1]==c2 && corner[0]==c3) ||
-             (corner[2]==c1 && corner[0]==c2 && corner[1]==c3)  );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCornersPresent(int[][] corners)
-    {
-    boolean ybr = false;
-    boolean gbr = false;
-    boolean gyr = false;
-    boolean gyb = false;
-
-    for(int i=0; i<4; i++)
-      {
-      if( cornerEqual(corners[i],0,1,2) ) gyb = true;
-      if( cornerEqual(corners[i],0,1,3) ) gyr = true;
-      if( cornerEqual(corners[i],0,2,3) ) gbr = true;
-      if( cornerEqual(corners[i],1,2,3) ) ybr = true;
-      }
-
-    if( !ybr ) { mErrColor1=1; mErrColor2=2; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gbr ) { mErrColor1=0; mErrColor2=2; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gyr ) { mErrColor1=0; mErrColor2=1; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gyb ) { mErrColor1=0; mErrColor2=1; mErrColor3=2; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCentersPresent(int[] centers)
-    {
-    for(int i=0; i<4; i++)
-      if( centers[0]!=i && centers[1]!=i && centers[2]!=i && centers[3]!=i )
-        { mErrColor1=i; return ERROR_CENTER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getFaceOfCenter(int color, int[] centers)
-    {
-    if( centers[0]==color ) return 0;
-    if( centers[1]==color ) return 1;
-    if( centers[2]==color ) return 2;
-    if( centers[3]==color ) return 3;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] computeFaceColor(int[][] corners)
-    {
-    int[] ret = new int[4];
-
-    for(int i=0; i<4; i++)
-      for(int j=0; j<4; j++)
-        if( corners[i][0]!=j && corners[i][1]!=j && corners[i][2]!=j ) ret[i]=j;
-
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeCornerTwist(int index, int[] corner, int[] missing)
-    {
-    int twist1=0, twist2=0, twist3=0;
-
-    switch(index)
-      {
-      case 0: if( corner[1]==missing[1] ) twist1=1;
-              if( corner[2]==missing[1] ) twist1=2;
-              if( corner[0]==missing[2] ) twist2=2;
-              if( corner[2]==missing[2] ) twist2=1;
-              if( corner[0]==missing[3] ) twist3=1;
-              if( corner[1]==missing[3] ) twist3=2;
-              break;
-      case 1: if( corner[1]==missing[0] ) twist1=1;
-              if( corner[2]==missing[0] ) twist1=2;
-              if( corner[0]==missing[2] ) twist2=1;
-              if( corner[1]==missing[2] ) twist2=2;
-              if( corner[0]==missing[3] ) twist3=2;
-              if( corner[2]==missing[3] ) twist3=1;
-              break;
-      case 2: if( corner[1]==missing[0] ) twist1=1;
-              if( corner[2]==missing[0] ) twist1=2;
-              if( corner[0]==missing[1] ) twist2=2;
-              if( corner[2]==missing[1] ) twist2=1;
-              if( corner[0]==missing[3] ) twist3=1;
-              if( corner[1]==missing[3] ) twist3=2;
-              break;
-      case 3: if( corner[1]==missing[0] ) twist1=1;
-              if( corner[2]==missing[0] ) twist1=2;
-              if( corner[0]==missing[1] ) twist2=1;
-              if( corner[1]==missing[1] ) twist2=2;
-              if( corner[0]==missing[2] ) twist3=2;
-              if( corner[2]==missing[2] ) twist3=1;
-              break;
-      }
-
-    return ( twist1!=twist2 || twist1!=twist3 ) ? ERROR_CORNERS_CANNOT : twist1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computeCenterTwist(int[] centers, int color1, int color2)
-    {
-    if( centers[0]==color1 )
-      {
-      if( centers[1]==color2 ) return 1;
-      if( centers[2]==color2 ) return 2;
-      if( centers[3]==color2 ) return 0;
-
-      return -1;
-      }
-    if( centers[1]==color1 )
-      {
-      if( centers[0]==color2 ) return 1;
-      if( centers[2]==color2 ) return 0;
-      if( centers[3]==color2 ) return 2;
-
-      return -1;
-      }
-    if( centers[2]==color1 )
-      {
-      if( centers[0]==color2 ) return 2;
-      if( centers[1]==color2 ) return 0;
-      if( centers[3]==color2 ) return 1;
-
-      return -1;
-      }
-    if( centers[3]==color1 )
-      {
-      if( centers[0]==color2 ) return 0;
-      if( centers[1]==color2 ) return 2;
-      if( centers[2]==color2 ) return 1;
-
-      return -1;
-      }
-
-    return -2;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebasePDUO2(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners = new int[4][3];
-    int[] centers = new int[4];
-    int[] corner_twist = new int[4];
-
-    for(int i=0; i<4; i++)
-      {
-      centers[i] = object.getCubitFaceStickerIndex(i+4,0) - 4;
-
-      for(int j=0; j<3; j++)
-        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
-      }
-
-    int result1 = checkAllCornersPresent(corners);
-    if( result1<0 ) return result1;
-
-    int result2 = checkAllCentersPresent(centers);
-    if( result2<0 ) return result2;
-
-    int[] faces = computeFaceColor(corners);
-
-    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;
-
-    int total_twist=0;
-
-    for(int i=0; i<4; i++)
-      {
-      corner_twist[i] = computeCornerTwist(i,corners[i],faces);
-      if( corner_twist[i]<0 ) return corner_twist[i];
-      total_twist += corner_twist[i];
-      }
-
-    if( (total_twist-twist_gr)%3 !=0 ) return ERROR_CORNER_TWISTED;
-
-    int green_face = getFaceOfCenter(faces[1],centers);
-
-    return green_face + 4*(corner_twist[3] + 3*(corner_twist[2] + 3*(corner_twist[1] + 3*corner_twist[0])));
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int color0, int color1, int color2)
-    {
-    int j0 = getTetColor(color0,3);
-    int j1 = getTetColor(color1,3);
-    int j2 = getTetColor(color2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String centerError(Resources res, int face)
-    {
-    int color = getTetColor(face,2);
-    String clr= res.getString(color);
-    return res.getString(R.string.solver_generic_missing_center,clr);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING: return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_CENTER_MISSING: return centerError(res,mErrColor1);
-      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);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebasePYRA3.java b/src/main/java/org/distorted/solvers/SolverTablebasePYRA3.java
deleted file mode 100644
index 1e38a925..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebasePYRA3.java
+++ /dev/null
@@ -1,453 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-import org.distorted.objectlib.tablebases.TBPyraminx;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebasePYRA3 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING = -1;
-  private static final int ERROR_VERTEX_MISSING = -2;
-  private static final int ERROR_EDGE_MISSING   = -3;
-  private static final int ERROR_CORNERS_CANNOT = -4;
-  private static final int ERROR_VERTICES_CANNOT= -5;
-  private static final int ERROR_EDGE_TWISTED   = -6;
-  private static final int ERROR_C_V_DONT_MATCH = -7;
-  private static final int ERROR_TWO_EDGES      = -8;
-
-  private int[] mCornerTwist;
-  private int[] mFaceColors;
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean pieceEqual3(int[] piece, int c1, int c2, int c3)
-    {
-    return ( (piece[0]==c1 && piece[1]==c2 && piece[2]==c3) ||
-             (piece[0]==c1 && piece[2]==c2 && piece[1]==c3) ||
-             (piece[1]==c1 && piece[0]==c2 && piece[2]==c3) ||
-             (piece[1]==c1 && piece[2]==c2 && piece[0]==c3) ||
-             (piece[2]==c1 && piece[1]==c2 && piece[0]==c3) ||
-             (piece[2]==c1 && piece[0]==c2 && piece[1]==c3)  );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean pieceEqual2(int[] piece, int[] colors)
-    {
-    return ( (piece[0]==colors[0] && piece[1]==colors[1]) ||
-             (piece[0]==colors[1] && piece[1]==colors[0])  );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllCornersPresent(int[][] corners)
-    {
-    boolean ybr = false;
-    boolean gbr = false;
-    boolean gyr = false;
-    boolean gyb = false;
-
-    for(int i=0; i<4; i++)
-      {
-      if( pieceEqual3(corners[i],0,1,2) ) gyb = true;
-      if( pieceEqual3(corners[i],0,1,3) ) gyr = true;
-      if( pieceEqual3(corners[i],0,2,3) ) gbr = true;
-      if( pieceEqual3(corners[i],1,2,3) ) ybr = true;
-      }
-
-    if( !ybr ) { mErrColor1=1; mErrColor2=2; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gbr ) { mErrColor1=0; mErrColor2=2; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gyr ) { mErrColor1=0; mErrColor2=1; mErrColor3=3; return ERROR_CORNER_MISSING; }
-    if( !gyb ) { mErrColor1=0; mErrColor2=1; mErrColor3=2; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllVerticesPresent(int[][] vertex)
-    {
-    boolean ybr = false;
-    boolean gbr = false;
-    boolean gyr = false;
-    boolean gyb = false;
-
-    for(int i=0; i<4; i++)
-      {
-      if( pieceEqual3(vertex[i],0,1,2) ) gyb = true;
-      if( pieceEqual3(vertex[i],0,1,3) ) gyr = true;
-      if( pieceEqual3(vertex[i],0,2,3) ) gbr = true;
-      if( pieceEqual3(vertex[i],1,2,3) ) ybr = true;
-      }
-
-    if( !ybr ) { mErrColor1=1; mErrColor2=2; mErrColor3=3; return ERROR_VERTEX_MISSING; }
-    if( !gbr ) { mErrColor1=0; mErrColor2=2; mErrColor3=3; return ERROR_VERTEX_MISSING; }
-    if( !gyr ) { mErrColor1=0; mErrColor2=1; mErrColor3=3; return ERROR_VERTEX_MISSING; }
-    if( !gyb ) { mErrColor1=0; mErrColor2=1; mErrColor3=2; return ERROR_VERTEX_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAllEdgesPresent(int[][] edges, int[][] edgeColors)
-    {
-    boolean[] present = new boolean[6];
-    for(int i=0; i<6; i++) present[i] = false;
-
-    for(int i=0; i<6; i++)
-      for(int j=0; j<6; j++)
-        if( pieceEqual2(edges[i], edgeColors[j]) )
-          {
-          present[j] = true;
-          break;
-          }
-
-    if( !present[0] ) { mErrColor1=3; mErrColor2=2; return ERROR_EDGE_MISSING; }
-    if( !present[1] ) { mErrColor1=2; mErrColor2=0; return ERROR_EDGE_MISSING; }
-    if( !present[2] ) { mErrColor1=2; mErrColor2=1; return ERROR_EDGE_MISSING; }
-    if( !present[3] ) { mErrColor1=3; mErrColor2=0; return ERROR_EDGE_MISSING; }
-    if( !present[4] ) { mErrColor1=3; mErrColor2=1; return ERROR_EDGE_MISSING; }
-    if( !present[5] ) { mErrColor1=1; mErrColor2=0; return ERROR_EDGE_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] computeFaceColors(int[][] corners)
-    {
-    int[] ret = new int[4];
-
-    for(int i=0; i<4; i++)
-      for(int j=0; j<4; j++)
-        if( corners[i][0]!=j && corners[i][1]!=j && corners[i][2]!=j ) ret[i]=j;
-
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int checkAgreement(int[] faces1, int[] faces2)
-    {
-    for(int i=0; i<4; i++)
-      if( faces1[i]!=faces2[i] ) return ERROR_C_V_DONT_MATCH;
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int computePieceTwist(int index, int[] corner, int[] faceColor)
-    {
-    int twist1=0, twist2=0, twist3=0;
-
-    switch(index)
-      {
-      case 0: if( corner[1]==faceColor[1] ) twist1=1;
-              if( corner[2]==faceColor[1] ) twist1=2;
-              if( corner[0]==faceColor[2] ) twist2=2;
-              if( corner[2]==faceColor[2] ) twist2=1;
-              if( corner[0]==faceColor[3] ) twist3=1;
-              if( corner[1]==faceColor[3] ) twist3=2;
-              break;
-      case 1: if( corner[1]==faceColor[0] ) twist1=1;
-              if( corner[2]==faceColor[0] ) twist1=2;
-              if( corner[0]==faceColor[2] ) twist2=1;
-              if( corner[1]==faceColor[2] ) twist2=2;
-              if( corner[0]==faceColor[3] ) twist3=2;
-              if( corner[2]==faceColor[3] ) twist3=1;
-              break;
-      case 2: if( corner[1]==faceColor[0] ) twist1=1;
-              if( corner[2]==faceColor[0] ) twist1=2;
-              if( corner[0]==faceColor[1] ) twist2=2;
-              if( corner[2]==faceColor[1] ) twist2=1;
-              if( corner[0]==faceColor[3] ) twist3=1;
-              if( corner[1]==faceColor[3] ) twist3=2;
-              break;
-      case 3: if( corner[1]==faceColor[0] ) twist1=1;
-              if( corner[2]==faceColor[0] ) twist1=2;
-              if( corner[0]==faceColor[1] ) twist2=1;
-              if( corner[1]==faceColor[1] ) twist2=2;
-              if( corner[0]==faceColor[2] ) twist3=2;
-              if( corner[2]==faceColor[2] ) twist3=1;
-              break;
-      }
-
-    return ( twist1!=twist2 || twist1!=twist3 ) ? ERROR_CORNERS_CANNOT : twist1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int locateEdge(int[][] edges, int[] colors)
-    {
-    for(int i=0; i<6; i++)
-      if( edges[i][0]==colors[0] && edges[i][1]==colors[1] ||
-          edges[i][0]==colors[1] && edges[i][1]==colors[0]  ) return i;
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int edgeTwist(int[] edge, int[] colors)
-    {
-    return edge[0]==colors[0] ? 0:1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[] computeEdgeQuats(int[][] edges, int[][] edgeColors)
-    {
-    int[] quats = new int[6];
-
-    for(int i=0; i<6; i++)
-      {
-      int pos   = locateEdge(edges,edgeColors[i]);
-      int twist = edgeTwist(edges[pos],edgeColors[i]);
-      quats[i]  = TBPyraminx.EDGE_QUATS[pos][twist];
-      }
-
-    return quats;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebasePYRA3(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,res,object);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getCorners(TwistyObject object, int[][] corners)
-    {
-    corners[0][0] = object.getCubitFaceStickerIndex(4,0);  // G
-    corners[0][1] = object.getCubitFaceStickerIndex(4,3);  // R
-    corners[0][2] = object.getCubitFaceStickerIndex(4,2);  // B
-
-    corners[1][0] = object.getCubitFaceStickerIndex(6,1);  // Y
-    corners[1][1] = object.getCubitFaceStickerIndex(6,2);  // B
-    corners[1][2] = object.getCubitFaceStickerIndex(6,3);  // R
-
-    corners[2][0] = object.getCubitFaceStickerIndex(11,1);  // Y
-    corners[2][1] = object.getCubitFaceStickerIndex(11,0);  // G
-    corners[2][2] = object.getCubitFaceStickerIndex(11,2);  // B
-
-    corners[3][0] = object.getCubitFaceStickerIndex(13,1);  // Y
-    corners[3][1] = object.getCubitFaceStickerIndex(13,3);  // R
-    corners[3][2] = object.getCubitFaceStickerIndex(13,0);  // G
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getVertices(TwistyObject object, int[][] vertex)
-    {
-    vertex[0][0] = object.getCubitFaceStickerIndex(0,0);  // G
-    vertex[0][1] = object.getCubitFaceStickerIndex(0,5);  // R
-    vertex[0][2] = object.getCubitFaceStickerIndex(0,7);  // B
-
-    vertex[1][0] = object.getCubitFaceStickerIndex(1,2);  // Y
-    vertex[1][1] = object.getCubitFaceStickerIndex(1,7);  // B
-    vertex[1][2] = object.getCubitFaceStickerIndex(1,5);  // R
-
-    vertex[2][0] = object.getCubitFaceStickerIndex(2,2);  // Y
-    vertex[2][1] = object.getCubitFaceStickerIndex(2,0);  // G
-    vertex[2][2] = object.getCubitFaceStickerIndex(2,7);  // B
-
-    vertex[3][0] = object.getCubitFaceStickerIndex(3,2);  // Y
-    vertex[3][1] = object.getCubitFaceStickerIndex(3,5);  // R
-    vertex[3][2] = object.getCubitFaceStickerIndex(3,0);  // G
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void getEdges(TwistyObject object, int[][] edges)
-    {
-    edges[0][0] = object.getCubitFaceStickerIndex(5,3);  // R
-    edges[0][1] = object.getCubitFaceStickerIndex(5,2);  // B
-
-    edges[1][0] = object.getCubitFaceStickerIndex(10,1); // Y
-    edges[1][1] = object.getCubitFaceStickerIndex(10,3); // R
-
-    edges[2][0] = object.getCubitFaceStickerIndex(9,0);  // G
-    edges[2][1] = object.getCubitFaceStickerIndex(9,3);  // R
-
-    edges[3][0] = object.getCubitFaceStickerIndex(8,2);  // B
-    edges[3][1] = object.getCubitFaceStickerIndex(8,1);  // Y
-
-    edges[4][0] = object.getCubitFaceStickerIndex(7,2);  // B
-    edges[4][1] = object.getCubitFaceStickerIndex(7,0);  // G
-
-    edges[5][0] = object.getCubitFaceStickerIndex(12,1); // Y
-    edges[5][1] = object.getCubitFaceStickerIndex(12,0); // G
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int[][] computeEdgeColors(int[] faceColor)
-    {
-    // The first pair being (2,3) means 'the first edge's first face is on the tetrahedron
-    // face which oppeses corner number 2, and its second face on tetra face which opposes
-    // corner number 3'
-    // Order of those pairs determines edge twist.
-
-    final int[][] edgeColorIndices = new int[][] { {2,3},{0,2},{1,2},{3,0},{3,1},{0,1}  };
-    int[][] ret = new int[6][2];
-
-    for(int i=0; i<6; i++)
-      {
-      ret[i][0] = faceColor[edgeColorIndices[i][0]];
-      ret[i][1] = faceColor[edgeColorIndices[i][1]];
-      }
-
-    return ret;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners = new int[4][3];
-    int[][] edges   = new int[6][2];
-    int[][] vertices= new int[4][3];
-    int[] vertex_twist = new int[4];
-    mCornerTwist = new int[4];
-
-    getCorners(object,corners);
-    getVertices(object,vertices);
-
-    int result1 = checkAllCornersPresent(corners);
-    if( result1<0 ) return result1;
-
-    int result2 = checkAllVerticesPresent(vertices);
-    if( result2<0 ) return result2;
-
-    int[] facesC = computeFaceColors(corners);
-    int[] facesV = computeFaceColors(vertices);
-
-    int result3 = checkAgreement(facesC,facesV);
-    if( result3<0 ) return result3;
-
-    mFaceColors = facesC;
-
-    int[][] edgeColors = computeEdgeColors(mFaceColors);
-
-    getEdges(object,edges);
-    int result4 = checkAllEdgesPresent(edges,edgeColors);
-    if( result4<0 ) return result4;
-
-    for(int i=0; i<4; i++)
-      {
-      mCornerTwist[i] = computePieceTwist(i,corners[i],mFaceColors);
-      if( mCornerTwist[i]<0 ) return ERROR_CORNERS_CANNOT;
-      }
-
-    for(int i=0; i<4; i++)
-      {
-      vertex_twist[i] = computePieceTwist(i,vertices[i],mFaceColors);
-      if( vertex_twist[i]<0 ) return ERROR_VERTICES_CANNOT;
-      }
-
-    int[] quats = computeEdgeQuats(edges,edgeColors);
-    int[] permutation = new int[6];
-    TBPyraminx.getEdgePermutation(permutation,quats,0);
-    boolean even = TablebaseHelpers.permutationIsEven(permutation);
-    if( !even ) return ERROR_TWO_EDGES;
-    int[] edge_twist = new int[6];
-    TBPyraminx.getEdgeTwist(edge_twist,quats,0);
-
-    int totalEdgeTwist=0;
-    for(int i=0; i<6; i++) totalEdgeTwist += edge_twist[i];
-    if( (totalEdgeTwist%2)!=0 ) return ERROR_EDGE_TWISTED;
-
-    int vertexTwist = vertex_twist[0]+ 3*(vertex_twist[1]+ 3*(vertex_twist[2]+ 3*vertex_twist[3]));
-    int edgeTwist = edge_twist[0]+ 2*(edge_twist[1]+ 2*(edge_twist[2]+ 2*(edge_twist[3]+ 2*edge_twist[4])));
-    int perm_num = TablebaseHelpers.computeEvenPermutationNum(permutation);
-
-    return vertexTwist + 81*(edgeTwist + 32*perm_num);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int color0, int color1, int color2)
-    {
-    int j0 = getTetColor(color0,3);
-    int j1 = getTetColor(color1,3);
-    int j2 = getTetColor(color2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String vertexError(Resources res, int color0, int color1, int color2)
-    {
-    int j0 = getTetColor(color0,3);
-    int j1 = getTetColor(color1,3);
-    int j2 = getTetColor(color2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_vertex,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String edgeError(Resources res, int color0, int color1)
-    {
-    int j0 = getTetColor(mFaceColors[color0],3);
-    int j1 = getTetColor(mFaceColors[color1],6);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-
-    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING : return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_VERTEX_MISSING : return vertexError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_EDGE_MISSING   : return edgeError(res,mErrColor1,mErrColor2);
-      case ERROR_EDGE_TWISTED   : return res.getString(R.string.solver_generic_edge_twist);
-      case ERROR_CORNERS_CANNOT : return res.getString(R.string.solver_generic_corners_cannot);
-      case ERROR_VERTICES_CANNOT: return res.getString(R.string.solver_generic_vertices_cannot);
-      case ERROR_C_V_DONT_MATCH : return res.getString(R.string.solver_generic_c_v_dont_match);
-      case ERROR_TWO_EDGES      : return res.getString(R.string.solver_generic_two_edges);
-      }
-
-    return null;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  @Override int[] getExtra() { return mCornerTwist; }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolverTablebaseSKEW2.java b/src/main/java/org/distorted/solvers/SolverTablebaseSKEW2.java
deleted file mode 100644
index e8ded988..00000000
--- a/src/main/java/org/distorted/solvers/SolverTablebaseSKEW2.java
+++ /dev/null
@@ -1,351 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2023 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import static org.distorted.objectlib.tablebases.TBSkewb.FIXED;
-import static org.distorted.objectlib.tablebases.TBSkewb.FREE;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.tablebases.TBSkewb;
-import org.distorted.objectlib.tablebases.TablebaseHelpers;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolverTablebaseSKEW2 extends SolverTablebase
-{
-  private static final int ERROR_CORNER_MISSING       = -1;
-  private static final int ERROR_CENTER_MISSING       = -2;
-  private static final int ERROR_CORNERS_CANNOT       = -3;
-  private static final int ERROR_CORNER_TWISTED       = -4;
-  private static final int ERROR_TWO_CENTERS          = -5;
-  private static final int ERROR_TWO_CORNERS          = -6;
-  private static final int ERROR_FREE_CORNERS_NOT_EVEN= -7;
-  private static final int ERROR_FREE_CORNERS_ROTATED = -8;
-
-  private final int[] mFaceColors;
-  private int mErrColor1, mErrColor2, mErrColor3;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolverTablebaseSKEW2(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    super(os,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 createCenterPermutation(int[] output, int[] symbols, int[] perm)
-    {
-    for(int s=0; s<6; s++)
-      {
-      int symbol = symbols[s];
-
-      for(int p=0; p<6; p++)
-        if( perm[p]==symbol )
-          {
-          output[s] = p;
-          break;
-          }
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getCenters(TwistyObject object, int[] out)
-    {
-    final int[] map = {4,5,2,3,0,1};
-    int[] tmp = new int[6];
-    int[] mcl = new int[6];
-    boolean[] present = new boolean[6];
-
-    for(int i=0; i<6; i++)
-      {
-      int color = object.getCubitFaceStickerIndex(i+8,0) - 6;
-      present[color] = true;
-      tmp[i] = color;
-      }
-
-    for(int i=0; i<6; i++)
-      if( !present[i] ) { mErrColor1=i; return ERROR_CENTER_MISSING; }
-
-    for(int i=0; i<6; i++) mcl[i] = map[mFaceColors[i]];
-    createCenterPermutation(out,mcl,tmp);
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  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[][] corner_indices = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
-
-    for(int i=0; i<6; i++)
-      {
-      int c1 = corner_indices[i][0];
-      int c2 = corner_indices[i][1];
-      output[i] = commonCornerColor(corners[c1],corners[c2]);
-      if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
-      }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private boolean cornerIs(int[] corner, int f0, int f1, int f2)
-    {
-    int c0 = mFaceColors[f0];
-    int c1 = mFaceColors[f1];
-    int c2 = mFaceColors[f2];
-
-    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 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] ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( !present[1] ) { mErrColor1=0; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( !present[2] ) { mErrColor1=0; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( !present[3] ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( !present[4] ) { mErrColor1=1; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( !present[5] ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( !present[6] ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( !present[7] ) { mErrColor1=1; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int retFreeCornerPermutation(int[] perm, int[][] corners)
-    {
-    perm[0] = -1;
-    perm[1] = -1;
-    perm[2] = -1;
-    perm[3] = -1;
-
-    for(int i=0; i<4; i++)
-      {
-      int[] cor = corners[FREE[i]];
-
-      if( cornerIs(cor,2,5,0) ) perm[0] = i;
-      if( cornerIs(cor,3,4,0) ) perm[1] = i;
-      if( cornerIs(cor,1,2,4) ) perm[2] = i;
-      if( cornerIs(cor,1,3,5) ) perm[3] = i;
-      }
-
-    if( perm[0]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
-    if( perm[1]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( perm[2]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
-    if( perm[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
-
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void computeCornerQuats(int[] quats, int[][] corners, int[] perm)
-    {
-    final int[] zeroeth_face_map = { 4,2,3,5,1,5,4,1 };
-    int[] twist = new int[8];
-
-    for(int i=0; i<4; i++)
-      {
-      int fi = FIXED[i];
-      int colorFi = mFaceColors[zeroeth_face_map[fi]];
-      int[] cFi = corners[fi];
-
-           if( cFi[0]==colorFi ) twist[fi] = 0;
-      else if( cFi[1]==colorFi ) twist[fi] = 1;
-      else                       twist[fi] = 2;
-      }
-
-    int[] inv_perm = new int[4];
-    TablebaseHelpers.invertPermutation(perm,inv_perm);
-
-    int common14 = commonCornerColor(corners[1], corners[4]);
-    int common27 = commonCornerColor(corners[2], corners[7]);
-    int common47 = commonCornerColor(corners[4], corners[7]);
-    int index;
-    int[] c;
-
-    index = FREE[inv_perm[0]];
-    c = corners[FREE[0]];
-
-         if(c[0]==common14) twist[index] = 0;
-    else if(c[1]==common14) twist[index] = 2;
-    else                    twist[index] = 1;
-
-    index = FREE[inv_perm[1]];
-    c = corners[FREE[1]];
-
-         if(c[0]==common27) twist[index] = 0;
-    else if(c[1]==common27) twist[index] = 2;
-    else                    twist[index] = 1;
-
-    index = FREE[inv_perm[2]];
-    c = corners[FREE[2]];
-
-         if(c[0]==common47) twist[index] = 0;
-    else if(c[1]==common47) twist[index] = 2;
-    else                    twist[index] = 1;
-
-    index = FREE[inv_perm[3]];
-    c = corners[FREE[3]];
-
-         if(c[0]==common47) twist[index] = 0;
-    else if(c[1]==common47) twist[index] = 2;
-    else                    twist[index] = 1;
-
-    TBSkewb.fillInQuats(quats,perm,twist);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int tablebaseIndex(TwistyObject object)
-    {
-    int[][] corners= new int[8][3];
-    int[] centers  = new int[6];
-    int[] twist    = new int[8];
-    int[] freePerm = new int[4];
-    int[] quats    = new int[8];
-
-    getCorners(object,corners);
-
-    int result1 = computeFaceColors(corners,mFaceColors);
-    if( result1<0 ) return result1;
-
-    int result2 = checkAllCornersPresent(corners);
-    if( result2<0 ) return result2;
-
-    int result3 = getCenters(object,centers);
-    if( result3<0 ) return result3;
-
-    if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
-    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
-
-    int result4 = retFreeCornerPermutation(freePerm,corners);
-    if( result4<0 ) return result4;
-
-    computeCornerQuats(quats,corners,freePerm);
-
-    int[] freeLoc = new int[4];
-    for(int f=0; f<4; f++) freeLoc[f] = TBSkewb.computeLocation(f,quats[FREE[f]]);
-    if( !TablebaseHelpers.permutationIsEven(freeLoc) ) return ERROR_FREE_CORNERS_NOT_EVEN;
-
-    TBSkewb.computeCornerTwists(twist,quats);
-
-    int total = 0;
-    for(int i=0; i<8; i++) total += twist[i];
-    if( (total%3)!=0 ) return ERROR_CORNER_TWISTED;
-    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
-
-    int sumFixedTwists = twist[FIXED[0]]+twist[FIXED[1]]+twist[FIXED[2]]+twist[FIXED[3]];
-    int freeLoc1 = TBSkewb.permFree1(freeLoc[0],sumFixedTwists);
-    if( freeLoc[1] != freeLoc1 ) return ERROR_FREE_CORNERS_ROTATED;
-
-    return center_perm_num+ 360*(totalTwist + 2187*freeLoc[0]);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String cornerError(Resources res, int face0, int face1, int face2)
-    {
-    int j0 = getHexColor(face0,3);
-    int j1 = getHexColor(face1,3);
-    int j2 = getHexColor(face2,4);
-
-    String c0 = res.getString(j0);
-    String c1 = res.getString(j1);
-    String c2 = res.getString(j2);
-
-    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private String centerError(Resources res, int face)
-    {
-    int color = getHexColor(face,2);
-    String clr= res.getString(color);
-    return res.getString(R.string.solver_generic_missing_center,clr);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public String error(int index, Resources res)
-    {
-    switch(index)
-      {
-      case ERROR_CORNER_MISSING       : return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
-      case ERROR_CENTER_MISSING       : return centerError(res,mErrColor1);
-      case ERROR_CORNERS_CANNOT       : return res.getString(R.string.solver_generic_corners_cannot);
-      case ERROR_CORNER_TWISTED       : return res.getString(R.string.solver_generic_corner_twist);
-      case ERROR_TWO_CENTERS          : return res.getString(R.string.solver_generic_two_centers);
-      case ERROR_TWO_CORNERS          : return res.getString(R.string.solver_generic_two_corners);
-      case ERROR_FREE_CORNERS_NOT_EVEN: return res.getString(R.string.solver_generic_free_corners_odd);
-      case ERROR_FREE_CORNERS_ROTATED : return res.getString(R.string.solver_generic_free_corners_rotated);
-      }
-
-    return null;
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solvers/SolvingInterface.java b/src/main/java/org/distorted/solvers/SolvingInterface.java
deleted file mode 100644
index 75b04b9e..00000000
--- a/src/main/java/org/distorted/solvers/SolvingInterface.java
+++ /dev/null
@@ -1,19 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2024 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import org.distorted.solverui.ScreenSolver;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public interface SolvingInterface
-{
-  void solve(ScreenSolver screen);
-}
diff --git a/src/main/java/org/distorted/solvers/SolvingList.java b/src/main/java/org/distorted/solvers/SolvingList.java
deleted file mode 100644
index e3de870a..00000000
--- a/src/main/java/org/distorted/solvers/SolvingList.java
+++ /dev/null
@@ -1,166 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import static org.distorted.objectlib.metadata.ListObjects.*;
-
-import android.content.res.Resources;
-
-import org.distorted.main.R;
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-import org.distorted.objectlib.metadata.*;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public enum SolvingList
-{
-  CUBE2          (CUBE_2.ordinal(), SolverTablebaseCUBE2.class  , R.string.solver_cube2_title, R.string.solver_cube2_description, true),
-  CUBE3_KOCIEMBA (CUBE_3.ordinal(), SolverKociembaCUBE3.class   , R.string.solver_cube3_title, R.string.solver_cube3_description, true),
-  CUBE3_ALGO     (CUBE_3.ordinal(), SolverAlgorithmicCUBE3.class, R.string.solver_3algo_title, R.string.solver_3algo_description, true),
-  CU232          (CU_232.ordinal(), SolverTablebaseCU232.class  , R.string.solver_cu232_title, R.string.solver_cu232_description, true),
-  CU323          (CU_323.ordinal(), SolverTablebaseCU323.class  , R.string.solver_cu323_title, R.string.solver_cu323_description, true),
-  PYRAMINX       (PYRA_3.ordinal(), SolverTablebasePYRA3.class  , R.string.solver_pyra3_title, R.string.solver_pyra3_description, true),
-  SKEWB          (SKEW_2.ordinal(), SolverTablebaseSKEW2.class  , R.string.solver_skew2_title, R.string.solver_skew2_description, true),
-  PYRAMINX_DUO   (PDUO_2.ordinal(), SolverTablebasePDUO2.class  , R.string.solver_pduo2_title, R.string.solver_pduo2_description, true),
-  IVY            (IVY_2.ordinal() , SolverTablebaseIVY2.class   , R.string.solver_ivy_title, R.string.solver_ivy_description, true),
-  DIAMOND        (DIAM_2.ordinal(), SolverTablebaseDIAM2.class  , R.string.solver_diam2_title, R.string.solver_diam2_description, true),
-  JING2          (JING_2.ordinal(), SolverTablebaseJING2.class  , R.string.solver_jing2_title, R.string.solver_jing2_description, true),
-  DINO6          (DINO_3.ordinal(), SolverTablebaseDINO6.class  , R.string.solver_dino6_title, R.string.solver_dino6_description, true),
-  DINO4          (DIN4_3.ordinal(), SolverTablebaseDINO4.class  , R.string.solver_dino4_title, R.string.solver_dino4_description, true),
-  PDIA           (PDIA_3.ordinal(), SolverTablebasePDIA3.class  , R.string.solver_pdia_title, R.string.solver_pdia_description, true),
-  ;
-
-  public static final int NUM_OBJECTS = values().length;
-
-  private final int mObjectOrdinal;
-  private final Class<? extends SolvingInterface> mClass;
-  private final int mTitle;
-  private final int mDescription;
-  private final boolean mImplemented;
-
-  private static final SolvingList[] objects;
-
-  static
-    {
-    objects = new SolvingList[NUM_OBJECTS];
-    int i=0;
-
-    for( SolvingList object: SolvingList.values())
-      {
-      objects[i++] = object;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static SolvingList getSolver(int solverOrdinal)
-    {
-    return objects[solverOrdinal];
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static int[] getSolverOrdinals(int objectOrdinal)
-    {
-    int num = 0;
-
-    for(int o=0; o<NUM_OBJECTS; o++)
-      if( objects[o].mObjectOrdinal==objectOrdinal ) num++;
-
-    if( num>0 )
-      {
-      int[] ret = new int[num];
-      int index = 0;
-
-      for(int o=0; o<NUM_OBJECTS; o++)
-        if( objects[o].mObjectOrdinal==objectOrdinal ) ret[index++] = o;
-
-      return ret;
-      }
-    return null;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  SolvingList(int object, final Class<? extends SolvingInterface> clazz, int title, int descripton, boolean implemented)
-    {
-    mObjectOrdinal= object;
-    mClass        = clazz;
-    mTitle        = title;
-    mDescription  = descripton;
-    mImplemented  = implemented;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// certain objects have certain cubits locked - for example, the Cube3's centers of
-// sides always have the same color.
-// If a certain cubit is locked, return the color (index into it's FACE_COLORS array) it
-// must have. Otherwise return -1.
-
-  public static int cubitIsLocked(int object, int cubit)
-    {
-    if( object == MetadataCUBE_3.INDEX )
-      {
-      if( cubit==20 ) return 0; // center of the right  face
-      if( cubit==21 ) return 1; // center of the left   face
-      if( cubit==22 ) return 2; // center of the up     face
-      if( cubit==23 ) return 3; // center of the bottom face
-      if( cubit==24 ) return 4; // center of the front  face
-      if( cubit==25 ) return 5; // center of the back   face
-      }
-
-    return -1;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getObjectOrdinal() { return mObjectOrdinal; }
-  public int getTitle() { return mTitle; }
-  public int getDescription() { return mDescription; }
-  public boolean isImplemented() { return mImplemented; }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolvingInterface create(OperatingSystemInterface os, Resources res, TwistyObject object)
-    {
-    try
-      {
-      Constructor<?>[] cons = mClass.getConstructors();
-
-      if( cons.length==1 )
-        {
-        Object[] parameters = new Object[] { os,res,object };
-        return (SolvingInterface)cons[0].newInstance(parameters);
-        }
-      else
-        {
-        android.util.Log.e("SolvingList", "ERROR! number of SolverInterface constructors="+cons.length);
-        }
-      }
-    catch(IllegalAccessException iae)
-      {
-      android.util.Log.e("SolvingList", "Illegal Access Exception: "+iae.getMessage());
-      }
-    catch(InstantiationException ie)
-      {
-      android.util.Log.e("SolvingList", "Instantiation Exception: "+ie.getMessage());
-      }
-    catch(InvocationTargetException ite)
-      {
-      android.util.Log.e("SolvingList", "Invocation Target Exception: "+ite.getMessage());
-      }
-
-    return null;
-    }
-}
diff --git a/src/main/java/org/distorted/solvers/SolvingThread.java b/src/main/java/org/distorted/solvers/SolvingThread.java
deleted file mode 100644
index 6b1e71e9..00000000
--- a/src/main/java/org/distorted/solvers/SolvingThread.java
+++ /dev/null
@@ -1,58 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is proprietary software licensed under an EULA which you should have received      //
-// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.solvers;
-
-import android.content.res.Resources;
-
-import org.distorted.objectlib.helpers.OperatingSystemInterface;
-import org.distorted.objectlib.main.TwistyObject;
-
-import org.distorted.main.R;
-import org.distorted.solverui.ScreenList;
-import org.distorted.solverui.ScreenSolver;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class SolvingThread implements Runnable
-{
-  private final Resources mRes;
-  private final OperatingSystemInterface mOS;
-  private final TwistyObject mObject;
-  private final SolvingList mList;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public SolvingThread(OperatingSystemInterface os, Resources res, TwistyObject object, SolvingList list)
-    {
-    mRes   = res;
-    mOS    = os;
-    mObject= object;
-    mList  = list;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void start()
-    {
-    Thread thr = new Thread(this);
-    thr.start();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void run()
-    {
-    ScreenSolver screen=(ScreenSolver) ScreenList.SVER.getScreenClass();
-    SolvingInterface solver = mList.create(mOS,mRes,mObject);
-    if( solver!=null ) solver.solve(screen);
-    else screen.displayErrorDialog(mRes.getString(R.string.solver_generic_not_implemented));
-    }
-}  
-
diff --git a/src/main/java/org/distorted/solverui/ScreenSolution.java b/src/main/java/org/distorted/solverui/ScreenSolution.java
index ba7433a4..9d8f83b5 100644
--- a/src/main/java/org/distorted/solverui/ScreenSolution.java
+++ b/src/main/java/org/distorted/solverui/ScreenSolution.java
@@ -23,6 +23,8 @@ import org.distorted.objectlib.helpers.MovesFinished;
 import org.distorted.objectlib.main.ObjectControl;
 import org.distorted.objectlib.patterns.RubikPattern;
 
+import java.lang.ref.WeakReference;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class ScreenSolution extends ScreenAbstract implements MovesFinished
@@ -35,6 +37,7 @@ public class ScreenSolution extends ScreenAbstract implements MovesFinished
   private int mCurrMove, mNumMoves;
   private boolean mCanRotate;
   private float mButtonSize;
+  private WeakReference<SolverActivity> mAct;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -48,6 +51,8 @@ public class ScreenSolution extends ScreenAbstract implements MovesFinished
 
   void enterScreen(final SolverActivity act)
     {
+    mAct = new WeakReference<>(act);
+
     float width = act.getScreenWidthInPixels();
     mButtonSize = width*SolverActivity.BUTTON_TEXT_SIZE;
     float titleSize  = width*SolverActivity.TITLE_TEXT_SIZE;
@@ -245,7 +250,7 @@ public class ScreenSolution extends ScreenAbstract implements MovesFinished
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  void setupMoves(final SolverActivity act, String moves)
+  void setSolution(String moves)
     {
     mCanRotate= true;
     mCurrMove = 0;
@@ -254,39 +259,26 @@ public class ScreenSolution extends ScreenAbstract implements MovesFinished
 
     RubikPattern.parseMoves(mMoves,mNumMoves,moves);
 
+    SolverActivity act = mAct.get();
     mMovesText.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  void setupMoves(final SolverActivity act, int[][] moves)
+  void setSolution(int[][] moves)
     {
     mCanRotate= true;
     mCurrMove = 0;
     mNumMoves = moves==null ? 0 : moves.length;
     mMoves    = moves;
 
+    SolverActivity act = mAct.get();
     mMovesText.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void savePreferences(SharedPreferences.Editor editor)
-    {
-
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void restorePreferences(SharedPreferences preferences)
-    {
-
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void onActionFinished(final long effectID)
-    {
-    mCanRotate = true;
-    }
+  public void savePreferences(SharedPreferences.Editor editor) { }
+  public void restorePreferences(SharedPreferences preferences) { }
+  public void onActionFinished(final long effectID) { mCanRotate = true; }
   }
diff --git a/src/main/java/org/distorted/solverui/ScreenSolver.java b/src/main/java/org/distorted/solverui/ScreenSolver.java
index 96934d5e..31b7e8ca 100644
--- a/src/main/java/org/distorted/solverui/ScreenSolver.java
+++ b/src/main/java/org/distorted/solverui/ScreenSolver.java
@@ -10,6 +10,7 @@
 package org.distorted.solverui;
 
 import static org.distorted.objectlib.metadata.ListObjects.*;
+import static org.distorted.objectlib.solvers.verifiers.SolverTablebase.*;
 
 import android.content.SharedPreferences;
 import android.content.res.Resources;
@@ -36,19 +37,55 @@ import org.distorted.objectlib.main.ObjectControl;
 import org.distorted.objectlib.main.TwistyObject;
 import org.distorted.objectlib.metadata.ListObjects;
 import org.distorted.objectlib.shape.*;
-import org.distorted.solvers.SolvingList;
-import org.distorted.solvers.SolvingThread;
+import org.distorted.objectlib.solvers.verifiers.ResultScreen;
+import org.distorted.objectlib.solvers.verifiers.SolverAbstract;
+import org.distorted.objectlib.solvers.verifiers.SolvingList;
 
 import java.lang.ref.WeakReference;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class ScreenSolver extends ScreenAbstract
+public class ScreenSolver extends ScreenAbstract implements ResultScreen
   {
   private static final int RESET_DURATION = 1000;
   private static final int MODE_NORMAL = 0;
   private static final int MODE_DINO_4 = 1;
 
+  private static final int[][] colorsHex =
+    {
+      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
+      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
+      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
+      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
+      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
+      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
+    };
+  private static final int[][] colorsTet =
+    {
+      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
+      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
+      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
+      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
+    };
+  private static final int[][] colorsOct =
+    {
+      {R.string.color_violet1,R.string.color_violet2,R.string.color_violet3,R.string.color_violet4,R.string.color_violet5,R.string.color_violet6,R.string.color_violet7 },
+      {R.string.color_grey1  ,R.string.color_grey2  ,R.string.color_grey3  ,R.string.color_grey4  ,R.string.color_grey5  ,R.string.color_grey6  ,R.string.color_grey7   },
+      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
+      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
+      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
+      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
+      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
+      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
+    };
+  private static final int[][] colorsDi4 =
+    {
+      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
+      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
+      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
+      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
+    };
+
   private static Bitmap[] mBitmap;
   private ImageButton[] mColorButton;
   private TransparentImageButton mResetButton,mBackButton, mSolveButton;
@@ -60,6 +97,7 @@ public class ScreenSolver extends ScreenAbstract
   private float mBitmapSize;
   private WeakReference<SolverActivity> mWeakAct;
   private int mObjectOrdinal;
+  private String[] mPhaseNames;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -81,6 +119,7 @@ public class ScreenSolver extends ScreenAbstract
 
     mWeakAct = new WeakReference<>(act);
     mSolving = false;
+    mPhaseNames = null;
 
     mObjectOrdinal = act.getObjectOrdinal();
     control.solveOnly();
@@ -255,10 +294,17 @@ public class ScreenSolver extends ScreenAbstract
         {
         SolvingList list = SolvingList.getSolver(solverOrdinals[0]);
         OperatingSystemInterface os = act.getInterface();
-        Resources res = act.getResources();
         TwistyObject object = act.getObject();
-        SolvingThread solver = new SolvingThread( os,res,object,list );
-        solver.start();
+        SolverAbstract solver = list.create(os,object);
+
+        if( solver!=null )
+          {
+          int[] result = solver.validatePosition(object);
+          if( result[0]>=0 ) solver.solve(this,result);
+          else displayImpossibleDialog(result,solver.getFaceColors());
+          }
+        else displayErrorDialog(act.getString(R.string.solver_generic_not_implemented));
+
         return true;
         }
       else  // more than one solver - launch a choosing dialog
@@ -280,6 +326,11 @@ public class ScreenSolver extends ScreenAbstract
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void fail(String result) {}
+  public void setPhaseNames(String[] names) { mPhaseNames = names; }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void setupColorButtons(final SolverActivity act, final float width)
@@ -426,7 +477,7 @@ public class ScreenSolver extends ScreenAbstract
           {
           ScreenList.switchScreen(act, ScreenList.SOLU);
           ScreenSolution solution = (ScreenSolution) ScreenList.SOLU.getScreenClass();
-          solution.setupMoves(act, moves);
+          solution.setSolution(moves);
           if( !moves.isEmpty() ) act.doNotShowDialogAnymore();
           }
         });
@@ -435,7 +486,7 @@ public class ScreenSolver extends ScreenAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void setSolved(final int[][] moves)
+  public void setSolved(final int[][] moves, final int phaseNumber, final int[][] subphases)
     {
     mSolving = false;
     final SolverActivity act = mWeakAct.get();
@@ -447,9 +498,23 @@ public class ScreenSolver extends ScreenAbstract
         @Override
         public void run()
           {
-          ScreenList.switchScreen(act, ScreenList.SOLU);
-          ScreenSolution solution = (ScreenSolution) ScreenList.SOLU.getScreenClass();
-          solution.setupMoves(act, moves);
+          if( mPhaseNames!=null )
+            {
+            ScreenPhasedSolution screen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass();
+            if( phaseNumber==0 )
+              {
+              ScreenList.switchScreen(act, ScreenList.PHAS);
+              screen.updateNames(mPhaseNames);
+              }
+            screen.setSolution(moves, phaseNumber,subphases);
+            }
+          else
+            {
+            ScreenList.switchScreen(act, ScreenList.SOLU);
+            ScreenSolution screen = (ScreenSolution) ScreenList.SOLU.getScreenClass();
+            screen.setSolution(moves);
+            }
+
           if( moves!=null && moves.length>0 ) act.doNotShowDialogAnymore();
           }
         });
@@ -458,37 +523,31 @@ public class ScreenSolver extends ScreenAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void setSolved(final int[][] moves, final int phaseNumber, final int[][] subphases)
+  public void displayErrorDialog(String message)
     {
     mSolving = false;
-    final SolverActivity act = mWeakAct.get();
+    SolverActivity act = mWeakAct.get();
 
     if( act!=null )
       {
-      act.runOnUiThread(new Runnable()
-        {
-        @Override
-        public void run()
-          {
-          if( phaseNumber==0 ) ScreenList.switchScreen(act, ScreenList.PHAS);
-          ScreenPhasedSolution screen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass();
-          screen.setSolution(moves, phaseNumber,subphases);
-          if( moves!=null && moves.length>0 ) act.doNotShowDialogAnymore();
-          }
-        });
+      RubikDialogSolverError dialog = new RubikDialogSolverError();
+      Bundle bundle = new Bundle();
+      bundle.putString("argument", message );
+      dialog.setArguments(bundle);
+      dialog.show( act.getSupportFragmentManager(), null);
       }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void displayErrorDialog(String message)
+  public void displayImpossibleDialog(String message)
     {
     mSolving = false;
     SolverActivity act = mWeakAct.get();
 
     if( act!=null )
       {
-      RubikDialogSolverError dialog = new RubikDialogSolverError();
+      RubikDialogSolverImpossible dialog = new RubikDialogSolverImpossible();
       Bundle bundle = new Bundle();
       bundle.putString("argument", message );
       dialog.setArguments(bundle);
@@ -498,18 +557,234 @@ public class ScreenSolver extends ScreenAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void displayImpossibleDialog(String message)
+  public void displayImpossibleDialog(int[] errorCode, int[] faceColors)
     {
     mSolving = false;
     SolverActivity act = mWeakAct.get();
 
     if( act!=null )
       {
-      RubikDialogSolverImpossible dialog = new RubikDialogSolverImpossible();
-      Bundle bundle = new Bundle();
-      bundle.putString("argument", message );
-      dialog.setArguments(bundle);
-      dialog.show( act.getSupportFragmentManager(), null);
+      String message = error(act.getResources(),errorCode,faceColors);
+      displayImpossibleDialog(message);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int getHexColor(int color,int variant) { return colorsHex[color][variant]; }
+  int getTetColor(int color,int variant) { return colorsTet[color][variant]; }
+  int getOctColor(int color,int variant) { return colorsOct[color][variant]; }
+  int getDi4Color(int color,int variant) { return colorsDi4[color][variant]; }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexCornerMissingError(Resources res, int face0, int face1, int face2)
+    {
+    int j0 = getHexColor(face0,3);
+    int j1 = getHexColor(face1,3);
+    int j2 = getHexColor(face2,4);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+    String c2 = res.getString(j2);
+
+    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexCenterMissingError(Resources res, int face)
+    {
+    int color = getHexColor(face,2);
+    String clr= res.getString(color);
+    return res.getString(R.string.solver_generic_missing_center,clr);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexEdgeMissingError(Resources res, int face0, int face1)
+    {
+    int j0 = getHexColor(face0,3);
+    int j1 = getHexColor(face1,6);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+
+    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexEdgeTwistedError(Resources res, int color0, int color1)
+    {
+    int j0 = getHexColor(color0,3);
+    int j1 = getHexColor(color1,6);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+
+    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexCornerTwistedError(Resources res, int color0, int color1, int color2)
+    {
+    int j0 = getHexColor(color0,3);
+    int j1 = getHexColor(color1,3);
+    int j2 = getHexColor(color2,5);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+    String c2 = res.getString(j2);
+
+    return res.getString(R.string.solver_generic_twisted_corner,c0,c1,c2);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexEdgeMonoError(Resources res, int color)
+    {
+    int j0 = getHexColor(color,3);
+    int j1 = getHexColor(color,6);
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+
+    return res.getString(R.string.solver_generic_edge_mono,c0,c1);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String hexEdgeTwiceError(Resources res, int color0, int color1)
+    {
+    int j0 = getHexColor(color0,3);
+    int j1 = getHexColor(color1,6);
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+
+    return res.getString(R.string.solver_generic_edge_twice,c0,c1);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String octCenterMissingError(Resources res, int face)
+    {
+    int index = getOctColor(face,2);
+    String color = res.getString(index);
+    return res.getString(R.string.solver_generic_missing_center,color);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String octCornerMissingError(Resources res, int f1, int f2)
+    {
+    int i1 = getOctColor(f1,3);
+    int i2 = getOctColor(f2,4);
+    String c1 = res.getString(i1);
+    String c2 = res.getString(i2);
+    return res.getString(R.string.solver_generic_missing_corner2,c1,c2);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String tetCornerMissingError(Resources res, int color0, int color1, int color2)
+    {
+    int j0 = getTetColor(color0,3);
+    int j1 = getTetColor(color1,3);
+    int j2 = getTetColor(color2,4);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+    String c2 = res.getString(j2);
+
+    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String tetEdgeMissingError(Resources res, int face0, int face1)
+    {
+    int j0 = getTetColor(face0,3);
+    int j1 = getTetColor(face1,6);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+
+    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String tetCenterMissingError(Resources res, int face)
+    {
+    int j = getTetColor(face,2);
+    String c = res.getString(j);
+    return res.getString(R.string.solver_generic_missing_center,c);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String tetVertexMissingError(Resources res, int color0, int color1, int color2)
+    {
+    int j0 = getTetColor(color0,3);
+    int j1 = getTetColor(color1,3);
+    int j2 = getTetColor(color2,4);
+
+    String c0 = res.getString(j0);
+    String c1 = res.getString(j1);
+    String c2 = res.getString(j2);
+
+    return res.getString(R.string.solver_generic_missing_vertex,c0,c1,c2);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  String di4EdgeThreeError(Resources res, int color)
+    {
+    int j0 = getDi4Color(color,7);
+    String c0 = res.getString(j0);
+    return res.getString(R.string.solver_generic_edge_three,c0);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String error(Resources res, int[] err, int[] faceColors)
+    {
+    switch(err[0])
+      {
+      case ERROR_HEX_CORNER_MISSING    : return hexCornerMissingError(res,err[1],err[2],err[3]);
+      case ERROR_HEX_CENTER_MISSING    : return hexCenterMissingError(res,err[1]);
+      case ERROR_HEX_EDGE_MISSING      : return hexEdgeMissingError(res,err[1],err[2]);
+      case ERROR_HEX_EDGE_TWISTED      : return hexEdgeTwistedError(res,err[1],err[2]);
+      case ERROR_HEX_EDGE_MONOCHROMATIC: return hexEdgeMonoError(res,err[1]);
+      case ERROR_HEX_EDGE_TWICE        : return hexEdgeTwiceError(res,err[1],err[2]);
+      case ERROR_HEX_CORNER_TWISTED    : return hexCornerTwistedError(res,err[1],err[2],err[3]);
+
+      case ERROR_TET_CORNER_MISSING    : return tetCornerMissingError(res,err[1],err[2],err[3]);
+      case ERROR_TET_VERTEX_MISSING    : return tetVertexMissingError(res,err[1],err[2],err[3]);
+      case ERROR_TET_EDGE_MISSING      : return tetEdgeMissingError(res,faceColors[err[1]],faceColors[err[2]]);
+      case ERROR_TET_CENTER_MISSING    : return tetCenterMissingError(res,err[1]);
+
+      case ERROR_OCT_CENTER_MISSING    : return octCenterMissingError(res,err[1]);
+      case ERROR_OCT_CORNER_MISSING    : return octCornerMissingError(res,err[1],err[2]);
+
+      case ERROR_DI4_EDGE_THREE        : return di4EdgeThreeError(res,err[1]);
+
+      case ERROR_CORNERS_CANNOT        : return res.getString(R.string.solver_generic_corners_cannot);
+      case ERROR_EDGE_CANNOT           : return res.getString(R.string.solver_generic_edges_cannot);
+      case ERROR_CORNER_TWISTED        : return res.getString(R.string.solver_generic_corner_twist);
+      case ERROR_CORNER_TWIST_90       : return res.getString(R.string.solver_generic_corner_twist) + " (90)";
+      case ERROR_CORNER_TWIST_180      : return res.getString(R.string.solver_generic_corner_twist) + " (180)";
+      case ERROR_EDGE_TWISTED          : return res.getString(R.string.solver_generic_edge_twist);
+      case ERROR_TWO_CENTERS           : return res.getString(R.string.solver_generic_two_centers);
+      case ERROR_TWO_CORNERS           : return res.getString(R.string.solver_generic_two_corners);
+      case ERROR_TWO_EDGES             : return res.getString(R.string.solver_generic_two_edges);
+      case ERROR_FREE_CORNERS_NOT_EVEN : return res.getString(R.string.solver_generic_free_corners_odd);
+      case ERROR_FREE_CORNERS_ROTATED  : return res.getString(R.string.solver_generic_free_corners_rotated);
+      case ERROR_VERTICES_CANNOT       : return res.getString(R.string.solver_generic_vertices_cannot);
+      case ERROR_C_V_DONT_MATCH        : return res.getString(R.string.solver_generic_c_v_dont_match);
       }
+
+    return null;
     }
   }
diff --git a/src/main/java/org/distorted/solverui/SolverObjectLibInterface.java b/src/main/java/org/distorted/solverui/SolverObjectLibInterface.java
index 22d5fe1d..676e1bc7 100644
--- a/src/main/java/org/distorted/solverui/SolverObjectLibInterface.java
+++ b/src/main/java/org/distorted/solverui/SolverObjectLibInterface.java
@@ -18,7 +18,7 @@ import org.distorted.objectlib.helpers.ObjectLibInterface;
 import org.distorted.objectlib.main.ObjectControl;
 import org.distorted.objects.RubikObject;
 import org.distorted.objects.RubikObjectList;
-import org.distorted.solvers.SolvingList;
+import org.distorted.objectlib.solvers.verifiers.SolvingList;
 
 import java.lang.ref.WeakReference;
 
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 915c116c..85bb3d17 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -231,37 +231,6 @@
     <string name="color_violet7">violet</string>
     <string name="color_grey7">grey</string>
 
-    <string name="solver_cube3_title" translatable="false">Kociemba Solver</string>
-    <string name="solver_3algo_title" translatable="false">3x3 Beginner</string>
-    <string name="solver_pduo2_title" translatable="false">Pyraminx Duo Solver</string>
-    <string name="solver_pyra3_title" translatable="false">Pyraminx Solver</string>
-    <string name="solver_ivy_title" translatable="false">Ivy Solver</string>
-    <string name="solver_cu232_title" translatable="false">2x2x3 Cuboid Solver</string>
-    <string name="solver_cu323_title" translatable="false">3x3x2 Cuboid Solver</string>
-    <string name="solver_diam2_title" translatable="false">Skewb Diamond Solver</string>
-    <string name="solver_cube2_title" translatable="false">2x2 Cube Solver</string>
-    <string name="solver_skew2_title" translatable="false">Skewb Solver</string>
-    <string name="solver_jing2_title" translatable="false">Jing Pyraminx Solver</string>
-    <string name="solver_dino6_title" translatable="false">6-color Dino Solver</string>
-    <string name="solver_dino4_title" translatable="false">4-color Dino Solver</string>
-    <string name="solver_pdia_title" translatable="false">Pyraminx Diamond Solver</string>
-
-    <string name="solver_cube3_description">A near-perfect, instantaneous, two-phase 3x3x3 solver.\nAuthor: Herbert Kociemba.</string>
-    <string name="solver_3algo_description">Implementation of the beginner algorithm. 7 phases. Produces about 100 move long solutions.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_pduo2_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_ivy_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_cu232_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_pyra3_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_diam2_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_cube2_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_skew2_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_jing2_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_dino6_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_dino4_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_pdia_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_cu323_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
-    <string name="solver_cube4_description">Not implemented yet.\nAuthor: Leszek Koltunski.</string>
-
     <string name="creators">Creators</string>
     <string name="creator_cuboid_title" translatable="false">Bandaged Cuboids</string>
     <string name="creator_pyraminx_title" translatable="false">Bandaged Pyraminxes</string>
