/***************************************************************************
                           cubedecoration.cpp
                           -------------------
    copyright            : (C) 2004 by Jos van den Oever
    email                : jos@vandenoever.info
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "cubedecoration.h"

/* An empty cube can be placed on a table in 24 different ways such that you
   cannot tell the difference between any of these placements. If we want to
   know if two cubes are distinguishable, we need to compare all 24 different
   ways of looking at a cube. Only if all of these are different, can we
   distinguish between two cubes. */

/* List of 24 arrays used for comparing cube A to cube B

   Each of the 24 arrays has 6 pairs of numbers. Each pair corresponds to one
   side of a cube.
   Look at array 9. In orientation 0, side 0 of cube A corresponds to side 2 of
   cube B. If the side type or the side symmetry of the sides do not match, the
   sides are not equal. Even if type and symmetry match, the sides need not be
   equal: their orientation has to match too.
   The second number of each pair gives information on how the orientation of
   the side of cube B has to be adjusted to be comparable to the orientaion of
   the corresponding side on cube A.
   In order to compare the orientations, they have to be reduced. For a side
   with symmetry C4, each orientation is equivalent, so an orientation '3' can
   be reduced to '0'. For a side with symmetry C2, an orientation of '3' can
   be reduced to '1'.
*/

//                      0     1     2     3     4     5
const short t00[12] = { 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0};
const short t01[12] = { 0, 1, 3, 1, 1, 1, 4, 1, 2, 1, 5, 3};
const short t02[12] = { 0, 2, 4, 2, 3, 2, 2, 2, 1, 2, 5, 2};
const short t03[12] = { 0, 3, 2, 3, 4, 3, 1, 3, 3, 3, 5, 1};
//                      0     1     2     3     4     5
const short t04[12] = { 1, 0, 5, 0, 2, 3, 3, 1, 0, 0, 4, 0};
const short t05[12] = { 1, 1, 3, 2, 5, 1, 0, 1, 2, 0, 4, 3};
const short t06[12] = { 1, 2, 0, 2, 3, 3, 2, 1, 5, 2, 4, 2};
const short t07[12] = { 1, 3, 2, 2, 0, 3, 5, 3, 3, 0, 4, 1};
//                      0     1     2     3     4     5
const short t08[12] = { 2, 0, 1, 1, 5, 2, 0, 0, 4, 3, 3, 2};
const short t09[12] = { 2, 1, 0, 1, 1, 2, 4, 0, 5, 3, 3, 1};
const short t10[12] = { 2, 2, 4, 1, 0, 2, 5, 0, 1, 3, 3, 0};
const short t11[12] = { 2, 3, 5, 1, 4, 2, 1, 0, 0, 3, 3, 3};
//                      0     1     2     3     4     5
const short t12[12] = { 3, 0, 1, 3, 0, 0, 5, 2, 4, 1, 2, 2};
const short t13[12] = { 3, 1, 5, 3, 1, 0, 4, 2, 0, 1, 2, 1};
const short t14[12] = { 3, 2, 4, 3, 5, 0, 0, 2, 1, 1, 2, 0};
const short t15[12] = { 3, 3, 0, 3, 4, 0, 1, 2, 5, 1, 2, 3};
//                      0     1     2     3     4     5
const short t16[12] = { 4, 0, 0, 0, 2, 1, 3, 3, 5, 0, 1, 0};
const short t17[12] = { 4, 1, 3, 0, 0, 1, 5, 1, 2, 2, 1, 3};
const short t18[12] = { 4, 2, 5, 2, 3, 1, 2, 3, 0, 2, 1, 2};
const short t19[12] = { 4, 3, 2, 0, 5, 3, 0, 3, 3, 2, 1, 1};
//                      0     1     2     3     4     5
const short t20[12] = { 5, 0, 4, 0, 2, 2, 3, 2, 1, 0, 0, 0};
const short t21[12] = { 5, 1, 3, 3, 4, 1, 1, 1, 2, 3, 0, 3};
const short t22[12] = { 5, 2, 1, 2, 3, 0, 2, 0, 4, 2, 0, 2};
const short t23[12] = { 5, 3, 2, 1, 1, 3, 4, 3, 3, 1, 0, 1};

const short *t[24] = {t00, t01, t02, t03, t04, t05, t06, t07, t08, t09,
			t10, t11, t12, t13, t14, t15, t16, t17, t18, t19,
			t20, t21, t22, t23};

/* Function for comparing two cubes. The cubes need to be compared in all 24
   possible orientations, as described above.
   The function return true if the two cubes are equal in at least one
   orientation and false otherwise. */
bool
CubeDecoration::operator==(const CubeDecoration &b) const {
	bool equal = false;
	// loop over all orientations while no orientation has been found in
	// which the cubes are equal
	for (short i=0; !equal && i<24; i++) {
		equal = true;
		// loop over all sides, but stop at the first difference
		for (short j=0; j<6 && equal; j++) {
			equal = type[j] == b.type[t[i][2*j]];
			equal &= sym[j] == b.sym[t[i][2*j]];
			if (sym[j] != C4) {
				// compare the orientations of the sides
				short brot = b.siderot[t[i][2*j]]+t[i][2*j+1];
				if (sym[j] == C1) {
					equal &= siderot[j] == brot%4;
				} else if (sym[j] == C2) {
					equal &= siderot[j] == brot%4
						|| siderot[j] == (brot+2)%4;
				}
			}
		}
	}
	return equal;
}
