commit 7dbbda72b7dc14e29e157ad54759ab5b92f8f1f9
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Feb 26 18:38:01 2023 +0100

    Pyraminx solver: error messages

diff --git a/src/main/java/org/distorted/solvers/SolverCube3.java b/src/main/java/org/distorted/solvers/SolverCube3.java
index 6f9b4bfb..ab0e9992 100644
--- a/src/main/java/org/distorted/solvers/SolverCube3.java
+++ b/src/main/java/org/distorted/solvers/SolverCube3.java
@@ -190,7 +190,7 @@ public class SolverCube3
           {
           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_cube3_error3); 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;
diff --git a/src/main/java/org/distorted/solvers/SolverMain.java b/src/main/java/org/distorted/solvers/SolverMain.java
index 10a9292b..e91fc2e2 100644
--- a/src/main/java/org/distorted/solvers/SolverMain.java
+++ b/src/main/java/org/distorted/solvers/SolverMain.java
@@ -91,6 +91,11 @@ public class SolverMain implements Runnable
       SolverTablebase solver = new SolverCuboid232(mRes,mObject);
       solver.solve(screen);
       }
+    else if( mSignature==ObjectSignatures.PYRA_3 )
+      {
+      SolverTablebase solver = new SolverPyraminx(mRes,mObject);
+      solver.solve(screen);
+      }
     else
       {
       screen.displayErrorDialog(mRes.getString(R.string.solver_generic_not_implemented));
diff --git a/src/main/java/org/distorted/solvers/SolverPyraminx.java b/src/main/java/org/distorted/solvers/SolverPyraminx.java
new file mode 100644
index 00000000..9e39c43a
--- /dev/null
+++ b/src/main/java/org/distorted/solvers/SolverPyraminx.java
@@ -0,0 +1,463 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.main.ObjectType;
+import org.distorted.objectlib.main.TwistyObject;
+import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
+import org.distorted.objectlib.tablebases.TablebasesAbstract;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SolverPyraminx extends SolverTablebase
+{
+  private static final int ERROR_CORNER_GYB_MISSING = -1;
+  private static final int ERROR_CORNER_GYR_MISSING = -2;
+  private static final int ERROR_CORNER_GBR_MISSING = -3;
+  private static final int ERROR_CORNER_YBR_MISSING = -4;
+
+  private static final int ERROR_VERTEX_GYB_MISSING = -5;
+  private static final int ERROR_VERTEX_GYR_MISSING = -6;
+  private static final int ERROR_VERTEX_GBR_MISSING = -7;
+  private static final int ERROR_VERTEX_YBR_MISSING = -8;
+
+  private static final int ERROR_EDGE_RB_MISSING = -9;
+  private static final int ERROR_EDGE_RY_MISSING = -10;
+  private static final int ERROR_EDGE_RG_MISSING = -11;
+  private static final int ERROR_EDGE_YB_MISSING = -12;
+  private static final int ERROR_EDGE_GB_MISSING = -13;
+  private static final int ERROR_EDGE_GY_MISSING = -14;
+
+  private static final int ERROR_CORNERS_CANNOT   = -15;
+  private static final int ERROR_VERTICES_CANNOT  = -16;
+  private static final int ERROR_CORNER_TWISTED   = -17;
+  private static final int ERROR_EDGE_TWISTED     = -18;
+  private static final int ERROR_C_V_DONT_MATCH   = -19;
+
+  TablebasesAbstract mSolver;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  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 c1, int c2)
+    {
+    return ( (piece[0]==c1 && piece[1]==c2) ||
+             (piece[0]==c2 && piece[1]==c1)  );
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  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 ) return ERROR_CORNER_YBR_MISSING;
+    if( !gbr ) return ERROR_CORNER_GBR_MISSING;
+    if( !gyr ) return ERROR_CORNER_GYR_MISSING;
+    if( !gyb ) return ERROR_CORNER_GYB_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 ) return ERROR_VERTEX_YBR_MISSING;
+    if( !gbr ) return ERROR_VERTEX_GBR_MISSING;
+    if( !gyr ) return ERROR_VERTEX_GYR_MISSING;
+    if( !gyb ) return ERROR_VERTEX_GYB_MISSING;
+
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int checkAllEdgesPresent(int[][] edges)
+    {
+    boolean rb = false;
+    boolean ry = false;
+    boolean rg = false;
+    boolean yb = false;
+    boolean gb = false;
+    boolean gy = false;
+
+    for(int i=0; i<6; i++)
+      {
+      if( pieceEqual2(edges[i],3,2) ) rb = true;
+      if( pieceEqual2(edges[i],3,1) ) ry = true;
+      if( pieceEqual2(edges[i],3,0) ) rg = true;
+      if( pieceEqual2(edges[i],2,1) ) yb = true;
+      if( pieceEqual2(edges[i],2,0) ) gb = true;
+      if( pieceEqual2(edges[i],1,0) ) gy = true;
+      }
+
+    if( !rb ) return ERROR_EDGE_RB_MISSING;
+    if( !ry ) return ERROR_EDGE_RY_MISSING;
+    if( !rg ) return ERROR_EDGE_RG_MISSING;
+    if( !yb ) return ERROR_EDGE_YB_MISSING;
+    if( !gb ) return ERROR_EDGE_GB_MISSING;
+    if( !gy ) return ERROR_EDGE_GY_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 ) ? -1 : twist1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public SolverPyraminx(Resources res, TwistyObject object)
+    {
+    super(res,object);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void getCorners(TwistyObject object, int[][] corners)
+    {
+    corners[0][0] = object.getCubitFaceStickerIndex(6,3);  // R
+    corners[0][1] = object.getCubitFaceStickerIndex(6,2);  // B
+    corners[0][2] = object.getCubitFaceStickerIndex(6,1);  // Y
+
+    corners[1][0] = object.getCubitFaceStickerIndex(4,3);  // R
+    corners[1][1] = object.getCubitFaceStickerIndex(4,0);  // G
+    corners[1][2] = object.getCubitFaceStickerIndex(4,2);  // B
+
+    corners[2][0] = object.getCubitFaceStickerIndex(13,3);  // R
+    corners[2][1] = object.getCubitFaceStickerIndex(13,1);  // Y
+    corners[2][2] = object.getCubitFaceStickerIndex(13,0);  // G
+
+    corners[3][0] = object.getCubitFaceStickerIndex(11,0);  // G
+    corners[3][1] = object.getCubitFaceStickerIndex(11,1);  // Y
+    corners[3][2] = object.getCubitFaceStickerIndex(11,2);  // B
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void getVertices(TwistyObject object, int[][] vertex)
+    {
+    vertex[0][0] = object.getCubitFaceStickerIndex(1,5);  // R
+    vertex[0][1] = object.getCubitFaceStickerIndex(1,7);  // B
+    vertex[0][2] = object.getCubitFaceStickerIndex(1,2);  // Y
+
+    vertex[1][0] = object.getCubitFaceStickerIndex(0,5);  // R
+    vertex[1][1] = object.getCubitFaceStickerIndex(0,0);  // G
+    vertex[1][2] = object.getCubitFaceStickerIndex(0,7);  // B
+
+    vertex[2][0] = object.getCubitFaceStickerIndex(3,5);  // R
+    vertex[2][1] = object.getCubitFaceStickerIndex(3,2);  // Y
+    vertex[2][2] = object.getCubitFaceStickerIndex(3,0);  // G
+
+    vertex[3][0] = object.getCubitFaceStickerIndex(2,0);  // G
+    vertex[3][1] = object.getCubitFaceStickerIndex(2,2);  // Y
+    vertex[3][2] = object.getCubitFaceStickerIndex(2,7);  // B
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  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,3); // R
+    edges[1][1] = object.getCubitFaceStickerIndex(10,1); // Y
+
+    edges[2][0] = object.getCubitFaceStickerIndex(9,3);  // R
+    edges[2][1] = object.getCubitFaceStickerIndex(9,0);  // G
+
+    edges[3][0] = object.getCubitFaceStickerIndex(8,1);  // Y
+    edges[3][1] = object.getCubitFaceStickerIndex(8,2);  // B
+
+    edges[4][0] = object.getCubitFaceStickerIndex(7,0);  // G
+    edges[4][1] = object.getCubitFaceStickerIndex(7,2);  // B
+
+    edges[5][0] = object.getCubitFaceStickerIndex(12,0); // G
+    edges[5][1] = object.getCubitFaceStickerIndex(12,1); // Y
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int tablebaseIndex(TwistyObject object)
+    {
+    int[][] corners = new int[4][3];
+    int[][] edges   = new int[6][2];
+    int[][] vertices= new int[4][3];
+    int[] corner_twist = new int[4];
+    int[] vertex_twist = new int[4];
+
+    getCorners(object,corners);
+    getVertices(object,vertices);
+    getEdges(object,edges);
+
+    int result1 = checkAllCornersPresent(corners);
+    if( result1<0 ) return result1;
+
+    int result2 = checkAllVerticesPresent(vertices);
+    if( result2<0 ) return result2;
+
+    int result3 = checkAllEdgesPresent(edges);
+    if( result3<0 ) return result3;
+
+    int[] faces1 = computeFaceColors(corners);
+    int[] faces2 = computeFaceColors(vertices);
+
+    int result4 = checkAgreement(faces1,faces2);
+    if( result4<0 ) return result4;
+
+    for(int i=0; i<4; i++)
+      {
+      corner_twist[i] = computePieceTwist(i,corners[i],faces1);
+      if( corner_twist[i]<0 ) return ERROR_CORNERS_CANNOT;
+      }
+
+    for(int i=0; i<4; i++)
+      {
+      vertex_twist[i] = computePieceTwist(i,vertices[i],faces1);
+      if( vertex_twist[i]<0 ) return ERROR_VERTICES_CANNOT;
+      }
+
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int getColorIndex3(int color)
+    {
+    switch(color)
+      {
+      case 0: return R.string.color_green3;
+      case 1: return R.string.color_yellow3;
+      case 2: return R.string.color_blue3;
+      case 3: return R.string.color_red3;
+      }
+
+    return -1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int getColorIndex4(int color)
+    {
+    switch(color)
+      {
+      case 0: return R.string.color_green4;
+      case 1: return R.string.color_yellow4;
+      case 2: return R.string.color_blue4;
+      case 3: return R.string.color_red4;
+      }
+
+    return -1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int getColorIndex6(int color)
+    {
+    switch(color)
+      {
+      case 0: return R.string.color_green6;
+      case 1: return R.string.color_yellow6;
+      case 2: return R.string.color_blue6;
+      case 3: return R.string.color_red6;
+      }
+
+    return -1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private String cornerError(Resources res, int color0, int color1, int color2)
+    {
+    int j0 = getColorIndex3(color0);
+    int j1 = getColorIndex3(color1);
+    int j2 = getColorIndex4(color2);
+
+    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 = getColorIndex3(color0);
+    int j1 = getColorIndex3(color1);
+    int j2 = getColorIndex4(color2);
+
+    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 = getColorIndex3(color0);
+    int j1 = getColorIndex6(color1);
+
+    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_YBR_MISSING: return cornerError(res,3,2,1);
+      case ERROR_CORNER_GBR_MISSING: return cornerError(res,3,2,0);
+      case ERROR_CORNER_GYR_MISSING: return cornerError(res,3,1,0);
+      case ERROR_CORNER_GYB_MISSING: return cornerError(res,2,1,0);
+      case ERROR_VERTEX_YBR_MISSING: return vertexError(res,3,2,1);
+      case ERROR_VERTEX_GBR_MISSING: return vertexError(res,3,2,0);
+      case ERROR_VERTEX_GYR_MISSING: return vertexError(res,3,1,0);
+      case ERROR_VERTEX_GYB_MISSING: return vertexError(res,2,1,0);
+      case ERROR_EDGE_RB_MISSING   : return edgeError(res,3,2);
+      case ERROR_EDGE_RY_MISSING   : return edgeError(res,3,1);
+      case ERROR_EDGE_RG_MISSING   : return edgeError(res,3,0);
+      case ERROR_EDGE_YB_MISSING   : return edgeError(res,2,1);
+      case ERROR_EDGE_GB_MISSING   : return edgeError(res,2,0);
+      case ERROR_EDGE_GY_MISSING   : return edgeError(res,1,0);
+      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_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;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int[][] solution(int index, Resources res)
+    {
+    if( mSolver==null )
+      {
+      //mSolver = ImplementedTablebasesList.createPacked(res,ObjectType.PYRA_3);
+      mSolver = ImplementedTablebasesList.createUnpacked(ObjectType.PYRA_3);
+      if( mSolver!=null ) mSolver.createTablebase();
+      }
+
+    return mSolver!=null ? mSolver.solution(index) : null;
+    }
+}  
+
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index 38e98a39..9ba5c0b0 100755
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">Zwei Zentren müssen ausgetauscht werden!</string>
     <string name="solver_generic_missing_center">Die %1$s Mitte fehlt!</string>
     <string name="solver_generic_missing_corner">Die %1$s-%2$s-%3$s Ecke fehlt!</string>
+    <string name="solver_generic_missing_vertex">Der %1$s-%2$s-%3$s Oktaeder fehlt!</string>
     <string name="solver_generic_missing_edge">Die %1$s-%2$s Kante fehlt!</string>
-    <string name="solver_generic_corners_cannot">Ecken können nicht verdreht werden, sodass alle Flächen einfarbig sind!</string>
+    <string name="solver_generic_corners_cannot">Ecken können nicht verdreht werden, sodass alle Seiten einfarbig sind!</string>
+    <string name="solver_generic_vertices_cannot">Oktaederstücke können nicht so verdreht werden, sodass alle Seiten einfarbig sind!</string>
 
     <string name="solver_cube3_error1">Es gibt nur %1$d %2$s Facelets.</string>
     <string name="solver_cube3_error2">Nicht alle 12 Kanten gibt es genau einmal!</string>
-    <string name="solver_cube3_error3">Eine Kante muss umgedreht werden!</string>
     <string name="solver_cube3_error4">Nicht alle 8 Ecken gibt es genau einmal!</string>
     <string name="solver_cube3_error6">Zwei Ecken oder zwei Kanten müssen ausgetauscht werden!</string>
     <string name="solver_cube3_error7">Für die angegebene maximale Zugzahl gibt es keine Lösung!</string>
diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml
index de2ed623..6a6d0470 100755
--- a/src/main/res/values-es/strings.xml
+++ b/src/main/res/values-es/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">¡Hay que cambiar dos centros!</string>
     <string name="solver_generic_missing_center">¡Falta el centro %1$s!</string>
     <string name="solver_generic_missing_corner">¡Falta la esquina %1$s-%2$s-%3$s!</string>
+    <string name="solver_generic_missing_vertex">¡Falta el octaedro %1$s-%2$s-%3$s!</string>
     <string name="solver_generic_missing_edge">¡Falta la pieza del borde %1$s-%2$s!</string>
     <string name="solver_generic_corners_cannot">¡Las esquinas no se pueden torcer para que todos los lados sean monocromáticos!</string>
+    <string name="solver_generic_vertices_cannot">¡Las piezas del octaedro no se pueden torcer para que todos los lados sean monocromáticos!</string>
 
     <string name="solver_cube3_error1">Solo hay %1$d facetas %2$s.</string>
     <string name="solver_cube3_error2">¡No todos los 12 bordes existen exactamente una vez!</string>
-    <string name="solver_cube3_error3">¡Un borde tiene que voltearse!</string>
     <string name="solver_cube3_error4">¡No todas las 8 esquinas existen exactamente una vez!</string>
     <string name="solver_cube3_error6">¡Hay que cambiar dos esquinas o dos bordes!</string>
     <string name="solver_cube3_error7">¡No existe una solución para el número de movimientos máximos dado!</string>
diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml
index 5bd68cee..4c929fc5 100755
--- a/src/main/res/values-fr/strings.xml
+++ b/src/main/res/values-fr/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">Deux centres doivent être échangés !</string>
     <string name="solver_generic_missing_center">Centre %1$s manquant !</string>
     <string name="solver_generic_missing_corner">Coin %1$s-%2$s-%3$s manquant !</string>
+    <string name="solver_generic_missing_vertex">L\'octaèdre %1$s-%2$s-%3$s manque !</string>
     <string name="solver_generic_missing_edge">La pièce de bordure %1$s-%2$s manque!</string>
     <string name="solver_generic_corners_cannot">Les coins ne peuvent pas être tordus afin que tous les côtés soient monochromes !</string>
+    <string name="solver_generic_vertices_cannot">Les pièces d\'octaèdre ne peuvent pas être tordues afin que tous les côtés soient monochromes !</string>
 
     <string name="solver_cube3_error1">Il n\'y a que %1$d facettes %2$s.</string>
     <string name="solver_cube3_error2">Les 12 arêtes n\'existent pas exactement une fois !</string>
-    <string name="solver_cube3_error3">Une arête doit être inversée !</string>
     <string name="solver_cube3_error4">Les 8 coins n\'existent pas tous une seule fois !</string>
     <string name="solver_cube3_error6">Deux coins ou deux arêtes doivent être échangés !</string>
     <string name="solver_cube3_error7">Aucune solution n\'existe pour le nombre maximum de coups donné !</string>
diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml
index e023ce33..4a3a8c2f 100755
--- a/src/main/res/values-ja/strings.xml
+++ b/src/main/res/values-ja/strings.xml
@@ -85,13 +85,14 @@
     <string name="solver_generic_edge_twist">片方の端をひねる必要がある!</string>
     <string name="solver_generic_two_centers">2つのセンターを交換しなければならない!</string>
     <string name="solver_generic_missing_center">%1$sのセンターが欠けてる！</string>
-    <string name="solver_generic_missing_corner">%1$s%2$s%3$sのコーナーがない!</string>
+    <string name="solver_generic_missing_corner">%1$s%2$s%3$sのコーナーがない！</string>
+    <string name="solver_generic_missing_vertex">%1$s-%2$s-%3$s八面体がありません！</string>
     <string name="solver_generic_missing_edge">%1$s%2$sボーダーピースはありません！</string>
     <string name="solver_generic_corners_cannot">すべての面がモノクロになるようにコーナーをねじることはできません。</string>
+    <string name="solver_generic_vertices_cannot">すべての面が単色になるように、八面体のピースをねじることはできません。</string>
 
     <string name="solver_cube3_error1">%2$s小顔は%1$dつだけ</string>
     <string name="solver_cube3_error2">12 のエッジすべてが 存在するわけではありません。</string>
-    <string name="solver_cube3_error3">1 つのエッジを反転する必要があります！</string>
     <string name="solver_cube3_error4">8 つのコーナーすべてが存在するわけではありません！</string>
     <string name="solver_cube3_error6">2 つのコーナーまたは 2 つのエッジを交換する必要があります！</string>
     <string name="solver_cube3_error7">指定された最大移動数の解答はありません！</string>
diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml
index 815fcb2d..f46744c8 100755
--- a/src/main/res/values-ko/strings.xml
+++ b/src/main/res/values-ko/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">두 개의 센터를 교환해야 합니다!</string>
     <string name="solver_generic_missing_center">%1$s 중앙이 사라졌습니다!</string>
     <string name="solver_generic_missing_corner">%1$s-%2$s-%3$s 모서리 금지!</string>
+    <string name="solver_generic_missing_vertex">%1$s-%2$s-%3$s 팔면체가 없습니다!</string>
     <string name="solver_generic_missing_edge">%1$s%2$s테두리 조각이 없습니다!</string>
     <string name="solver_generic_corners_cannot">모든면이 단색이되도록 모서리를 비틀 수 없습니다!</string>
+    <string name="solver_generic_vertices_cannot">정팔면체 조각은 뒤틀릴 수 없어 모든 면이 단색입니다!</string>
 
     <string name="solver_cube3_error1">%2$s작은 얼굴은  %1$d개뿐입니다.</string>
     <string name="solver_cube3_error2">12개의 가장자리 모두가 정확하게 한 번 존재하지 않습니다!</string>
-    <string name="solver_cube3_error3">한쪽 가장자리를 뒤집어야 합니다!</string>
     <string name="solver_cube3_error4">8개의 모서리 모두가 정확하게 한 번 존재하지 않습니다!</string>
     <string name="solver_cube3_error6">두 모서리 또는 두 가장자리를 교환해야합니다!</string>
     <string name="solver_cube3_error7">지정된 최대 이동 수에 대한 해답이 없습니다!</string>
diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml
index c463c7cd..cb0ae7f2 100644
--- a/src/main/res/values-pl/strings.xml
+++ b/src/main/res/values-pl/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">Dwa środki muszą być wymienione!</string>
     <string name="solver_generic_missing_center">Brakuje %1$s środka!</string>
     <string name="solver_generic_missing_corner">Brakuje %1$s-%2$s-%3$s rogu!</string>
+    <string name="solver_generic_missing_vertex">Brakuje %1$s-%2$s-%3$s ośmiokątu!</string>
     <string name="solver_generic_missing_edge">Brakuje %1$s-%2$s krawędzi!</string>
     <string name="solver_generic_corners_cannot">Narożników nie można skręcić tak, aby wszystkie boki były monochromatyczne!</string>
+    <string name="solver_generic_vertices_cannot">Części ośmiościennych nie można skręcić tak, aby wszystkie boki były monochromatyczne!</string>
 
     <string name="solver_cube3_error1">Jest tylko %1$d %2$s ścian.</string>
     <string name="solver_cube3_error2">Któraś z 12 krawędzi nie istnieje!</string>
-    <string name="solver_cube3_error3">Jedna z krawędzi musi być odwrócona!</string>
     <string name="solver_cube3_error4">Jeden z 8 rogów nie istnieje!</string>
     <string name="solver_cube3_error6">Dwa rogi albo dwie krawędzie muszą byc obrócone!</string>
     <string name="solver_cube3_error7">Rozwiązanie nie zostało znalezione!</string>
diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml
index e8f50621..9d07d357 100755
--- a/src/main/res/values-ru/strings.xml
+++ b/src/main/res/values-ru/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">Два центра должны быть обменены!</string>
     <string name="solver_generic_missing_center">Нет %1$s центра!</string>
     <string name="solver_generic_missing_corner">Нет %1$s-%2$s-%3$s угла!</string>
+    <string name="solver_generic_missing_vertex">Нет %1$s-%2$s-%3$s октаэдра!</string>
     <string name="solver_generic_missing_edge">Нет %1$s-%2$s края!</string>
     <string name="solver_generic_corners_cannot">Углы нельзя скручивать так, чтобы все стороны были однотонными!</string>
+    <string name="solver_generic_vertices_cannot">Кусочки октаэдра нельзя скрутить так, чтобы все стороны были одноцветными!</string>
 
     <string name="solver_cube3_error1">Всего %1$d %2$s граней!</string>
     <string name="solver_cube3_error2">Не все 12 ребер существуют в единичном экземпляре!</string>
-    <string name="solver_cube3_error3">Надо перевернуть одно ребро!</string>
     <string name="solver_cube3_error4">Не все 8 углов существуют в единичном экземпляре!</string>
     <string name="solver_cube3_error6">Надо поменять местами два угла или два ребра!</string>
     <string name="solver_cube3_error7">Не существует решения для данного максимального числа ходов!</string>
diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml
index 005d637c..3da68a2f 100644
--- a/src/main/res/values-zh-rCN/strings.xml
+++ b/src/main/res/values-zh-rCN/strings.xml
@@ -91,12 +91,13 @@
     <string name="solver_generic_two_centers">必须要交换两个中心！</string>
     <string name="solver_generic_missing_center">%1$s中心不見了！</string>
     <string name="solver_generic_missing_corner">没有%1$s-%2$s-%3$s的角落！</string>
+    <string name="solver_generic_missing_vertex">没有%1$s-%2$s-%3$s八面体！</string>
     <string name="solver_generic_missing_edge">没有1$s-%2$s边！</string>
     <string name="solver_generic_corners_cannot">角不能扭曲，这样所有的面都是单色的！</string>
+    <string name="solver_generic_vertices_cannot">八面体块不能扭曲，所以所有面都是单色的！</string>
 
     <string name="solver_cube3_error1">只有%1$d个%2$s小面</string>
     <string name="solver_cube3_error2">并非所有12条边都只存在一次！</string>
-    <string name="solver_cube3_error3">一条边需要翻转！</string>
     <string name="solver_cube3_error4">并非所有8个角都只存在一次！</string>
     <string name="solver_cube3_error6">两个角或两条边需要交换！</string>
     <string name="solver_cube3_error7">对于给定的最大移动数，没有解决方案！</string>
diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml
index 248ca54e..28bba877 100644
--- a/src/main/res/values-zh-rTW/strings.xml
+++ b/src/main/res/values-zh-rTW/strings.xml
@@ -85,12 +85,13 @@
     <string name="solver_generic_two_centers">兩個中鋒要互換！</string>
     <string name="solver_generic_missing_center">%1$s的中心不见了！</string>
     <string name="solver_generic_missing_corner">沒有%1$s-%2$s-%3$s的角落!</string>
+    <string name="solver_generic_missing_vertex">沒有%1$s-%2$s-%3$s八面體！</string>
     <string name="solver_generic_missing_edge">沒有1$s-%2$s邊！</string>
     <string name="solver_generic_corners_cannot">角不能扭曲，這樣所有的面都是單色的！</string>
+    <string name="solver_generic_vertices_cannot">八面體塊不能扭曲，所以所有面都是單色的！</string>
 
     <string name="solver_cube3_error1">只有%1$d個%2$s小臉</string>
     <string name="solver_cube3_error2">並非所有12條邊都只存在一次！</string>
-    <string name="solver_cube3_error3">一條邊需要翻轉！</string>
     <string name="solver_cube3_error4">並非所有8個角都只存在一次！</string>
     <string name="solver_cube3_error6">兩個角或兩條邊需要交换！</string>
     <string name="solver_cube3_error7">對於给定的最大移動數，没有解决方案！</string>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index dc8dbadb..86b00dc0 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -105,12 +105,13 @@
     <string name="solver_generic_two_centers">Two centers have to be exchanged!</string>
     <string name="solver_generic_missing_center">The %1$s center is missing!</string>
     <string name="solver_generic_missing_corner">The %1$s-%2$s-%3$s corner is missing!</string>
+    <string name="solver_generic_missing_vertex">The %1$s-%2$s-%3$s octahedron piece is missing!</string>
     <string name="solver_generic_missing_edge">The %1$s-%2$s edge is missing!</string>
     <string name="solver_generic_corners_cannot">Corners cannot be twisted so that all faces are monochromatic!</string>
+    <string name="solver_generic_vertices_cannot">Octahedron pieces cannot be twisted so that all faces are monochromatic!</string>
 
     <string name="solver_cube3_error1">There are only %1$d %2$s facelets.</string>
     <string name="solver_cube3_error2">Not all 12 edges exist exactly once!</string>
-    <string name="solver_cube3_error3">One edge has to be flipped!</string>
     <string name="solver_cube3_error4">Not all 8 corners exist exactly once!</string>
     <string name="solver_cube3_error6">Two corners or two edges have to be exchanged!</string>
     <string name="solver_cube3_error7">No solution exists for the given maximum move number!</string>
