/*
 * @(#)DinoS.c
 *
 * Break ability taken from the X puzzle by Don Bennett, HP Labs
 *
 * Copyright 2010 - 2023  David A. Bagley, bagleyd AT verizon.net
 *
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of the author not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * This program is distributed in the hope that it will be "useful",
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Solver file for Dino */

/* This puzzle is relatively easy as an edge cannot be flipped upsidedown. */
/* There are 2 different orientations possible when solved, red, yellow, */
/* blue in clockwise or counterclockwise order, in orientation mode, the */
/* order of the colors is clockwise. */

/* To swap from one orientation to other
1.  turn 4 non-overlapping corners clockwise (or counterclockwise),
2.  turn the other non-overlapping corners clockwise (or counterclockwise),
3.  repeat steps 1 and 2 now turning counterclockwise (clockwise) */

#include "rngs.h"
#define JMP
#ifdef JMP
#include <setjmp.h> /* longjmp ... interrupt */
#endif
#include "DinoP.h"

static Boolean solvingFlag = False;
#ifdef JMP
static Boolean abortSolvingFlag = False;
static jmp_buf solve_env;

static void
abortSolving(void)
{
	if (solvingFlag)
		abortSolvingFlag = True;
}

#ifdef WINVER
static Boolean
processMessage(UINT msg)
{
	switch (msg) {
	case WM_KEYDOWN:
	case WM_CLOSE:
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
		abortSolving();
		return True;
	default:
		return False;
	}
}
#else
static void
processButton(void /*XButtonEvent *event*/)
{
	abortSolving();
}

static void
processVisibility(XVisibilityEvent *event)
{
	if (event->state != VisibilityUnobscured)
		abortSolving();
}

static void
getNextEvent(DinoWidget w, XEvent *event)
{
	if (!XCheckMaskEvent(XtDisplay(w), VisibilityChangeMask, event))
		(void) XNextEvent(XtDisplay(w), event);
}

static void
processEvent(XEvent *event)
{
	switch(event->type) {
	case KeyPress:
	case ButtonPress:
		processButton(/*&event->xbutton*/);
		break;
	case VisibilityNotify:
		processVisibility(&event->xvisibility);
		break;
	default:
		break;
	}
}

static void
processEvents(DinoWidget w)
{
	XEvent event;

	while (XPending(XtDisplay(w))) {
		getNextEvent(w, &event);
		processEvent(&event);
	}
}
#endif
#endif

static void
movePuzzleCorner(DinoWidget w, int face, int position,
	int direction, int control)
{
#ifdef JMP
#ifdef WINVER
	MSG msg;

	if (PeekMessage(&msg, NULL, 0, 0, 0)) {
		if (!processMessage(msg.message)) {
			if (GetMessage(&msg, NULL, 0, 0))
				DispatchMessage(&msg);
		}
	}
#else
	processEvents(w);
#endif
	if (solvingFlag && abortSolvingFlag)
		longjmp(solve_env, 1);
#endif
#ifdef DEBUG
	(void) printf("movePuzzleCorner %d %d %d %d %d\n", face, position, direction, CORNER, control);
#endif
	movePuzzleDelay(w, face, position, direction, CORNER, control);
}

#define MAX_CORNERS 8
#define MAX_EDGES 12
static int dinoCorner[MAX_CORNERS][3] =
{
	{1, 4, 5},
	{1, 2, 4},
	{0, 1, 5},
	{0, 2, 1},
	{0, 5, 3},
	{3, 5, 4},
	{0, 3, 2},
	{2, 3, 4}
};

#if 0
static int dinoCornerOrient[MAX_CORNERS][3] =
{
	{2, 2, 3},
	{1, 2, 3},
	{3, 3, 2},
	{2, 3, 0},
	{1, 0, 1},
	{1, 2, 0},
	{0, 1, 0},
	{1, 3, 0}
};
#endif

static int dinoEdge[MAX_EDGES][2] =
{
	{4, 5}, {2, 4}, {5, 0}, {0, 2},
	{1, 5}, {1, 2}, {3, 5}, {3, 2},
	{1, 4}, {1, 0}, {3, 4}, {3, 0}
};

static int dinoEdgeOrient[MAX_EDGES][2] =
{
	{2, 0}, {2, 0}, {2, 0}, {2, 0},
	{3, 3}, {1, 3}, {1, 1}, {3, 1},
	{2, 3}, {0, 3}, {2, 1}, {0, 1}
};

/* Corner layout, bits correspond to position
   2 6
 2 3 7 6
 0 1 5 4
   0 4
   2 6
  Edge layout
     2
   9  11
     3
4  5  10  6
     1
   8   7
     0
   4   6
     2
 */

static int
edgeColor(DinoWidget w, int edge, int n)
{
	return w->dino.cubeLoc[dinoEdge[edge][n]][dinoEdgeOrient[edge][n]].face;
}

static int
findCorner(Boolean reverse, int colorFace1, int colorFace2)
{
	int corner, face, i, j;

	if (reverse) {
		i = 2;
		j = 1;
	} else {
		i = 1;
		j = 2;
	}
	for (corner = 0; corner < MAX_CORNERS; corner++) {
		for (face = 0; face < 3; face++) {
			if (dinoCorner[corner][face] == colorFace1 &&
					dinoCorner[corner][(face + i) % 3] == colorFace2) {
				return dinoCorner[corner][(face + j) % 3];
			}
		}
	}
	return -1;
}

static int
getEdgeIndex(int color0, int color1)
{
	int i;

	for (i = 0; i < MAX_EDGES; i++) {
		if ((dinoEdge[i][0] == color0 && dinoEdge[i][1] == color1) ||
				(dinoEdge[i][1] == color0 && dinoEdge[i][0] == color1))
			return i;
	}
	return MAX_EDGES;
}

static int
findEdge(DinoWidget w, int edge)
{
	int i, j, t, count;
	int c[2];

	c[0] = dinoEdge[edge][0];
	c[1] = dinoEdge[edge][1];
	for (i = 0; i < MAX_EDGES; i++) {
		count = 0;
		for (j = 0; j < 2; j++) {
			t = edgeColor(w, i, j);
			if (c[0] == t || c[1] == t)
				count++;
		}
		if (count == 2)
			return i;
	}
	return MAX_EDGES;
}

static void
setFirstEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 5, 0, BL, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 4, 0, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 3:
		movePuzzleCorner(w, 2, 0, BL, FALSE);
		movePuzzleCorner(w, 1, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 4:
		break;
	case 5:
		movePuzzleCorner(w, 1, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 6:
		movePuzzleCorner(w, 5, 1, TL, FALSE);
		movePuzzleCorner(w, 5, 0, BL, FALSE);
		break;
	case 7:
		movePuzzleCorner(w, 2, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 0, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 8:
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 9:
		movePuzzleCorner(w, 1, 0, BR, FALSE);
		movePuzzleCorner(w, 1, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 10:
		movePuzzleCorner(w, 4, 1, BL, FALSE);
		movePuzzleCorner(w, 5, 0, BL, FALSE);
		break;
	case 11:
		movePuzzleCorner(w, 5, 2, TR, FALSE);
		movePuzzleCorner(w, 5, 2, TL, FALSE);
		movePuzzleCorner(w, 5, 1, BL, FALSE);
		break;
	case 2:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
		return;
	}
}

static void
setSecondEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 1, 0, BL, FALSE);
		movePuzzleCorner(w, 1, 3, BR, FALSE);
		movePuzzleCorner(w, 1, 3, TR, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 2, 2, TL, FALSE);
		movePuzzleCorner(w, 1, 1, TL, FALSE);
		break;
	case 3:
		movePuzzleCorner(w, 0, 2, TL, FALSE);
		break;
	case 5:
		movePuzzleCorner(w, 1, 1, TL, FALSE);
		break;
	case 6:
		movePuzzleCorner(w, 0, 3, TR, FALSE);
		movePuzzleCorner(w, 5, 1, BL, FALSE);
		movePuzzleCorner(w, 0, 0, BL, FALSE);
		break;
	case 7:
		movePuzzleCorner(w, 2, 1, TL, FALSE);
		movePuzzleCorner(w, 0, 2, TL, FALSE);
		break;
	case 8:
		movePuzzleCorner(w, 1, 2, TR, FALSE);
		movePuzzleCorner(w, 1, 1, TL, FALSE);
		break;
	case 9:
		break;
	case 10:
		if (NRAND(2) == 0) {
			movePuzzleCorner(w, 4, 1, TL, FALSE);
			movePuzzleCorner(w, 2, 2, TL, FALSE);
			movePuzzleCorner(w, 1, 1, TL, FALSE);
		} else {
			movePuzzleCorner(w, 3, 2, TL, FALSE);
			movePuzzleCorner(w, 2, 1, TL, FALSE);
			movePuzzleCorner(w, 0, 2, TL, FALSE);
		}
		break;
	case 11:
		movePuzzleCorner(w, 0, 1, BL, FALSE);
		movePuzzleCorner(w, 0, 2, TL, FALSE);
		break;
	case 2:
	case 4:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
		return;
	}
}

static void
setThirdEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 5, 1, BL, FALSE);
		movePuzzleCorner(w, 5, 0, BR, FALSE);
		movePuzzleCorner(w, 5, 2, TR, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		movePuzzleCorner(w, 3, 3, TR, FALSE);
		break;
	case 3:
		movePuzzleCorner(w, 0, 2, TR, FALSE);
		break;
	case 5:
		movePuzzleCorner(w, 2, 3, BR, FALSE);
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		movePuzzleCorner(w, 3, 3, TR, FALSE);
		break;
	case 6:
		movePuzzleCorner(w, 3, 1, BL, FALSE);
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		movePuzzleCorner(w, 3, 3, TR, FALSE);
		break;
	case 7:
		movePuzzleCorner(w, 3, 3, TR, FALSE);
		break;
	case 8:
		movePuzzleCorner(w, 4, 3, TR, FALSE);
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		movePuzzleCorner(w, 3, 3, TR, FALSE);
		break;
	case 10:
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		movePuzzleCorner(w, 3, 3, TR, FALSE);
		break;
	case 11:
		break;
	case 2:
	case 4:
	case 9:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
		return;
	}
}

static void
setForthEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 4, 2, TR, FALSE);
		movePuzzleCorner(w, 2, 0, BR, FALSE);
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		movePuzzleCorner(w, 2, 1, TL, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 2, 0, BR, FALSE);
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		movePuzzleCorner(w, 2, 1, TL, FALSE);
		break;
	case 3:
		break;
	case 5:
		movePuzzleCorner(w, 2, 3, BR, FALSE);
		movePuzzleCorner(w, 2, 0, BL, FALSE);
		movePuzzleCorner(w, 2, 2, TL, FALSE);
		movePuzzleCorner(w, 2, 3, TR, FALSE);
		break;
	case 6:
		movePuzzleCorner(w, 3, 1, BL, FALSE);
		movePuzzleCorner(w, 2, 0, BR, FALSE);
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		movePuzzleCorner(w, 2, 1, TL, FALSE);
		break;
	case 7:
		movePuzzleCorner(w, 2, 1, BL, FALSE);
		movePuzzleCorner(w, 2, 0, BR, FALSE);
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		movePuzzleCorner(w, 2, 1, TL, FALSE);
		break;
	case 8:
		movePuzzleCorner(w, 2, 0, BL, FALSE);
		movePuzzleCorner(w, 1, 2, TR, FALSE);
		movePuzzleCorner(w, 2, 3, TR, FALSE);
		break;
	case 10:
		movePuzzleCorner(w, 2, 0, BR, FALSE);
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		movePuzzleCorner(w, 2, 1, TL, FALSE);
		break;
	case 2:
	case 4:
	case 9:
	case 11:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
	}
}

static void
setFifthEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 4, 2, TR, FALSE);
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		break;
	case 5:
		movePuzzleCorner(w, 2, 3, BR, FALSE);
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		break;
	case 6:
		movePuzzleCorner(w, 3, 1, BL, FALSE);
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		break;
	case 7:
		break;
	case 8:
		movePuzzleCorner(w, 4, 3, TR, FALSE);
		movePuzzleCorner(w, 2, 2, TR, FALSE);
		break;
	case 10:
		movePuzzleCorner(w, 3, 2, TL, FALSE);
		break;
	case 2:
	case 3:
	case 4:
	case 9:
	case 11:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
	}
}

static void
setSixthEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		movePuzzleCorner(w, 4, 0, BL, FALSE);
		movePuzzleCorner(w, 4, 3, BR, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 2, 2, TL, FALSE);
		break;
	case 5:
		break;
	case 6:
		movePuzzleCorner(w, 3, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 1, TL, FALSE);
		movePuzzleCorner(w, 2, 2, TL, FALSE);
		movePuzzleCorner(w, 4, 0, BR, FALSE);
		break;
	case 8:
		movePuzzleCorner(w, 4, 0, BL, FALSE);
		break;
	case 10:
		movePuzzleCorner(w, 4, 1, TL, FALSE);
		movePuzzleCorner(w, 2, 2, TL, FALSE);
		movePuzzleCorner(w, 4, 0, BR, FALSE);
		break;
	case 2:
	case 3:
	case 4:
	case 7:
	case 9:
	case 11:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
	}
}

static void
setSeventhEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 4, 2, TR, FALSE);
		movePuzzleCorner(w, 4, 3, BR, FALSE);
		movePuzzleCorner(w, 4, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 1:
		movePuzzleCorner(w, 4, 1, TL, FALSE);
		movePuzzleCorner(w, 4, 3, TR, FALSE);
		movePuzzleCorner(w, 4, 0, BR, FALSE);
		movePuzzleCorner(w, 4, 0, BL, FALSE);
		break;
	case 6:
		movePuzzleCorner(w, 5, 0, BL, FALSE);
		movePuzzleCorner(w, 5, 1, TL, FALSE);
		movePuzzleCorner(w, 5, 3, TR, FALSE);
		break;
	case 8:
		break;
	case 10:
		movePuzzleCorner(w, 4, 3, BR, FALSE);
		movePuzzleCorner(w, 4, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 2, TL, FALSE);
		break;
	case 2:
	case 3:
	case 4:
	case 5:
	case 7:
	case 9:
	case 11:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
	}
}

static void
setEighthEdge(DinoWidget w, int i)
{
	int e = findEdge(w, i);

#if DEBUG
	(void) printf("nextEdge %d, (%d)\n", e, i);
#endif
	switch (e) {
	case 0:
		movePuzzleCorner(w, 4, 0, BR, FALSE);
		movePuzzleCorner(w, 4, 2, TR, FALSE);
		movePuzzleCorner(w, 4, 1, TL, FALSE);
		break;
	case 1:
		break;
	case 6:
		movePuzzleCorner(w, 4, 0, BR, FALSE);
		movePuzzleCorner(w, 4, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 1, TL, FALSE);
		break;
	case 10:
		movePuzzleCorner(w, 4, 1, BL, FALSE);
		movePuzzleCorner(w, 4, 0, BR, FALSE);
		movePuzzleCorner(w, 4, 2, TR, FALSE);
		movePuzzleCorner(w, 4, 1, TL, FALSE);
		break;
	case 2:
	case 3:
	case 4:
	case 5:
	case 7:
	case 8:
	case 9:
	case 11:
	default:
		if (w->dino.mode != BOTH)
			(void) printf("Wrong edge %d\n", e);
	}
}

static void
setLastEdges(DinoWidget w)
{
	int f;

	movePuzzleCorner(w, 0, 1, TL, TRUE);
	f = w->dino.cubeLoc[0][0].face;
	if (w->dino.cubeLoc[0][1].face == f) {
		return;
	} else if (w->dino.cubeLoc[2][0].face == f) {
		movePuzzleCorner(w, 2, 1, TL, FALSE);
	} else {
		movePuzzleCorner(w, 0, 1, BL, FALSE);
	}
}

/* This solves red, yellow, blue in clockwise order unless reverse. */
static void
solveEdges(DinoWidget w)
{
	int faces[6];
	Boolean reverse = (w->dino.orient) ? False : (NRAND(2) == 0);

	faces[5] = w->dino.cubeLoc[5][2].face;
	faces[0] = w->dino.cubeLoc[0][0].face;
	faces[1] = findCorner(reverse, faces[5], faces[0]);
#ifdef DEBUG
	(void) printf("zeroethEdge %d %d %d\n", faces[5], faces[0], faces[1]);
#endif
	if (faces[1] < 0) {
		if (w->dino.mode != BOTH)
			(void) printf("Wrong face %d\n", faces[1]);
		return;
	}
	setFirstEdge(w, getEdgeIndex(faces[1], faces[5]));
	setSecondEdge(w, getEdgeIndex(faces[0], faces[1]));
	faces[3] = findCorner(reverse, faces[0], faces[5]);
	if (faces[3] < 0) {
		if (w->dino.mode != BOTH)
			(void) printf("Wrong face %d\n", faces[3]);
		return;
	}
	setThirdEdge(w, getEdgeIndex(faces[0], faces[3]));
	faces[2] = findCorner(reverse, faces[1], faces[0]);
	if (faces[2] < 0) {
		if (w->dino.mode != BOTH)
			(void) printf("Wrong face %d\n", faces[2]);
		return;
	}
	setForthEdge(w, getEdgeIndex(faces[0], faces[2]));
	setFifthEdge(w, getEdgeIndex(faces[2], faces[3]));
	setSixthEdge(w, getEdgeIndex(faces[1], faces[2]));
	faces[4] = findCorner(reverse, faces[1], faces[2]);
	if (faces[4] < 0) {
		if (w->dino.mode != BOTH)
			(void) printf("Wrong face %d\n", faces[4]);
		return;
	}
	setSeventhEdge(w, getEdgeIndex(faces[1], faces[4]));
	setEighthEdge(w, getEdgeIndex(faces[2], faces[4]));
	setLastEdges(w);
}

static int dinoFace[MAX_FACES][MAX_ORIENT] =
{
	{5, 3, 2, 1},
	{0, 2, 4, 5},
	{0, 3, 4, 1},
	{0, 5, 4, 2},
	{2, 3, 5, 1},
	{4, 3, 0, 1}
};

static int dinoFaceOrient[MAX_FACES][MAX_ORIENT] =
{
	{0, 1, 0, 1},
	{1, 0, 3, 2},
	{0, 0, 0, 0},
	{3, 2, 1, 0},
	{0, 3, 0, 3},
	{0, 2, 0, 2}
};

static void
movePuzzleEdge(DinoWidget w, int face, int position,
	int direction, int control)
{
#ifdef JMP
#ifdef WINVER
	MSG msg;

	if (PeekMessage(&msg, NULL, 0, 0, 0)) {
		if (!processMessage(msg.message)) {
			if (GetMessage(&msg, NULL, 0, 0))
				DispatchMessage(&msg);
		}
	}
#else
	processEvents(w);
#endif
	if (solvingFlag && abortSolvingFlag)
		longjmp(solve_env, 1);
#endif
#ifdef DEBUG
	(void) printf("movePuzzleEdge %d %d %d %d %d\n", face, position, direction, EDGE, control);
#endif
	movePuzzleDelay(w, face, position, direction, EDGE, control);
}

static void
movePuzzleFace(DinoWidget w, int face, int position,
	int direction, int control)
{
#ifdef JMP
#ifdef WINVER
	MSG msg;

	if (PeekMessage(&msg, NULL, 0, 0, 0)) {
		if (!processMessage(msg.message)) {
			if (GetMessage(&msg, NULL, 0, 0))
				DispatchMessage(&msg);
		}
	}
#else
	processEvents(w);
#endif
	if (solvingFlag && abortSolvingFlag)
		longjmp(solve_env, 1);
#endif
#ifdef DEBUG
	(void) printf("movePuzzleFace %d %d %d %d %d\n", face, position, direction, FACE, control);
#endif
	movePuzzleDelay(w, face, position, direction, FACE, control);
}
#ifdef DEBUG
static int position[MAX_ORIENT][2];

static void
findFacets(DinoWidget w, int colorFace)
{
	int face, edge, i = 0;

	for (edge = 0; edge < MAX_ORIENT; edge++) {
		position[edge][0] = -1;
		position[edge][1] = -1;
	}
	for (face = 0; face < MAX_FACES; face++) {
		for (edge = 0; edge < MAX_ORIENT; edge++) {
			if (colorFace == w->dino.cubeLoc[face][edge].face) {
				position[i][0] = face;
				position[i][1] = edge;
				i++;
			}
			if (i == MAX_ORIENT)
				return;
		}
	}
}

static void
printPosition(void)
{
	int edge;
	for (edge = 0; edge < MAX_ORIENT; edge++) {
		(void) printf("face %d, position %d\n",
			position[edge][0], position[edge][1]);
	}
}
#endif

static void
flipFace(DinoWidget w, int face)
{
	int i;
	for (i = 0; i < 14; i++) {
		movePuzzleEdge(w, dinoFace[face][0],
			(dinoFaceOrient[face][0] + 1) % 4,
			(dinoFaceOrient[face][0] + BL) % 4, FALSE);
		movePuzzleEdge(w, face, 0, BR, FALSE);
		movePuzzleEdge(w, dinoFace[face][1],
			(dinoFaceOrient[face][1] + 3) % 4,
			(dinoFaceOrient[face][1] + TR) % 4, FALSE);
	}
}

/* equivalent to a movePuzzleCorner,
   so BOTH mode does not make puzzle harder, 28 moves */
static void
turnCorner(DinoWidget w, int face, int position, int direction)
{
	int i;

	if (w->dino.mode == BOTH) {
		movePuzzleCorner(w, face, position, direction, FALSE);
		return;
	}
	switch (direction) {
	case 0:
		switch (position) {
		case 0:
		case 3:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, face, 0, BL, FALSE);
				movePuzzleEdge(w, dinoFace[face][0],
					dinoFaceOrient[face][0],
					(dinoFaceOrient[face][0] + BL) % 4, FALSE);
				movePuzzleEdge(w, face, 3, BR, FALSE);
				movePuzzleEdge(w, dinoFace[face][2],
					dinoFaceOrient[face][2],
					(dinoFaceOrient[face][2] + BL) % 4, FALSE);
			}
			break;
		case 1:
		case 2:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, dinoFace[face][2],
					(dinoFaceOrient[face][2] + 1) % 4,
					(dinoFaceOrient[face][2] + TL) % 4, FALSE);
				movePuzzleEdge(w, face, 1, TL, FALSE);
				movePuzzleEdge(w, dinoFace[face][0],
					(dinoFaceOrient[face][0] + 1) % 4,
					(dinoFaceOrient[face][0] + TL) % 4, FALSE);
				movePuzzleEdge(w, face, 2, TR, FALSE);
			}
			break;
		}
		break;
	case 1:
		switch (position) {
		case 0:
		case 1:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, dinoFace[face][2],
					dinoFaceOrient[face][2],
					(dinoFaceOrient[face][2] + BR) % 4, FALSE);
				movePuzzleEdge(w, face, 1, BL, FALSE);
				movePuzzleEdge(w, dinoFace[face][0],
					dinoFaceOrient[face][0],
					(dinoFaceOrient[face][0] + BR) % 4, FALSE);
				movePuzzleEdge(w, face, 0, BR, FALSE);
			}
			break;
		case 2:
		case 3:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, face, 3, BR, FALSE);
				movePuzzleEdge(w, dinoFace[face][2],
					(dinoFaceOrient[face][2] + 3) % 4,
					(dinoFaceOrient[face][2] + BR) % 4, FALSE);
				movePuzzleEdge(w, face, 3, BL, FALSE);
				movePuzzleEdge(w, dinoFace[face][2],
					(dinoFaceOrient[face][2] + 3) % 4,
					(dinoFaceOrient[face][2] + BL) % 4, FALSE);
			}
			break;
		}
		break;
	case 2:
		switch (position) {
		case 0:
		case 3:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, dinoFace[face][2],
					dinoFaceOrient[face][2],
					(dinoFaceOrient[face][2] + BL) % 4, FALSE);
				movePuzzleEdge(w, face, 3, BR, FALSE);
				movePuzzleEdge(w, dinoFace[face][0],
					dinoFaceOrient[face][0],
					(dinoFaceOrient[face][0] + BL) % 4, FALSE);
				movePuzzleEdge(w, face, 0, BL, FALSE);
			}
			break;
		case 1:
		case 2:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, face, 2, TR, FALSE);
				movePuzzleEdge(w, dinoFace[face][0],
					(dinoFaceOrient[face][0] + 1) % 4,
					(dinoFaceOrient[face][0] + TL) % 4, FALSE);
				movePuzzleEdge(w, face, 1, TL, FALSE);
				movePuzzleEdge(w, dinoFace[face][2],
					(dinoFaceOrient[face][2] + 1) % 4,
					(dinoFaceOrient[face][2] + TL) % 4, FALSE);
			}
			break;
		}
		break;
	case 3:
		switch (position) {
		case 0:
		case 1:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, face, 0, BR, FALSE);
				movePuzzleEdge(w, dinoFace[face][0],
					dinoFaceOrient[face][0],
					(dinoFaceOrient[face][0] + BR) % 4, FALSE);
				movePuzzleEdge(w, face, 1, BL, FALSE);
				movePuzzleEdge(w, dinoFace[face][2],
					dinoFaceOrient[face][2],
					(dinoFaceOrient[face][2] + BR) % 4, FALSE);
			}
			break;
		case 2:
		case 3:
			for (i = 0; i < 7; i++) {
				movePuzzleEdge(w, dinoFace[face][2],
					(dinoFaceOrient[face][2] + 3) % 4,
					(dinoFaceOrient[face][2] + BL) % 4, FALSE);
				movePuzzleEdge(w, face, 3, BL, FALSE);
				movePuzzleEdge(w, dinoFace[face][2],
					(dinoFaceOrient[face][2] + 3) % 4,
					(dinoFaceOrient[face][2] + BR) % 4, FALSE);
				movePuzzleEdge(w, face, 3, BR, FALSE);
			}
			break;
		}
		break;
	}
}

/* face and position of lone changed piece, next piece CW or CCW to that,
  repeat 4 times so no orientation change, 24 or 192 moves */
static void
oppSwap(DinoWidget w, int face, int position, int direction,
		Boolean repeat)
{
	int i;
	switch (direction) {
	case CW:
		switch (face) {
		case 0:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);

					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);

					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);

					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);

					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);

					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);

					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);

					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);

					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);

					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);

					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
				}
				break;
			}
			break;
		case 1:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);

					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);

					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);

					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);

					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);

					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);

					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);

					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);

					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
				}
				break;
			}
			break;
		case 2:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);

					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);

					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);

					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);

					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);

					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);

					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);

					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);

					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);

					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);

					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
				}
				break;
			}
			break;
		case 3:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);

					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);

					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);

					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);

					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);

					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);

					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);

					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);

					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
				}
				break;
			}
			break;
		case 4:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);

					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);

					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);

					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);

					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);

					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);

					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);

					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);

					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);

					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);

					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
				}
				break;
			}
			break;
		case 5:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);

					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);

					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);

					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);

					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);

					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);

					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);

					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);

					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);

					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);

					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
				}
				break;
			}
			break;
		}
		break;
	case CCW:
		switch (face) {
		case 0:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);

					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);

					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);

					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);

					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);

					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);

					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);

					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);

					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);

					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);

					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
				}
				break;
			}
			break;
		case 1:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);

					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);

					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);

					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);

					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);

					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);

					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);

					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);

					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);

					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
				}
				break;
			}
			break;
		case 2:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);

					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);

					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);

					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);

					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);

					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);

					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);

					movePuzzleEdge(w, 2, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);

					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);

					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);

					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
				}
				break;
			}
			break;
		case 3:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);

					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);

					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 2, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);

					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);

					movePuzzleEdge(w, 2, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 3, BR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);

					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);

					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);

					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);

					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, BR, FALSE);
					movePuzzleEdge(w, 0, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);

					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
				}
				break;
			}
			break;
		case 4:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);

					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);

					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);

					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);

					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);

					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 2, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);

					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);

					movePuzzleEdge(w, 4, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);

					movePuzzleEdge(w, 2, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 2, 0, TR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 4, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);

					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);

					movePuzzleEdge(w, 4, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 0, TR, FALSE);
					movePuzzleEdge(w, 4, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 0, BR, FALSE);
				}
				break;
			}
			break;
		case 5:
			switch (position) {
			case 0:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);

					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);

					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);

					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
				}
				break;
			case 1:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);

					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);

					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);

					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
				}
				break;
			case 2:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 2, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 4, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);

					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);

					movePuzzleEdge(w, 5, 2, BR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 3, TR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 2, TR, FALSE);

					movePuzzleEdge(w, 4, 0, TR, FALSE);
					movePuzzleEdge(w, 1, 1, BR, FALSE);
					movePuzzleEdge(w, 1, 1, TR, FALSE);
					movePuzzleEdge(w, 4, 0, BR, FALSE);
					movePuzzleEdge(w, 5, 0, BR, FALSE);
					movePuzzleEdge(w, 4, 0, TR, FALSE);
				}
				break;
			case 3:
				for (i = 0; i < ((repeat) ? 8 : 2); i++) {
					movePuzzleEdge(w, 5, 3, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);

					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);

					movePuzzleEdge(w, 5, 3, BR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 5, 1, TR, FALSE);
					movePuzzleEdge(w, 0, 0, TR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 5, 3, TR, FALSE);

					movePuzzleEdge(w, 3, 3, TR, FALSE);
					movePuzzleEdge(w, 0, 2, BR, FALSE);
					movePuzzleEdge(w, 0, 2, TR, FALSE);
					movePuzzleEdge(w, 3, 3, BR, FALSE);
					movePuzzleEdge(w, 5, 1, BR, FALSE);
					movePuzzleEdge(w, 3, 3, TR, FALSE);
				}
				break;
			}
			break;
		}
		break;
	}
}

/* 6 moves + 1 control move */
static void
swapAdjFaces(DinoWidget w, int face0, int face1)
{
	if ((face0 == 0 && face1 == 1) ||
			(face0 == 1 && face1 == 0)) {
		movePuzzleEdge(w, 2, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, FALSE);
		movePuzzleEdge(w, 0, 0, BR, FALSE);
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, FALSE);
		movePuzzleEdge(w, 1, 0, BR, FALSE);
		movePuzzleEdge(w, 0, 0, BR, TRUE);
	} else if ((face0 == 0 && face1 == 2) ||
			(face0 == 2 && face1 == 0)) {
		movePuzzleEdge(w, 1, 0, BR, FALSE);
		movePuzzleEdge(w, 1, 0, TR, FALSE);
		movePuzzleEdge(w, 5, 2, BR, FALSE);
		movePuzzleEdge(w, 5, 2, TR, FALSE);
		movePuzzleEdge(w, 5, 0, BR, FALSE);
		movePuzzleEdge(w, 4, 0, TR, FALSE);
		movePuzzleEdge(w, 5, 2, BR, TRUE);
	} else if ((face0 == 0 && face1 == 3) ||
			(face0 == 3 && face1 == 0)) {
		movePuzzleEdge(w, 2, 0, BR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 0, 0, TR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, FALSE);
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 0, BR, FALSE);
		movePuzzleEdge(w, 0, 0, TR, TRUE);
	} else if ((face0 == 0 && face1 == 5) ||
			(face0 == 5 && face1 == 0)) {
		movePuzzleEdge(w, 1, 3, TR, FALSE);
		movePuzzleEdge(w, 1, 3, BR, FALSE);
		movePuzzleEdge(w, 4, 2, BR, FALSE);
		movePuzzleEdge(w, 4, 2, TR, FALSE);
		movePuzzleEdge(w, 4, 0, BR, FALSE);
		movePuzzleEdge(w, 2, 0, TR, FALSE);
		movePuzzleEdge(w, 4, 2, BR, TRUE);
	} else if ((face0 == 1 && face1 == 2) ||
			(face0 == 2 && face1 == 1)) {
		movePuzzleEdge(w, 0, 2, BR, FALSE);
		movePuzzleEdge(w, 0, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 0, BR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 0, BR, TRUE);
	} else if ((face0 == 1 && face1 == 4) ||
			(face0 == 4 && face1 == 1)) {
		movePuzzleEdge(w, 5, 0, TR, FALSE);
		movePuzzleEdge(w, 5, 2, BR, FALSE);
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 0, 0, BR, FALSE);
		movePuzzleEdge(w, 0, 0, TR, FALSE);
		movePuzzleEdge(w, 1, 3, BR, FALSE);
		movePuzzleEdge(w, 0, 2, TR, TRUE);
	} else if ((face0 == 1 && face1 == 5) ||
			(face0 == 5 && face1 == 1)) {
		movePuzzleEdge(w, 0, 0, TR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 0, BR, FALSE);
		movePuzzleEdge(w, 2, 0, TR, FALSE);
		movePuzzleEdge(w, 1, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, TRUE);
	} else if ((face0 == 2 && face1 == 3) ||
			(face0 == 3 && face1 == 2)) {
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 0, 0, BR, FALSE);
		movePuzzleEdge(w, 2, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 0, TR, TRUE);
	} else if ((face0 == 2 && face1 == 4) ||
			(face0 == 4 && face1 == 2)) {
		movePuzzleEdge(w, 1, 1, TR, FALSE);
		movePuzzleEdge(w, 1, 1, BR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, FALSE);
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 0, 0, BR, FALSE);
		movePuzzleEdge(w, 5, 0, TR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, TRUE);
	} else if ((face0 == 3 && face1 == 4) ||
			(face0 == 4 && face1 == 3)) {
		movePuzzleEdge(w, 5, 0, BR, FALSE);
		movePuzzleEdge(w, 5, 2, TR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, FALSE);
		movePuzzleEdge(w, 0, 0, TR, FALSE);
		movePuzzleEdge(w, 0, 0, BR, FALSE);
		movePuzzleEdge(w, 3, 1, TR, FALSE);
		movePuzzleEdge(w, 0, 2, BR, TRUE);
	} else if ((face0 == 3 && face1 == 5) ||
			(face0 == 5 && face1 == 3)) {
		movePuzzleEdge(w, 0, 0, BR, FALSE);
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, FALSE);
		movePuzzleEdge(w, 2, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 0, BR, FALSE);
		movePuzzleEdge(w, 1, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, TRUE);
	} else if ((face0 == 4 && face1 == 5) ||
			(face0 == 5 && face1 == 4)) {
		movePuzzleEdge(w, 1, 2, BR, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 0, BR, FALSE);
		movePuzzleEdge(w, 0, 0, TR, FALSE);
		movePuzzleEdge(w, 2, 2, BR, TRUE);
	}
}

static void
rotatePairs(DinoWidget w, int face0, int face1)
{
	switch (face0) {
	case 0:
		switch(face1) {
		case 1:
			/* CCW */
			swapAdjFaces(w, 2, 3);
			swapAdjFaces(w, 3, 4);
			swapAdjFaces(w, 2, 4);
			swapAdjFaces(w, 3, 4);
			break;
		case 3:
			/* CW */
			swapAdjFaces(w, 1, 2);
			swapAdjFaces(w, 1, 4);
			swapAdjFaces(w, 2, 4);
			swapAdjFaces(w, 1, 4);
			break;
		}
		break;
	case 1:
		switch(face1) {
		case 4:
			/* CW */
			swapAdjFaces(w, 2, 3);
			swapAdjFaces(w, 0, 3);
			swapAdjFaces(w, 0, 2);
			swapAdjFaces(w, 0, 3);
			break;
		}
		break;
	case 3:
		switch(face1) {
		case 4:
			/* CCW */
			swapAdjFaces(w, 1, 2);
			swapAdjFaces(w, 0, 1);
			swapAdjFaces(w, 0, 2);
			swapAdjFaces(w, 0, 1);
			break;
		}
		break;
	}
}

static void
balancedRotate(DinoWidget w) {
	int i;
	for (i = 0; i< 5; i++) {
		movePuzzleEdge(w, 2, 0, TL, FALSE);
		movePuzzleEdge(w, 0, 1, TR, FALSE);
		movePuzzleEdge(w, 3, 3, BL, FALSE);
		movePuzzleEdge(w, 2, 3, TR, FALSE);
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 0, BR, FALSE);
	}
}

static void
flipLR(DinoWidget w, int face)
{
	movePuzzleEdge(w, face, 0, TR, FALSE);
	movePuzzleEdge(w, face, 0, TL, FALSE);
	movePuzzleEdge(w, face, 0, TR, FALSE);
}

#if 0
static void
flipTB(DinoWidget w, int face)
{
	movePuzzleEdge(w, face, 1, TR, FALSE);
	movePuzzleEdge(w, face, 1, BR, FALSE);
	movePuzzleEdge(w, face, 1, TR, FALSE);
}

static void
adjacentSplit40(DinoWidget w, int face)
{
	int i;
	for (i = 0; i < 40; i++) {
		movePuzzleEdge(w, dinoFace[face][0],
			dinoFaceOrient[face][0],
			(dinoFaceOrient[face][0] + TR) % 4, FALSE);
		movePuzzleEdge(w, 5, 0, TR, FALSE);
		movePuzzleEdge(w, dinoFace[face][0],
			(dinoFaceOrient[face][0] + 3) % 4,
			(dinoFaceOrient[face][0] + TL) % 4, FALSE);
		movePuzzleEdge(w, dinoFace[face][0],
			(dinoFaceOrient[face][0] + 1) % 4,
			(dinoFaceOrient[face][0] + BL) % 4, FALSE);
		movePuzzleEdge(w, 5, 0, BR, FALSE);
		movePuzzleEdge(w, dinoFace[face][0],
			dinoFaceOrient[face][0],
			(dinoFaceOrient[face][0] + BR) % 4, FALSE);
	}
}

static void
adjacentSplit(DinoWidget w, int face)
{
	int i;
	for (i = 0; i < 3; i++) {
		movePuzzleEdge(w, face, 1, BL, FALSE);
		movePuzzleEdge(w, face, 0, BR, FALSE);
		movePuzzleEdge(w, dinoFace[face][0],
			dinoFaceOrient[face][0],
			(dinoFaceOrient[face][0] + BR) % 4, FALSE);
		if (i == 2)
			break;
		movePuzzleEdge(w, face, 0, BR, FALSE);
	}
}

static void
spinOut(DinoWidget w, int face)
{
	int i, j;
	for (i = 0; i < 2; i++) {
		for (j = 0; j < 2; j++) {
			movePuzzleEdge(w, dinoFace[face][0],
				(dinoFaceOrient[face][0] + 3) % 4,
				(dinoFaceOrient[face][0] + BR) % 4, FALSE);
			movePuzzleEdge(w, dinoFace[face][3],
				dinoFaceOrient[face][3],
				(dinoFaceOrient[face][3] + BR) % 4, FALSE);
		}
		for (j = 0; j < 2; j++) {
			movePuzzleEdge(w, dinoFace[face][1],
				(dinoFaceOrient[face][1] + 2) % 4,
				(dinoFaceOrient[face][1] + TL) % 4, FALSE);
			movePuzzleEdge(w, dinoFace[face][2],
				(dinoFaceOrient[face][2] + 1) % 4,
				(dinoFaceOrient[face][2] + TL) % 4, FALSE);
		}
	}
}

static void
fiveOut(DinoWidget w, int face)
{
	int i;
	for (i = 0; i < 10; i++) {
		movePuzzleEdge(w, dinoFace[face][0],
			(dinoFaceOrient[face][0] + 3) % 4,
			(dinoFaceOrient[face][0] + BR) % 4, FALSE);
		movePuzzleEdge(w, face, 0, BR, FALSE);
		movePuzzleEdge(w, dinoFace[face][2],
			dinoFaceOrient[face][2],
			(dinoFaceOrient[face][2] + BR) % 4, FALSE);
	}
}

static void
turnCube(DinoWidget w, int face)
{
	movePuzzleEdge(w, face, 2, TL, FALSE);
	movePuzzleEdge(w, dinoFace[face][2],
		dinoFaceOrient[face][2],
		(dinoFaceOrient[face][2] + BL) % 4, FALSE);
	movePuzzleEdge(w, dinoFace[face][0],
		(dinoFaceOrient[face][0] + 1) % 4,
		(dinoFaceOrient[face][0] + TL) % 4, FALSE);
	movePuzzleEdge(w, dinoFace[face][3],
		(dinoFaceOrient[face][3] + 2) % 4,
		(dinoFaceOrient[face][3] + TL) % 4, FALSE);
}
#endif

/* first part of oppSwap(0, 0, CW), result similar to oppSwap(4, 2, CW) */
static void
topFaceFromRightSide(DinoWidget w)
{
	movePuzzleEdge(w, 0, 0, BR, FALSE);
	movePuzzleEdge(w, 2, 2, TR, FALSE);
	movePuzzleEdge(w, 0, 0, TR, FALSE);
	movePuzzleEdge(w, 2, 0, BR, FALSE);
	movePuzzleEdge(w, 0, 2, BR, FALSE);
	movePuzzleEdge(w, 0, 2, TR, FALSE);

	movePuzzleEdge(w, 1, 2, BR, FALSE);
	movePuzzleEdge(w, 2, 2, TR, FALSE);
	movePuzzleEdge(w, 2, 2, BR, FALSE);
	movePuzzleEdge(w, 1, 2, TR, FALSE);
	movePuzzleEdge(w, 0, 2, BR, FALSE);
	movePuzzleEdge(w, 1, 2, BR, FALSE);
}

/* first part of oppSwap(0, 0, CCW), result similar to oppSwap(4, 2, CCW) */
static void
topFaceFromLeftSide(DinoWidget w)
{
	movePuzzleEdge(w, 0, 0, TR, FALSE);
	movePuzzleEdge(w, 2, 2, BR, FALSE);
	movePuzzleEdge(w, 0, 0, BR, FALSE);
	movePuzzleEdge(w, 2, 0, TR, FALSE);
	movePuzzleEdge(w, 0, 2, TR, FALSE);
	movePuzzleEdge(w, 0, 2, BR, FALSE);

	movePuzzleEdge(w, 3, 2, TR, FALSE);
	movePuzzleEdge(w, 2, 2, BR, FALSE);
	movePuzzleEdge(w, 2, 2, TR, FALSE);
	movePuzzleEdge(w, 3, 2, BR, FALSE);
	movePuzzleEdge(w, 0, 2, TR, FALSE);
	movePuzzleEdge(w, 3, 2, TR, FALSE);
}

static void
setFace0Pos1(DinoWidget w, int color)
{
	int face = 0;
	int pos = 1;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[4][0].face == color) {
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[0][3].face == color) {
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[1][3].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[1][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][3].face == color) {
		movePuzzleEdge(w, 0, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[1][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][0].face == color) {
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[0][2].face == color) {
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[1][0].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace0Pos3(DinoWidget w, int color)
{
	int face = 0;
	int pos = 3;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[4][0].face == color) {
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[1][3].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[1][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[1][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[0][2].face == color) {
		movePuzzleEdge(w, 0, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[1][0].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][0].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace0Pos2(DinoWidget w, int color)
{
	int face = 0;
	int pos = 2;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[4][1].face == color) {
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[1][0].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[1][2].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[2][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[1][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[1][3].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		topFaceFromLeftSide(w);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[2][0].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TL, FALSE);
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		topFaceFromRightSide(w);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace1Pos3(DinoWidget w, int color)
{
	int face = 1;
	int pos = 3;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[3][2].face == color) {
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[1][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		turnCorner(w, 4, 3, TL);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		turnCorner(w, 5, 0, BL);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		turnCorner(w, 2, 1, TR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 3, TL);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		turnCorner(w, 4, 0, BR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		turnCorner(w, 4, 2, TR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		turnCorner(w, 5, 1, BR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][0].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		turnCorner(w, 4, 2, TR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		turnCorner(w, 4, 0, BR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, BR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 2, TR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		movePuzzleEdge(w, 1, 2, TL, FALSE);
		turnCorner(w, 4, 0, BR);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else if (w->dino.cubeLoc[1][2].face == color) {
		turnCorner(w, 2, 3, BR);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TL, FALSE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace1Pos2(DinoWidget w, int color)
{
	int face = 1;
	int pos = 2;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[3][3].face == color) {
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][3].face == color) {
		turnCorner(w, 2, 2, TL);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		turnCorner(w, 4, 3, BL);
	} else if (w->dino.cubeLoc[2][0].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		turnCorner(w, 4, 3, BL);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, BL);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		turnCorner(w, 2, 2, TL);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, BR);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 2, 2, TR);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[1][1].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, BR);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		turnCorner(w, 2, 1, BL);
		turnCorner(w, 4, 3, BL);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		turnCorner(w, 2, 1, BL);
		turnCorner(w, 4, 3, BL);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 2, 1, BL);
		turnCorner(w, 4, 3, BL);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		turnCorner(w, 2, 1, BL);
		turnCorner(w, 4, 3, BL);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		oppSwap(w, 2, 0, CW, TRUE);
		movePuzzleEdge(w, 1, 2, TR, FALSE);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		movePuzzleEdge(w, face, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		oppSwap(w, 2, 3, CW, TRUE);
		turnCorner(w, 2, 2, TL);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace1Pos1(DinoWidget w, int color)
{
	int face = 1;
	int pos = 1;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[3][0].face == color) {
		oppSwap(w, 1, 1, CW, FALSE);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		oppSwap(w, 1, 1, CW, FALSE);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		turnCorner(w, 2, 1, TR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		turnCorner(w, 4, 0, BR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		turnCorner(w, 4, 1, TR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		turnCorner(w, 5, 0, BR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		turnCorner(w, 4, 1, BL);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		turnCorner(w, 4, 1, TL);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 2, 1, TR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		oppSwap(w, 2, 1, CCW, TRUE);
		turnCorner(w, 2, 1, TR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[2][0].face == color) {
		oppSwap(w, 5, 1, CW, TRUE);
		turnCorner(w, 5, 0, BR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		oppSwap(w, 5, 1, CCW, TRUE);
		turnCorner(w, 5, 0, BR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[2][3].face == color) {
		oppSwap(w, 5, 0, CCW, TRUE); /* across face */
		turnCorner(w, 2, 1, TR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		oppSwap(w, 2, 2, CW, TRUE); /* across face */
		turnCorner(w, 5, 0, BR);
		oppSwap(w, 1, 1, CCW, FALSE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace2Pos3(DinoWidget w, int color)
{
	int face = 2;
	int pos = 3;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[2][1].face == color) {
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		oppSwap(w, 5, 2, CW, TRUE);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		oppSwap(w, 5, 0, CCW, TRUE);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		turnCorner(w, 4, 0, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		turnCorner(w, 3, 1, TR);
		oppSwap(w, 5, 0, CCW, TRUE);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		turnCorner(w, 4, 1, TR);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		turnCorner(w, 5, 0, BR);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[2][2].face == color) {
		turnCorner(w, 2, 1, BL);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		turnCorner(w, 3, 2, BR);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		flipFace(w, 3);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		flipFace(w, 4);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		flipFace(w, 5);
		turnCorner(w, 5, 0, BR);
		turnCorner(w, 3, 2, TL);
		oppSwap(w, 5, 0, CW, TRUE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace2Pos2(DinoWidget w, int color)
{
	int face = 2;
	int pos = 2;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[5][1].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		turnCorner(w, 3, 2, TL);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		turnCorner(w, 4, 0, TL);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 3, 2, TL);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, TL);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		flipFace(w, 3);
		turnCorner(w, 3, 2, TL);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		flipFace(w, 4);
		turnCorner(w, 4, 0, TL);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		flipFace(w, 5);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
	} else if (w->dino.cubeLoc[2][1].face == color) {
		turnCorner(w, 2, 1, TR);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, TL);
	} else if (w->dino.cubeLoc[3][0].face == color) {
		flipFace(w, 3);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, TL);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		flipFace(w, 4);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 3, 2, TL);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 2, 1, TR);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, TL);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		flipFace(w, 5);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 2, 1, TR);
		movePuzzleEdge(w, 2, 2, TR, FALSE);
		turnCorner(w, 4, 0, TL);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace2Pos1(DinoWidget w, int color)
{
	int face = 2;
	int pos = 1;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[3][0].face == color) {
		balancedRotate(w);
	} else if (w->dino.cubeLoc[3][2].face == color) {
		flipFace(w, 3);
		balancedRotate(w);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		turnCorner(w, 4, 1, TR);
		flipFace(w, 3);
		balancedRotate(w);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		flipFace(w, 4);
		turnCorner(w, 4, 1, TR);
		flipFace(w, 3);
		balancedRotate(w);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		turnCorner(w, 5, 0, BR);
		flipFace(w, 3);
		balancedRotate(w);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		flipFace(w, 5);
		turnCorner(w, 5, 0, BR);
		flipFace(w, 3);
		balancedRotate(w);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		oppSwap(w, 2, 1, CW, FALSE);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		oppSwap(w, 2, 1, CCW, FALSE);
	} else if (w->dino.cubeLoc[3][1].face == color) {
		turnCorner(w, 3, 1, TR);
		oppSwap(w, 2, 1, CW, FALSE);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		turnCorner(w, 4, 1, BL);
		oppSwap(w, 2, 1, CW, FALSE);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		flipFace(w, 3);
		turnCorner(w, 3, 1, TR);
		oppSwap(w, 2, 1, CW, FALSE);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		flipFace(w, 4);
		turnCorner(w, 4, 1, BL);
		oppSwap(w, 2, 1, CW, FALSE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace3Pos1(DinoWidget w, int color)
{
	int face = 3;
	int pos = 1;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[3][2].face == color) {
		turnCorner(w, 3, 1, BL);
		swapAdjFaces(w, 1, 2);
		turnCorner(w, 4, 1, TR);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		swapAdjFaces(w, 1, 2);
		flipFace(w, 4);
		turnCorner(w, 4, 1, TR);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		swapAdjFaces(w, 1, 2);
		turnCorner(w, 4, 1, TR);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 5, 0, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		turnCorner(w, 4, 1, TR);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		flipFace(w, 4);
		turnCorner(w, 4, 1, TR);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		turnCorner(w, 5, 0, BR);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		swapAdjFaces(w, 0, 1);
		turnCorner(w, 5, 0, BR);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 3, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 3, CW, FALSE);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace3Pos2(DinoWidget w, int color)
{
	int face = 3;
	int pos = 2;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[5][0].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 2, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 2, CCW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		swapAdjFaces(w, 0, 2);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 4, 5);
		turnCorner(w, 2, 1, TR);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 0, 2);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		swapAdjFaces(w, 0, 2);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 4, 5);
		turnCorner(w, 4, 0, BR);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 0, 2);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		swapAdjFaces(w, 0, 2);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 4, 5);
		flipFace(w, 2);
		turnCorner(w, 2, 1, TR);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 0, 2);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		swapAdjFaces(w, 0, 2);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 4, 5);
		flipFace(w, 4);
		turnCorner(w, 4, 0, BR);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 0, 2);
	} else if (w->dino.cubeLoc[3][3].face == color) {
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 1, CCW, TRUE);
		swapAdjFaces(w, 2, 3);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 2, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 5, 0, CCW, TRUE);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 2, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 5, 0, CW, TRUE);
		swapAdjFaces(w, 2, 4);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 2, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace3Pos3(DinoWidget w, int color)
{
	int face = 3;
	int pos = 3;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[5][0].face == color) {
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 1, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 1, CCW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 1, CW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
		oppSwap(w, 2, 1, CCW, FALSE);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][1].face == color) {
		swapAdjFaces(w, 2, 3);
		swapAdjFaces(w, 4, 5);
		oppSwap(w, 2, 1, CCW, FALSE);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][3].face == color) {
		swapAdjFaces(w, 2, 3);
		swapAdjFaces(w, 4, 5);
		oppSwap(w, 2, 1, CW, FALSE);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][0].face == color) {
		swapAdjFaces(w, 2, 3);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 4, 5);
		oppSwap(w, 2, 2, CW, FALSE);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
	} else if (w->dino.cubeLoc[4][2].face == color) {
		swapAdjFaces(w, 2, 3);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 4, 5);
		oppSwap(w, 2, 2, CCW, FALSE);
		swapAdjFaces(w, 4, 5);
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 3);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace4Pos1(DinoWidget w, int color)
{
	int face = 4;
	int pos = 1;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[5][0].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 1, CW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 1, CCW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 1, CW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 1, CCW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace4Pos2(DinoWidget w, int color)
{
	int face = 4;
	int pos = 2;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[5][1].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 0, CCW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 0, CW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][0].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 0, CCW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 0, CW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace4Pos3(DinoWidget w, int color)
{
	int face = 4;
	int pos = 3;

	if (w->dino.cubeLoc[face][pos].face == color) {
		return;
	} else if (w->dino.cubeLoc[5][0].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 3, CCW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][2].face == color) {
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 3, CW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][1].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 3, CCW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else if (w->dino.cubeLoc[5][3].face == color) {
		swapAdjFaces(w, 0, 1);
		swapAdjFaces(w, 2, 4);
		oppSwap(w, 2, 3, CW, FALSE);
		swapAdjFaces(w, 2, 4);
	} else {
		(void) printf("Fix face %d pos %d\n", face, pos);
	}
}

static void
setFace0(DinoWidget w)
{
	int face = 0;
	int pos = 0;
	int color = w->dino.cubeLoc[face][pos].face;
#ifdef DEBUG
	(void) printf("face %d: zeroethEdge %d\n", face, color);
#endif
	setFace0Pos1(w, color);
	setFace0Pos3(w, color);
	setFace0Pos2(w, color);
}

static void
setFace1(DinoWidget w)
{
	int face = 1;
	int pos = 0;
	int color = w->dino.cubeLoc[face][pos].face;
#ifdef DEBUG
	(void) printf("face %d: zeroethEdge %d\n", face, color);
#endif
	setFace1Pos3(w, color);
	setFace1Pos2(w, color);
	setFace1Pos1(w, color);
}

static void
setFace2(DinoWidget w)
{
	int face = 2;
	int pos = 0;
	int color = w->dino.cubeLoc[face][pos].face;
#ifdef DEBUG
	(void) printf("face %d: zeroethEdge %d\n", face, color);
#endif
	setFace2Pos3(w, color);
	setFace2Pos2(w, color);
	setFace2Pos1(w, color);
}

static void
setFace3(DinoWidget w)
{
	int face = 3;
	int pos = 0;
	int color = w->dino.cubeLoc[face][pos].face;
#ifdef DEBUG
	(void) printf("face %d: zeroethEdge %d\n", face, color);
#endif
	setFace3Pos1(w, color);
	setFace3Pos2(w, color);
	setFace3Pos3(w, color);
}

static void
setFace4(DinoWidget w)
{
	int face = 4;
	int pos = 0;
	int color = w->dino.cubeLoc[face][pos].face;
#ifdef DEBUG
	(void) printf("face %d: zeroethEdge %d\n", face, color);
#endif
	/*
	findFacets(w, color);
	printPosition();
	*/
	setFace4Pos1(w, color);
	setFace4Pos2(w, color);
	setFace4Pos3(w, color);
}

static int
oppFace(int face)
{
	switch (face) {
	case 0: return 4;
	case 1: return 3;
	case 2: return 5;
	case 3: return 1;
	case 4: return 0;
	case 5: return 2;
	default: return -1;
	}
}

static int
findAMixup(DinoWidget w, int face)
{
	int i;

	for (i = face + 1; i < MAX_FACES; i++) {
		if ((w->dino.cubeLoc[i][3].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				(w->dino.cubeLoc[i][1].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4)) {
			/* best */
			return i;
		}
	}
	for (i = face + 1; i < MAX_FACES; i++) {
		if ((w->dino.cubeLoc[i][3].rotation !=
				w->dino.cubeLoc[i][0].rotation) ||
				(w->dino.cubeLoc[i][1].rotation !=
				w->dino.cubeLoc[i][0].rotation)) {
			/* 2nd best */
			return i;
		}
	}
	return -1;
}

static int
startOfBadOrder(DinoWidget w, int face)
{
	int i;
	for (i = 0; i < MAX_ORIENT; i++) {
		if ((w->dino.cubeLoc[face][i].rotation ==
				w->dino.cubeLoc[face][(i + 1) % MAX_ORIENT].rotation) &&
				(w->dino.cubeLoc[face][i].rotation !=
				w->dino.cubeLoc[face][(i + 2) % MAX_ORIENT].rotation))
			return (i + 2) % MAX_ORIENT;
		if ((w->dino.cubeLoc[face][i].rotation ==
				w->dino.cubeLoc[face][(i + 1) % MAX_ORIENT].rotation) &&
				(w->dino.cubeLoc[face][i].rotation ==
				w->dino.cubeLoc[face][(i + 2) % MAX_ORIENT].rotation))
			return -1; /* OK */
	}
	return -2; /* inverted */
}

static void
setFaceOrient(DinoWidget w)
{
	int i, j, k;

	for (i = 0; i < MAX_FACES; i++) {
		j = startOfBadOrder(w, 0);
		if (j >= 0) {
			oppSwap(w, 0, j, CW, FALSE);
			if ((j % 2) == 1)
				rotatePairs(w, 0, 1);
			else
				rotatePairs(w, 0, 3);
			oppSwap(w, 0, j, CCW, FALSE);
			if ((j % 2) == 1)
				rotatePairs(w, 0, 1);
			else
				rotatePairs(w, 0, 3);
			oppSwap(w, 0, j, CW, FALSE);
		}
		if (i == 3)
			movePuzzleFace(w, 1, 0, BOTTOM, TRUE);
		else if (i < 3)
			movePuzzleFace(w, 0, 0, BOTTOM, TRUE);
		else if (i == 4) {
			movePuzzleFace(w, 0, 0, BOTTOM, TRUE);
			movePuzzleFace(w, 0, 0, BOTTOM, TRUE);
		}
	}
	for (i = 0; i < MAX_FACES; i++) {
		j = oppFace(i);
		if ((w->dino.cubeLoc[i][3].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				(w->dino.cubeLoc[i][1].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				((w->dino.cubeLoc[j][3].rotation !=
				w->dino.cubeLoc[j][0].rotation) ||
				(w->dino.cubeLoc[j][1].rotation !=
				w->dino.cubeLoc[j][0].rotation))) {
			flipLR(w, i);
		}
	}
	for (i = 0; i < MAX_FACES; i++) {
		j = oppFace(i);
		if ((w->dino.cubeLoc[i][3].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				(w->dino.cubeLoc[i][1].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				(w->dino.cubeLoc[j][1].rotation ==
				w->dino.cubeLoc[j][0].rotation) &&
				(w->dino.cubeLoc[j][3].rotation ==
				w->dino.cubeLoc[j][0].rotation)) {
			k = findAMixup(w, i);
			if (k == -1)
				break;
			swapAdjFaces(w, i, k);
		}
	}
	for (i = 0; i < MAX_FACES; i++) {
		j = oppFace(i);
		if ((w->dino.cubeLoc[i][3].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				(w->dino.cubeLoc[i][1].rotation ==
				(w->dino.cubeLoc[i][0].rotation + 2) % 4) &&
				((w->dino.cubeLoc[j][3].rotation !=
				w->dino.cubeLoc[j][0].rotation) ||
				(w->dino.cubeLoc[j][1].rotation !=
				w->dino.cubeLoc[j][0].rotation))) {
			flipLR(w, i);
		}
	}
	/* could have one inverted */
	if (startOfBadOrder(w, 4) == -2)
		movePuzzleFace(w, 0, 0, TOP, TRUE);
	if (startOfBadOrder(w, 1) == -2)
		movePuzzleFace(w, 1, 0, TOP, TRUE);
	else if (startOfBadOrder(w, 2) == -2)
		movePuzzleFace(w, 0, 0, TOP, TRUE);
	else if (startOfBadOrder(w, 3) == -2)
		movePuzzleFace(w, 3, 0, TOP, TRUE);
	else if (startOfBadOrder(w, 5) == -2)
		movePuzzleFace(w, 0, 0, BOTTOM, TRUE);
	if (startOfBadOrder(w, 0) == -2) {
		oppSwap(w, 4, 0, CW, FALSE);
		rotatePairs(w, 0, 1);
		oppSwap(w, 4, 0, CW, FALSE);
		rotatePairs(w, 0, 1);
		oppSwap(w, 4, 0, CW, FALSE);
		rotatePairs(w, 0, 1);
		oppSwap(w, 4, 0, CW, FALSE);
		rotatePairs(w, 0, 1);
		oppSwap(w, 4, 0, CW, FALSE);
	}
}

static void
solveFaces(DinoWidget w)
{
	setFace0(w);
	setFace1(w);
	setFace2(w);
	setFace3(w);
	setFace4(w);
	if (w->dino.orient) {
		setFaceOrient(w);
	}
#if 0
	int face = 4, pos = 0;
	for (face = 4; face < 5; face++) {
		for (pos = 0; pos < 4; pos++) {
			oppSwap(w, face, pos, CW, FALSE);
			printf("face %d  pos %d\n", face, pos);
			sleep(8);
			clearPieces(w);
		}
	}
#endif
}

/* This procedure coordinates the solution process. */
void
solveSomePieces(DinoWidget w)
{
	setPuzzle(w, ACTION_RESET);
	if (solvingFlag)
		return;
#ifdef JMP
	if (!setjmp(solve_env))
#endif
	{
		solvingFlag = True;
		if (w->dino.mode == PERIOD3)
			solveEdges(w);
		else if (w->dino.mode == PERIOD2)
			solveFaces(w);
		else {
			solveEdges(w);
			solveFaces(w);
		}
	}
#ifdef JMP
	abortSolvingFlag = False;
#endif
	solvingFlag = False;
	w->dino.cheat = True; /* Assume the worst. */
	setPuzzle(w, ACTION_CHEAT);
	setPuzzle(w, ACTION_COMPUTED);
}
