the NEW 4x4x4 Rubik's Cube Solver
.................................


CONTENTS:
* COMMAND LINE INTERFACE DOCUMENTATION
* COMPILING
* SOURCE CODE DOCUMENTATION
* CONTACT INFORMATION



COMMAND LINE INTERFACE DOCUMENTATION
....................................


The command-line interface attempts to be simple, but some may still find it a
bit frustrating.  For that reason, I have provided this documentation.

Essentially, to pass a cube to the solver, all you need to have is 6 different
characters to represent each color on the cube, and the correct order to type
them to the solver.  Any 6 characters will work - "1, 2, 3, 4, 5, 6, " if you
are more mathematically inclined, or perhaps "W, G, O, B, R, Y, " if you prefer
something more intuitive and symbolic.  Getting them in the correct order is
also important.  If you get it wrong, the solver will show you what your
diagram looked like so that you can try to get a better understanding of how to
input cubes.
You pass cubes in one of two methods: either all in one string of characters, or
seperated out face by face.  It's generally easier to seperate out the input by
face.
The syntax is like this:
 mcube M:################ M:################ ...
where M: is any of U: D: L: R: F: or B: (not case sensitive) representing the
top, bottom, left, right, front or back faces respectively, and ################
is the string of characters representing the colors on that face.  Examples
below.
If you wish to use the all-in-one-string method, just remember, the order is:
top face, left face, front face, right face, back face, bottom face.
In either case, each face should be inputted from top to bottom, left to right,
like if it was a flattened box.  You just read off the colors in the same order
you read text (English text at least).
Here is an example

If your cube looks like this:

 top      Y R R Y
          W Y R W
          G B Y B
          B G W O
 O O W R  W Y B G  Y Y G G  R B W B
 O O Y Y  R B G B  Y B W W  R O W W
 B B O B  R G O G  R R W R  G G R O
 O G O G  R O R Y  B O O O  W W G W
          W Y Y R
          Y W Y G
          O G R B
 bottom   G Y B B

then the command-line looks like this:

 mcube U:YRRYWYRWGBYBBGWO L:OOWROOYYBBOBOGOG F:WYBGRBGBRGOGRORY R:YYGGYBWWRRWRBOOO B:RBWBROWWGGROWWGW D:WYYRYWYGOGRBGYBB
or the single-string syntax:
 mcube YRRYWYRWGBYBBGWOOOWROOYYBBOBOGOGWYBGRBGBRGOGRORYYYGGYBWWRRWRBOOORBWBROWWGGROWWGWWYYRYWYGOGRBGYBB

  Once you've figured out the somewhat cryptic act of passing a cube to the
solver, you will need to master the even more cryptic action of deciphering the
output.  The solver is designed to be pipable to other programs, so it uses
certain numeric codes to identify what information it is sending.  Those codes
are explained below.
  Between codes 210 and 211 are where the solution is sent.  The solution looks
like a series of tokens representing moves, like this:

210 sending solution:
BC, fA, dR, fC, RD, RD, fC, rU, FC, rU, fA, ...
211 completed solution.

These codes are meant to be somewhat intuitive, although many people find them
confusing at first.  Each 2-letter code has 2 components.  The 1st letter
represents the slice (of which there are 12 different possibilities), and the
2nd letter represents the direction to turn that face (of which there are 6
different possibilities - but each particular slice only has 2 possibilities).

The slices correspond like so (NOTE: they are CASE SENSITIVe):

U -> Top slice
u -> Inner top slice (e.g. 2nd slice from the top -- inner means 2nd row in)
d -> Inner bottom slice
D -> Bottom slice
L -> Left slice
l -> Inner left slice
r -> Inner right slice
R -> Right slice
F -> Front slice
f -> Inner front slice
b -> Inner back slice
B -> Back slice

The directions correspond like so:

L -> rotate slice left (applies to U,u,d,D slices)
R -> rotate slice right (U,u,d,D slices)
U -> rotate slice up (L,l,r,R slices)
D -> rotate slice down (L,l,r,R slices)
C -> rotate slice clockwise (F,f,b,B slices)
A -> rotate slice anticlockwise (F,f,b,B slices)

Thus, the example solution given above would be translated like so:
BC, fA, dR, fC, RD, RD, fC, rU, FC, rU, fA, ...  ->

Back Clockwise,
Inner Front Anticlockwise
Inner Bottom Right
Inner Front Clockwise
Right Down
Right Down
Inner Front Clockwise
Inner Right Up
Front Clockwise
Inner Right Up
Inner Front Anticlockwise

***NOTE***: many people ask me whether BC means rotate the back face clockwise
when looking at it from the back or from the front.  The answer is, rotate it
clockwise when looking from the FRONT.  All the moves assume you are looking at
the cube from the front (not the TOP, nor any other face but the front!!!).  The
front face is in the middle of the "t", not the top; so the diagram corresponds
like so:

       TOP
LEFT   FRONT  RIGHT  BACK
       BOTTOM

*** Update - Aug / 2005: there are now a number of compile-time config options
in the file config.h, and by default, I have enabled it to verbose output with
a keyboard pause every pageful of data.  If you wish to pipe this program and
would rather it use the shorter tokenized syntax without waiting for keypresses,
just edit config.h and recompile.  There are also a few other settings in
config.h that have to do with certain output format settings.

 Finally, all the possible numeric codes are shown below:

101 version %s (%s)                     -> the version of the solver
200 cube solved ok.                     -> successful solve code
201 terminating successfully.           -> successful terminate code
202 %i moves %i groups %i %i %i %i %i %i %i %i %i %i %i     -> information:
                    -> total moves, number of moves groups, number of moves in
                       each group.  Groups are described below.
203 command-line: mcube %s              -> the commandline to generate that
                                           particular solution again.
210 sending solution:                   -> means the next lines will be the
                                           solution
211 completed solution.                 -> means the solution has been
                                           completely sent
220 diagram:                            -> start of visual diagram
221 diagram end.                        -> end of visual diagram
400 syntax:                             -> start of syntax notes (e.g. error)
401 end of notes.                       -> end of syntax notes
500 ERROR: ...                          -> unsuccessful solve code (proceeded by
                                           a specific error code)
501 terminating unsuccessfully.         -> unsuccessful terminate code
502 unexpected error (not used)         -> yeah who knows......
510 non-protocol input...               -> a bad string was sent to the solver
511 not inited (not used)               -> something wrong with cube class!!!
512 incorrect cubelets                  -> most common error:
                    -> means an invalid cube was passed to the solver (probably
                       just made a minor mistake somewhere - check and retry)
513 nondescript (hopefully not used)    -> you found a bug in the solver!
                                           (infinite loop) email me about it.
514 edge flip parity                    -> your cube has an edge flip parity
                                           error (did you reassemble it?)
515 corner rotation parity              -> your cube has a corner rotation
                                           error (did you reassemble it?)
516 backward corner parity              -> your cube has a backward corner
                                           error (mispainted)
517 center swap parity                  -> your cube has swapped centers (did
                                           you reassemble it?) - NOT USED

  Unlike the 3x3x3 solver, Edge swap parity is not an issue in 4x4x4 cubes, due
to the physics of the 4x4x4 cube.  What would be edge swap parity is replaced by
certain restrictions on the ordered placement of the centers.

  It is also important to note that this solver "solves" a cube by making each
face a solid color.  It is not programmed to be able to re-order centers (e.g.,
it may or may not work for novelty "picture" cubes).  In this sense, the
definition of "solved" is ambiguous - since there are 4 of each center, and
those centers can be in any order (as long as they're on the same face), there
are numerous combinations that meet the criterion of "a solid color on each
face," and thus many combinations that are considered "solved."  If you have
insight as to an algorithm to reorder centers, or are just very keen on having
me investigate one, please let me know.

  Also, for informative purposes, the solver breaks a solution down into GROUPS.
A group is what you might consider a "phase" of the solution.  At present there
are 11 groups, in the following order:

1. Top centers
2. Bottom centers
3. Top corners
4. Bottom corners position
5. Bottom corners orient
6. 3/4 of top edge pairs
7. Bottom edge pairs
8. Keyhole top edge pair
9. 2nd layer edges
10. 3rd layer edges
11. Side centers



COMPILING
.........


First, a quick note - the command-line version of the solver has a few compile-
time options which you can #define, located in config.h.  Here's a quick list:
  #define SHOWENDINGDIAGRAM       // whether to show the ending diagram
  #define WAITFORENTERTOEND       // whether to wait for a key when ending
  #define SHOWBADCOMMANDLINE      // whether to regurgitate bad input
These are fairly inconsequential as to the functionality of the solver, but they
do have an effect on the "user interface" (if you want to call it that).

Second, a quick instructions to compile.  It's VERY easy.  All you need is GCC
with C++ (g++) on *nix, or MSVS on Win32 (or you can even probably figure it out
on your own if you don't have any of those - just compile the two .cpp's and
link them together).
on *nix, type (from a console):
  make
on win32, type (from the visual studio command prompt):
  nmake -f makefile.win32
or just use the .sln file...
the output is: mcube (on *nix) or mcube.exe (on win32).

Here's a list of files that should be included:
  config.h          -> compile time config options
  mcube.h           -> cube class header
  mcube.cpp         -> cube class
  main.cpp          -> main UI
  Makefile          -> make script for *nix
  makefile.win32    -> make script for win32
  readme.txt        -> docs (this file)



SOURCE CODE DOCUMENTATION
.........................


Source code documentation (if you want to use the solver in your own programs):

Well the solver class has a lot of things you can do with it... here's a quick
start guide if you feel like (for whatever reason) having a 4x4x4 rubik's cube
solver in your own program.

the solver is in C++ (not C sorry) but can be pretty easily translated to
languages like java or whatever.. For now I'll assume you're using C++.

So, first thing, remember to
 #include "mcube.h"
into your program, and add mcube.cpp to your project files and include mcube.o
(or mcube.obj on win32) into your list of objects during linking.

Now then, you can instantiate a new cube quite simply like this

mcube mycube;

It will automatically reset the new cube in the constructor...
Now that you have mycube, you can do things with it;)

mycube.resetcube(); to reset the cube
  (returns nothing)

mycube.scramblecube(); to scramble the cube model
  (returns nothing)

mycube.solvecube(); to solve the cube
  (returns an int which is the same as mycube.erval)

mycube.issolved(); to see if a cube is solved (see definition of solved below)
  (returns a bool true if solved or false if not..

mycube.UL(); - rotate top left
       UR(); - rotate top right
       DL(); - bottom left
       DR(); - etc...
       LU(); - left up
       LD();
       RU();
       RD();
       FC(); - front clockwise
       FA(); - front counterclockwise
       BC();
       BA();
       uL(); - inner-top left
       uR();
       dL();
       dR();
       lU();
       lD();
       rU();
       rD();
       fC();
       fA();
       bC();
       bA();
       CL(); - whole cube left
       CR();
       CU();
       CD();
       CC();
       CA();
       U2(); - top twice
       D2();
       L2();
       R2();
       F2();
       B2();
       u2();
       d2();
       l2();
       r2();
       f2();
       b2();

Also you can rotate slices with these calls:
mycube.slice_l(x); - rotate slice x left
       slice_r(x); - etc...
       slice_u(x);
       slice_d(x);
       slice_c(x);
       slice_a(x);

more things to do:

mycube.cube[x][y][z] = color;
  -  to repaint a face
*mycube.face(x, y, z) = color;
  - another way to repaint a face

face = mycube.cube[x][y][z];
  -  to read an indidual face
face = *mycube.face(x, y, z);
  - another way to read an individual face

if (mycube == yourcube)
  - an overloaded == (and !=) comparison...

numberofcubes = mycube.numcubes
  - to see how many instantiated cubes there are
numberofcubes = mcube::numcubes
  - another way

mycube.domoves(string s); - to execute a series of moves
  - see notes on string format

mycube.dosolution(); - to execute the solution
  (won't do anything until mycube.solvecube() is called)


Other things in the mcube class (take them or leave them):

string shortersolution = mycube.concise(string s);
  - to strip redundant moves from a string
  (there's an optional second parameter, bool b, which, if true, will affect the
  mov[] array as well)

string usehalfs = mycube.usehalfturns(string s);
  - to change occurances like "LU.LU." to "L2." in a move string
  (like concise, there's an optional second parameter, bool b)

int mycube.erval
  - if there was an error during solvecube() it will be set here

int mycube.warnval
  - if there was a warning during solvecube() it will be set here
  (warnings = possible redundancy bugs)

int mycube.shorten
  - set this to one of the shorten constants to define how much solvecube()
  should try to find shorter solutions...

string mycube.solution
  - a formated string containing the solution for the cube (set by solvecube())

int mycube.fx, fy & fz
  - coordinates for a cubelet set by find* functions

To find a given cubelet, use these functions:

mycube.findcenter_u(int a); find given center on top
       findcenter_d(int a); find given center on bottom
       findcenter_l(int a); etc...
       findcenter_r(int a);
       findcenter_f(int a);
       findcenter_b(int a);
       findcenter_not_u(int a); find given center NOT on top
       findcenter_not_d(int a);
       findcenter_not_l(int a);
       findcenter_not_r(int a);
       findcenter_not_f(int a);
       findcenter_not_b(int a);
       findcenter(int a); - just find the given center anywhere
       find_not_center_u(int a); find center on top that is NOT of given color
       find_not_center_d(int a); etc...
       find_not_center_l(int a);
       find_not_center_r(int a);
       find_not_center_f(int a);
       find_not_center_b(int a);
       findedge_l(int a, int b); find given left edge (NOT to be confused with find given edge on left side)
       findedge_r(int a, int b); find right edge (see notes on edge leftism/rightism)
       findedge(int a, int b); just find either left or right edge
       findcorner_c(int a, int b, int c); find given corner with parameters given in clockwise order
       findcorner_a(int a, int b, int c); find corner with parameters in counterclockwise order
       findcorner(int a, int b, int c); just find the given corner (any order)

string formatting functions -
 there are 3 general formatting notations (described in the notes)

string mcube::std_to_metr(string s)
  converts a "standard" string to "metric"
string mcube::metr_to_std(string s)
  converts a "metric" string to "standard"
string mcube::std_to_rel(string s)
  converts a "standard" string to "relative"
string mcube::rel_to_std(string s)
  converts a "relative" string to "standard"
string mcube::metr_to_rel(string s)
  converts a "metric" string to "relative"
string mcube::rel_to_metr(string s)
  converts a "relative" string to "metric"

If you want your solution broken down by groups -

int totalmoves = mycube.mov[0];
int movesforstep1 = mycube.mov[1];
int movesforstep2 = mycube.mov[2];
  there are a total of mcube::MOV (constant) "steps" or "groups"
  (e.g., solve top centers = group 1, solve bottom centers = group 2,
  solve top corners = group 3, etc...)

class constants:

group 1 - error codes returned by solvecube()

mcube::ERR_NOTINITED
  means you tried to solve an uninitialized cube
mcube::ERR_MISPAINTED
  you tried to solve a mispainted cube
mcube::ERR_NONDESCRIPT
  some problem occured during the solvecube() phase and the solver bailed out to
  prevent an apparent infinite loop (means there's a bug somewhere)
mcube::ERR_PARITY_EDGE_FLIP
  there was an edge flip parity error
mcube::ERR_PARITY_CORNER_ROTATION
  there was a corner rotation parity error
mcube::ERR_PARITY_CORNER_BACKWARD
  there was a backward corner parity error
mcube::ERR_PARITY_CENTER_SWAP
  there was a center swap parity (NOT USED)

group 2 - flags to set mycube.shorten to:

mcube::SHORTEN_NONE
  don't shorten at all
mcube::SHORTEN_STRIP_SOME
  call concise only after each move group
mcube::SHORTEN_STRIP_ALL
  call concise also at the very end of the solution...
mcube::SHORTEN_STRIP_ROTATE_SOME
  strip all + try the solution with every color on top and return shortest
mcube::SHORTEN_STRIP_ROTATE_ALL
  also try each four orientations of each color on top (takes longest time)

group 3 - codes returned by find*()

mcube::NEGX = -1
  negative X axis (left)
mcube::POSX = 1
  positive X axis (right)
mcube::NEGY = -2
  negative Y axis (bottom)
mcube::POSY = 2
  positive Y axis (top)
mcube::NEGZ = -3
  negative Z axis (front/near)
mcube::POSZ = 3
  positive Z axis (back/far)

group 4 - misc

mcube::ITER_THRESHOLD - don't mess with this
  how many times findsolution() should try a certain section of the cube before
  bailing out for an apparent infinite loop

Other miscellaneous class items...

bool mycube.inited - whether the cube has been initialized
  (generally don't need to mess with it.. the constructor, resetcube() and
  scramblecube() will set this to true)

static const char mcube::version - the version of the solver
  if for whatever reason you want to know what version it is...

static const int mcube::N = 4
  the width of the dimensions (e.g., NxNxN).. many of the functions in the
  solver are generalized for any size cube...

void mycube.copytemp(c, t)
  copies the array c into t (where c and t are of size [N+2][N+2][N+2])

and the various macros:

DOMOVES(a, b) - does the sequence of moves (b) and then appends string a with b.
  - for those of you who want it easier when toying with findsolution()...
  (instead of a += "UL.LU."; UL(); LU(); you can just do DOMOVES(a, "UL.LU.");)

GETCORNER_C(a,b,c,x,y,z,f)
  f = findcorner_c(a, b, c); x = fx; y = fy; z = fz
GETCORNER_A(a,b,c,x,y,z,f)
  f = findcorner_a(a, b, c); x = fx; y = fy; z = fz
GETEDGE_L(a,b,x,y,z,f)
  f = findedge_l(a, b); x = fx; y = fy; z = fz
GETEDGE_R(a,b,x,y,z,f)
  f = findedge_r(a, b); x = fx; y = fy; z = fz

and finally, for solidarity, the private class members and methods which you
can't access directly:

string findsolution(); - contains the actual solver algorithm - but note, this
  only works when cube[][][] has been specially prepared (arranged to match a
  specific color scheme), which is why it is private (it is used from within
  solvecube(), which has a lot of code to prepare the cube properly).

Notes:
1. definition of solved: we define solved simply as meaning: a solid color on
   each face, and each of the colors 1-6 used (e.g., a totally white cube is not
   solved)
2. overloaded == comparison: this only checks if 2 cubes have the same colors in
   the same position, however if one cube is just the second cube but, say,
   rotated to the left, then the == comparison will return false.
3. edges can be either left or right - parity prevents an edge from moving to
   the opposite edge row without also flipping which makes "left" and "right"
   edges distinctly unique from eachother.
4. formatted strings: the "standard" string notation (used by default) is like
   so: <slice><dir>.
   so for example, "top left, inner back counterclockwise" would look like this:
   "UL.bA."
   the same move in "metric" notation is:
   "4L.3A." (faces DduU=1234, LlrR=1234, FfbB=1234)
   the same move in "relative" notation is:
   "U+.b-." (directions L=+, R=-, D=+, U=-, C=+, A=-)
   also, halfturns ONLY apply to relative or standard strings (in metric it
   would be ambiguous)



CONTACT INFORMATION
...................


Well, I hope that all helped.  If you are still baffled, drop me an email.

 - Eric, root@wrongway.org
